Install Invoice Ninja v5 on Ubuntu 20.04.04 LTS

Hi everyone

After almost a year and a troubled Debian installation, I gave Invoice Ninja v5 on Ubuntu another try :slight_smile:
I wrote a basic tutorial for Ubuntu 20.04.04 LTS and Ninja v5.
I only tested this behind a reverse proxy and would love to hear some feedback from you.
PDF creation with snappdf works, but the optional supervisor part is not done yet.

I like this forum but I think github is better suited to open bug reports than here and it is simpler for me to keep it up to date. Link to Github

I am not a native English speaker and will spell check it in the future or you guys help me :wink:

# This is a basic tutorial for a

# default installation of a InvoiceNinja instance on Ubuntu

# You can also find this and report a bug on

# update and upgrade

sudo apt update && sudo apt upgrade -y

# optional step vor QEMU VM

sudo apt install qemu-guest-agent

# install dependencies

# do we really need curl, git, vim, maridb-client?

sudo apt install php php-{fpm,bcmath,ctype,fileinfo,json,mbstring,pdo,tokenizer,xml,curl,zip,gmp,gd,mysqli} mariadb-server mariadb-client curl git nginx vim composer -y

# if we visit http://yourIP , you should see a running Apache page. https://yourIP will not work you need to use http instead of https for now!

# Check if php-fpm is running. You should see something like active: active (running)

systemctl status php7.4-fpm

# press q to quit

# enable mariadb

sudo systemctl enable --now mariadb

# This command will take you through a guided wizard to initialize the SQL database. Use default values written in capital letters

sudo mysql_secure_installation

# Enter,  insert a password for the root account, repeat, Enter, Enter, Enter, Enter. You should see "Thanks for using MariaDB"

# login to the database

sudo mysql -u root -p

# enter the password you just set

# you should see MariaDB [(none)]> on the left of your cursor

# create database ninjadb


# You should see Query OK, 1 row affected

# create the user ninja and set a Password

CREATE USER 'ninja'@'localhost' IDENTIFIED BY 'Password';

# You should see Query OK, 0 rows affected

# give all permissions for to the local ninja user to access ninjadb

GRANT ALL PRIVILEGES ON ninjadb.* TO 'ninja'@'localhost';

# You should see Query OK, 0 rows affected

# reload privileges


# You should see Query OK, 0 rows affected

# exit the db


# You should see Bye


# create config for webpage

sudo nano /etc/nginx/sites-available/invoiceninja.conf

# insert this:


# You should look at the following URL's in order to grasp a solid understanding

# of Nginx configuration files in order to fully unleash the power of Nginx.





# In most cases, administrators will remove this file from sites-enabled/ and

# leave it as reference inside of sites-available where it will continue to be

# updated by the nginx packaging team.


# This file will automatically load configuration files provided by other

# applications, such as Drupal or Wordpress. These applications will be made

# available underneath a path with that package name, such as /drupal8.


# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.


# Default server configuration


