Firefly III Personal Finance Manager in a jail

Install Firefly III Personal Finance Manager in a jail

User zamana on the “Official” FreeNAS forum posted some notes on installing Firefly III in a FreeNAS jail. Firefly III is a web-based personal finance manager that’s intended to be self-hosted. None of your data leaves your installation unless you explicitly request it. It’s a full-featured, open-source web application. The official installation instructions are written with Linux in mind, but can be adapted readily enough for FreeBSD.

Installation

Create a jail for Firefly III using the FreeNAS GUI. Call it whatever you like (though for the remainder of this guide, I’ll assume you called it firefly), assign it an IP address, enable vnet and auto-start, and start it up. Configure your router to associate the name of your jail with its IP address–with my pfSense router, that’s done using the DNS resolver service. Then enter the jail by running iocage console firefly.

Begin by installing a bunch of software packages using the following command:

pkg install -y curl mariadb103-server php73 php73-bcmath php73-curl php73-dom php73-fileinfo php73-filter php73-gd php73-hash php73-iconv php73-intl php73-json php73-ldap php73-mbstring php73-mysqli php73-openssl php73-pdo php73-pdo_mysql php73-pear php73-pear-MDB2 php73-pear-MDB2_Driver_mysql php73-pear-MDB2_Driver_mysqli php73-phar php73-session php73-simplexml php73-tokenizer php73-xml php73-zip php73-zlib sudo nano bash caddy

Install Composer using the following command:

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

Prepare your web root directory:

mkdir -p /usr/local/www
chown -R www:www /usr/local/www
cd /usr/local/www

Use Composer to install Firefly III. In the command below, replace <latest> with the latest release version on the release list. As of this writing, the latest release is 4.8.1.4.

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

Set the following system configuration options:

sysrc mysql_enable=YES
sysrc php_fpm_enable=YES
sysrc caddy_enable=YES
sysrc caddy_cert_email="somebody@yourdomain.org"

The caddy_cert_email value is mandatory, even if you won’t be using Caddy to manage your TLS certificate. However, it’s only used if you’re using Caddy to get certificates from Let’s Encrypt.

Configuration

Then start and secure your database:

service mysql-server start
mysql_secure_installation

Choose and make a note of a secure root password, and accept the defaults for the remaining questions. Then save that password to your profile so you don’t need to enter it to use mysql: nano /root/.my.cnf. Its contents should look like this:

# MySQL client config file
[client]
password=mypassword

You’ll now need to create the database, user and password. Run mysql and then enter the commands below, replacing secure_firefly_password with an actual secure password:

MariaDB [(none)]> create database firefly;
MariaDB [(none)]> grant all on firefly.* to firefly@localhost identified by 'secure_firefly_password';
MariaDB [(none)]> flush privileges;
MariaDB [(none)]> quit

You’ll need to make edits to the Firefly III config file. Run cd /usr/local/www/firefly-iii/ followed by nano .env. You’ll need to make a few changes to this file:

  • SITE_OWNER should be set to your email address
  • TZ should be set to your time zone–see http://php.net/manual/en/timezones.php
  • APP_URL should be set to the URL of your installation
  • The DB_* settings should look like these:
DB_CONNECTION=mysql
DB_HOST=firefly       
DB_DATABASE=firefly
DB_USERNAME=firefly
DB_PASSWORD=secure_firefly_password

Then run these commands:

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

The Caddyfile

The Caddyfile is the configuration file for the Caddy web server. Its contents will depend mostly on whether you want to use HTTPS for your Firefly III installation, and if so, how you want to obtain the certificate.

No TLS

This is the simplest installation type. Your Firefly III installation won’t have HTTPS support, though if you’re only running it on your LAN this may not be a critical problem.

Create the Caddyfile with nano /usr/local/www/Caddyfile. Its contents should look like this:

firefly.local:80 {

	root /usr/local/www/firefly-iii/public
	log /var/log/firefly_access.log
	errors /var/log/firefly_errors.log

	gzip
	fastcgi / 127.0.0.1:9000 php

	rewrite {
		to {path} {path}/ /index.php?{1}
	}

}

TLS Certificate with TLS-ALPN validation

If you have a real domain name and you’re comfortable opening your installation to the Internet (which I wouldn’t really recommend), this is the second-simplest installation type.

You’ll first need to configure your router to pass ports 80 and 443 through to your Firefly III installation. These ports must be open to the entire Internet for Let’s Encrypt to validate your control over the domain name. Also, you need to have public DNS records for whatever domain name you use in the Caddyfile, pointing to your public IP address. You’re on your own to accomplish these; there are too many variations among routers and DNS hosts for me to give you accurate guidance.

Create the Caddyfile with nano /usr/local/www/Caddyfile. Its contents should look like this:

