Invoice Ninja is an open-source invoicing platform for freelancers and small businesses: quotes, invoices, recurring billing, expenses, time tracking, a client portal, and online payments through Stripe, PayPal and dozens of other gateways. The self-hosted edition is free (with optional white-label licensing), and keeps your client and financial data on your own server.

Requirements

  • 1–2 vCPU and 2 GB RAM is enough for most small businesses.
  • Docker and Docker Compose. See install Docker.
  • A domain, e.g. billing.example.com, with HTTPS.
  • SMTP for sending invoices. See transactional email services.

Docker setup

Invoice Ninja provides an official dockerfiles repository with a Compose file (app + Nginx + MySQL/MariaDB + optionally Redis). Clone it, and configure env:

git clone https://github.com/invoiceninja/dockerfiles.git -b debian /opt/invoiceninja
cd /opt/invoiceninja

Key settings in the .env / env file:

APP_URL=https://billing.example.com
APP_KEY=<generate>          # docker run --rm -it invoiceninja/invoiceninja-debian php artisan key:generate --show
APP_DEBUG=false
REQUIRE_HTTPS=true
TRUSTED_PROXIES='*'
DB_HOST=mysql
DB_DATABASE=ninja
DB_USERNAME=ninja
DB_PASSWORD=change-me-db
IN_USER_EMAIL[email protected]
IN_PASSWORD=change-me-admin
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=…
MAIL_PASSWORD=…
MAIL_FROM_ADDRESS[email protected]
MAIL_FROM_NAME="Example Ltd"
PDF_GENERATOR=snappdf

Follow the repository README for the current branch and variable names, then:

docker compose up -d
docker compose logs -f

HTTPS with a reverse proxy

Bind the bundled Nginx container’s port to 127.0.0.1, and proxy from your host Nginx:

server {
    server_name billing.example.com;
    client_max_body_size 50M;
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    # listen 443 ssl; certbot --nginx -d billing.example.com
}

APP_URL must match the public URL, and TRUSTED_PROXIES must allow the proxy, or links and payment redirects break. See Let’s Encrypt and real IP behind a proxy.

First configuration

Log in with the admin account, then go through Settings:

  • Company details: logo, address, tax and VAT numbers, currency and language;
  • Invoice design: templates, custom fields, numbering patterns;
  • Tax rates, and payment terms;
  • Email settings: send a test invoice to yourself, and check SPF and DKIM for your sending domain. See SPF, DKIM and DMARC;
  • Payment gateways: connect Stripe, PayPal, GoCardless and others, so clients can pay invoices online through the client portal.

PDF generation

Invoice Ninja renders PDFs with a headless Chromium (snappdf) or other engines. If PDFs fail to generate, check the container logs. Missing Chromium dependencies, or low memory, are typical causes. Hosted PDF generation services are also supported.

Recurring invoices, reminders and cron

Recurring invoices, payment reminders and scheduled tasks run via Laravel’s scheduler and queue. The official Docker setup includes them (supervisor in the app container). On manual installs, add the scheduler cron:

* * * * * php /var/www/invoiceninja/artisan schedule:run >> /dev/null 2>&1

See Laravel scheduler.

Backups

Your invoices are legally relevant records. Back up:

  • the MySQL database:
docker compose exec -T mysql mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" ninja | gzip > /backups/ninja-$(date +%F).sql.gz
  • the storage and public volumes (logos, documents, generated PDFs);
  • the .env file (especially APP_KEY, which decrypts stored secrets).

Copy everything off-server, encrypted. See backup strategy.

Updates and security

  • Update: docker compose pull && docker compose up -d. Migrations run automatically. Back up first. See updating self-hosted apps.
  • Enable 2FA for admin users. Use strong passwords, and HTTPS only.
  • Keep the database container internal.

Quick reference

Item Value / setting
Public URL APP_URL
Encryption key APP_KEY (back it up!)
Behind proxy TRUSTED_PROXIES, REQUIRE_HTTPS=true
PDF engine PDF_GENERATOR=snappdf
Scheduler artisan schedule:run (every minute)

Related: ERPNext and Docker security.

  • Self-Hosting
  • Business
  • Docker