How to Deploy Invoice Ninja – An Opensource Invoicing Application and Alternative to Freshbooks

Learn how to deploy Invoice Ninja on Ubuntu 24.04 to manage invoices, payments, and financial tasks.

Invoice Ninja is an open-source invoicing application built on top of Laravel for sending invoices and tracking payments. It’s a free and open-source alternative to accounting applications like Freshbooks and QuickBooks. You can use Invoice Ninja to perform financial management tasks, including income, expenses, payments, and time tracking.

In this article, you will deploy Invoice Ninja on an Ubuntu 24.04 based server. You will install Invoice Ninja and use the application to perform financial management tasks on the server.

Prerequisites

Before you begin:

  • Have access to an Ubuntu 24.04 instance as a non-root sudo user.
  • Create a domain A record pointing to the instance’s IP address. For example, invoiceninja.example.com

Install Invoice Ninja

Invoice Ninja is based on Laravel, and you can install it using the latest release file or with Docker. Installing Invoice Ninja with a release file enables you to access the latest application features, while Docker allows you to run Invoice Ninja without any manual package installations. Use the following steps to install Invoice Ninja on your server.

  1. Update your package repository.
    console
    $ sudo apt update
    
  2. Allow HTTP and HTTPS traffic through your firewall.
    console
    $ sudo ufw allow http && sudo ufw allow https
    

Installing Invoice Ninja using the latest release file enables access to the latest application features and compatibility with other applications, such as web servers. Invoice Ninja requires PHP 8.3 with an active LAMP or LEMP stack to run with all required PHP extensions on your server. Use the following steps to install the LEMP stack and all the necessary dependencies to install Invoice Ninja.

Install Required Dependencies for Invoice Ninja

  1. Install Nginx, MySQL, and PHP.
    console
    $ sudo apt install nginx mysql-server php -y
    
  2. Verify the installed PHP version and confirm it’s PHP 8.3 or higher.
    console
    $ php -v
    
  3. Install PHP-FPM and all required PHP extensions for Invoice Ninja.
    console
    $ 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
    
  4. Enable Nginx to start at boot.
    console
    $ sudo systemctl enable nginx
    
  5. Start the Nginx system service.
    console
    $ sudo systemctl start nginx
    
  6. Check the Nginx service status and verify that it’s running.
    console
    $ sudo systemctl status nginx
    

    Output:

    ● nginx.service - A high performance web server and a reverse proxy server
        Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
        Active: active (running) since Fri 2025-05-02 00:34:30 UTC; 1s ago
    ...

Create a MySQL Database for Invoice Ninja

Invoice Ninja requires a MySQL database to run correctly on your server. Use the following steps to create a new MySQL database for Invoice Ninja.

  1. Log in to MySQL as the root database user.
    console
    $ sudo mysql -u root
    
  2. Create a new invoiceninjadb database.
    sql
    mysql> CREATE DATABASE invoiceninjadb;
    
  3. Create a new invoiceninja-admin user with a strong password. Replace secure-password with your actual password.
    sql
    mysql> CREATE USER 'invoiceninja-admin'@'localhost' IDENTIFIED BY 'secure-password';
    
  4. Grant the invoiceninja-admin user full privileges to the invoiceninjadb database.
    sql
    mysql> GRANT ALL PRIVILEGES ON invoiceninjadb.* TO 'invoiceninja-admin'@'localhost';
    
  5. Flush the MySQL privileges table to apply the user permission changes.
    sql
    mysql> FLUSH PRIVILEGES;
    
  6. Exit the MySQL database console.
    sql
    mysql> EXIT;
    

Download Invoice Ninja

Use the following steps to download the latest Invoice Ninja release file and install it on your server.

  1. Create a new invoiceninja directory in /var/www/.
    console
    $ sudo mkdir -p /var/www/invoiceninja
    
  2. Switch to the invoiceninja directory.
    console
    $ cd /var/www/invoiceninja
    
  3. Visit the Invoice Ninja releases page and verify the latest version to download. For example, run the following command to download version 5.11.72 using Wget.
    console
    $ sudo wget https://github.com/invoiceninja/invoiceninja/releases/download/v5.11.72/invoiceninja.tar.gz
    
  4. Extract all files from the downloaded invoiceninja.tar.gz archive.
    console
    $ sudo tar -xvf invoiceninja.tar.gz
    
  5. Remove the archive to save your disk space.
    console
    $ sudo rm invoiceninja.tar.gz
    
  6. Copy the .env.example file to create a new .env file.
    console
    $ sudo cp .env.example .env
    
  7. Grant the www-data Nginx user and group full permissions to the invoiceninja directory.
    console
    $ sudo chown -R www-data:www-data /var/www/invoiceninja
    
  8. Open the system crontab as the www-data user.
    console
    $ sudo -u www-data crontab -e
    
  9. Add the following Laravel schedule command to run regular maintenance tasks for Invoice Ninja.
    ini
    * * * * * php8.3 /var/www/invoiceninja/artisan schedule:run >> /dev/null 2>&1
    

    Save and close the Crontab file.

  10. Test the system’s Crontab to verify that the Invoice Ninja task is active.
    console
    $ 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