firefly.yourdomain.org {

	root /usr/local/www/firefly-iii/public
	log /var/log/firefly_access.log
	errors /var/log/firefly_errors.log

	tls {
		ca https://acme-staging-v02.api.letsencrypt.org/directory
	}

	gzip
	fastcgi / 127.0.0.1:9000 php

	rewrite {
		to {path} {path}/ /index.php?{1}
	}

}

(If you’re comparing notes, you’ll see that this Caddyfile is almost identical to the one above; the only differences are that it doesn’t specify the port number on the first line, the first line does have a FQDN, and the tls stanza in the Caddyfile).

This configuration will give you certificate errors, because it’s using the Let’s Encrypt staging Certificate Authority to issue certificates. This is done to avoid exceeding the rate limits during testing. Once you’re sure everything is working properly, you can obtain a trusted cert by removing the tls stanza from the Caddyfile, and then running service caddy restart.

TLS Certificate with DNS Validation

This is my preferred method–it allows you to obtain a trusted certificate without exposing your jail to the Internet. For this one to work, you’re going to need a real domain name (as above), and your DNS will need to be hosted with a provider that Caddy supports–you can find the list at https://caddyserver.com/docs in the left-hand column (scroll down to find the heading of DNS Providers).

We’ll need to start by downloading a new version of Caddy. Run pkg lock -y caddy to keep pkg from overwriting files, then go to https://caddyserver.com/download. Under Plugins, select the appropriate DNS provider’s plugin, and under Plan, select Personal. Then look at the bottom of the page for the “One-step installer script (bash)”. It will look like this:


Run that command in your jail.

You’ll next need to set the configuration options Caddy will need to update your DNS records appropriately. You can find details on the required credentials in the docs. For Cloudflare, you’d run sysrc caddy_env="CLOUDFLARE_EMAIL=nobody@example.com CLOUDFLARE_API_KEY=cjvioeaw489-j3849iofnrbv7850wq034nm". The API Key needs to be the Global API Key from Cloudflare; again, other providers will use different credentials.

Next, you’ll need to create the Caddyfile. Run nano /usr/local/www/Caddyfile. Its contents should look like this:

firefly.yourdomain.org {

	root /usr/local/www/firefly-iii/public
	log /var/log/firefly_access.log
	errors /var/log/firefly_errors.log

	tls {
		dns cloudflare
		ca https://acme-staging-v02.api.letsencrypt.org/directory
	}

	gzip
	fastcgi / 127.0.0.1:9000 php

	rewrite {
		to {path} {path}/ /index.php?{1}
	}

}

This configuration will give you certificate errors, because it’s using the Let’s Encrypt staging Certificate Authority to issue certificates. This is done to avoid exceeding the rate limits during testing. Once you’re sure everything is working properly, you can obtain a trusted cert by removing the line that reads ca https://acme-staging-v02.api.letsencrypt.org/directory from the Caddyfile, and then running service caddy restart.

Self-signed TLS certificate

If you want to use HTTPs for your Firefly III installation, but don’t have (and aren’t willing or able to get) a domain, this is your only other option. The Caddyfile described below will also work if you want to use a trusted certificate from a different CA.

First we’ll need to create directories for the certificate and the private key to live in:

mkdir -p /usr/local/etc/pki/tls/private
mkdir -p /usr/local/etc/pki/tls/certs

Then create the cert itself. In the openssl command below, replace ${HOST_NAME} with the hostname you’ll use to reach this installation over your LAN. If you have a cert from a commercial CA, put its private key in /usr/local/etc/pki/tls/private/privkey.pem, and its “full chain” (your own certificate and any intermediate certs, combined into one file) in /usr/local/etc/pki/tls/certs/fullchain.pem, and don’t run the command below.

openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=${HOST_NAME}" -keyout /usr/local/etc/pki/tls/private/privkey.pem -out /usr/local/etc/pki/tls/certs/fullchain.pem

Then create the Caddyfile. Run nano /usr/local/www/Caddyfile. Its contents should look like this:

firefly.local {

	root /usr/local/www/firefly-iii/public
	log /var/log/firefly_access.log
	errors /var/log/firefly_errors.log

	tls tls /usr/local/etc/pki/tls/certs/fullchain.pem /usr/local/etc/pki/tls/private/privkey.pem

	gzip
	fastcgi / 127.0.0.1:9000 php

	rewrite {
		to {path} {path}/ /index.php?{1}
	}

}

Test it out

All the installation and configuration are complete. Start PHP and Caddy by running service php-fpm start followed by service caddy start. Browse to your jail and you should be ready to go.

2 Likes

Hi dan35,

First of all thank you for this guide. I’ve been following it, or at least trying to follow it as best as I can. However, I’m running into a lot of problems considering the php packages have been updated from 7.3 to 8.1. Is there any chance you could update this guide so that it would work with 8.1? Thank you in advance!

1 Like