Deploying an InvoiceNinja App
Introduction
InvoiceNinja is an open-source invoicing and billing platform built on Laravel. Deploying InvoiceNinja with a Dockerfile on Klutch.sh delivers reproducible builds, managed secrets, and persistent storage for uploads and cache—all managed from klutch.sh/app. This guide covers installation, repository prep, a production-ready Dockerfile, deployment steps, Nixpacks overrides, and best practices for reliable billing workflows.
Prerequisites
- A Klutch.sh account (create one)
- A GitHub repository with your InvoiceNinja code (GitHub is the only supported git source)
- Docker familiarity and PHP 8.1+ knowledge
- Database credentials (MySQL/MariaDB) and Redis for queues/cache
- Storage capacity for PDFs, logos, and uploads
For platform onboarding, see the Quick Start.
Architecture and ports
- InvoiceNinja serves HTTP; set the internal container port to
9000when using PHP-FPM with a bundled web server, or8000/8080if you serve directly. This guide uses9000for consistency with FPM + Nginx. - MySQL/MariaDB and Redis should run as separate Klutch.sh TCP apps. Expose them on port
8000and connect internally on3306(MySQL/MariaDB) and6379(Redis). - Persistent storage is required for
/var/www/html/storageand recommended for logs.
Repository layout
invoiceninja/├── public/ # Web root├── storage/ # Must be on persistent volume├── docker/ # Optional helper scripts/configs├── Dockerfile # Must be at repo root for auto-detection├── composer.json├── composer.lock└── .env.example # Template only; no secretsKeep secrets out of Git; store them in Klutch.sh environment variables.
Installation (local) and starter commands
Install dependencies and run locally before pushing to GitHub:
composer install --no-dev --optimize-autoloaderphp artisan key:generatephp artisan migrate --forcephp artisan serve --host=0.0.0.0 --port=9000Optional helper start.sh for portability and Nixpacks fallback:
#!/usr/bin/env bashset -euo pipefailphp artisan migrate --forceexec php artisan serve --host=0.0.0.0 --port=9000Make it executable with chmod +x start.sh.
Dockerfile for InvoiceNinja (production-ready)
Place this Dockerfile at the repo root; Klutch.sh auto-detects it (no Docker selection in the UI):
FROM php:8.1-fpm
RUN apt-get update && apt-get install -y \ libpng-dev libjpeg-dev libfreetype6-dev libzip-dev libonig-dev libicu-dev libxml2-dev unzip git \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install pdo_mysql gd intl zip opcache \ && rm -rf /var/lib/apt/lists/*
WORKDIR /var/www/html
COPY . /var/www/html
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \ composer install --no-dev --optimize-autoloader && \ chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
ENV PORT=9000
EXPOSE 9000CMD ["php-fpm"]Notes:
- If you prefer Nginx + PHP-FPM in one container, add Nginx and a site config, still exposing
9000internally for the app service. - Keep
storage/writable and on a persistent volume.
Environment variables (Klutch.sh)
Set these in the Klutch.sh app settings (Secrets tab) before deploying:
APP_ENV=productionAPP_KEY=<generated-app-key>APP_URL=https://example-app.klutch.shAPP_DEBUG=falseDB_HOSTDB_PORT=3306DB_DATABASEDB_USERNAMEDB_PASSWORDREDIS_HOSTREDIS_PORT=6379QUEUE_CONNECTION=redisSESSION_DRIVER=redisCACHE_DRIVER=redisLOG_CHANNEL=stderrPORT=9000
If you deploy without the Dockerfile and need Nixpacks overrides:
NIXPACKS_BUILD_CMD=composer install --no-dev --optimize-autoloaderNIXPACKS_START_CMD=php -S 0.0.0.0:9000 -t publicNIXPACKS_INSTALL_PKGS="php81 php81Extensions.pdo_mysql php81Extensions.intl php81Extensions.gd php81Extensions.zip"
These keep InvoiceNinja compatible with Nixpacks defaults when a Dockerfile is absent.
Attach persistent volumes
In Klutch.sh storage settings, add mount paths and sizes (no names required):
/var/www/html/storage— required for uploads, cache, and logs./var/www/html/bootstrap/cache— optional if you want to persist caches.
Ensure these paths are writable inside the container.
Deploy InvoiceNinja on Klutch.sh (Dockerfile workflow)
- Push your repository (with the Dockerfile at the root) to GitHub.
- Open klutch.sh/app, create a project, and add an app.
- Connect the GitHub repository; Klutch.sh automatically detects the Dockerfile.
- Choose **HTTP** traffic for InvoiceNinja.
- Set the internal port to `9000`.
- Add the environment variables above (database, Redis, app key, and any `NIXPACKS_*` overrides if you temporarily deploy without the Dockerfile).
- Attach persistent volumes for `/var/www/html/storage` (and `/var/www/html/bootstrap/cache` if used), selecting sizes that fit your attachment and log needs.
- Deploy. Your app will be reachable at `https://example-app.klutch.sh`; attach a custom domain if desired.
For MySQL/MariaDB or Redis on Klutch.sh, create separate TCP apps, expose them on port 8000, and point DB_HOST or REDIS_HOST to those endpoints (internal ports 3306/6379).
Health checks and production tips
- Add a
/healthendpoint or reuse a lightweight route for uptime monitoring. - Enforce HTTPS at the edge; forward HTTP to port 9000 internally.
- Monitor storage usage for
/var/www/html/storageand resize before it fills. - Rotate
APP_KEYonly during maintenance; changing it will invalidate sessions. - Back up your database and storage regularly; do not rely on container filesystems for durability.
InvoiceNinja on Klutch.sh combines reproducible Docker builds with managed secrets, persistent storage for billing assets, and flexible HTTP/TCP routing. With the Dockerfile at the repo root and ports set to 9000 for the app (8000 externally for TCP databases or caches), you can deliver a reliable invoicing platform without extra YAML or workflow overhead.