Install Invoice Ninja v5 on Debian 11 Bullseye

Edit: Appereantly Ubuntu is preferred over Debian for InvoiceNinja. Please switch to this repo https://github.com/jameskimmel/InvoiceNinja-V5-on-Ubuntu

Hi everyone

I wrote a basic tutorial for Debian and Ninja v5.
I only tested this behind a reverse proxy and would love to hear some feedback from you.
Also 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 reread my horrible spelling, but not today :wink:

# This is a basic tutorial for a

# default installation of a InvoiceNinja instance on Debian

# You can also find this and report a bug on https://github.com/jameskimmel/InvoiceNinja5onDebian11

# I did a mostly default Debian installation

# no password for root, and invoiceninja as a user. That way invoiceninja is member of the sudo group

# selected ssh server to be installed. This is optional.

# if you set a password for the root user, install sudo and add user invoiceninja to sudoer group. Otherwise you can skip this.

su -

apt install sudo

usermod -a -G sudo invoiceninja

# I import my public ssh keys from github. This step is optional.

sudo apt install ssh-import-id

ssh-import-id-gh HereYourUsername

# You can skip this, if you don't use ssh server. Otherwise I would recommend disabling PasswordAuth for ssh.

# uncomment by removing # and change PasswordAuhtentication from yes to no

sudo nano /etc/ssh/sshd_config

# I like to have security updates automatically installed. This is optional.

sudo apt install unattended-upgrades

sudo systemctl enable --now unattended-upgrades

# install dependencies

# Debian 11 Bullseye currently uses php 7.4

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

sudo apt install php7.4 php7.4-{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 NGINX page. https://yourIP will not work you need to use http instead of https for now!

# delete the default site

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

# 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, Enter, Enter, insert a password for the root account, enter it again, Enter, Enter, Enter, Enter. You should see "Thanks for using MariaDB"

# login to the database

mysql -u root -p

# enter the password you just set

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

# create database ninjadb

CREATE SCHEMA `ninjadb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

# 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

FLUSH PRIVILEGES;

# You should see Query OK, 0 rows affected

# exit the db

exit

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

# https://www.nginx.com/resources/wiki/start/

# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/

# https://wiki.debian.org/Nginx/DirectoryStructure

#

# 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: https://bugs.debian.org/773332

        #

        # Read up on ssl_ciphers to ensure a secure configuration.

        # See: https://bugs.debian.org/765782

        #

        # 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 127.0.0.1:9000;

        }

        # 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, InvoiceNinja still uses php7.4 and you don't need to change anything.

# make sure NGINX is running and not apache

sudo systemctl stop apache2

sudo systemctl disable apache2

sudo systemctl enable --now nginx

# time for a break :) take a snapshot if possible

# make install dir

cd /usr/share/nginx

sudo mkdir invoiceninja && cd invoiceninja

# Find latest version here https://github.com/invoiceninja/invoiceninja/releases

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

# Download the zip

sudo wget https://github.com/invoiceninja/invoiceninja/releases/download/v5.3.68/invoiceninja.zip

# unzip and remove the zip file

sudo unzip invoiceninja.zip

sudo rm invoiceninja.zip

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

# dependancies for snappdf

# more info https://github.com/beganovich/snappdf#headless-chrome-doesnt-launch-on-unix

sudo apt install 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"

APP_ENV=production

APP_KEY=base64:RCPMPb5yWnrE2+rb+R4xd5XQ0qQJ5vwy1lNSvsmB6g=

APP_DEBUG="false"

APP_URL=http://localhost

DB_CONNECTION="mysql"

MULTI_DB_ENABLED=false

DB_HOST="localhost"

DB_DATABASE="ninja"

DB_USERNAME="ninja"

DB_PASSWORD="ninja"

DB_PORT="3306"

DEMO_MODE=false

BROADCAST_DRIVER=log

LOG_CHANNEL=stack

CACHE_DRIVER=file

QUEUE_CONNECTION=sync

SESSION_DRIVER=file

SESSION_LIFETIME=120

REDIS_HOST=127.0.0.1

REDIS_PASSWORD=null

REDIS_PORT=6379

MAIL_MAILER=smtp

MAIL_HOST=smtp.mailtrap.io

MAIL_PORT=2525

MAIL_USERNAME=null

MAIL_PASSWORD=null

MAIL_ENCRYPTION=null

MAIL_FROM_ADDRESS='user@example.com'

MAIL_FROM_NAME='Self Hosted User'

POSTMARK_API_TOKEN=

REQUIRE_HTTPS="false"

GOOGLE_MAPS_API_KEY=

ERROR_EMAIL=

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

TRUSTED_PROXIES=10.0.1.1

NINJA_ENVIRONMENT="selfhost"

# change this to snappdf

#options - snappdf / phantom / hosted_ninja

PDF_GENERATOR=snappdf

PHANTOMJS_KEY='a-demo-key-with-low-quota-per-ip-address'

PHANTOMJS_SECRET=secret

UPDATE_SECRET=secret

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

SENTRY_LARAVEL_DSN=https://39389664f3f14969b4c43dadda00a40b@sentry2.invoicing.co/5

# save and exit

# I take another break and make the second snapshot

# 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

# I shutdown the VM before the webconfig and take a third snapshot

sudo shutdown

# The next steps are very much dependant if you use InvoiceNinja behind a proxy or not or if you only use invoiceninja local and tous do not need 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

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

# mail@domain.com

# mail@domain.com

# mail@domain.com

# smtp.office365.com

# 587

# STARTTLS

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

    server_name ninja.domain.com;

    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;

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

                    proxy_pass              http://10.0.1.2/;

                    proxy_redirect          off;

                    }

}

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

# https://invoiceninja.github.io/docs/self-host-installation/#final-setup-steps

# install supervisor

sudo apt-get install supervisor

# configure supervisor

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

[program:laravel-worker]

process_name=%(program_name)s_%(process_num)02d

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

autostart=true

autorestart=true

stopasgroup=true

killasgroup=true

user=forge

numprocs=8

redirect_stderr=true

stdout_logfile=/var/log/supervisor.log

stopwaitsecs=3600

# save and exit

# start supervisor

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start laravel-worker:*

# edit .env

QUEUE_CONNECTION=database

INTERNAL_QUEUE_ENABLED=falseThis text will be hidden
1 Like

Hi,

Thanks for sharing this!

Hi hillel, thank you for writing the code!

I would love to hear some feedback. This stuff is pretty new to me so I guess there is room for improvement :grinning: