Klonkt is open-source and self-hostable — run it on a small VPS or with Docker. Your data, your server, your domain.
Good if: you have (or just rented) a fresh, empty Debian/Ubuntu VPS and want the easiest path — no technical setup.
This single line does everything: installs Node 20, sets up Caddy for automatic HTTPS, runs Klonkt as a background service that auto-restarts on reboot, and adds an update command. (It's coexistence-safe — if the server already runs something it picks a free port and skips Caddy — but a clean VPS is simplest.) First point your domain's DNS (A + AAAA records) at the server, then run as root:
curl -fsSL https://klonkt.com/install.sh | sudo bash -s -- --domain yourdomain.com
Then open https://yourdomain.com and finish setup in the browser. Update anytime with klonkt-update.
Good if: you already use Docker, or want everything bundled in one isolated container.
Node, ffmpeg and the image tools are all inside the image — you only need Docker + Docker Compose installed.
git clone https://github.com/roboburr/klonkt.git
cd klonkt
cp .env.example .env # works as-is; optionally set PUBLIC_BASE_URL to your domain
docker compose up -d
SESSION_SECRET is auto-generated on first start, so the defaults just work. Klonkt runs on port 3000 — put your own reverse proxy in front for HTTPS (see step 5 of Option C). Your data lives in the klonkt-data volume and survives updates. Update with git pull && docker compose up -d --build.
Good if: you want full control, are adding Klonkt to a server you already manage, or just want to test it locally.
1. Get the code & install dependencies. First check your Node version — Klonkt needs 20 or newer:
node -v # must print v20.x or higher
git clone https://github.com/roboburr/klonkt.git
cd klonkt
npm ci
On an older Node the fediverse (ActivityPub) features silently fail (the code uses APIs added in Node 18+) and the native database module may not load. If you later switch Node versions, run npm rebuild better-sqlite3.
2. Create your config. SESSION_SECRET (the key that signs login cookies) is auto-generated on first start. For any public site set two things in .env: NODE_ENV=production (secure cookies + trusting your reverse proxy) and PUBLIC_BASE_URL = your site address. PUBLIC_BASE_URL is required for the fediverse (ActivityPub) to work — federation builds absolute URLs from it, so without it nothing federates and email/login links break:
cp .env.example .env
nano .env
# NODE_ENV=production
# PUBLIC_BASE_URL=https://yourdomain.com
# (optional: SMTP_* for email; HSTS_STRICT=1 for stricter HTTPS if Klonkt owns the whole domain)
3. Start it. The SQLite database is created automatically on first start:
npm start # runs on http://localhost:3000
Just testing locally? Stop here and open http://localhost:3000.
4. Keep it running across crashes and reboots. Easiest is pm2:
npm install -g pm2
pm2 start src/server.js --name klonkt
pm2 save && pm2 startup # run the one command it prints, once
5. Add HTTPS with a reverse proxy in front. With Caddy (automatic certificates), put this in /etc/caddy/Caddyfile and reload Caddy:
yourdomain.com {
reverse_proxy localhost:3000
}
By default the app binds to 127.0.0.1 (set in .env), so only your reverse proxy reaches it — not the open internet. Local testing on the same machine (localhost:3000) still works. Only if you need direct external access without a proxy, set HOST=0.0.0.0 and open the port in your firewall — but then add HTTPS yourself.
Using a different proxy (nginx, an SSH tunnel + proxy, etc.)? Two things matter: forward the original Host header (so links + federation use your real domain, not localhost), and run with NODE_ENV=production (so the app trusts the proxy's X-Forwarded-* headers and sets secure cookies). Caddy's reverse_proxy passes the Host by default; with nginx add proxy_set_header Host $host;. Forward all paths — the fediverse lives under /ap/* and /.well-known/*.
Open your site and you'll get a setup wizard: pick your language, name your site and create your admin account. That's it — the first user becomes the administrator and registration then closes.
Set KLONKT_AUDIO=off to run a lightweight blog / photo / EPK / links site without ffmpeg — fits even on minimal hosting. Hub and Circles keep working.
Klonkt is deliberately lightweight. It uses SQLite (embedded, WAL mode) — no separate database server to run or tune. The database is an in-process file the OS keeps in RAM, so reads are memory-fast; media (audio/images) are served as files, not from the database.
A single instance comfortably runs an artist or label site on a small, cheap VPS. For traffic spikes — a release going viral — put a CDN (e.g. Cloudflare) in front: it absorbs the (cacheable) reads and your origin only sees cache-misses and writes. The realistic limit of one instance isn't "too much traffic" but a too-small VPS without a CDN.
Because every artist self-hosts their own instance, there's no central database to cluster or saturate — the network scales horizontally by itself, and Circles federation is decentralized and cached too. (Single-node SQLite is the right tool for a content site; it's not meant to be one giant shared write-heavy database — which this model never needs.)
See the troubleshooting guide — the fediverse not working, pages looking broken behind a proxy, better-sqlite3 errors, locked out, HTTPS, and more. Most issues come down to your Node version, PUBLIC_BASE_URL, or your reverse proxy.
Want the music features too? That's the full version (the default). Questions: info@robingenis.com.
← back to klonkt.com