David Schlachter

How to Install Firefly III on FreeBSD

The documentation for installing personal finance manager Firefly III focuses on Linux. There are a few differences for getting it working on FreeBSD. I'm currently running FreeBSD 15.0-RELEASE.

First, install the needed packages. You'll need all the following PHP stuff:

pkg install php85-bcmath php85-curl php85-dom php85-fileinfo php85-filter php85-gd php85-intl php85-mbstring php85-pdo_sqlite php85-session php85-simplexml php85-sodium php85-sqlite3 php85-tokenizer php85-xml php85-xmlreader php85-xmlwriter php85-zip

Note that this is a lot more than what the official documentation recommends — it seems that common PHP installations on Linux include modules that you have to explicitly install on FreeBSD. I'm using SQLite as my database, so you may need to replace php85-pdo_sqlite and php85-sqlite3 with appropriate packages for your database if you're using something else.

Next, download the latest release of firefly-iii from Github. Expand it into wherever you'll be hosting it from. For me, that's /usr/local/www.

Follow standard installation steps, such as populating the .env file with required values. Notably, you'll need to fill out the database configuration. These days, I'm using DB_CONNECTION=sqlite because it's fast enough and then I don't need to run a full database. Just be sure to touch storage/database.sqlite if you haven't already. You'll also have to follow the database initialization steps.

For the web server configuration, I'm using nginx with FastCGI. If you've installed all the PHP dependencies above, you'll just need to install nginx with pkg install nginx.

Here are my basic config files:

# /usr/local/etc/nginx/nginx.conf
user  www;
worker_processes  1;
events {
  worker_connections  1024;
}
http {
  include	   mime.types;
  default_type  application/octet-stream;
  sendfile		on;
  keepalive_timeout  65;
  server {
    # If this is going behind a reverse proxy that
    # handles TLS, you could change this to listen
    # on port 80 instead. This would then simply
    # become:
    # listen 80;
    listen	   443 ssl;
    server_name  localhost;

    # Fill in your TLS configuration as needed.

    root /usr/local/www/public;
    index index.html index.php;
    location / {
      try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
      try_files $uri =404;
      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;
    }
  }
}

As I mention in the comment, you'll need to adapt this to support your TLS configuration.

The most important part of the php-fpm configuration is that the location of the socket and its ownership needs to match the corresponding parts of the nginx configuration.

# usr/local/etc/php-fpm.d/www.conf 
[www]
user = www
group = www
listen = /var/run/php-fpm.sock
listen.owner = www
listen.group = www
listen.mode = 0660
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

In order to run large reports, I also had to increase memory_limit in /usr/local/etc/php.ini to at least 256M.

With all that set up, you should be able to

service enable nginx
service enable php_fpm
service start php_fpm
service start nginx

and access the application however you configured in your nginx.conf.

Bastille

I'm currently running firefly-iii in a jail that's configured with Bastille. If you want to use a similar configuration, here's my Bastillefile.

PKG php85-bcmath php85-curl php85-dom php85-fileinfo php85-filter php85-gd php85-intl php85-mbstring php85-pdo_sqlite php85-session php85-simplexml php85-sodium php85-sqlite3 php85-tokenizer php85-xml php85-xmlreader php85-xmlwriter php85-zip

# Download the latest firefly-iii version.
PKG jq curl
CMD curl -o /tmp/release-info 'https://api.github.com/repos/firefly-iii/firefly-iii/releases/latest'
CMD curl -L -o firefly-iii.tar.gz "$(jq -r '.assets[] | select (.browser_download_url | endswith(".tar.gz") ) | .browser_download_url' /tmp/release-info)"
CMD mkdir -p /usr/local/www
CMD tar -xf firefly-iii.tar.gz -C /usr/local/www

# Copy in the .env file, and the nginx/php configs
CP usr /

# Note that this mountpoint includes the sqlite database
FSTAB /jails-persisted/firefly/storage /usr/local/www/storage nullfs rw 0 0

# Run post-upgrade database tasks
CMD cd /usr/local/www && php artisan migrate --seed
CMD cd /usr/local/www && php artisan cache:clear
CMD cd /usr/local/www && php artisan view:clear
CMD cd /usr/local/www && php artisan firefly-iii:upgrade-database
CMD cd /usr/local/www && php artisan firefly-iii:laravel-passport-keys
CMD chown -R www:www /usr/local/www/storage

# Set up the web server
PKG nginx
SYSRC nginx_enable=YES
SYSRC php_fpm_enable=YES
SERVICE php_fpm start
SERVICE nginx start

The Bastille configuration assumes that you have the nginx and php-fpm configurations in the same folder as the Bastille template, as well as the .env file, like this:

$ tree -a
.
├── Bastillefile
└── usr
    └── local
        ├── etc
        │   ├── nginx
        │   │   └── nginx.conf
        │   └── php-fpm.d
        │       └── www.conf
        └── www
            └── .env

It also assumes that you have a local directory for persisting firefly-iii's data in /jails-persisted/firefly/storage.