1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
# 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
On the server, you need the `estampa` binary (CGI handler + cleanup
tool) and the `estampa-ssh` wrapper (forced command for the upload
account). Build from source:
```sh
cargo build --release
sudo install -m 755 target/release/estampa /usr/bin/estampa
sudo install -m 755 extras/estampa-ssh /usr/local/bin/estampa-ssh
```
## 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/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
|