Skip to content

Repository files navigation

TadPad

Go License Footprint Dependencies

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.

tadpad editor showing a grocery list pad

Features

  • 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.

Quick start

go install

go install github.com/Tadakai/tadpad@latest
tadpad

Pre-built binary

Grab one from the Releases page (Linux x86_64, Raspberry Pi arm64/armv7, macOS, Windows) and run it:

./tadpad-linux-arm64

Or 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'

Build from source

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 .
./tadpad

Docker

docker compose up -d --build

Builds a scratch-based image (no OS, no shell) around the static binary and keeps pads in ./data on the host.

systemd (native service, no Docker)

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 tadpad

Then open http://<that machine's IP>:8080/hello from any device on your network.

Configuration

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

Resource footprint

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.

Security notes

  • 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.

How syncing works

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.

License

MIT © Tadakai — see LICENSE.

About

A tiny self-hosted clone of dontpad.com.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages