Finance intermediate ⏱ 45 minutes

Firefly III: Personal Finance Manager

Complete personal finance tracking. Budgets, transactions, and financial reports.

By Homelab Team • 2025-01-15
#firefly-iii#finance#budgeting#transactions#docker

Introduction

Firefly III is a sophisticated, self-hosted personal finance manager designed to help you understand where your money goes. Unlike simple budgeting apps, Firefly III provides comprehensive financial tracking with powerful analytics, multi-currency support, and automation capabilities that rival commercial platforms.

With over 15,000 GitHub stars and active development since 2016, Firefly III has become the gold standard for self-hosted financial management. It’s particularly powerful for users with complex financial situations: multiple income sources, investments, foreign currency transactions, or small business expenses.

What Makes Firefly III Different?

Comprehensive Financial Picture

While budgeting apps focus on monthly spending, Firefly III tracks your entire financial ecosystem:

  • Asset accounts (checking, savings, cash)
  • Revenue accounts (salary, freelance, investments)
  • Expense accounts (groceries, rent, entertainment)
  • Liabilities (credit cards, loans, mortgages)
  • Investment tracking with portfolio performance
  • Cryptocurrency holdings and transactions

Powerful Automation

Firefly III includes automation features that save hours of manual entry:

  • Recurring transactions with flexible schedules
  • Rule-based automatic categorization
  • Import from 6,000+ banks via integrations
  • API for custom automation scripts
  • Webhooks for real-time processing

Advanced Reporting

Generate insights that commercial platforms charge premium prices for:

  • Net worth tracking over time
  • Budget vs. actual spending analysis
  • Category-based expense trends
  • Income and expense forecasting
  • Custom date range comparisons
  • Export reports to CSV for further analysis

Why Self-Host Firefly III?

Privacy and Data Ownership

Your complete financial history - every transaction, every account balance, every investment position - stays on your infrastructure. Commercial platforms like Personal Capital, Mint, or Quicken aggregate this data for advertising profiles and may sell it to data brokers.

Zero Recurring Costs

Quicken costs $35.99-71.99/year. Personal Capital is free but requires $100k+ investable assets. YNAB charges $99/year. Firefly III is completely free, forever.

Unlimited Customization

With access to the source code and a thriving plugin ecosystem, you can customize Firefly III to match your exact workflow. Need custom categories? Want specific reports? Require integration with proprietary systems? All possible with Firefly III.

Multi-Currency Native

Managing finances across countries? Firefly III handles multiple currencies naturally, with automatic exchange rate updates and proper conversion tracking - features that cost extra in commercial platforms.

Prerequisites

Before deploying Firefly III, ensure you have:

System Requirements

Minimum Configuration:

  • 1 CPU core
  • 1GB RAM (2GB recommended)
  • 5GB disk space (10GB+ for multi-year history)
  • Docker 20.10+ and Docker Compose v2.0+

Recommended Configuration:

  • 2 CPU cores
  • 2GB RAM
  • 20GB disk space
  • MariaDB or PostgreSQL for production use
  • Reverse proxy with HTTPS

Required Knowledge

  • Basic Docker and container concepts
  • Understanding of double-entry bookkeeping (Firefly uses this accounting method)
  • Familiarity with financial account types
  • Basic command line skills

Financial Data Preparation

Gather before starting:

  • List of all financial accounts with current balances
  • Recent transaction history (CSV exports from banks)
  • Recurring bills and subscriptions
  • Investment account information
  • List of budget categories you want to track

Understanding Firefly III’s Architecture

Firefly III uses a traditional web application stack:

Application Layer:

  • PHP 8.2+ with Laravel framework
  • Handles business logic and data processing
  • Generates web interface
  • Provides REST API

Database Layer:

  • MySQL/MariaDB or PostgreSQL
  • Stores all financial data
  • Maintains transaction history
  • Handles relationships between accounts

Optional Components:

  • Firefly III Importer (separate tool for bank imports)
  • Firefly III Data Importer (new unified import tool)
  • Cron container for scheduled tasks
  • Redis for caching (performance improvement)

Data Flow:

