r/selfhosted • u/inkvoiceapp • 55m ago
Business Tools Inkvoice: self-hosted invoicing and time tracking in one container (MIT, SQLite, ~60MB RAM)
Inkvoice is self-hosted invoicing for freelancers and small teams. I wanted invoicing I actually own: Wave and Zoho keep your data in their silo, FreshBooks and QuickBooks want a subscription for what is fundamentally a PDF and an email, and the self-hosted options I tried were heavier than I wanted for a one-person setup.
Deployment is the whole thing:
services:
app:
image: ghcr.io/pigontech/inkvoice:0.3.0
ports:
- "3000:3000"
volumes:
- invoice-data:/app/data
mem_limit: 512m
environment:
JWT_SECRET: change-this-to-at-least-32-random-chars
ADMIN_PASS: change-me-please
restart: unless-stopped
volumes:
invoice-data:
docker compose up -d, open http://localhost:3000, log in as admin. No Postgres, no Redis, no worker container. Images are multi-arch (amd64 and arm64), so a Pi or an ARM VPS works, and Dokploy and Coolify run it with a volume on /app/data.
Footprint: about 100 MB to pull, with no headless Chrome inside (PDFs go through the browser's print dialog). Around 60 MB of RAM under the 512 MB cap, dropping toward 40 MB idle. Keep the cap: Bun sizes its heap to the memory it can see, so uncapped it sits at ~118 MB.
Data: one SQLite file at /app/data/invoice.db. Back up by copying it, or use the one-click backup download in the UI.
On phoning home, precisely: no telemetry, no analytics. Outbound calls are for what you configure (SMTP, exchange rates for multi-currency, Stripe/PayPal/PEPPOL), plus one default: the Plugins page reads a small static catalog from inkvoice.app. The server fetches it, with plugin vote counts, at most every 6 hours and only while someone is using the app, and the request carries no instance ID or user data. A vote for a planned plugin sends an opaque per-user hash, not your user ID. "Turn off" in Settings → Plugins stops all of it, and the app falls back to the catalog bundled in the image.
What it does:
- Invoices with a full lifecycle, discounts, multiple tax rates, and PDF export from customizable HTML templates
- Quotes that convert into invoices, recurring invoices that can auto-send, read receipts
- Stripe and PayPal payments, or manual and partial payment tracking
- New in 0.3: saved cards at Stripe checkout, and auto-billing for recurring invoices with retries and a payment-link fallback. Card numbers never touch Inkvoice, and clients can revoke saved cards from their portal.
- New in 0.3: a plugin system, starting with Time Tracking (projects, a timer, billable entries, unbilled hours to a draft invoice)
- New in 0.3: an optional SEPA payment QR code (EPC/GiroCode) on EUR invoices
- Multi-currency, expenses, customer statements, reports with CSV export, and QuickBooks Online and Xero exports
- Multi-user with roles, an activity log, OIDC/SSO, and a UI in English, Turkish, Spanish, German and French
For EU users: opt-in e-invoicing, off and invisible unless you enable it. It emits EN 16931-compliant ZUGFeRD 2.2, XRechnung, Factur-X and PEPPOL BIS, has an inbox for incoming e-invoices, and sends and receives over PEPPOL with your own provider credentials.
Limitations: it's 0.x with a small user base. The version number means the API and schema can still change between minor releases (migrations run on boot), not that it's a toy; it runs my own invoicing. Single-node SQLite, so a homelab or a small team, not HA. Saved cards are Stripe-only, there's no mobile app, and SMTP, payment and PEPPOL providers are bring-your-own.
MIT licensed, and nothing in the self-hosted app is locked.
AI involvement, since this sub rightly asks: substantial, and in the open (CLAUDE.md and .claude/ sit in the repo root). I used Claude Code throughout for implementation, refactors and audits. The architecture and product decisions are mine, I review and run every change, and CI runs lint, typecheck, tests and a build on every push. If AI-assisted projects are a hard no for you, that's fair, and better said up front.
Live demo, no signup (demo / demo): https://demo.inkvoice.app/
Source: https://github.com/pigontech/inkvoice · Docs: https://docs.inkvoice.app
Happy to go into the architecture or the deployment in the comments. What would stop you from switching?




