docs / invoices / getting-started / installation.md
Installation
Self-host Invoices, the contacts and AI-native invoicing app. It is not the entrytwo accounting ledger.
The source repository is public.
There is no published Invoices Docker image. Build the included Dockerfile
locally. No GitHub account, access token, or registry login is needed.
invoices:latest is a local image tag, not a downloadable registry image.
The code is proprietary source-available shareware, not open source. You may inspect, clone, build, and privately modify it under that license. Full use is free for 30 days; continued use requires a one-time Invoices license. An entrytwo accounting key does not activate Invoices.
Let an AI agent help: give your coding agent this page and the Invoices install skill. State whether you want a local installation or a VPS with a domain. Keep secrets out of chat. Agents may install and configure; a human must approve purchases and complete checkout.
Prerequisites
- Git, Docker, and Docker Compose v2 or newer (Docker Desktop on macOS).
- At least 2 GB RAM; 4 GB or more is preferable for building on the host.
- Working SMTP and/or Google/Microsoft OAuth for sign-in. SMTP is also needed to send invoice emails.
- For an internet-facing VPS: a domain pointing at the server and an HTTPS reverse proxy such as Caddy or nginx.
- Optional: your own AI provider credentials for chat invoice drafts.
1. Clone the source
git clone https://github.com/felixkrusch/invoices.git
cd invoices
cp .env.example .env
Keep .env private. Do not overwrite an existing installation's environment.
2. Configure the environment
Generate separate values and enter them in .env:
openssl rand -base64 48 # AUTH_SECRET
openssl rand -hex 32 # ENCRYPTION_KEY (keep for future restores)
openssl rand -base64 48 # JOB_RUNNER_SECRET
openssl rand -base64 48 # UPDATER_TOKEN
openssl rand -hex 24 # POSTGRES_PASSWORD
AUTH_SECRET and JOB_RUNNER_SECRET need at least 32 characters;
ENCRYPTION_KEY needs exactly 64 hexadecimal characters. Compose currently
interpolates the optional updater service too, so set UPDATER_TOKEN even
though the updater is not enabled. Compose supplies the database URL from
POSTGRES_PASSWORD; no host PostgreSQL install is needed for this path.
Set these shared values:
APP_IMAGE="invoices:latest"
APP_VERSION="dev"
UPDATER_URL=""
UPDATE_MANIFEST_URL=""
LICENSE_VERIFY_URL="https://entrytwo.com/api/license/verify"
AUTH_TRUST_HOST="true"
Record git rev-parse HEAD so you know which source revision you built.
Do not enable the updater profile or configure an entrytwo update feed.
Local Docker installation
For example, use port 3001 to avoid conflicting with entrytwo:
APP_PORT="127.0.0.1:3001"
AUTH_URL="http://localhost:3001"
APP_PUBLIC_URL="http://localhost:3001"
AUTH_ALLOW_HTTP="true"
Docker runs the app in production mode, even on a laptop. Real SMTP/OAuth
and administrator TOTP are still required; instant development login is not
available. AUTH_ALLOW_HTTP=true is an explicit localhost/lab-only exception,
not a public deployment setting. Bind to loopback as above. For native Node.js
development instead, follow the repository's SETUP.md.
VPS with HTTPS
APP_PORT="127.0.0.1:3000"
AUTH_URL="https://invoices.example.com"
APP_PUBLIC_URL="https://invoices.example.com"
AUTH_ALLOW_HTTP="false"
Replace the example domain with yours. Point DNS at the VPS before requesting
a TLS certificate. Proxy HTTPS to 127.0.0.1:3000, forwarding the original
host and HTTPS scheme. Do not expose PostgreSQL publicly.
Sign-in and email
Configure SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, and SMTP_FROM,
and/or a complete Google or Microsoft OAuth configuration from .env.example.
Register the exact callback URL at your provider:
{AUTH_URL}/api/auth/callback/google{AUTH_URL}/api/auth/callback/microsoft-entra-id
OAuth alone is sufficient for sign-in, but SMTP plus the worker are needed for outbound invoice emails. Leave optional AI/payment credentials empty unless you intend to use those integrations.
3. Build locally and start
After configuring .env, run from the cloned repository:
docker compose -f compose.yaml pull db
docker compose -f compose.yaml build app
docker compose -f compose.yaml up -d --no-build --pull never app worker db
docker compose -f compose.yaml ps
Only PostgreSQL is pulled from a public registry. The app is built locally;
the worker uses that same local image and must start after the build. Do not
run docker compose pull app worker. The entrypoint applies Prisma migrations.
For the local example:
curl --fail --silent --show-error http://localhost:3001/api/health
For a VPS, check https://your-domain/api/health. Proceed only when
"ready": true and "status": "ok". .env values are not automatically shell
variables, and APP_PORT can include a bind address; use the actual URL, not
${APP_PORT:-3000} in curl commands.
If startup fails:
docker compose -f compose.yaml logs --tail=100 app worker
Missing secrets, incomplete SMTP/OAuth, and an HTTP AUTH_URL without the
explicit local exception prevent production startup. Do not fix these by
disabling authentication or deleting database volumes.
4. First use and licensing
Open the configured URL, create the first ADMIN, enable TOTP, then set up company details, tax rates, a contact, and a test invoice. Verify PDF download and email delivery. Keep the worker running or invoice emails remain queued.
The 30-day trial requires no key. A human can buy at
Buy Invoices, then activate the Invoices key in the
app's license UI. The authenticated activation API is POST /api/license/activate
with {"key":"et1.<payload>.<sig>"}. The app submits product: invoices to the
verification service once; successful activation is permanent for that install.
One paid Invoices license covers installations for businesses you own. Use a separate stack and database per company. Unrelated client businesses need their own licenses, even if you administer their servers.
Backups, updates, and multiple companies
- Give every company's stack its own directory,
COMPOSE_PROJECT_NAME, port, secrets, database, and private-file volumes. Invoices is not multi-tenant. - Export
.invbackupbackups and store them off-host with the originalENCRYPTION_KEYsecured separately. They are not compatible with entrytwo.etbackupfiles. Test restore on an isolated installation. - Do not run
docker compose down -v; it deletes persistent volumes. - Updates currently mean reviewing a source revision, backing up, rebuilding
app, and recreating both app and worker. There is no published image feed for the in-app updater. Follow the source update guide.
Further operator references: production checklist and authentication checklist.
Need a full ledger instead? entrytwo installation.