Install Invoice Ninja on Debian Jessie (8) with Nginx

Invoice Ninja is a free, open-source solution for invoicing and billing customers and it’s based on Laravel 4.1 framework. It can be installed on a LAMP/LEMP system. We are going to follow this installation guide for Debian 7 and apply it to a Debian 8 VM.

We assume to have a base VM with Debian 8 along with the VirtualBox Guest Additions already available, which we'll clone from the VirtualBox GUI as our starting point.

Once your clone is complete, launch it from the VirtualBox GUI and log into it from a terminal (our VM can be accessed from local ip 172.20.20.10), and upgrade the system so everything is up to date:

> ssh root@172.20.20.10
> apt-get update
> apt-get upgrade


During deployment of the Ninja Invoice system, we'll need a few extra packages, let's get them installed:

> apt-get install python-software-properties git curl openssl nano


MariaDB is an open source fork, by the original main developer of MySQL Monty Widenius, of the MySQL code that is now a property of Oracle. So we'll use MariaDB instead of MySQL.

> apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xcbcb082a1bb943db
> nano /etc/apt/sources.list.d/mariadb-10.1.list

PASTE:
deb http://mirror.jmu.edu/pub/mariadb/repo/10.1/debian jessie main

> apt-get update
> apt-get install mariadb-server
> mysql_secure_installation

Our MariaDB server is now ready to be used.


Create Database and User for Invoice Ninja

We need to create a database for our Invoice Ninja instance, as well as a specific user with privileges to manage it.

> mysql -uroot -p
> MariaDB [(none)]> CREATE DATABASE ininja;
> MariaDB [(none)]> GRANT ALL PRIVILEGES ON ininja.* TO '<ininja-user>'@'localhost' IDENTIFIED BY '<ininja-user_passwd>';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> \q

Don't forget to substitute <ininja-user> and <ininja-user_passwd> with the values that fit your needs.



All required packages are available straight from the Debian Jessie repositories:

> apt-get install nginx php5-fpm php5-cli php5-mcrypt php5-gd php5-curl php5-mysql
> php5enmod mcrypt

Install Composer

Composer is a dependency manager for PHP with which you can install packages. Composer will pull in all the required libraries and dependencies that you need for your project.

> curl -sS https://getcomposer.org/installer | php
> mv composer.phar /usr/local/bin/composer


The install location of your Invoice Ninja instance can be freely chosen. Although, as the default Nginx web page is located in /var/www/html, we'll install it in /var/www/ininja/.
To keep things clear, we'll also create a specific user that we'll call ininja, we're gonna use it for the install procedure:

> adduser ininja
> mkdir /var/www/ininja
> chown -R ininja:ininja /var/www/ininja
[ SWITCH TO ininja USER ]
> su ininja
> git clone https://github.com/hillelcoren/invoice-ninja.git /var/www/ininja
> cd /var/www/ininja
> composer install [--no-dev -o]

The composer install process will install all of the project's dependencies, but it will pause halfway because the public download limit of Github will be reached, you'll need to have a Github account to obtain a token using the link that will be displayed in the terminal.

The --no-dev option might be used to specify not to install the dev packages of the project, those that are referenced in the require-dev section of the composer.json file.

The -o option means “dumping the autoloader” and has yet to be clarified here.

Composer will create a new vendor directory where all its files will be stored.



Make sure that the environment is set to production

> cat bootstrap/environment.php
<?php return 'production';

Configure and init database

> nano config/database.php

...
'mysql' => array(
            'driver'    => 'mysql',
            'host'      => 'localhost',
            'database'  => '<ininja>',
            'username'  => '<ininjauser>',
            'password'  => '<ininjauser_passwd>',
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
        ),
...

Be sure to substitute <ininja>, <ininjauser> and <ininjauser_passwd> with the values you entered when creating the database.

> php artisan migrate
> php artisan db:seed

Generate a new application key

> php artisan key:generate
Application key [htxxxxxxxxxxxxxxxxxxxxxxxxxxxxGY] set successfully.
> nano -c config/app.php

SET LINE 83:
     'key' => env('APP_KEY', 'htqGwktj0oDzolDW2c45qyNx0mD5NvGY'),


Create a New PHP-FPM Pool for Our User

(the following commands are to be executed as root, or using sudo)

> nano /etc/php5/fpm/pool.d/<ininja>.conf

PASTE:
[<ininja>]
user = <ininja>
group = <ininja>
listen = /var/run/php5-fpm-ininja.sock
listen.owner = <ininja>
listen.group = <ininja>
listen.mode = 0666  
pm = ondemand
pm.max_children = 5
pm.process_idle_timeout = 10s;
pm.max_requests = 200
chdir = /

> service php5-fpm restart

Once again do not forget to substitute <ininja> with the user name you created earlier.


Generate a Self Signed SSL Certificate

> mkdir -p /etc/nginx/ssl
> cd /etc/nginx/ssl
> openssl genrsa -des3 -passout pass:x -out ininja.pass.key 2048
> openssl rsa -passin pass:x -in ininja.pass.key -out ininja.key
> rm ininja.pass.key
> openssl req -new -key ininja.key -out ininja.csr
> openssl x509 -req -days 365 -in ininja.csr -signkey ininja.key -out ininja.crt

Create a New Nginx Server Block

> nano /etc/nginx/sites-available/ininja

PASTE:
server {
    listen      443 default;
    server_name ininja;

    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 /var/www/ininja/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/php5-fpm-ininja.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;
    server_name 172.20.20.10;

    add_header Strict-Transport-Security max-age=2592000;
    rewrite ^ https://$server_name$request_uri? permanent;
}

You'll need to adapt the “ininja” values to your configuration… Also we've used the IP as server name as we're using a VM, you'd need to put the FQDN of your server in case your are deploying on a production machine.

Activate the server block

This is done by creating a symbolic link from /etc/nginx/sites-available/ to /etc/nginx/sites-enabled/, then restarting nginx:

> ln -s /etc/nginx/sites-available/<ininja> /etc/nginx/sites-enabled/<ininja>
> service nginx restart


Directing a web browser to your VM's IP should now display the Invoice Ninja Setup page, enjoy !


Backup the Database

For development purposes it might sometimes be usefull to make a backup of the database at a certain state. To do that, use the mysqldump command:

backup:

> mysqldump -uininja -p ininja > /path/to/ininja-state.sql
Enter password:

restore:

> mysql -uininja -p ininja < /path/to/ininja-state.sql
Enter password: