Self-Hosted Invoicing with Docker (Coolify & Dokploy Guide)
Self-hosting your invoicing means your client data, invoices, and numbers live on infrastructure you control — no subscription, no lock-in, no third party holding your books. With a single-container app like Inkvoice it takes minutes. Here’s how to do it on plain Docker, Coolify, or Dokploy.
Why self-host your invoicing
- You own the data. Everything lives in one SQLite file on your server.
- No per-seat pricing. Run it for your whole team for the cost of a tiny VPS.
- Tiny footprint. Inkvoice idles around ~50–100 MB RAM — the cheapest VPS tier is plenty.
(Prefer not to run a server at all? There’s a managed Cloud — skip to the end.)
What you need
A host that runs Docker. A $4–6/mo VPS is fine. You’ll expose port 3000 and keep a persistent volume so the database survives redeploys.
Option A — Plain Docker
docker compose up -d
Open http://localhost:3000 (or your server’s IP) and log in with admin / changeme — then change the password from the user menu immediately. Mount a volume on /app/data so the SQLite database persists across restarts.
Option B — Coolify
- New Resource → Public Repository → paste the repo URL.
- Build pack: Dockerfile (repo root).
- Port:
3000. - Persistent storage: add a volume on
/app/data— without it, every deploy wipes the database. - Environment: set
JWT_SECRET(≥ 32 chars),ADMIN_PASS, andCOOKIE_SECURE=true. - Domain: attach one (Coolify issues a Let’s Encrypt cert), then set
ENABLE_HSTS=true. - Health check: point it at
/health.
Option C — Dokploy
Same shape as Coolify: create a Docker service from the repo, expose port 3000, mount a volume on /app/data, and set JWT_SECRET + ADMIN_PASS. Attach a domain and you’re live.
The env vars that actually matter
JWT_SECRET— a random string ≥ 32 chars. Don’t skip this.ADMIN_PASS— your initial admin password.COOKIE_SECURE=trueandENABLE_HSTS=true— once you’re on HTTPS.- A volume on
/app/data— the single most important step; it’s where your data lives.
Backups are trivial
Because it’s one SQLite file under /app/data, backing up is just copying that file (or snapshotting the volume) on a schedule. Restoring is dropping it back. No database dumps, no orchestration.
…or skip the ops entirely
Self-hosting is great, but it’s not for everyone. If you’d rather not manage a server, Inkvoice Cloud gives you the same app — free, open-source, your data exportable anytime — with zero setup. Either way you own your billing. Star or fork it on GitHub.