server {

        listen 80 default_server;

        listen [::]:80 default_server;

        # SSL configuration


        # listen 443 ssl default_server;

        # listen [::]:443 ssl default_server;


        # Note: You should disable gzip for SSL traffic.

        # See:


        # Read up on ssl_ciphers to ensure a secure configuration.

        # See:


        # Self signed certs generated by the ssl-cert package

        # Don't use them in a production server!


        # include snippets/snakeoil.conf;

        root /usr/share/nginx/invoiceninja/public;

        # Add index.php to the list if you are using PHP

        index index.html index.htm index.php index.nginx-debian.html;

        charset utf-8;

        client_max_body_size 20M;

        #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;        

        server_name _;

        location / {

                # First attempt to serve request as file, then

                # as directory, then fall back to displaying a 404.

                try_files $uri $uri/ =404;


        # pass PHP scripts to FastCGI server


        location ~ \.php$ {

               include snippets/fastcgi-php.conf;


               # With php-fpm (or other unix sockets):

               fastcgi_pass unix:/run/php/php7.4-fpm.sock;

               # With php-cgi (or other tcp sockets):

        #       fastcgi_pass;


        # deny access to .htaccess files, if Apache's document root

        # concurs with nginx's one


        location ~ /\.ht {

               deny all;


        location ~* \.pdf$ {

                add_header Cache-Control no-store;


        if (!-e $request_filename) {

                rewrite ^(.+)$ /index.php?q= last;


        location = /favicon.ico {

                access_log off; log_not_found off;


        location = /robots.txt {

                access_log off; log_not_found off;



# save and exit

# If php7.4 is not the used php version anymore, you need to check the FastCGI socket path.

# As of march 2022, Ubuntu still uses php7.4 and you don't need to change anything.

# Check if syntax of your file is ok

sudo nginx -t

# make sure NGINX is running and not apache

sudo systemctl stop apache2

sudo systemctl disable apache2

sudo systemctl enable --now nginx

# delete the nginx default site and reload. Webpage should now be offline

sudo rm /etc/nginx/sites-enabled/default

sudo systemctl reload nginx

# make install dir

sudo mkdir /usr/share/nginx/invoiceninja && cd /usr/share/nginx/invoiceninja

# Find latest version here

# Right click the link to the zip file and copy the download link

# Download the zip

sudo wget

# unzip and remove the zip file

sudo unzip

sudo rm

# if you wanna use snappdf instead of the cloud service phantomPDF, we need some

# dependancies for snappdf

# more info

sudo apt install libgbm-dev libxshmfence-dev ca-certificates fonts-liberation libappindicator3-0.1-cil libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc-s1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 lsb-release wget xdg-utils

# Copy the example .env

sudo cp /usr/share/nginx/invoiceninja/.env.example /usr/share/nginx/invoiceninja/.env

# Now we need to edit your .env file

# you only need to edit one line (or two if you have a revers proxy) everything else we can setup later in the webgui setup

sudo nano /usr/share/nginx/invoiceninja/.env

APP_NAME="Invoice Ninja"




























MAIL_FROM_NAME='Self Hosted User'





# If you have a reverse proxy you can set its ip here



# change this to snappdf

#options - snappdf / phantom / hosted_ninja





COMPOSER_AUTH='{"github-oauth": {"": "${{ secrets.GITHUB_TOKEN }}"}}'


# save and exit

# set permissions to the nginx user

sudo chown -R www-data:www-data /usr/share/nginx/invoiceninja

# edit crontab to run Laravel Scheduler every minute

sudo -u www-data crontab -e

# insert this at the end:

* * * * * cd /usr/share/nginx/invoiceninja/ && php artisan schedule:run >> /dev/null 2>&1

# save and exit

# enable webpage

sudo ln -s /etc/nginx/sites-available/invoiceninja.conf /etc/nginx/sites-enabled/

# test the invoiceninja.conf

# this should give you no error

sudo nginx -t

# reload nginx

sudo systemctl reload nginx

# The next steps are very much dependant if you use InvoiceNinja behind a proxy or not or if you only use invoiceninja local without a cert.

# If you don't use it behind a proxy, you need to install certbot on the InvoiceNinja host.

# If you use it behind a proxy, you configure certbot on the proxy

# If you don't use https, you don't have to do anything

# visit our http://ipofyourhost/setup address to setup InvoiceNinja

# For URL you set the desired URL or the IP address if you use it local only

# HTTPS should be require unless you use a reverse proxy

# Test PDF should show success

# Insert the database credentials

# localhost

# 3306

# ninjadb

# ninja

# The password you set during the DB setup

# Test PDF should show success

# If you wanna send mail, you can set SMTP instead of Log

# Example config for Office 365





# 587


# Password

# Send test email shoud work

# Create a User Account, agree to the terms and click submit

# Now this could take some time. You should be redirected to the URL you defined earlier.

# Don't leave the page and have some patience. If the page is just gray, try to disable pihole or any other adblockers

# Your browser redirect will probably point to https and because we have not setup nginx to listen on https yet the site is unreachable.

# In this case setup certbot first before you try to login.

# install and run certbot to get a cert

# install snapd

sudo apt install snapd

# update snapd

sudo snap install core

sudo snap refresh core

# install certbot

sudo snap install --classic certbot

# create a cert

sudo certbot --nginx

# this will lead you trough the setup process. If something fails, it is probably because you forgot to set the public dns or your firewall blocks port 80 to certbot

# Anyway, there are a lot of good tutorials online how to setup certbot.

# Certbot automatically changes your NGINX .conf file to listen on port 443

# if you run invoiceninja behind a proxy, here is a sample config.

# otherwise you can ignore this

server {


    listen       80;

    listen      [::]:80;

    # This is important or you will get 413 Server error from the proxy side

    client_max_body_size 20M;

    location / {

                    proxy_set_header        Host $host;

                    proxy_set_header        X-Real-IP $remote_addr;

                    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

                    proxy_set_header        X-Forwarded-Proto $scheme;

                    proxy_buffering         off;

                    proxy_request_buffering off;

                    proxy_pass_header       Server;

                    # Enter the IP or Internal DNS name of the server Invoice Ninja is installed on

                    proxy_pass    ;

                    proxy_redirect          off;

                    #add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;



# You are done and hopefully everything is up and running!

# Next step would be setting up supervisor to get rid of the queque warning

# This is untested yet. You should better not use this :)

# optimize performance by using Laravel supervisor. This guide requires root access. If you don't have that, here is more documentation:


# install supervisor

sudo apt-get install supervisor

# configure supervisor

sudo nano /etc/supervisor/conf.d/laravel-worker.conf



command=php /usr/share/nginx/invoiceninja/artisan queue:work sqs --sleep=3 --tries=3 --max-time=3600










# save and exit

# start supervisor

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start laravel-worker:*

# edit .env




Thanks for sharing this!