Firefly III Personal Finance Manager on FreeNAS (FreeBSD jail)

This guide details the steps needed to install Firefly-iii (a popular open-source and self-hosted personal finance manager) in a FreeNAS jail (FreeBSD). As a bonus it also details how to extend the base install with the CSV importer tool which allows you to import CSV based data which you exported from your bank account.

The exact versions used for this guide are:

  • FreeNAS-11.3-U5
  • Firefly-iii v5.4.6
  • Firefly CSV importer v2.2.3

Setting up the LEMP stack

First, we’ll be setting up a LEMP (Linux, Nginx, MariaDB, PHP) stack which will serve the Firefly-iii web application.

PHP setup

Execute the following commands to install the necessary PHP modules (first command contains all modules needed by firefly:

pkg install -y php74 php74-bcmath php74-intl php74-curl php74-zip php74-gd php74-xml php74-xml php74-mbstring php74-ldap php74-mysqli php74-pear-MDB2 php74-pear-MDB2_Driver_mysqli php74-fileinfo php74-pdo php74-pdo_mysql php74-session php74-simplexml php74-xmlwriter php74-tok
enizer php74-iconv php74-dom php74-json php74-phar php74-filter php74-openssl php74-zlib
echo 'php_fpm_enable="YES"' >> /etc/rc.conf
service php-fpm start

NGINX install

Install the NGINX web server.

pkg install -y nginx
echo 'nginx_enable="YES"' >> /etc/rc.conf
service nginx start

This will create the webserver root under ‘/usr/local/www’, which should be owned by www:www. If this is not the case

Database setup

First install the package and add it to the list of startup services so that it automatically runs. Finally start the database.

(Optionally run “service mysql-server start” to improve the security of your database if your using this in a production environment.)

pkg install -y mariadb105-server
echo 'mysql_enable="YES"' >> /etc/rc.conf
service mysql-server start

Now we can create the database and user (replace #password# with your own selected password)

mysql
create database firefly;
grant all on firefly.* to firefly@localhost identified by '#password#';
flush privileges;
quit

Remember this password as you’ll need to enter it into the configuration file of Firefly-iii.

Installing Firefly III

Composer

We need to install some packages before we can jump into the composer based install of Firefly III.

pkg install -y curl sudo

Note: All steps from here on out are also documented in the official documentation. Some paths have been adjusted to match the FreeBSD folder structure.

Now install composer and verify that the installation is successful by calling the command.

curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
composer -v

Change directory to the web root and run the install (replace ‘latest’ with an actual release tag. This guide was created using ‘5.4.6’.).

composer create-project grumpydictator/firefly-iii --no-dev --prefer-dist firefly-iii <latest>

Make sure the permissions are set correctly

sudo chown -R www-data:www-data firefly-iii
sudo chmod -R 775 firefly-iii/storage

And then adjust the ‘.env’ file in the ‘firefly-iii’ directory. Make sure to change the following settings:

  • SITE_OWNER, set to your email address
  • DEFAULT_LANGUAGE, if you want to switch the language used.
  • TZ, to set the correct timezone.
  • DB_HOST, set to ‘127.0.0.1’
  • DB_PASSWORD, set to the password you entered for the ‘firefly’ user while setting up the database before.
  • APP_URL, set to the IP or associated DNS name of the jail.

Now we can initialize the database

sudo -u www php artisan migrate:refresh --seed
sudo -u www php artisan firefly-iii:upgrade-database
sudo -u www php artisan passport:install

Connect NGINX and PHP-FPM

In ‘/usr/local/etc/php-fpm.d/www.conf’. Make sure the following values are set (and are uncommented!)

listen = /var/run/php-fpm.sock;

listen.owner = www
listen.group = www
listen.mode = 0660

In ‘/usr/local/etc/nginx/nginx.conf’ put the following content:

worker_processes  1;

events {
    worker_connections  1024;
}


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

    sendfile        on;

    keepalive_timeout  65;

    gzip  on;

    server {
        listen       80;
        server_name  localhost;
        root /usr/local/www/firefly-iii/public;
        index index.php;

        location / {
            try_files $uri $uri/ /index.php?$query_string;
            index  index.php;
        }

        # pass the PHP scripts to FastCGI server listening on a UNIX file socket

        location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass   unix:/var/run/php-fpm.sock;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
    }
}

Final steps

Run the following commands to make sure all configuration changes have been picked up:

service php-fpm restart
service nginx restart

You should now be able to browse to the website, where you will be prompted to create a user account!

Optional: Setup CSV importer

We’ll be using the same jail and LEMP stack to setup the CSV importer. This assumes you have an internal DNS resolving a local domainname to the jail. We’ll be configuring NGINX so that it serves the two tools on separate subdomains:

  • firefly-iii on ‘firefly-iii.home’
  • csv-importer on ‘csv.firefly-iii.home’

You can of course select a different domain name, but then you need to make sure to adjust the csv-importer .env file NGINX configuration file accordingly (see below).

By separating the tool on another subdomain, we know that the two apps will never conflict.

Start in the ‘/usr/local/www’ folder and use compose to install the CSV importer (again replace <latest> with a release tag. This guide was created using ‘2.2.3’.).

composer create-project firefly-iii/csv-importer --no-dev --prefer-dist csv-importer 2.2.3

Make sure the permissions are set correctly

chown -R www:www csv-importer
chmod -R 775 csv-importer/storage/

And then adjust the ‘.env’ file in the ‘csv-importer’ directory. Make sure to change the following settings:

  • FIREFLY_III_URI, set to ‘firefly-iii.home’
  • Check the docs and determine if you want to hardcode a FIREFLY_III_ACESS_TOKEN or FIREFLY_III_CLIENT_ID.
  • TZ, to set the correct timezone.

In ‘/usr/local/etc/nginx/nginx.conf’ put the following content:

worker_processes  1;

events {
    worker_connections  1024;
}


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

    sendfile        on;

    keepalive_timeout  65;

    gzip  on;

    server {
        # csv-importer on csv.firefly-iii.home subdomain
        listen 80;

        server_name csv.*;
        root /usr/local/www/csv-importer/public;
        index index.php;

        location / {
            try_files $uri $uri/ /index.php?$query_string;
            index  index.php;
        }

        # pass the PHP scripts to FastCGI server listening on a UNIX file socket
        #
        location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass   unix:/var/run/php-fpm.sock;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
    }

    server {
        # All other domains (i.e. the main firefly app at firefly-iii.home)
        listen 80 default_server;

        server_name _;  # Will match all other domains
        root /usr/local/www/firefly-iii/public;
        index index.php;

        location / {
            try_files $uri $uri/ /index.php?$query_string;
            index  index.php;
        }

        # pass the PHP scripts to FastCGI server listening on a UNIX file socket
        #
        location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass   unix:/var/run/php-fpm.sock;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
    }
}

Make sure to adjust the <mylocaldomain.home> to your own domainname.

Go to ‘http://csv.firefly-iii.home’ and you should now be able to access the CSV importer app. After authenticating (if you didn’t set the keys in the configuration file) you should be able to start importing CSV files.

Note: if you get a HTTP 502 Internal server error. Check the latest additions to ‘/var/log/nginx/error.log’ If this states

80 upstream sent too big header while reading response header from upstream, client: xxx.xxx.xxx.xxx server: csv., request: “GET /callback?code=[…]”

Add the following lines to your nginx.conf file to increase the buffer size:

fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;

Leave a Comment