Invoice Ninja iocage Install

Not open for further replies.


Feb 4, 2018
Invoice ninja is a open source self hosted invoice managing system. I thought it would be nice to have on FreeNAS so I decided to install it, I did not follow any documentation related to FreeBSD as there is very little information on it. Hence this guide may not be complete and its NOT production ready. I just read error files to find the packages that it needs. Hopefully with more people using it we can sort out any bugs that arise.

Compared to any other invoice offerings like planeinvoice or odoo this looks waaay better and has all the features that the others have. Thats why I decided to use this. It's perfect for a small business/ personal services / freelancers. It has features like client portals which provides a different UI to clients with a lot of features. It also supports the most online payment gateways by far. (from what I could find) Ok sorry just had to justify my reasons for using it.......

I just updated the wiki on their git with FreeNAS instructions with same / similar instructions, feel free to make changes you feel suitable and ill update them here.

All the commands can just be run in succession without understanding and they should work. I personally have script with these same commands to install it and it works.
I would recommend a ssh client like Royal TSI which you can paste multiple commands at once and has a really nice UI to manage all your ssh servers.

Host Invoice Ninja on FreeNAS with a self signed cert:

First lets create the iocage jail, you can do this through the new UI but its waaay faster to use CLI. ssh into freenas and lets get going.

Create the iocage jail (Replace the ip with what works for you):

iocage create -n InvoiceNinja -r 11.1-RELEASE ip4_addr="vnet0|" defaultrouter="" vnet="on" allow_raw_sockets="1" boot="on"

Lets log into the jail:

iocage console InvoiceNinja

Install all the dependencies:

pkg install -y nginx nano git curl openssl mariadb102-server php71 php71-ctype php71-pdo php71-pdo_mysql php71-session php71-iconv php71-filter php71-openssl php71-phar php71-mysqli aws-sdk-php php71-simplexml php71-xmlreader php71-xmlwriter php71-fileinfo php71-pear-PHP_Parser php71-tokenizer php71-mcrypt php71-gd php71-curl php71-gmp php71-json php71-zip php71-xml php71-readline php71-opcache php71-mbstring

AutoStart php, mysql and nginx:

sysrc mysql_enable=YES
sysrc nginx_enable=YES
sysrc php_fpm_enable=YES
service mysql-server start

Modify php files to host the web server using user www:

sed -i '' -e 's?listen = = /var/run/php-fpm.sock?g' /usr/local/etc/php-fpm.d/www.conf

sed -i '' -e 's/;listen.owner = www/listen.owner = www/g' /usr/local/etc/php-fpm.d/www.conf

sed -i '' -e 's/; = www/ = www/g' /usr/local/etc/php-fpm.d/www.conf

sed -i '' -e 's/;listen.mode = 0660/listen.mode = 0600/g' /usr/local/etc/php-fpm.d/www.conf

cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini

sed -i '' -e 's?;cgi.fix_pathinfo=1?cgi.fix_pathinfo=0?g' /usr/local/etc/php.ini

Create the MySQL database for invoice ninja:

mysql -u root -e "CREATE DATABASE ninja;"
grant all on ninja.* to ninja@localhost identified by 'ninja';
mysql -u root -e "FLUSH PRIVILEGES;"

Secure the database:
Answer most of the questions with yes. Read them.


Install Invoice Ninja (Installed to /usr/local/ninja):

curl -sS | php
mv composer.phar /usr/local/bin/composer
mkdir /usr/local/ninja
git clone /usr/local/ninja
cd /usr/local/ninja && composer install --no-dev -o

Generate a self signed cert named "ininja":

mkdir -p /etc/nginx/ssl

openssl genrsa -des3 -passout pass:x -out /etc/nginx/ssl/ininja.pass.key 2048

openssl rsa -passin pass:x -in /etc/nginx/ssl/ininja.pass.key -out /etc/nginx/ssl/ininja.key

rm /etc/nginx/ssl/ininja.pass.key

openssl req -new -key /etc/nginx/ssl/ininja.key -out /etc/nginx/ssl/ininja.csr

