This repository contains the necessary configuration to deploy Firefly III (a personal finance manager) with MariaDB as the database, running behind an Nginx reverse proxy with proper SSL termination.
The architecture follows this flow:
The setup consists of:
- Firefly III - Personal finance management application
- MariaDB - Database for Firefly III
- Nginx - Reverse proxy handling SSL and forwarding requests to the application
- Certbot - For automatic SSL certificate management
- A server with a static IP address
- A domain name pointed to your server's IP
- Docker and Docker Compose installed
- Nginx installed on the host system (not in Docker)
- Basic knowledge of server administration
- Register a domain or use an existing one
- Set up Cloudflare as your DNS provider:
- Add an A record pointing your domain to your server's static IP
- Set Proxy status to OFF initially
- Set SSL/TLS encryption mode to FULL
- Configure WAF rules as needed (e.g., whitelist by country or IP)
-
Clone this repository:
git clone https://github.com/nim444/firefly-mariadb-nginx-self-hosted.git cd firefly-mariadb-nginx-self-hosted -
Create environment files:
Create
.envfile for Firefly III:cp .env.example .env nano .env
Update the following variables:
APP_KEY: Generate withopenssl rand -base64 32APP_URL: Set to your domain (e.g., https://yourdomain.ro)STATIC_CRON_TOKEN: Generate withopenssl rand -base64 32(ensure it's exactly 32 characters)TZ: Your timezone (e.g., Europe/Bucharest)- Other database credentials (must match .db.env)
Create
.db.envfile for MariaDB:nano .db.env
Add the following variables:
MYSQL_ROOT_PASSWORD=strong_root_password MYSQL_USER=firefly MYSQL_PASSWORD=fireflypass MYSQL_DATABASE=firefly -
Start the Docker containers:
docker compose up -d
-
Verify containers are running:
docker ps
-
Test if the application is accessible locally:
curl localhost:8777
-
Create a new Nginx site configuration:
sudo nano /etc/nginx/sites-available/yourdomain.ro
-
Add the configuration from nginx-reverse-proxy.conf:
server { listen 80; server_name yourdomain.ro www.yourdomain.ro; location / { proxy_pass http://localhost:8777; 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; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } }
-
Enable the site and test Nginx configuration:
sudo ln -s /etc/nginx/sites-available/yourdomain.ro /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx
-
Install Certbot:
sudo snap install --classic certbot sudo ln -s /snap/bin/certbot /usr/bin/certbot
-
Obtain SSL certificate:
sudo certbot --nginx
Follow the prompts to configure SSL for your domain.
-
Test automatic renewal:
sudo certbot renew --dry-run
-
Configure UFW (Uncomplicated Firewall):
sudo ufw allow 'Nginx Full' sudo ufw allow 'OpenSSH' sudo ufw enable sudo ufw status
-
Install Fail2Ban for SSH protection:
sudo apt install fail2ban sudo systemctl enable fail2ban sudo systemctl start fail2ban
If you encounter issues, here are some commands to help diagnose problems:
-
Check if Nginx is listening on port 80:
sudo lsof -i :80
-
View Nginx logs:
sudo journalctl -xeu nginx cat /var/log/nginx/error.log
-
Check Docker container status:
docker ps docker logs firefly_iii_core docker logs firefly_iii_db
-
View firewall status:
sudo ufw status
To update to the latest version:
docker compose down
docker compose pull
docker compose up -dCertbot automatically renews certificates before they expire. To manually trigger renewal:
sudo certbot renew- Keep your server updated with security patches
- Regularly backup your database (the volume
firefly_iii_db) - Use strong passwords for all services
- Consider implementing additional security measures in Cloudflare (rate limiting, etc.)
- Monitor server logs for suspicious activity

