Deploying Invoice Ninja on Ubuntu 24.04
Invoice Ninja is an open-source invoicing platform built on Laravel that helps businesses send invoices and track payments. It provides a free alternative to popular accounting solutions like FreshBooks and QuickBooks. With Invoice Ninja, you can handle financial tasks such as managing income, expenses, payments, and even time tracking.
This guide explains how to deploy Invoice Ninja on an Ubuntu 24.04 server. You will install and configure the application so that it can be used for financial management directly on your server.
Prerequisites
Before starting, make sure you have the following:
- An Ubuntu 24.04 server instance with a non-root user that has sudo privileges.
- A configured domain A record pointing to your server’s IP address, for example: invoiceninja.example.com.
Installing Invoice Ninja
Invoice Ninja can be installed using the latest release package or Docker. Using the release file provides immediate access to new features, while Docker simplifies deployment by avoiding manual package installations. The following steps explain how to install Invoice Ninja using the release file method on your server.
Step 1: Update System Packages
$ sudo apt update
Step 2: Configure Firewall
Allow HTTP and HTTPS traffic through your firewall:
$ sudo ufw allow http && sudo ufw allow https
Step 3: Install Required Dependencies
Invoice Ninja requires PHP 8.3 and a LAMP or LEMP stack. First, install Nginx, MySQL, and PHP:
$ sudo apt install nginx mysql-server php -y
Check that the installed PHP version is 8.3 or newer:
$ php -v
Now install PHP-FPM and the required extensions:
$ sudo apt install php8.3-bcmath php8.3-gmp php8.3-fileinfo \
php8.3-gd php8.3-mbstring php8.3-pdo php8.3-xml php8.3-cli \
php8.3-curl php8.3-zip php8.3-gmp php8.3-mysql php8.3-fpm -y
Enable and start the Nginx service:
$ sudo systemctl enable nginx
$ sudo systemctl start nginx
$ sudo systemctl status nginx
Create MySQL Database
Invoice Ninja requires a MySQL database. Follow these steps:
Log in as root:
$ sudo mysql -u root
Create the database and user:
mysql> CREATE DATABASE invoiceninjadb;
mysql> CREATE USER 'invoiceninja-admin'@'localhost' IDENTIFIED BY 'secure-password';
mysql> GRANT ALL PRIVILEGES ON invoiceninjadb.* TO 'invoiceninja-admin'@'localhost';
mysql> FLUSH PRIVILEGES;
mysql> EXIT;
Download and Configure Invoice Ninja
Create the application directory and move into it:
$ sudo mkdir -p /var/www/invoiceninja
$ cd /var/www/invoiceninja
Download and extract the latest release (example version 5.11.72):
$ sudo wget https://github.com/invoiceninja/invoiceninja/releases/download/v5.11.72/invoiceninja.tar.gz
$ sudo tar -xvf invoiceninja.tar.gz
$ sudo rm invoiceninja.tar.gz
Set up environment file and permissions:
$ sudo cp .env.example .env
$ sudo chown -R www-data:www-data /var/www/invoiceninja
Configure Cron Jobs
Open the crontab as www-data
user:
$ sudo -u www-data crontab -e
Add the following Laravel scheduling command:
* * * * * php8.3 /var/www/invoiceninja/artisan schedule:run >> /dev/null 2>&1
Verify that the cron task is active:
$ sudo -u www-data crontab -l
Output:
# m h dom mon dow command
* * * * * php8.3 /var/www/invoiceninja/artisan schedule:run >> /dev/null 2>&1
Configure Invoice Ninja
To run Invoice Ninja, you need to configure a virtual host in Nginx so that all files inside the /var/www/invoiceninja
directory are properly served. Follow these steps to create and configure a new virtual host.
Step 1: Create a Virtual Host File
Create a new configuration file named invoiceninja.conf
in the /etc/nginx/sites-available
directory:
$ sudo nano /etc/nginx/sites-available/invoiceninja.conf
Add the following Nginx server block (replace invoiceninja.example.com with your actual domain):
server {
listen 80;
listen [::]:80;
server_name invoiceninja.example.com;
root /var/www/invoiceninja/public;
index index.php index.html index.htm;
client_max_body_size 20M;
charset utf-8;
access_log /var/log/nginx/ininja.access.log;
error_log /var/log/nginx/ininja.error.log;
gzip on;
gzip_types application/javascript application/x-javascript text/javascript text/plain application/xml application/json;
gzip_proxied no-cache no-store private expired auth;
gzip_min_length 1000;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
if (!-e $request_filename) {
rewrite ^(.+)$ /index.php?q= last;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
}
}
This virtual host configuration ensures that Invoice Ninja files in the /var/www/invoiceninja/public
directory are served under your domain, and all PHP requests are processed by PHP 8.3 FPM.
Step 2: Enable the Virtual Host
Remove the default Nginx virtual host configuration:
$ sudo rm /etc/nginx/sites-enabled/default
Activate the new virtual host by linking it into the sites-enabled
directory:
$ sudo ln -s /etc/nginx/sites-available/invoiceninja.conf /etc/nginx/sites-enabled/invoiceninja.conf
Test the Nginx configuration for syntax errors:
$ sudo nginx -t
Output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Restart Nginx to apply the changes:
$ sudo systemctl restart nginx
Secure Invoice Ninja with SSL
Next, secure Invoice Ninja with Let’s Encrypt SSL certificates.
Install the Certbot plugin for Nginx:
$ sudo apt install python3-certbot-nginx
Request a new TLS certificate. Replace invoiceninja.example.com with your domain and admin@example.com with your email:
$ sudo certbot --nginx -d invoiceninja.example.com -m admin@example.com --agree-tos
Restart Nginx to load the new SSL configuration:
$ sudo systemctl restart nginx
Set Up Invoice Ninja
Now that your server is configured, you can finish setting up Invoice Ninja in a web browser. Open the setup page:
https://invoiceninja.example.com/setup
The setup wizard will guide you through the configuration:
- Enter your domain in the URL field and leave the HTTPS Require option enabled.
- Confirm that MySQL is selected as the database driver.
- Keep
localhost
as the host (or specify another if needed). - Keep port
3306
unless your database is configured differently. - Provide the database name, username, and password you created earlier.
- Click Test connection to ensure the database settings are correct.
- Fill in your administrator details in the User Details form.
- Accept the terms of service and privacy policy.
- Click Submit to complete the setup.
Install Invoice Ninja with Docker Compose
You can also install Invoice Ninja using Docker Compose. This method deploys Invoice Ninja together with all required services like Nginx, MariaDB, and Redis. Follow the steps below to complete the installation.
Step 1: Install Docker and Dependencies
Install Docker, Docker Compose, and Certbot with the Nginx plugin:
$ sudo apt install docker.io docker-compose certbot python3-certbot-nginx -y
Remove Nginx to free up port 80:
$ sudo apt purge nginx -y
Step 2: Prepare the Project Directory
Switch to your home directory and create the project structure:
$ cd
$ mkdir invoiceninja
$ cd invoiceninja
$ mkdir -p storage config public
Change the permissions for storage and public directories so that the container can write to them:
$ sudo chmod -R 777 storage public
Step 3: Generate an API Key
Generate a new API key for Invoice Ninja:
$ sudo docker run --rm -it invoiceninja/invoiceninja php artisan key:generate --show
Copy the generated key, for example:
base64:3OoSrTSLswQyfY/NjMvVaxoODn/NyFzzwwkjfou6JuQ=
Step 4: Create docker-compose.yml
Create a new Docker Compose file:
$ nano docker-compose.yml
Paste the following configuration and adjust the values as explained below:
version: '3.7'
services:
nginx:
image: nginx
restart: unless-stopped
volumes:
- ./config/in-vhost.conf:/etc/nginx/conf.d/in-vhost.conf:ro
- ./public:/var/www/app/public:ro
- /etc/letsencrypt:/etc/letsencrypt:ro
depends_on:
- app
ports:
- "80:80"
- "443:443"
healthcheck:
test: curl -f http://localhost:80/ || exit 1
networks:
- invoice_ninja_network
db:
image: mariadb:10.4
restart: unless-stopped
volumes:
- ./data:/var/lib/mysql:rw,delegated
environment:
MARIADB_PASSWORD: ninja
MARIADB_ROOT_PASSWORD: ninja
MARIADB_DATABASE: ninja
MARIADB_USER: ninja
PUID: "1026"
PGID: "100"
networks:
- invoice_ninja_network
cache:
image: redis
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "redis-cli ping || exit 1"]
networks:
- invoice_ninja_network
app:
image: invoiceninja/invoiceninja:5
restart: unless-stopped
volumes:
- ./public:/var/www/app/public:rw,delegated
- ./storage:/var/www/app/storage:rw,delegated
depends_on:
db:
condition: service_started
cache:
condition: service_healthy
environment:
APP_NAME: "Invoice Ninja"
APP_ENV: "production"
APP_KEY: base64:3OoSrTSLswQyfY/NjMvVaxoODn/NyFzzwwkjfou6JuQ= # Replace with your key
APP_DEBUG: "0"
APP_URL: "https://invoiceninja.example.com" # Replace with your domain
IS_DOCKER: "true"
PHANTOMJS_PDF_GENERATION: "0"
PDF_GENERATOR: "snappdf"
TRUSTED_PROXIES: "*"
MULTI_DB_ENABLED: "0"
DB_HOST: db
DB_DATABASE: ninja
DB_USERNAME: ninja
DB_PASSWORD: ninja
DB_PORT: "3306"
PUID: "1026"
PGID: "100"
CACHE_DRIVER: redis
SESSION_DRIVER: redis
REDIS_HOST: cache
MAIL_MAILER: smtp
MAIL_HOST: smtp.ionos.de
MAIL_PORT: "465"
MAIL_USERNAME: xxx@yyyy
MAIL_PASSWORD: XXX
MAIL_ENCRYPTION: SSL
MAIL_FROM_ADDRESS: "invoiceninja@example.com"
MAIL_FROM_NAME: "Max Crisp"
REQUIRE_HTTPS: "1"
NINJA_ENVIRONMENT: "selfhost"
IN_USER_EMAIL: admin@example.com
IN_PASSWORD: GEHEIM
networks:
- invoice_ninja_network
networks:
invoice_ninja_network:
driver: bridge
Make sure to replace:
- APP_KEY with the generated API key.
- APP_URL with your domain.
- MARIADB_* values with your own database settings.
- DB_* values in the app service with those from the db section.
- MAIL_* values with your mail server details if used.
- IN_USER_EMAIL and IN_PASSWORD with your login credentials.
Step 5: Generate SSL Certificates
Generate a trusted TLS certificate for your domain:
$ sudo certbot certonly --standalone -d invoiceninja.example.com --email invoiceninja@example.com --agree-tos --non-interactive
The certificates are stored in /etc/letsencrypt/live/invoiceninja.example.com/
. These paths are used in the virtual host configuration.
Step 6: Configure Nginx Virtual Host
Create the Nginx configuration file in the config
directory:
$ nano config/in-vhost.conf
Add the following configuration (replace domain values with your own):
server {
listen 80 default_server;
server_name invoiceninja.example.com; # Replace with your domain
# Redirect all HTTP traffic to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl default_server;
server_name invoiceninja.example.com; # Replace with your domain
server_tokens off;
client_max_body_size 100M;
# SSL certificate paths
ssl_certificate /etc/letsencrypt/live/invoiceninja.example.com/fullchain.pem; # Replace with your domain
ssl_certificate_key /etc/letsencrypt/live/invoiceninja.example.com/privkey.pem; # Replace with your domain
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
root /var/www/app/public/;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
location ~* /storage/.*\.php$ {
return 503;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
}
}
Step 7: Start Containers
Start all services in detached mode:
$ sudo docker-compose up -d
Verify that all containers are running:
$ sudo docker container ls
Output example:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2aeefe15c99c nginx "/docker-entrypoint.…" 3 minutes ago Up 2 minutes (healthy) 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp invoiceninja_nginx_1
9fc27c288ac4 invoiceninja/invoiceninja:5 "docker-entrypoint s…" 3 minutes ago Up 3 minutes 9000/tcp invoiceninja_app_1
fa2e661a93ab redis "docker-entrypoint.s…" 4 minutes ago Up 4 minutes (healthy) 6379/tcp invoiceninja_cache_1
0a27ba745af1 mariadb:10.4 "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 3306/tcp invoiceninja_db_1
Step 8: Enable Automatic Certificate Renewal
Edit the system crontab file:
$ sudo nano /etc/crontab
Add the following line to renew the SSL certificate automatically every day:
0 0 * * * root certbot renew --quiet
This ensures your TLS certificates remain valid without manual intervention.
Access and Use Invoice Ninja
Once the installation is complete, you can access and start using Invoice Ninja by following these steps:
Step 1: Log In
Open the login page in your browser using your configured domain:
https://invoiceninja.example.com/login
Enter your administrator email and password, then click Login to access the Invoice Ninja dashboard.
Step 2: Initial Setup
When prompted with the Welcome to Invoice Ninja screen:
- Enter your company name (e.g., example-company).
- Select the default currency for your invoices.
Step 3: Configure Company Information
Navigate to Settings and complete your company details such as address, tax number, and other relevant information.
Step 4: Create a New Invoice
From the main navigation menu, select Invoices and click New Invoice.
- Click New Client, add the client’s details, and click Save.
- Specify invoice details including date, due date, invoice number, PO number, and discounts.
- Click Add Item under the Products section to include new items in the invoice.
- Click New Product, enter the product details, and click Save.
- Provide unit cost and quantity information.
Step 5: Add Additional Information
Navigate through the Public Notes, Terms, and Footer sections to add extra details to your invoice.
Step 6: Review and Save
Scroll through the invoice preview to verify all information is correct.
- You can download or print the invoice directly from the preview screen.
- Click Save to store the invoice in your records.
Conclusion
In this tutorial, you learned how to deploy Invoice Ninja on Ubuntu 24.04 using both the official package and Docker. With Invoice Ninja, you can create invoices, manage clients, and maintain financial records easily from the dashboard.
For further details, check the official Invoice Ninja documentation.