User → Web Interface → PHP Application → Database
                  ↓
        Cron Jobs (recurring transactions)
                  ↓
        API → External Integrations

Installation with Docker Compose

Step 1: Create Project Structure

# Create directory structure
mkdir -p ~/firefly-iii
cd ~/firefly-iii

# Create subdirectories
mkdir -p mysql upload

Step 2: Generate Application Key

Firefly III requires a random 32-character application key:

# Generate secure random key
head /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 32
# Example output: SomeRandomStringOf32CharsExactly

Save this key - you’ll need it in the next step.

Step 3: Create Environment Configuration

Create .env file:

# Application Settings
APP_KEY=SomeRandomStringOf32CharsExactly
APP_ENV=local
APP_DEBUG=false
[email protected]
APP_URL=http://localhost

# Database Configuration
DB_CONNECTION=mysql
DB_HOST=firefly-db
DB_PORT=3306
DB_DATABASE=firefly
DB_USERNAME=firefly
DB_PASSWORD=your-secure-database-password-here

# Cache and Queue
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

# Cookie Settings (change for security)
COOKIE_PATH="/"
COOKIE_DOMAIN=
COOKIE_SECURE=false
COOKIE_SAMESITE=lax

# Mail Configuration (for notifications)
MAIL_MAILER=log
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
[email protected]
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

# Timezone
TZ=America/New_York

# Trusted Proxies (if using reverse proxy)
TRUSTED_PROXIES=**

# Optional: Enable demo mode (for testing)
IS_DEMO_SITE=false

Step 4: Create Docker Compose File

Create docker-compose.yml:

version: '3.8'

services:
  firefly-db:
    image: mariadb:11
    container_name: firefly-db
    restart: unless-stopped
    environment:
      MYSQL_RANDOM_ROOT_PASSWORD: "yes"
      MYSQL_USER: firefly
      MYSQL_PASSWORD: your-secure-database-password-here
      MYSQL_DATABASE: firefly
    volumes:
      - ./mysql:/var/lib/mysql
    networks:
      - firefly-network

  firefly-app:
    image: fireflyiii/core:latest
    container_name: firefly-app
    restart: unless-stopped
    ports:
      - "8080:8080"
    depends_on:
      - firefly-db
    env_file:
      - .env
    volumes:
      - ./upload:/var/www/html/storage/upload
    networks:
      - firefly-network
    labels:
      # Traefik configuration (optional)
      - "traefik.enable=true"
      - "traefik.http.routers.firefly.rule=Host(`firefly.yourdomain.com`)"
      - "traefik.http.routers.firefly.entrypoints=websecure"
      - "traefik.http.routers.firefly.tls=true"
      - "traefik.http.routers.firefly.tls.certresolver=letsencrypt"
      - "traefik.http.services.firefly.loadbalancer.server.port=8080"

  firefly-cron:
    image: fireflyiii/core:latest
    container_name: firefly-cron
    restart: unless-stopped
    depends_on:
      - firefly-app
    env_file:
      - .env
    command: |
      sh -c "while true; do
        php artisan firefly-iii:cron
        sleep 86400
      done"
    networks:
      - firefly-network

networks:
  firefly-network:
    driver: bridge

volumes:
  mysql:
  upload:

Step 5: Deploy Firefly III

# Start all services
docker compose up -d

# Wait for database initialization (30-60 seconds)
sleep 60

# Check container status
docker compose ps

# View logs for any errors
docker compose logs -f firefly-app

# You should see: "Application ready"

Step 6: Initial Setup

Navigate to http://YOUR-SERVER-IP:8080 in your browser.

First-Time Registration:

  1. Create admin account
  2. Complete profile
    • Name, timezone, language preferences
  3. Configure default currency (USD, EUR, GBP, etc.)
  4. Click “Finish Setup”

You’ll be redirected to the dashboard.

Bank Connection Setup

Firefly III supports multiple methods for importing transactions.

Option 1: Nordigen/GoCardless (European Banks - Free)

GoCardless provides free access to European bank APIs under PSD2 regulations.

