Configuration
Inkvoice is configured through environment variables. Copy .env.example to .env to get started.
Required
| Variable | Default | Description |
|---|---|---|
ADMIN_USER | admin | Initial admin username (demo when demo mode is on) |
ADMIN_PASS | changeme | Initial admin password (demo when demo mode is on) |
JWT_SECRET | — | JWT signing secret (min 32 characters) |
WARNING
Always set a strong JWT_SECRET in production. The default is only suitable for development.
Database
| Variable | Default | Description |
|---|---|---|
DATABASE_PATH | ./data/invoice.db | Path to the SQLite database file |
The database is created automatically on first run. Back it up by copying this file.
Server
| Variable | Default | Description |
|---|---|---|
PORT | 3000 | Server port |
HOST | 0.0.0.0 | Server bind address |
Security
| Variable | Default | Description |
|---|---|---|
SESSION_TTL | 3600 | JWT token lifetime in seconds |
COOKIE_SECURE | true | Use secure cookies (set to false for HTTP in development) |
ENABLE_HSTS | false | Enable HSTS header |
RATE_LIMIT_ENABLED | true | Enable login rate limiting |
RATE_LIMIT_MAX_ATTEMPTS | 5 | Max failed login attempts before lockout |
RATE_LIMIT_WINDOW | 900 | Rate limit window in seconds (15 min) |
CORS
| Variable | Default | Description |
|---|---|---|
ALLOWED_ORIGINS | http://localhost:5173,http://localhost:3000 | Comma-separated allowed origins |
Only needed if running the frontend dev server separately from the backend.
Email (SMTP)
Optional. Enables sending invoices and quotes by email.
| Variable | Default | Description |
|---|---|---|
SMTP_HOST | — | SMTP server hostname |
SMTP_PORT | 587 | SMTP server port |
SMTP_USER | — | SMTP username |
SMTP_PASS | — | SMTP password |
SMTP_FROM | — | Sender email address |
SMTP_SECURE | false | Use TLS (set to true for port 465) |
Online Payments (Stripe & PayPal)
Optional. Enables customers to pay invoices online from the public invoice link. Configure either gateway or both; each is enabled per workspace under Settings → Payments once its credentials (including the webhook secret/ID) are set. A gateway without its webhook credential will not appear as an option, because payments are confirmed server-side via webhooks.
Stripe
| Variable | Default | Description |
|---|---|---|
STRIPE_SECRET_KEY | — | Stripe secret key (sk_...) |
STRIPE_PUBLISHABLE_KEY | — | Stripe publishable key (pk_...) |
STRIPE_WEBHOOK_SECRET | — | Stripe webhook signing secret (whsec_...) — required |
PayPal
| Variable | Default | Description |
|---|---|---|
PAYPAL_CLIENT_ID | — | PayPal REST app client ID |
PAYPAL_SECRET | — | PayPal REST app secret |
PAYPAL_WEBHOOK_ID | — | PayPal webhook ID (for signature verification) — required |
PAYPAL_ENV | sandbox | sandbox or live |
See Online Payments for setup instructions.
PDF Generation
Nothing to configure. Inkvoice renders invoices and quotes as HTML and the browser's print dialog turns them into PDFs, so there is no Chrome or Chromium to install, bundle or point at. The CHROME_PATH variable used by older versions is gone and is ignored if still set.
Demo Mode
| Variable | Default | Description |
|---|---|---|
DEMO_MODE | false | Enable demo mode with sample data and periodic resets |
DEMO_RESET_INTERVAL | 86400000 | Reset interval in milliseconds (default 24 hours) |
With DEMO_MODE=true the admin defaults change from admin / changeme to demo / demo, and the login page shows those credentials so visitors can get in. Leave ADMIN_USER and ADMIN_PASS unset to pick up that default. The repo's docker-compose.yml passes them through empty so the app decides, but .env.example and the compose snippet in Getting Started set them explicitly, so clear them if you copied either.
The login page only ever advertises the literal demo / demo pair. If you set your own ADMIN_PASS alongside DEMO_MODE=true, no credentials are shown, so enabling demo mode on an instance that holds real data can never publish its password.