entrytwo

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 .invbackup backups and store them off-host with the original ENCRYPTION_KEY secured separately. They are not compatible with entrytwo .etbackup files. 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.