Setup Process:

  1. Create account at https://bankaccountdata.gocardless.com
  2. Register application (free tier: 100 API calls/day)
  3. Obtain Secret ID and Secret Key
  4. In Firefly III:
    Options → Preferences → Nordigen/GoCardless
    ├─ Enter Secret ID
    ├─ Enter Secret Key
    ├─ Select country and bank
    └─ Authenticate via bank OAuth

Supported Banks:

  • 2,000+ European banks across 31 countries
  • UK: Barclays, HSBC, Lloyds, NatWest, etc.
  • Germany: Deutsche Bank, Commerzbank, N26, etc.
  • France: BNP Paribas, Crédit Agricole, etc.

Limitations:

  • 90-day access token expiration
  • Free tier limited to 100 calls/day
  • European banks only

Option 2: Plaid (US Banks - Paid)

For US bank connections, Plaid provides robust API access.

Setup:

  1. Create Plaid developer account
  2. Apply for production access (free development mode available)
  3. Generate API keys
  4. Use Firefly III Data Importer with Plaid integration

Cost: Free for development, production pricing varies based on usage.

Option 3: CSV Import (Universal - Free)

Most reliable method for any bank worldwide.

Export from Bank:

Most banks offer transaction downloads in these formats:

  • CSV (Comma-Separated Values) - most common
  • OFX (Open Financial Exchange)
  • QFX (Quicken format)
  • MT940 (European banking standard)

Import to Firefly III:

1. Go to "Import Data" page
2. Select import type: "File"
3. Upload CSV/OFX file
4. Map columns:
   ├─ Date → Transaction Date
   ├─ Description → Description
   ├─ Amount → Amount
   ├─ Account → Your Firefly account
   └─ Category → (optional, can categorize later)
5. Configure options:
   ├─ Date format (YYYY-MM-DD, DD/MM/YYYY, etc.)
   ├─ Delimiter (comma, semicolon, tab)
   ├─ Skip duplicate detection
   └─ Apply rules automatically
6. Review import preview
7. Click "Import"

CSV Format Example:

Date,Description,Amount,Type
2025-01-15,Grocery Store,-125.43,Debit
2025-01-14,Employer Paycheck,3500.00,Credit
2025-01-13,Electric Bill,-89.50,Debit
2025-01-12,Gas Station,-45.00,Debit

Option 4: Firefly III Data Importer

The official Data Importer tool provides advanced import capabilities.

Deploy Data Importer:

# Add to docker-compose.yml
  firefly-importer:
    image: fireflyiii/data-importer:latest
    container_name: firefly-importer
    restart: unless-stopped
    ports:
      - "8081:8080"
    depends_on:
      - firefly-app
    environment:
      FIREFLY_III_URL: http://firefly-app:8080
      FIREFLY_III_ACCESS_TOKEN: your-personal-access-token
      VANITY_URL: http://YOUR-SERVER-IP:8080
    networks:
      - firefly-network

Generate Access Token:

  1. Firefly III → Options → Profile → Personal Access Tokens
  2. Create New Token
  3. Name: “Data Importer”
  4. Click “Create”
  5. Copy token (shown once)

Using the Importer:

Navigate to http://YOUR-SERVER-IP:8081:

  1. Select import source (CSV, Plaid, Nordigen, Spectre)
  2. Upload file or connect API
  3. Map accounts and categories
  4. Configure duplicate detection
  5. Apply import rules
  6. Execute import

Data Import from Other Tools

Migrating from Mint

Export from Mint:

1. Sign in to Mint.com
2. Transactions → All Transactions
3. Filter date range (Mint limits exports to 1 year)
4. Click "Export" button
5. Choose "CSV" format
6. Download file
7. Repeat for each year of history

Import to Firefly III:

# Mint CSV format has specific columns
# Date, Description, Original Description, Amount, Transaction Type, Category, Account Name, Labels, Notes

# Import steps:
1. Import Data → File Upload
2. Select Mint CSV
3. Map columns automatically (Firefly detects Mint format)
4. Select or create matching accounts
5. Review category mappings
6. Import transactions

Migrating from YNAB

Export from YNAB:

Desktop/YNAB4:
1. File → Export Budget Data
2. Choose "Register" format
3. Export each account separately

