Self-hosted personal finance manager

Table of Contents

Overview

This post is about self-hosting the personal finance manager app firefly-iii. The prerequisites are:

Install firefly

Some of the following steps are an excerpt from the documentation available at docs.firefly-iii.org:

Set up env variables

Firefly is configurable via a .env file. Download the basic configuration from the official github repository and store it as firefly.env in your server’s workspace folder (where you want to have all files for docker and firefly).

Create a docker-compose.yml file

We will use docker-compose to manage all the services required by firefly. The tutorial from the firefly docs provides and example docker-compose.yml. Here is my modified version:

version: "3.3"
services:
  firefly-app:
    image: fireflyiii/core:latest
    restart: always
    volumes:
      - firefly_iii_upload:/var/www/html/storage/upload
    env_file: firefly.env
    ports:
      - 8080:8080
    depends_on:
      - fireflydb
  firefly-db:
    image: mariadb
    hostname: fireflyiiidb
    restart: always
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=yes
      - MYSQL_USER=firefly
      - MYSQL_PASSWORD=INSERT_YOUR_SECURE_PASSWORD_HERE
      - MYSQL_DATABASE=firefly
    volumes:
      - firefly_iii_db:/var/lib/mysql
volumes:
  firefly_iii_upload:
  firefly_iii_db:

The values you need to adapt are:

  • the port and
  • the password for the database.

Start up everything with

docker-compose up -d firefly-app firefly-db

Check the status of the containers with

docker ps

which should show a similar output to

CONTAINER ID   IMAGE                    COMMAND                  CREATED        STATUS                 PORTS                                       NAMES
582fa3bee42f   fireflyiii/core:latest   "/usr/local/bin/entr…"   4 hours ago    Up 4 hours (healthy)   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   services_firefly-app_1
443e260b8aec   mariadb                  "docker-entrypoint.s…"   18 hours ago   Up 17 hours            3306/tcp                                    services_firefly-db_1

You should be able to access the firefly web interface by visiting http://YOUR_SERVER_IP_ADDRESS:8080/.

Configure nginx

The goal of this section is to set up nginx with an SSL certificate as a reverse-proxy to host the firefly app.

First, make sure to create a new A Record for the subdomain you want to host the app on. It should have the form of sub.yourdomain.com and point to your server’s IP address.

Create a new server configuration to set up nginx as a reverse-proxy for firefly:

touch /etc/nginx/sites-available/firefly.conf

and populate the file with the following content:

Listing 1: nginx server block configuration.

server {
    server_name sub.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8080/;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        client_max_body_size 64M;
        proxy_read_timeout 300s;
    }
}

Enable the site by creating a symlink in the sites-enabled folder:

ln -s /etc/nginx/sites-available/firefly.conf /etc/nginx/sites-enabled/

Create an SSL certificate

Execute

certbot --nginx

and follow the instructions to create a certificate for your server. This step touches the configuration file in Listing 1 and

  1. extends the old server block with certificate settings,
  2. and adds a new server block.
server {
    server_name sub.yourdomain.com;

    location / {
        # ...
    }

    # SSL configuration
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    if ($host = sub.yourdomain.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    server_name sub.yourdomain.com;
    listen 80;
    return 404; # managed by Certbot
}

Restart nginx with new configuration

Check the nginx configuration by running

nginx -t

and, if everything is fine, restart it with

systemctl restart nginx

Firefly should now be available through a secure connection via your subdomain.

Peter W. Egger
Peter W. Egger
Software Engineer / Data Scientist

Maker culture enthusiast and aspiring data scientist.