diff options
| author | Ruben Beltran del Rio <jj@r.bdr.sh> | 2026-04-30 15:17:30 +0200 |
|---|---|---|
| committer | Ruben Beltran del Rio <jj@r.bdr.sh> | 2026-04-30 15:37:23 +0200 |
| commit | 8cc11c52a88ec78d175b3ec8de854916f631caab (patch) | |
| tree | 4ad0bc1664a97418d0475b0b730c54d874953348 /README.md | |
Initial build
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..2cce13b --- /dev/null +++ b/README.md @@ -0,0 +1,107 @@ +# estampa + +A very very tiny pastebin. Files are uploaded over `scp` and served as +syntax-highlighted HTML by a CGI handler in front of nginx. Pastes +expire after a week. No JavaScript ever involved! + +## How it works + +Estampa is a single binary with two modes: + +- `estampa`: CGI handler (no arguments). Reads `DOCUMENT_ROOT` and + `DOCUMENT_URI` from the environment, joins them safely, and writes a + CGI response to stdout. +- `estampa --run <directory>`: Deletes regular files in `<directory>` whose + mtime is more than seven days old. + +The serving side is text-only. Anything that doesn't decode as UTF-8 +returns 404. + +## Install + +Build from source: + +```sh +cargo build --release +sudo install -m 755 target/release/estampa /usr/bin/estampa +``` + +Prebuilt packages are available on [build.r.bdr.sh][build]. + +## Serving (nginx + fcgiwrap) + +`estampa` with no arguments is a CGI program. +See [`extras/nginx.conf`](extras/nginx.conf). + +```nginx +server { + listen 80; + server_name paste.example.com; + + root /srv/estampa; + + # Only serve top-level, non-dotfile names. + location ~ /\. { return 404; } # .ssh/, .bashrc, ... + location ~ /.+/ { return 404; } # anything inside a subdirectory + + location / { + fastcgi_pass unix:/run/fcgiwrap.socket; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /usr/bin/estampa; + } +} +``` + +Status codes: + +| code | when | +| ---- | ----------------------------------------------------------------- | +| 200 | file exists, is a regular top-level file, and is valid UTF-8 | +| 404 | file is missing, in a subdirectory, starts with `.`, isn't a regular file, isn't valid UTF-8, or the request escapes the root | +| 500 | `DOCUMENT_ROOT` not set, or read error | + +## Uploading and expiring (scp + ssh) + +The smoothest setup is a dedicated `estampa` user whose home directory +*is* the paste root, so uploads need no destination path: + +```sh +scp paste.txt estampa@paste.example.com: +# https://paste.example.com/paste.txt +``` + +To wire that up: + +```sh +sudo install -d -m 755 /srv/estampa +sudo useradd estampa -s /usr/sbin/nologin --home /srv/http/estampa +sudo chown estampa:estampa /srv/estampa +sudo install -d -m 700 -o estampa -g estampa /srv/estampa/.ssh +sudo -u estampa touch /srv/estampa/.ssh/authorized_keys +sudo chmod 600 /srv/estampa/.ssh/authorized_keys +``` + +Add the upload key to `/srv/estampa/.ssh/authorized_keys` with the +forced-command wrapper from [`extras/estampa-ssh`](extras/estampa-ssh): + +``` +command="/usr/local/bin/estampa-ssh /srv/estampa",no-pty,no-agent-forwarding,no-port-forwarding,no-X11-forwarding ssh-ed25519 AAAA... uploader +``` + +That wrapper runs `estampa --run "$1"` as a side-effect of every +incoming session and then `exec`s the original `scp` or `sftp-server` +the client wanted, so a normal upload also triggers a cleanup pass. +`--run` only looks at the top level of the directory, so subdirectories +(like `.ssh/`) are not traversed and not deleted. + +Because the upload account's home lives inside the web root, the nginx +config in `extras/nginx.conf` returns 404 for any dotfile-prefixed path +— that's what keeps `/.ssh/authorized_keys` and friends private. + +## Development + +Build with `make`. +Test with `make test` +Lint with `make lint` + +[build]: https://build.r.bdr.sh/estampa |