Self-Hosting Invoice Ninja with Docker
What Is Invoice Ninja?
Invoice Ninja is an open-source invoicing, quoting, and payment platform for freelancers and businesses. It handles invoices, quotes, expenses, time tracking, projects, recurring billing, and client payments — with a self-hosted option that gives you full control over your financial data. It replaces FreshBooks, QuickBooks Online, and Wave. Official site
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 1 GB of free RAM
- A domain name (required for client portal and payment links)
Docker Compose Configuration
services:
invoice-ninja-db:
image: mariadb:11.4
container_name: invoice-ninja-db
environment:
MYSQL_ROOT_PASSWORD: change-this-root-password
MYSQL_DATABASE: invoiceninja
MYSQL_USER: invoiceninja
MYSQL_PASSWORD: change-this-db-password
volumes:
- invoice-ninja-db:/var/lib/mysql
networks:
- invoice-ninja
restart: unless-stopped
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
invoice-ninja:
image: invoiceninja/invoiceninja:5.13.1
container_name: invoice-ninja
ports:
- "8080:80"
environment:
# Application key (generate with: docker exec invoice-ninja php artisan key:generate --show)
APP_KEY: base64:GENERATE_THIS_ON_FIRST_RUN
APP_URL: https://invoice.example.com
APP_ENV: production
APP_DEBUG: "false"
# Database
DB_HOST: invoice-ninja-db
DB_PORT: 3306
DB_DATABASE: invoiceninja
DB_USERNAME: invoiceninja
DB_PASSWORD: change-this-db-password
DB_TYPE: mysql
# Mail
MAIL_MAILER: smtp
MAIL_HOST: smtp.example.com
MAIL_PORT: 587
MAIL_USERNAME: [email protected]
MAIL_PASSWORD: change-this-mail-password
MAIL_ENCRYPTION: tls
MAIL_FROM_ADDRESS: [email protected]
MAIL_FROM_NAME: "Your Business Name"
# Queue and cache
QUEUE_CONNECTION: database
CACHE_DRIVER: database
SESSION_DRIVER: database
volumes:
- invoice-ninja-public:/var/www/app/public
- invoice-ninja-storage:/var/www/app/storage
networks:
- invoice-ninja
depends_on:
invoice-ninja-db:
condition: service_healthy
restart: unless-stopped
networks:
invoice-ninja:
volumes:
invoice-ninja-db:
invoice-ninja-public:
invoice-ninja-storage:
First-Run Setup
# Start the stack
docker compose up -d
# Generate the application key
docker exec invoice-ninja php artisan key:generate --show
# Copy the output (base64:xxxx...) and set it as APP_KEY in docker-compose.yml
# Restart with the key set
docker compose down && docker compose up -d
# Run migrations
docker exec invoice-ninja php artisan migrate --force
Access the setup wizard at http://your-server:8080 and create your admin account.
Core Features
| Module | What It Does |
|---|---|
| Invoices | Create, send, and track invoices with line items, taxes, discounts |
| Quotes | Generate quotes that convert to invoices on acceptance |
| Recurring invoices | Auto-generate invoices on a schedule (weekly, monthly, yearly) |
| Expenses | Track business expenses, attach receipts, link to invoices |
| Projects | Project-based billing with time tracking integration |
| Payments | Record payments manually or accept online payments |
| Client portal | Clients view invoices, make payments, approve quotes |
| Reports | Profit & loss, invoice aging, expense reports, tax summary |
Payment Gateway Integration
Invoice Ninja supports multiple payment gateways for online payments:
| Gateway | Setup |
|---|---|
| Stripe | API keys in Settings → Online Payments |
| PayPal | Client ID and Secret |
| Square | Application credentials |
| Authorize.net | Login ID and Transaction Key |
| Braintree | Merchant ID, public/private keys |
| GoCardless | For direct debit (EU/UK) |
Clients receive an invoice email → click “Pay Now” → complete payment through the gateway → invoice auto-marked as paid.
Configuration
Custom Invoice Templates
Invoice Ninja uses HTML/CSS templates for invoice PDFs. Customize them in Settings → Invoice Design. The template editor supports:
- Custom HTML/CSS layouts
- Company logo placement
- Custom fields
- Multiple templates (one per client or project type)
Multi-Currency and Tax
Configure in Settings → Tax Settings:
- Multiple tax rates (VAT, sales tax, custom)
- Per-line-item or per-invoice tax
- Multi-currency support with exchange rate lookups
- Tax report generation for filing
Email Configuration
Email is critical — clients receive invoices and payment links via email. Verify SMTP works:
docker exec invoice-ninja php artisan ninja:send-test-email [email protected]
If using Gmail SMTP, you’ll need an App Password (not your regular password).
Reverse Proxy
Behind Nginx Proxy Manager:
Proxy Host: invoice.example.com → http://invoice-ninja:80
Enable: WebSocket Support, Force SSL
Set APP_URL in your environment to match the public URL (including https://). Without this, invoice links and the client portal break.
Backup
| Volume | Contains | Priority |
|---|---|---|
invoice-ninja-db | All invoices, clients, payments, settings | Critical |
invoice-ninja-storage | Uploaded files, logos, PDF cache | Important |
invoice-ninja-public | Custom assets | Low |
# Database backup
docker exec invoice-ninja-db mariadb-dump -u invoiceninja -p'change-this-db-password' invoiceninja > invoiceninja-backup-$(date +%Y%m%d).sql
See Backup Strategy.
Troubleshooting
Blank page after setup
Symptom: Web UI shows a white page or 500 error.
Fix: Check APP_KEY is set correctly. Run docker exec invoice-ninja php artisan config:cache and restart. Check logs: docker exec invoice-ninja cat /var/www/app/storage/logs/laravel.log.
Emails not sending
Symptom: Invoices created but clients never receive them.
Fix: Verify SMTP settings. Test with php artisan ninja:send-test-email. Check that MAIL_ENCRYPTION matches your SMTP provider (tls for port 587, ssl for port 465).
PDF generation fails
Symptom: Clicking “Download PDF” shows an error or blank PDF.
Fix: The container needs Chromium for PDF generation. The official Docker image includes it. If using a custom image, ensure PHANTOMJS_PDF_GENERATION or PDF_GENERATOR is configured correctly.
Recurring invoices not generating
Symptom: Recurring invoices don’t appear on schedule.
Fix: The scheduler must run. Add this cron to your host or use a sidecar: docker exec invoice-ninja php artisan schedule:run. For production, set up a cron job that runs every minute.
Resource Requirements
- RAM: ~250 MB idle (app + MariaDB), ~500 MB under load
- CPU: Low to moderate — PDF generation is the heaviest operation
- Disk: ~500 MB for application, database grows with invoice/client volume
Verdict
Invoice Ninja is the most complete self-hosted invoicing solution. The client portal with online payments is the killer feature — clients can view and pay invoices without you chasing them. For simpler invoicing without the overhead, Crater is a lighter Laravel-based alternative. If you need time tracking that feeds into invoicing, pair Invoice Ninja with Kimai or use its built-in time tracker.
Related
- Invoice Ninja vs Crater: Which Invoicing Tool to Self-Host?
- Invoice Ninja vs FreshBooks: Self-Hosted Invoicing
- Invoice Ninja vs SolidInvoice: Self-Hosted Invoicing
- How to Self-Host Kimai
- Best Self-Hosted Personal Finance
- Replace FreshBooks
- Replace QuickBooks
- Docker Compose Basics
- Reverse Proxy Setup
- Backup Strategy
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments