Firefly III Personal Finance: Track Your Budget and Accounts via Docker

Complete guide to self-hosting Firefly III personal finance manager on a VPS with Docker Compose. Organize your budgets and track expenses.

Self-Hosting Firefly III with Docker Compose

1. Database Configuration and Bindings

Firefly III supports MySQL, MariaDB, and PostgreSQL. For a robust self-hosted setup, MariaDB is highly recommended. The database service requires persistent volume bindings to ensure transaction logs and financial data survive container recreations.

Within the Firefly III container, the database connection is configured using the following environment variables:

Variable Description Recommended Value
DB_CONNECTION Database driver mysql (works for MariaDB) or pgsql
DB_HOST Hostname of the database service in the Docker network firefly_iii_db
DB_PORT Network port for database communication 3306 (MariaDB/MySQL) or 5432 (PostgreSQL)
DB_DATABASE Name of the database firefly
DB_USERNAME Username for database access firefly
DB_PASSWORD Password for database access Use a secure, randomly generated string

Persistent Volume Mapping

To prevent data loss, map a local directory or named volume to the database container's data directory. For MariaDB:

volumes:
  - /var/lib/firefly/db:/var/lib/mysql

For PostgreSQL:

volumes:
  - /var/lib/firefly/db:/var/lib/postgresql/data

2. Web Server Parameters and Reverse Proxy

Firefly III runs internally on port 8080 (HTTP). Exposure to the public internet must be mediated by a reverse proxy handling SSL termination.

Caddy Reverse Proxy Configuration

Caddy simplifies SSL handling by automatically provisioning Let's Encrypt certificates.

firefly.yourdomain.com {
    reverse_proxy firefly_iii_app:8080 {
        header_up Host {host}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
    }
}

Nginx Reverse Proxy Configuration

If using Nginx, configure the virtual host with the following parameters:

server {
    listen 443 ssl http2;
    server_name firefly.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/firefly.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/firefly.yourdomain.com/privkey.pem;

    client_max_body_size 64M;

    location / {
        proxy_pass http://firefly_iii_app:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Trusting Proxies

Firefly III must know it is behind a reverse proxy to correctly generate HTTPS links. Configure these environment variables in your Firefly III container:

  • TRUSTED_PROXIES=** (or specify the specific IP address of your reverse proxy/docker gateway, e.g., 172.16.0.0/12)
  • APP_URL=https://firefly.yourdomain.com

3. Cron Job Setup for Automated Tasks

Firefly III relies on a recurring cron job to process recurring transactions, fetch currency exchange rates, and run system checks.

You can run a lightweight Alpine container alongside your application that queries the Firefly III cron endpoint via curl at regular intervals.

Add this service to your docker-compose.yml:

  firefly_iii_cron:
    image: alpine:latest
    restart: always
    container_name: firefly_iii_cron
    depends_on:
      - firefly_iii_app
    entrypoint: |
      sh -c "
      echo '0 * * * * wget -qO- http://firefly_iii_app:8080/api/v1/cron/$STATIC_CRON_TOKEN' | crontab - &&
      crond -f -L /dev/stdout
      "
    environment:
      - STATIC_CRON_TOKEN=your_secure_cron_token_here

Method B: Host-Level Crontab

Alternatively, use the host system's crontab to hit the API endpoint hourly:

0 * * * * curl -s http://localhost:8080/api/v1/cron/your_secure_cron_token_here > /dev/null 2>&1

4. Complete docker-compose.yml Specification

Create a directory (e.g., /opt/firefly) and place the following configuration inside docker-compose.yml.

version: '3.8'

services:
  firefly_iii_db:
    image: mariadb:10.11
    container_name: firefly_iii_db
    restart: always
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=yes
      - MYSQL_DATABASE=firefly
      - MYSQL_USER=firefly
      - MYSQL_PASSWORD=your_db_secure_password
    volumes:
      - firefly_db:/var/lib/mysql
    networks:
      - firefly_network

  firefly_iii_app:
    image: fireflyiii/core:latest
    container_name: firefly_iii_app
    restart: always
    depends_on:
      - firefly_iii_db
    volumes:
      - firefly_upload:/var/www/html/storage/upload
    environment:
      - APP_KEY=ChangeThisToExactly32CharsLongString!
      - APP_ENV=local
      - APP_DEBUG=false
      - APP_URL=https://firefly.yourdomain.com
      - TRUSTED_PROXIES=**
      - DB_CONNECTION=mysql
      - DB_HOST=firefly_iii_db
      - DB_PORT=3306
      - DB_DATABASE=firefly
      - DB_USERNAME=firefly
      - DB_PASSWORD=your_db_secure_password
      - STATIC_CRON_TOKEN=your_secure_cron_token_here
      - TZ=UTC
    ports:
      - "127.0.0.1:8080:8080"
    networks:
      - firefly_network

  firefly_iii_cron:
    image: alpine:latest
    container_name: firefly_iii_cron
    restart: always
    depends_on:
      - firefly_iii_app
    entrypoint: >
      sh -c "
      echo '0 * * * * wget -qO- http://firefly_iii_app:8080/api/v1/cron/your_secure_cron_token_here' | crontab - &&
      crond -f -L /dev/stdout
      "
    networks:
      - firefly_network

volumes:
  firefly_db:
    driver: local
  firefly_upload:
    driver: local

networks:
  firefly_network:
    driver: bridge

5. Deployment and Verification

  1. Generate a Secure Encryption Key: Firefly III requires a 32-character application key (APP_KEY). Generate one using: bash head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32 ; echo Update the APP_KEY environment variable in your docker-compose.yml with this output.
  2. Launch the Stack: Execute the following command in the directory containing docker-compose.yml: bash docker compose up -d
  3. Run Database Migrations and Seed Data: The container automatically runs migrations on start. You can monitor the progress with: bash docker compose logs -f firefly_iii_app Wait for the log entry indicating that the web server is running.
  4. Create Your User Account: Access Firefly III through your configured reverse proxy URL (e.g., https://firefly.yourdomain.com). The first account registered automatically becomes the administrator.