Invoice Ninja requires a virtual host configuration to run all files in the /var/www/invoiceninja directory. Use the following steps to create a new Nginx virtual host configuration to serve InvoiceNinja.

  1. Create a new invoiceninja.conf virtual host configuration in the /etc/nginx/sites-available directory.
    console
    $ sudo nano /etc/nginx/sites-available/invoiceninja.conf
    
  2. Add the following Nginx server block configurations to the invoiceninja.conf file. Replace invoiceninja.example.com with your domain.
    ini
    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;
        }
    
    }
    

    Save and close the invoiceninja.conf file.

    The above Nginx virtual host configuration serves Invoice Ninja files from the /var/www/invoiceninja/public directory using the invoiceninja.example.com domain. All PHP requests are forwarded to the installed PHP 8.3 FPM service to process and serve the Invoice Ninja dashboard.

  3. Remove the default Nginx virtual host configuration.
    console
    $ sudo rm /etc/nginx/sites-enabled/default
    
  4. To enable this virtual host, link the invoiceninja.conf file to the /etc/nginx/sites-enabled directory.
    console
    $ sudo ln -s /etc/nginx/sites-available/invoiceninja.conf /etc/nginx/sites-enabled/invoiceninja.conf
    
  5. Test the Nginx configuration for syntax errors.
    console
    $ 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
  6. Restart Nginx to apply the Invoice Ninja virtual host configurations.
    console
    $ sudo systemctl restart nginx
    

Secure Invoice Ninja with Trusted SSL Certificates

Use the following steps to generate trusted Let’s Encrypt SSL certificates to secure all connections to Invoice Ninja.

  1. Install the Certbot Let’s Encrypt plugin for Nginx.
    console
    $ sudo apt install python3-certbot-nginx
    
  2. Request a new TLS certificate using your virtual host domain. Replace invoiceninja.example.com with your active domain and admin@example.com with your email address.
    console
    $ sudo certbot --nginx -d invoiceninja.example.com -m admin@example.com --agree-tos
    
  3. Restart Nginx to apply the Invoice Ninja configuration changes.
    console
    $ sudo systemctl restart nginx
    

Set Up Invoice Ninja

  1. Access the /setup path using your invoiceninja.example.com domain in a web browser.
    https://invoiceninja.example.com/setup
  2. Verify that the Invoice Ninja configuration page displays correctly.

  3. Enter your domain in the URL field and keep the HTTPS Require option enabled.
  4. Navigate to Database Connection.
  5. Verify that MySQL is the selected driver.

  6. Keep localhost as the MySQL host or specify your MySQL database server address.
  7. Keep 3306 as the MySQL port or set it depending on your server port.
  8. Enter the Invoice Ninja database, username, and password information you created earlier.
  9. Click Test connection to validate the MySQL connection information and verify that a success prompt displays.
  10. Enter your Invoice Ninja administrator details in the User Details form.

  11. Check the Invoice Ninja terms of service and privacy policy options.
  12. Click Submit to apply the Invoice Ninja configuration.

 

install Invoice Ninja using Docker