Web (nYNAB):
1. Account → Export Budget Data
2. Download ZIP file
3. Extract individual account CSVs

Import Process:

YNAB uses different terminology than Firefly III:

YNAB TermFirefly III Equivalent
On Budget AccountAsset Account
Off Budget AccountAsset Account (tracking)
CategoryBudget/Expense Category
PayeeDescription/Expense Account

Import each account’s CSV separately and reconcile balances.

Migrating from Quicken

Export from Quicken:

1. File → Export → QIF File
2. Select account to export
3. Choose date range
4. Save QIF file
5. Repeat for each account

Import QIF to Firefly III:

1. Import Data → File Upload
2. Select QIF format
3. Firefly III auto-detects QIF structure
4. Map accounts
5. Import transactions

Security Best Practices for Financial Data

Database Encryption

Enable Encrypted Database Storage:

# Using LUKS for database volume
sudo cryptsetup luksFormat /dev/sdX2
sudo cryptsetup luksOpen /dev/sdX2 firefly-db-encrypted
sudo mkfs.ext4 /dev/mapper/firefly-db-encrypted
sudo mount /dev/mapper/firefly-db-encrypted /mnt/firefly-db

# Update docker-compose.yml
volumes:
  - /mnt/firefly-db:/var/lib/mysql

HTTPS Configuration

Using Caddy (Simplest):

firefly.yourdomain.com {
    reverse_proxy localhost:8080
    encode gzip
}

Using Nginx:

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;

    location / {
        proxy_pass http://localhost: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;
    }
}

Two-Factor Authentication

Enable 2FA for admin account:

1. Options → Profile → Two-Factor Authentication
2. Scan QR code with authenticator app (Authy, Google Authenticator)
3. Enter 6-digit code to confirm
4. Save backup codes securely

API Security

Limit API Token Permissions:

1. Options → Profile → Personal Access Tokens
2. Create tokens with specific scopes:
   ├─ read-only: For reporting scripts
   ├─ write: For import automation
   └─ full: Only for trusted applications
3. Rotate tokens quarterly
4. Delete unused tokens immediately

Access Control

Restrict by IP Address:

# Using Traefik IP whitelist
labels:
  - "traefik.http.middlewares.firefly-ipwhitelist.ipwhitelist.sourcerange=192.168.1.0/24,10.8.0.0/24"
  - "traefik.http.routers.firefly.middlewares=firefly-ipwhitelist"

Or VPN-Only Access:

# Bind to VPN interface only
ports:
  - "10.8.0.1:8080:8080"  # WireGuard/OpenVPN IP

Backup Procedures

Automated Database Backups

Backup Script:

#!/bin/bash
# /usr/local/bin/backup-firefly.sh

BACKUP_DIR="/backups/firefly"
DATE=$(date +%Y%m%d-%H%M%S)
RETENTION_DAYS=30

# Create backup directory
mkdir -p "$BACKUP_DIR"

# Backup database
docker exec firefly-db mysqldump -u firefly -pyour-db-password firefly |   gzip > "$BACKUP_DIR/firefly-db-$DATE.sql.gz"

# Backup uploads directory
tar czf "$BACKUP_DIR/firefly-uploads-$DATE.tar.gz"   ~/firefly-iii/upload

# Verify backups
if [ -f "$BACKUP_DIR/firefly-db-$DATE.sql.gz" ]; then
    echo "Database backup successful: firefly-db-$DATE.sql.gz"
    SIZE=$(du -h "$BACKUP_DIR/firefly-db-$DATE.sql.gz" | cut -f1)
    echo "Size: $SIZE"
else
    echo "ERROR: Database backup failed!"
    exit 1
fi

# Remove old backups
find "$BACKUP_DIR" -name "firefly-*.gz" -mtime +$RETENTION_DAYS -delete

# Optional: Upload to remote storage
# rclone copy "$BACKUP_DIR/firefly-db-$DATE.sql.gz" remote:backups/firefly/

Schedule with Cron:

# Daily at 3 AM
0 3 * * * /usr/local/bin/backup-firefly.sh >> /var/log/firefly-backup.log 2>&1