openssl x509 -req -days 365 -in /etc/nginx/ssl/ininja.csr -signkey /etc/nginx/ssl/ininja.key -out /etc/nginx/ssl/ininja.crt

Set correct permissions for invoice ninja:

touch /usr/local/ninja/.env
chown www:www /usr/local/ninja/.env
chmod -R 755 /usr/local/ninja/storage
cd /usr/local/ninja && chown -R www:www storage bootstrap public/logo

Now lets create the nginx config. Replace the server_name with your IP or domain name:

rm /usr/local/etc/nginx/nginx.conf
nano /usr/local/etc/nginx/nginx.conf

Copy the contents below and replace ip the wiki formatted it weird, copy everything after nginx.conf till the next heading:

events { worker_connections 1024; }

http { include mime.types; default_type application/octet-stream;

#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
#				  '$status $body_bytes_sent "$http_referer" '
#				  '"$http_user_agent" "$http_x_forwarded_for"';

#access_log  logs/access.log  main;

sendfile		on;
#tcp_nopush	 on;

#keepalive_timeout  0;
keepalive_timeout  65;

#gzip  on;

server {
   listen	  443 default;
   ssl on;
   ssl_certificate	 /etc/nginx/ssl/ininja.crt;
   ssl_certificate_key /etc/nginx/ssl/ininja.key;
   ssl_session_timeout 5m;
   ssl_ciphers			   'AES128+EECDH:AES128+EDH:!aNULL';
   ssl_protocols			  TLSv1 TLSv1.1 TLSv1.2;
   ssl_prefer_server_ciphers on;
   root /usr/local/ninja/public;
   index index.html index.htm index.php;
   charset utf-8;
   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; }
   access_log  /var/log/nginx/ininja.access.log;
   error_log   /var/log/nginx/ininja.error.log;
   sendfile off;
   location ~ \.php$ {
	   fastcgi_split_path_info ^(.+\.php)(/.+)$;
	   fastcgi_pass unix:/var/run/php-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;
   location ~ /\.ht {
	   deny all;
server {
   listen	  80;
   add_header Strict-Transport-Security max-age=2592000;
   rewrite ^ https://$server_name$request_uri? permanent;


Ok lets restart all the services you should be able to access the GUI setup on https://yourip
HTTPS ONLY for now !!!

service mysql-server restart
service php-fpm start
service nginx start
Last edited:


Hall of Famer
Aug 16, 2011
Seems pretty slick. For some reason, the first sed command didn't work for me, but I was able to fix that easily enough once I realized what was going on. A couple of suggestions:
  • Use code tags for anything that's more than one line--they handle line breaks and formatting better than cmd tags. This is especially the case for the nginx.conf file.
  • You can skip the CREATE USER command by instead doing grant all on ninja.* to ninja@localhost identified by 'ninja'; (the caps for SQL commands are optional)
  • There's probably no reason to start nginx or php-fpm after installing all the packages
  • An obvious improvement would be to cover getting a cert from Let's Encrypt rather than using a self-signed one
The privacy policy is a little concerning, though--for a self-hosted, open-source package, it seems like it phones home with an awful lot of data that just isn't necessary. I get that they'd want to keep track of how many folks are using their software, in what kinds (and what size) of businesses, but company names? Tax ID numbers? Addresses? There just doesn't seem to be any reason they need that information.


Feb 4, 2018
Thanks for the feedback ! Ill update my post when I get the chance.
Do you know why the sed command did not work for you ? I tried it again and it works. I copied it from dureal9's nextcloud script which has been used by many people.
Yea there no reason to start nginx and php at that point ill fix that.
A letsencrypt cert would be ideal but I did not want this thread to be about problems obtaining a vaild cert, but ill update it with instructions later.
Also the nginx config does not redirect to https even though it should. My syntax is clearly wrong, http gets you the welcome to nginx site and https gives you invoice ninja, any tips on how to fix this ?
Regarding their privacy policy its says company name, tax id etc are optional.
Last edited:
Not open for further replies.