Hi everyone
After almost a year and a troubled Debian installation, I gave Invoice Ninja v5 on Ubuntu another try
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
# 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 https://github.com/jameskimmel/InvoiceNinja-V5-on-Ubuntu
# 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
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, 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 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.73/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 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"
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
# 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
# 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;
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 http://10.0.1.2/;
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:
# 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=false