5b9be808ed7e7bb91159ef34a82ce120708ebdb7
Cans UI + parity: unlock-cookie flow, /can page, listings badge, custom slug, delete, sweeper; #32 perf notes (#4, #32)
Palette
Palette is a fast, self-hosted pastebin. One Go binary, a SQLite database, and a web UI for sharing code and text with links that expire on your terms.
Features
- Paste cans — bundle notes, text, and files into one shareable page, with password/expiry/custom-slug parity and a
canbadge in listings - Password lock — protect individual pastes with a password
- Custom expiry — from 1 minute up to 1 year, or never
- Burn after N reads — a paste that vanishes after a chosen number of reads
- Custom URLs — reserve
/my-snippetinstead of a random slug - Syntax highlighting with language auto-detection (go-enry)
- Rate limiting on create and unlock
- Saved page — see and manage everything created from your browser
- API-first — every UI action is also a plain HTTP call
- Single binary — templates and assets are embedded; no external deps
Get Started
Build from source
Requires Go 1.21+.
go build -o palette .
./palette
# open http://localhost:8080
Docker
docker run -p 8080:8080 -v palette-data:/data git.archfox.org/poslop/palette
The SQLite database lives in the /data volume inside the container.
Screenshots
![]() |
![]() |
![]() |
Configuration
| Setting | Default | Description |
|---|---|---|
PALETTE_ADDR |
:8080 |
Listen address |
PALETTE_DB |
palette.db |
SQLite database path |
PALETTE_MAX_TEXT |
5242880 |
Max paste size in bytes (5 MB) |
PALETTE_MAX_ITEM |
26214400 |
Max can item size in bytes (25 MB) |
PALETTE_ADMIN_KEY |
generated | Admin key; if unset a 32-char hex key is generated and persisted to <db-dir>/admin-key (0600) |
Admin
GET /admin serves the admin page. Enter the admin key there — it is stored in
sessionStorage (never a cookie) and sent as the X-Admin-Key header on
GET/POST /admin/api/settings.
The admin API reads/sets: rate-limit burst, rate-limit refill per minute, max content bytes, default expiry, custom URL reservation days, and the burn viewer window (minutes). All admin access attempts are logged.
./palette --reset-admin-key # regenerate the admin key and print it
API
Create a paste with one call:
curl -X POST http://localhost:8080/api/pastes \
-H "Content-Type: application/json" \
-d '{"content": "print(hello)", "language": "python", "expires_in": "168h"}'
Full API docs: docs/API.md.
CI
Gitea Actions workflow at .gitea/workflows/ci.yml:
- On push to main:
go vet+go test - On tags: build and push Docker image to
git.archfox.org/poslop/palette


