A tiny self-hosted clone of dontpad.com: visit
http://yourserver:8080/anything and get a shared text pad that saves
itself as you type and syncs live to anyone else who opens the same
link. No accounts, no database, no setup screen — the URL is the
whole app.
Built for home labs: one static binary, ~7MB, under 15MB of RAM,
near-zero CPU at idle. Pure Go standard library — nothing to
npm install, nothing to break, nothing to patch.
- Visit any URL path → get a pad. First write creates it, nobody has to "make a note" first.
- Auto-saves ~500ms after you stop typing, no save button.
- Multiple tabs/devices on the same pad stay in sync (1.5s polling, last-write-wins).
- Pad names can include
/for folders, e.g./team/standup. - Empty pads leave no file on disk — nothing to clean up later.
- Path-traversal-safe pad names, a per-pad size cap, and atomic writes.
- Ships as a single static binary — cross-compiles to any OS/arch Go supports.
go install github.com/Tadakai/tadpad@latest
tadpadGrab one from the Releases page (Linux x86_64, Raspberry Pi arm64/armv7, macOS, Windows) and run it:
./tadpad-linux-arm64Or push it straight to a Pi:
scp tadpad-linux-arm64 pi@192.168.1.50:/usr/local/bin/tadpad
ssh pi@192.168.1.50 'chmod +x /usr/local/bin/tadpad && /usr/local/bin/tadpad'Needs Go 1.22+ and nothing else — no go.sum, no third-party packages:
git clone https://github.com/Tadakai/tadpad.git
cd tadpad
go build -o tadpad .
./tadpaddocker compose up -d --buildBuilds a scratch-based image (no OS, no shell) around the static
binary and keeps pads in ./data on the host.
sudo useradd --system --home /var/lib/tadpad --shell /usr/sbin/nologin tadpad
sudo mkdir -p /var/lib/tadpad
sudo chown tadpad:tadpad /var/lib/tadpad
sudo cp tadpad-linux-amd64 /usr/local/bin/tadpad # pick your arch
sudo cp tadpad.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now tadpadThen open http://<that machine's IP>:8080/hello from any device on
your network.
All options can be set as flags or environment variables:
| Flag | Env var | Default | Meaning |
|---|---|---|---|
-port |
PORT |
8080 |
port to listen on |
-data |
DATA_DIR |
./data |
directory where pads are stored |
-max-kb |
— | 5120 |
max size of a single pad, in KB |
Example: ./tadpad -port 9000 -data /mnt/nas/pads -max-kb 1024
Idle RSS sits under 9MB in testing, and there's no background polling or timer work on the server side — only what an incoming HTTP request triggers. It'll run comfortably on a Raspberry Pi Zero 2 W, an old router with a cross-compiled binary, a NAS's Docker app store, or a spare VM with 64MB of RAM allotted to it.
- No authentication. This mirrors dontpad's design: the pad name is the access control (like a shared secret in the URL). Keep it on your LAN, behind a VPN (Tailscale/WireGuard), or put a reverse proxy with basic auth in front of it if you need more.
- Pad names are sanitized against path traversal (
.., hidden files, absolute paths) and confined to the data directory. - Uploads are capped at 5MB per pad by default (
-max-kb). - The Docker image is built
FROM scratch— no shell, no package manager, nothing besides the binary.
Each open pad polls the server every 1.5 seconds. If the pad changed remotely and you haven't typed anything since your last save, your view updates automatically. If two people type into the same pad at the same moment, the last save wins — there's no operational-transform merge logic, by design, to keep this small and dependency-free. For a personal or small-team scratchpad that's a non-issue in practice.
MIT © Tadakai — see LICENSE.
