server-ovh-prod-01-main/docs/invoiceninja.md

5.9 KiB

Invoice Ninja

Type: Invoicing & Billing Application Domain: https://invoice.hyperthrive.io Version: 5.12.28 Architecture: Official Docker stack from invoiceninja/dockerfiles Deployment Date: 2025-10-14

Architecture

Invoice Ninja runs using the official Docker Compose stack with three services:

  1. invoiceninja-server-1 - Nginx web server (port 80 internal)
  2. invoiceninja-app-1 - Laravel application with supervisord (PHP-FPM, queue workers, scheduler)
  3. invoiceninja-db-1 - MariaDB 10.11 database

Traefik Integration

The nginx service connects to the external traefik network and uses labels for automatic SSL/routing:

  • Domain: invoice.hyperthrive.io
  • Protocol: HTTPS via Let's Encrypt
  • Entry Point: websecure (443)
  • Internal Port: 80 (nginx)

Directory Structure (Server)

~/services/invoiceninja/
├── docker-compose.yml          # Main compose file
├── env                         # Environment configuration
├── config/
│   └── nginx/
│       └── in-vhost.conf       # Nginx vhost config
├── docker/
│   ├── app/
│   │   ├── public/            # Application public files (shared with nginx)
│   │   └── storage/           # Application storage (logs, cache, uploads)
│   └── mysql/
│       └── data/              # Database files

Important: The docker/app/ directories must be owned by user 1500:1500 (the container's runtime user).

Common Operations

Check Status

ssh jared@15.204.247.153 "docker ps --filter name=invoiceninja"

View Logs

# Application logs
ssh jared@15.204.247.153 "docker logs invoiceninja-app-1 --tail 50"

# Database logs
ssh jared@15.204.247.153 "docker logs invoiceninja-db-1 --tail 50"

# Nginx logs
ssh jared@15.204.247.153 "docker logs invoiceninja-server-1 --tail 50"

Update Invoice Ninja

ssh jared@15.204.247.153 "cd ~/services/invoiceninja && \
  docker compose pull && \
  docker compose up -d && \
  docker exec invoiceninja-app-1 php artisan migrate --force && \
  docker exec invoiceninja-app-1 php artisan optimize"

Backup Database

ssh jared@15.204.247.153 "cd ~/services/invoiceninja && \
  docker compose exec -T db sh -c 'exec mysqldump --all-databases -uroot -p\"\$MYSQL_ROOT_PASSWORD\"' \
  > ~/backups/invoiceninja-$(date +%Y%m%d-%H%M%S).sql"

Restore Database

ssh jared@15.204.247.153 "cd ~/services/invoiceninja && \
  docker compose exec -T db sh -c 'exec mysql -uroot -p\"\$MYSQL_ROOT_PASSWORD\"' \
  < ~/backups/invoiceninja-TIMESTAMP.sql"

Restart Services

ssh jared@15.204.247.153 "cd ~/services/invoiceninja && docker compose restart"

Run Artisan Commands

# Generic pattern
ssh jared@15.204.247.153 "docker exec invoiceninja-app-1 php artisan <command>"

# Examples
ssh jared@15.204.247.153 "docker exec invoiceninja-app-1 php artisan queue:work"
ssh jared@15.204.247.153 "docker exec invoiceninja-app-1 php artisan cache:clear"
ssh jared@15.204.247.153 "docker exec invoiceninja-app-1 php artisan db:seed"

Key Configuration

Environment Variables (env file)

Critical settings in ~/services/invoiceninja/env:

  • APP_URL=https://invoice.hyperthrive.io - Public URL
  • APP_KEY=base64:... - Encryption key (DO NOT change after initial setup)
  • DB_HOST=db - Database hostname (container name)
  • MYSQL_ROOT_PASSWORD - DB root password
  • MYSQL_DATABASE=ninja - Database name
  • MYSQL_USER=ninja - DB user
  • MYSQL_PASSWORD - DB password
  • TRUSTED_PROXIES=* - Trust Traefik proxy
  • MAIL_MAILER=log - Mail driver (currently logging only)

Traefik Labels (docker-compose.yml)

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.invoiceninja.rule=Host(`invoice.hyperthrive.io`)"
  - "traefik.http.routers.invoiceninja.entrypoints=websecure"
  - "traefik.http.routers.invoiceninja.tls.certresolver=letsencrypt"
  - "traefik.http.services.invoiceninja.loadbalancer.server.port=80"
  - "traefik.docker.network=traefik"

Troubleshooting

Permission Denied Errors

If the app container fails with "Permission denied" creating directories:

ssh jared@15.204.247.153 "cd ~/services/invoiceninja && \
  docker compose down && \
  sudo chown -R 1500:1500 docker/app && \
  docker compose up -d"

Database Connection Issues

Check database is healthy:

ssh jared@15.204.247.153 "docker inspect invoiceninja-db-1 --format='{{.State.Health.Status}}'"

Should return healthy. If not, check logs.

502 Bad Gateway

Usually means the app container isn't running or PHP-FPM hasn't started:

  1. Check app container status: docker ps --filter name=invoiceninja-app-1
  2. Check app logs: docker logs invoiceninja-app-1 --tail 100
  3. Look for PHP-FPM startup message: "ready to handle connections"

SSL Certificate Issues

Traefik automatically handles SSL. If certificate issues occur:

  1. Check Traefik logs: docker logs traefik
  2. Verify DNS points to server: dig invoice.hyperthrive.io
  3. Check Traefik dashboard for router/certificate status

Queue Not Processing

The official stack includes queue workers via supervisord. Check they're running:

ssh jared@15.204.247.153 "docker exec invoiceninja-app-1 supervisorctl status"

Should show queue-worker_00 and queue-worker_01 as RUNNING.

Migration History

This deployment uses the official Invoice Ninja Docker stack (as of 2025-10-14). Previous custom stack was replaced to align with upstream recommendations and simplify maintenance.

Pre-migration backup location: ~/backups/invoiceninja-pre-official/ on server (retained until deployment proven stable)

References