Follow the steps below to install Invoice Ninja using Docker Compose with all necessary packages.

  1. Install Docker, Docker Compose, certbot, and certbot plugin for Nginx.
    console
    $ sudo apt install docker.io docker-compose certbot python3-certbot-nginx -y
    
  2. Remove Nginx to free up port 80 of your server.
    console
    $ sudo apt purge nginx -y
    
  3. Switch to your active user’s home directory.
    console
    $ cd
    
  4. Create a new invoiceninja project directory.
    console
    $ mkdir invoiceninja
    
  5. Switch to the invoiceninja directory.
    console
    $ cd invoiceninja
    
  6. Create new storageconfig, and public directories.
    console
    $ mkdir -p storage config public
    
  7. Change the default storage and public directory permissions to 777, enabling the Invoice Ninja container to write configuration files.
    console
    $ sudo chmod -R 777 storage public
    
  8. Generate a new Invoice Ninja API Key.
    console
    $ sudo docker run --rm -it invoiceninja/invoiceninja php artisan key:generate --show
    

    Copy the generated key in your output like the one below.

    base64:3OoSrTSLswQyfY/NjMvVaxoODn/NyFzzwwkjfou6JuQ=
  9. Create a new docker-compose.yml file.
    console
    $ nano docker-compose.yml
    
  10. Add the following Docker configurations to the docker-compose.yml file.
    yaml
    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
    

    In the above configuration,

    • Replace the APP_KEY value base64:/TIgzF1RTLm0D1VBUzbgZHTrtyQlJ9cxHPQ03VjDh7A= with your generated API key.
    • Replace the APP_URL value with your domain name.
    • In the db service, replace the values of the environment variables with names starting with MARIADB_ with your custom values.
    • In the app service, replace all the:
      • DB_ environment variables with the values you set in the db service section.
      • MAIL_ environment variables with your email server’s details if you’ve set one. Otherwise, you can leave it at its default values.
    • The IN_USER_EMAIL variable is your login email address, and the IN_PASSWORD variable is your login password. Set your values for these variables.

    Save and close the docker-compose.yml file.

    This Docker Compose configuration creates new containers for Nginx, MariaDB, and Redis, allowing Invoice Ninja to create databases and store data in memory for fast performance. Nginx forwards all connections to the Invoice Ninja port 9000.

  11. Generate a TLS certificate for your Invoice Ninja Docker application.
    console
    $ sudo certbot certonly --standalone -d invoiceninja.example.com --email invoiceninja@example.com --agree-tos --non-interactive
    

    To generate the certificate, replace invoiceninja.example.com with your domain name and provide your email address. Otherwise, the command will fail.

    Your TLS certificate and private key are stored at /etc/letsencrypt/live/invoiceninja.example.com/. In the later steps, use this path in the Nginx virtual host configuration file.

  12. Create a new in-vhost.conf virtual host configuration in the /config directory.
    console
    $ nano config/in-vhost.conf
    
  13. Add the following server block configurations ot the in-vhost.conf file.
    ini
    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;
        }
    }
    

    In the above configuration, replace all occurrences of invoiceninja.example.com with your domain name.

    Save and close the in-vhost.conf file.

    The above Nginx virtual host configuration listens for connection requests using all internal and host IP addresses to run Invoice Ninja on your server.

  14. Start all services in the background using Docker Compose in detached mode.
    console
    $ sudo docker-compose up -d
    
  15. List all Docker containers and verify that all services are running.
    console
    $ sudo docker container ls
    

    Output:

    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   
  16. To set up Automatic certificate renewal, edit the crontab file.
    console
    $ sudo nano /etc/crontab
    
  17. Add the following line at the end of the file.
    ini
    0 0 * * * root certbot renew --quiet
    

    This command runs the certbot renew --quiet command every day through the root user, which renews the certificate if it expires.

Access and Use Invoice Ninja

Use the following steps to access and use Invoice Ninja on your server.

  1. Open the Invoice Ninja login page using your domain in a new web browser tab..
    https://invoiceninja.example.com/login
  2. In the respective fields, enter your administrator email address and password and click Login to access the Invoice Ninja dashboard.

  3. In the open Welcome to Invoice Ninja prompt, enter your company name, such as example-company, and select the default currency to use in your invoices.

 

4.Navigate to Settings to fill-in your additional company information.

5.Click Invoices on the main navigation menu.

6.Click New Invoice to create a new invoice.

7.Click New Client, enter the client’s details, and click Save.

8.In the respective fields, set the Invoice date, due date, invoice number, PO, and discount information.

9.Click Add Item within the Products category to add new items to the invoice.

10.Click New Product, specify the Item details, and click Save.

11.Specify the unit cost and quantity details.

12.Enter additional information by navigating between the Public NotesTerms and Footer options.

13.Scroll and verify the Invoice information on the preview page.

14.Download or print the Invoice.

15.Click Save to export and save the Invoice in your collection.

Conclusion

In this article, you have deployed Invoice Ninja on an Ubuntu 24.04 server using the official package and using Docker. You can create invoices, manage records, and create financial records within the Invoice Ninja dashboard.

 

 

 

 

 

 

 

Learn how to deploy Invoice Ninja on Ubuntu 24.04 to manage invoices, payments, and financial tasks. Invoice Ninja is an open-source invoicing application built on top of Laravel for sending invoices and tracking payments. It’s a free and open-source alternative to accounting applications like Freshbooks and QuickBooks. You can use…

Learn how to deploy Invoice Ninja on Ubuntu 24.04 to manage invoices, payments, and financial tasks. Invoice Ninja is an open-source invoicing application built on top of Laravel for sending invoices and tracking payments. It’s a free and open-source alternative to accounting applications like Freshbooks and QuickBooks. You can use…

Leave a Reply

Your email address will not be published. Required fields are marked *