aboutsummaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorRuben Beltran del Rio <jj@r.bdr.sh>2026-04-30 15:17:30 +0200
committerRuben Beltran del Rio <jj@r.bdr.sh>2026-04-30 15:37:23 +0200
commit8cc11c52a88ec78d175b3ec8de854916f631caab (patch)
tree4ad0bc1664a97418d0475b0b730c54d874953348 /README.md
Initial build
Diffstat (limited to 'README.md')
-rw-r--r--README.md107
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