Restore Procedure

Restore from Backup:

#!/bin/bash
# restore-firefly.sh

BACKUP_FILE="/backups/firefly/firefly-db-20250115-030000.sql.gz"

# Stop Firefly III
cd ~/firefly-iii
docker compose stop firefly-app firefly-cron

# Restore database
gunzip < "$BACKUP_FILE" | docker exec -i firefly-db   mysql -u firefly -pyour-db-password firefly

# Restore uploads (if needed)
tar xzf /backups/firefly/firefly-uploads-20250115-030000.tar.gz -C ~/firefly-iii/

# Restart services
docker compose start firefly-app firefly-cron

echo "Restore complete"

Export Financial Data

Export All Data as JSON:

# Using Firefly III API
curl -X GET "http://YOUR-SERVER-IP:8080/api/v1/accounts"   -H "Authorization: Bearer YOUR_API_TOKEN"   -H "Accept: application/json" > accounts-export.json

curl -X GET "http://YOUR-SERVER-IP:8080/api/v1/transactions"   -H "Authorization: Bearer YOUR_API_TOKEN"   -H "Accept: application/json" > transactions-export.json

This creates a portable backup independent of database format.

Troubleshooting

Application Key Errors

Symptom: “No application key specified” error

Solution:

# Generate new key
head /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 32

# Update .env file
nano .env
# Set: APP_KEY=YourNewGeneratedKey

# Restart container
docker compose restart firefly-app

Database Connection Failed

Check database status:

docker compose logs firefly-db

# Common issues:
# - Database still initializing (wait 60 seconds)
# - Wrong password in .env
# - Network issues

# Test database connection
docker exec -it firefly-db mysql -u firefly -p
# Enter password when prompted

Import Fails with CSV Error

Common CSV issues:

# Date format mismatch
# Firefly expects: YYYY-MM-DD
# Fix: Edit CSV or specify format during import

# Encoding issues
# Convert to UTF-8:
iconv -f ISO-8859-1 -t UTF-8 input.csv > output.csv

# Delimiter confusion
# Ensure CSV uses commas, not semicolons or tabs
# Or specify delimiter during import

Slow Performance

Optimization steps:

# 1. Clear cache
docker exec firefly-app php artisan cache:clear

# 2. Optimize database
docker exec firefly-db mysqlcheck -u firefly -p --optimize --all-databases

# 3. Add Redis caching
# Add to docker-compose.yml:
  redis:
    image: redis:alpine
    restart: unless-stopped
    networks:
      - firefly-network

# Update .env:
CACHE_DRIVER=redis
REDIS_HOST=redis
REDIS_PORT=6379

# 4. Increase PHP memory
# Add to firefly-app environment:
environment:
  - PHP_MEMORY_LIMIT=512M

Recurring Transactions Not Creating

Check cron container:

# Verify cron is running
docker compose logs firefly-cron

# Manual trigger
docker exec firefly-app php artisan firefly-iii:cron

# Should create pending recurring transactions

Conclusion

Firefly III provides enterprise-grade personal finance management with complete privacy and control. By self-hosting, you maintain ownership of your financial data while accessing powerful budgeting, tracking, and reporting tools.

What you’ve accomplished:

  • Deployed comprehensive financial management platform
  • Configured secure database with automated backups
  • Set up bank import capabilities (API or CSV)
  • Implemented security best practices for financial data

Next steps:

  • Import historical transactions (2-3 years recommended)
  • Create budgets for expense categories
  • Set up recurring transactions for bills
  • Configure transaction rules for auto-categorization
  • Explore reports and analytics features
  • Consider adding Data Importer for automated bank sync

Additional resources:

  • Official documentation: https://docs.firefly-iii.org
  • API documentation: https://api-docs.firefly-iii.org
  • Community forum: Active discussion boards
  • GitHub: https://github.com/firefly-iii/firefly-iii

With Firefly III running in your homelab, you have complete visibility into your financial life without sacrificing privacy to commercial services. The powerful analytics and automation capabilities will help you make informed financial decisions and achieve your money goals.