How to Self-Host Firefly III with Docker Compose
What Is Firefly III?
Firefly III is a self-hosted personal finance manager built around double-entry bookkeeping. It tracks income, expenses, budgets, and savings goals — all on your own server. You get rule-based transaction automation, multi-currency support, recurring transaction management, and a comprehensive REST API. Firefly III replaces services like Mint (now dead) and YNAB without sending your financial data to a third party. It pairs with a separate Data Importer tool that can pull transactions directly from your bank.
Updated March 2026: Verified with latest Docker images and configurations.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 1 GB of free RAM (minimum)
- 2 GB of free disk space
- A domain name (optional, for remote access)
Docker Compose Configuration
Firefly III requires a relational database. PostgreSQL is recommended — it performs better than MySQL/MariaDB under Firefly III’s query patterns and is the stack the developers test against most.
Create a directory for your Firefly III deployment:
mkdir -p ~/firefly-iii && cd ~/firefly-iii
Create a docker-compose.yml file:
services:
firefly:
image: fireflyiii/core:version-6.5.6
container_name: firefly
restart: unless-stopped
depends_on:
db:
condition: service_healthy
ports:
- "8080:8080"
volumes:
- firefly_upload:/var/www/html/storage/upload
env_file:
- .env
networks:
- firefly_net
db:
image: postgres:16-alpine
container_name: firefly-db
restart: unless-stopped
volumes:
- firefly_db:/var/lib/postgresql/data
env_file:
- .db.env
networks:
- firefly_net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U firefly"]
interval: 10s
timeout: 5s
retries: 5
cron:
image: alpine:3.21
container_name: firefly-cron
restart: unless-stopped
depends_on:
- firefly
command: >
sh -c "echo '0 3 * * * wget -qO- http://firefly:8080/api/v1/cron/YOUR_STATIC_CRON_TOKEN' | crontab - && crond -f -L /dev/stdout"
networks:
- firefly_net
volumes:
firefly_upload:
firefly_db:
networks:
firefly_net:
driver: bridge
Create a .env file for the Firefly III application:
# Firefly III Application Environment
# Full reference: https://docs.firefly-iii.org/references/firefly-iii/env/
# ------- REQUIRED -------
# 32-character encryption key for sessions and encryption.
# Generate one with: head /dev/urandom | tr -dc 'A-Za-z0-9' | head -c 32
# CHANGE THIS before first startup. Do not use the example value.
APP_KEY=CHANGEME_32_CHAR_RANDOM_STRING__
# The external URL where you access Firefly III.
# Used for generating links in emails and API responses.
APP_URL=http://localhost:8080
# ------- DATABASE -------
# Use PostgreSQL (recommended over MySQL/MariaDB)
DB_CONNECTION=pgsql
DB_HOST=db
DB_PORT=5432
DB_DATABASE=firefly
DB_USERNAME=firefly
# CHANGE THIS — must match POSTGRES_PASSWORD in .db.env
DB_PASSWORD=change_this_firefly_db_password
# ------- APPLICATION -------
APP_ENV=production
APP_DEBUG=false
DEFAULT_LANGUAGE=en_US
DEFAULT_LOCALE=equal
TZ=UTC
# Email address of the site owner (used in error reports)
SITE_OWNER=admin@example.com
# ------- CRON -------
# Exactly 32 characters. Used to authenticate cron requests.
# Replace YOUR_STATIC_CRON_TOKEN in docker-compose.yml with this value.
STATIC_CRON_TOKEN=CHANGEME_32_CHAR_CRON_TOKEN_HERE
# ------- CACHE & SESSIONS -------
CACHE_DRIVER=file
SESSION_DRIVER=file
# ------- MAIL (optional) -------
# Set to 'smtp' and fill in details to enable email notifications
MAIL_MAILER=log
MAIL_HOST=null
MAIL_PORT=2525
MAIL_FROM=changeme@example.com
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
# ------- AUTHENTICATION -------
# 'web' for built-in auth, 'remote_user_guard' for reverse proxy auth
AUTHENTICATION_GUARD=web
# ------- TELEMETRY -------
# Disable all telemetry
SEND_TELEMETRY=false
Create a .db.env file for PostgreSQL:
# PostgreSQL Database Environment
POSTGRES_USER=firefly
POSTGRES_PASSWORD=change_this_firefly_db_password
POSTGRES_DB=firefly
Before starting: Replace these values:
APP_KEY— Generate a random 32-character string:head /dev/urandom | tr -dc 'A-Za-z0-9' | head -c 32 && echoDB_PASSWORDandPOSTGRES_PASSWORD— Set the same strong password in both.envand.db.envSTATIC_CRON_TOKEN— Generate another 32-character string and also replaceYOUR_STATIC_CRON_TOKENin the cron service command indocker-compose.ymlAPP_URL— Set to your actual domain if using one (e.g.,https://firefly.yourdomain.com)SITE_OWNER— Your email address
Start the stack:
docker compose up -d
Wait 30–60 seconds for the database to initialize and Firefly III to run migrations. Check startup logs:
docker logs firefly
Initial Setup
- Open
http://your-server-ip:8080in your browser - Click Register to create your admin account — the first registered user becomes the administrator
- Set your preferred language and locale
- Create your first asset account (checking account, savings account, or cash wallet)
Firefly III uses double-entry bookkeeping. Every transaction moves money between two accounts. Your bank accounts are “asset accounts.” Stores and services you pay are “expense accounts.” Your employer is a “revenue account.” The system creates expense and revenue accounts automatically as you enter transactions.
Configuration
Accounts
Set up your financial accounts under Accounts in the sidebar:
- Asset accounts — Your bank accounts, savings, cash, credit cards
- Expense accounts — Where money goes (grocery stores, utilities, subscriptions)
- Revenue accounts — Where money comes from (salary, freelance income, interest)
Asset accounts are the only ones you create manually. Expense and revenue accounts are auto-created from transactions.
Budgets
Under Budgets, create monthly spending limits for categories like groceries, dining, entertainment, and subscriptions. Firefly III tracks spending against each budget and shows remaining amounts. Set a total monthly budget to cap overall discretionary spending.
Categories and Tags
Categories group transactions by type (Food, Transport, Housing). Tags add cross-cutting labels (tax-deductible, reimbursable, vacation). Use categories for budgeting and tags for filtering.
Rules
Rules automate transaction processing. Under Rules, create conditions that match transactions and apply actions:
- Example: If description contains “AMZN” → set category to “Shopping”, set expense account to “Amazon”
- Example: If amount is greater than 1000 → add tag “large-purchase”
Rules run automatically on imported transactions and can be applied retroactively to existing ones.
Recurring Transactions
Under Recurring Transactions, set up repeating expenses and income:
- Rent, mortgage payments, subscriptions
- Salary deposits, regular transfers
The cron container (defined in Docker Compose) triggers these on schedule. Without the cron service, recurring transactions will not fire automatically.
Piggy Banks
Piggy banks are savings goals attached to asset accounts. Create one for a vacation fund, emergency savings, or a specific purchase. Firefly III tracks progress toward the target amount.
Advanced Configuration
Data Importer for Bank Imports
The Firefly III Data Importer is a separate container that imports transactions from CSV files, bank APIs (via GoCardless for European banks), or Spectre. To add it to your stack, append this to your docker-compose.yml:
data-importer:
image: fireflyiii/data-importer:version-2.2.1
container_name: firefly-data-importer
restart: unless-stopped
depends_on:
- firefly
ports:
- "8081:8080"
environment:
# Internal Docker URL — the importer connects to Firefly III over the Docker network
FIREFLY_III_URL: http://firefly:8080
# External URL — used for OAuth callback redirects in your browser
VANITY_URL: http://localhost:8080
# Generate a Personal Access Token in Firefly III under Options > Profile > OAuth
FIREFLY_III_ACCESS_TOKEN: your-personal-access-token-here
networks:
- firefly_net
After deploying, generate a Personal Access Token in Firefly III (go to Options → Profile → OAuth → Personal Access Tokens) and paste it into the FIREFLY_III_ACCESS_TOKEN variable. Access the importer at http://your-server-ip:8081.
The Data Importer supports:
- CSV/OFX/QIF file uploads — Export from your bank’s website and upload
- GoCardless (European banks) — Automated bank connection via open banking APIs. Requires a GoCardless account (free tier available). Set
NORDIGEN_IDandNORDIGEN_KEYenvironment variables. - Spectre (Salt Edge) — Bank connections outside Europe. Requires a Spectre developer account. Set
SPECTRE_APP_IDandSPECTRE_SECRET.
Email Notifications
To receive email alerts for rule matches and recurring transaction creation, update the mail variables in .env:
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_FROM=firefly@yourdomain.com
MAIL_USERNAME=your-smtp-username
MAIL_PASSWORD=your-smtp-password
MAIL_ENCRYPTION=tls
Restart the container after changing mail settings:
docker compose restart firefly
Webhooks and API
Firefly III has a full REST API at /api/v1/. Use it to build custom integrations, import data from scripts, or connect to other self-hosted tools. Create API tokens under Options → Profile → OAuth. Webhooks (under Automation → Webhooks) can fire on transaction creation, update, or deletion — useful for triggering n8n or Huginn automations.
Reverse Proxy
Firefly III runs on port 8080 internally. Place it behind a reverse proxy for HTTPS. Update APP_URL in .env to your public domain before configuring the proxy.
Nginx Proxy Manager configuration:
- Scheme: http
- Forward Hostname: your-server-ip (or the Docker host IP)
- Forward Port: 8080
- SSL: Request a new SSL certificate, enable Force SSL
For Caddy, add to your Caddyfile:
firefly.yourdomain.com {
reverse_proxy localhost:8080
}
See the full Reverse Proxy Setup guide for Nginx Proxy Manager, Traefik, and Caddy configurations.
Backup
Firefly III stores data in two places:
- PostgreSQL database — Contains all transactions, accounts, rules, and configuration
- Upload volume — User-uploaded attachments (receipts, documents)
Back up the database with pg_dump:
docker exec firefly-db pg_dump -U firefly firefly > firefly-backup-$(date +%Y%m%d).sql
Back up the upload volume:
docker run --rm -v firefly_upload:/data -v $(pwd):/backup alpine tar czf /backup/firefly-uploads-$(date +%Y%m%d).tar.gz -C /data .
To restore the database:
docker exec -i firefly-db psql -U firefly firefly < firefly-backup-20260224.sql
Automate this with a cron job on the host. Store backups off-server using Borgmatic or Restic. See the Backup Strategy guide for the full 3-2-1 approach.
Troubleshooting
Database Connection Refused on Startup
Symptom: SQLSTATE[08006] Connection refused in container logs.
Fix: The database container is not ready yet. The Docker Compose config includes a health check with pg_isready, so the app waits for the database. If you removed the health check or depends_on condition, add them back. Alternatively, restart the app container after the database is fully initialized:
docker compose restart firefly
“The MAC is invalid” Error
Symptom: The MAC is invalid error after restoring a backup or changing APP_KEY.
Fix: The APP_KEY must match the key used when the data was originally encrypted. If you changed APP_KEY after initial setup, revert it to the original value. This key encrypts session data and some stored values — changing it breaks existing encrypted data.
Recurring Transactions Not Firing
Symptom: Recurring transactions configured but never created automatically.
Fix: The cron container must be running and the STATIC_CRON_TOKEN must be exactly 32 characters and match between .env and the cron command in docker-compose.yml. Verify the cron container is running:
docker logs firefly-cron
If it shows errors, regenerate the token (exactly 32 alphanumeric characters) and ensure both locations match.
Permission Errors on Upload Volume
Symptom: Permission denied when uploading attachments.
Fix: The container runs as www-data (UID 82 on Alpine). Fix volume permissions:
docker exec firefly chown -R www-data:www-data /var/www/html/storage/upload
Slow Performance with Large Datasets
Symptom: Pages load slowly after importing thousands of transactions. Fix: PostgreSQL needs periodic maintenance. Run a vacuum and analyze:
docker exec firefly-db psql -U firefly -c "VACUUM ANALYZE;" firefly
Also confirm your server meets the memory requirements — Firefly III with a large dataset needs 512 MB or more of available RAM.
Resource Requirements
- RAM: ~200 MB idle, ~400 MB under active use. PostgreSQL adds ~100 MB.
- CPU: Low. Spikes briefly during large imports or report generation.
- Disk: ~500 MB for the application. Database grows with transaction count — expect 1 GB per 100,000 transactions including indexes.
Frequently Asked Questions
Is Firefly III free?
Yes. Firefly III is fully open source under the AGPL-3.0 license. All features are free. The developer accepts donations but there’s no paid version.
Can Firefly III import transactions from my bank?
Yes, through the separate Data Importer tool. It supports CSV/OFX/QIF file uploads from any bank, GoCardless for automated European bank connections (open banking), and Spectre/Salt Edge for banks outside Europe. See the Advanced Configuration section above.
How does Firefly III compare to YNAB?
Firefly III uses double-entry bookkeeping and focuses on comprehensive transaction tracking. YNAB uses envelope budgeting and focuses on monthly budget allocation. Firefly III is more powerful for tracking where money goes. YNAB is better if your primary goal is telling every dollar where to go. Actual Budget is the best self-hosted envelope budgeting alternative to YNAB.
Can I use Firefly III on my phone?
Firefly III’s web interface is responsive and works on mobile browsers. There are also community-built mobile apps — most notably “Waterfly III” for Android — that provide a native app experience connected to your Firefly III API.
Does Firefly III support multiple currencies?
Yes. Firefly III has full multi-currency support. Set a default currency and add transactions in any other currency with automatic conversion tracking. It tracks exchange rates and shows reports in your default currency.
What’s the difference between APP_KEY and STATIC_CRON_TOKEN?
APP_KEY encrypts session data and stored values — never change it after initial setup or you’ll lose access to encrypted data. STATIC_CRON_TOKEN authenticates the cron container’s API calls to trigger recurring transactions. Both must be exactly 32 characters. They should be different random strings.
How do I migrate from Mint or other finance apps?
Export your transactions as CSV from your current service. Use the Data Importer to upload the CSV file. Map the CSV columns to Firefly III’s fields (date, description, amount, account). Then set up rules to auto-categorize future imports based on patterns in the description.
Verdict
Firefly III is the most capable self-hosted personal finance manager available. The double-entry bookkeeping model, rule-based automation, and bank import pipeline (via the Data Importer) put it ahead of the alternatives for anyone who wants serious financial tracking on their own server.
Compared to Actual Budget, Firefly III is more powerful but more complex. Actual uses envelope budgeting with a clean, fast UI — pick it if your primary goal is monthly budgeting and you want something minimal. Firefly III is the choice when you need comprehensive transaction tracking, automated categorization, multi-currency support, and detailed reporting across multiple accounts.
GnuCash is the traditional open-source option, but it is desktop software without a native Docker deployment or web interface. Firefly III gives you the same double-entry rigor in a modern, self-hosted web app.
Use Firefly III if: You want full control over your financial data, track multiple accounts and currencies, want automated bank imports, and don’t mind a short learning curve.
Use Actual Budget if: You primarily want envelope budgeting with a clean UI and don’t need double-entry bookkeeping.
Related
- Firefly III: Import Not Working — Fix
- Firefly III vs Beancount: Which Finance App?
- Firefly III vs GnuCash: Personal Finance Compared
- Firefly III vs IHateMoney: Finance Tools Compared
- Ghostfolio vs Firefly III: Which Should You Self-Host?
- How to Self-Host Actual Budget
- Actual Budget vs Firefly III
- Best Self-Hosted Personal Finance Apps
- Self-Hosted Alternatives to Mint
- Self-Hosted Alternatives to YNAB
- Self-Hosted Alternatives to Personal Capital
- Docker Compose Basics
- Reverse Proxy Setup
- Backup Strategy
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments