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.
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
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.
> cat bootstrap/environment.php <?php return 'production';
> 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
> php artisan key:generate Application key [htxxxxxxxxxxxxxxxxxxxxxxxxxxxxGY] set successfully. > nano -c config/app.php SET LINE 83: 'key' => env('APP_KEY', 'htqGwktj0oDzolDW2c45qyNx0mD5NvGY'),
(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.
> 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
> 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.
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 !
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: