# 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 - 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-snippet` instead 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+. ```bash go build -o palette . ./palette # open http://localhost:8080 ``` ### Docker ```bash 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 | | | |---|---| | ![Editor](docs/palette-previews/pastel-lavender-new.png) | ![Paste view](docs/palette-previews/pastel-lavender-paste.png) | | ![History](docs/palette-previews/midnight-history.png) | | ## 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 `/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. ```bash ./palette --reset-admin-key # regenerate the admin key and print it ``` ## API Create a paste with one call: ```bash 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](docs/API.md). Design docs: [docs/design/](docs/design/) (currently: [client-side E2E encryption](docs/design/e2e-encryption.md), issue #39). ## Performance Notes The history and Saved pages use client-side filtering: when you type in the search box, the UI fetches the most recent 100 pastes (`limit=100`, the API maximum) once per query and filters/sorts them in the browser. Pastes beyond the newest 100 are not searched; a match count against the full total is still shown. This keeps search instant without a server-side query. If large instances need full search later, it will be a server-side endpoint (see issue #32). ## 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`