MAATRIX / Блог / Firefly III в Docker Compose: готовый файл

Firefly III в Docker Compose: готовый файл

MAATRIX

Приложения для учёта финансов вроде YNAB или Monarch удобны, но каждый месяц отправляют ваши транзакции на чужие серверы — и просят за это подписку в долларах, которую из России ещё поди оплати. Firefly III решает обе проблемы: это open-source менеджер личных финансов с бюджетами, счетами, отчётами и правилами автоматической категоризации, который вы разворачиваете сами, на своём сервере, и данные о том, сколько вы потратили на кофе, не покидают вашу инфраструктуру. Ниже — рабочий docker-compose.yml, который поднимает Firefly III вместе с PostgreSQL за один docker compose up, плюс нюансы, которые обычно вылезают уже после установки.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое Firefly III и кому он подходит

Firefly III — это веб-приложение на PHP (Laravel), которое закрывает типичный набор задач личных финансов: несколько счетов (наличные, карты, вклады), бюджеты по категориям, повторяющиеся транзакции, теги, правила автоматической разметки платежей и подробные отчёты — от помесячного баланса до net worth за год. Есть импорт из CSV и отдельный модуль Data Importer, который умеет разбирать банковские выписки и синхронизироваться через открытый стандарт GoCardless (бывший Nordigen) для части европейских банков — для российских банков автоматической интеграции нет, операции заводятся вручную или через CSV.

Кому это подходит:

  • тем, кто ведёт семейный или личный бюджет и хочет видеть реальную картину трат, а не гадать по выпискам;
  • фрилансерам и небольшим ИП, которым нужно разделять личные и рабочие потоки денег без бухгалтерского SaaS;
  • людям, которым принципиально важно, чтобы данные о доходах и расходах не лежали на серверах третьей компании.

Для учёта бизнес-финансов с двойной записью и налоговой отчётностью Firefly III не подойдёт — это про личные и семейные деньги, не про ERP.

Требования к серверу

Firefly III — не тяжёлое приложение, но PHP-FPM плюс PostgreSQL плюс опциональный Data Importer суммарно просят чуть больше, чем «самый дешёвый тариф»:

РесурсМинимумКомфортно
CPU1 vCPU2 vCPU
RAM1 GB2 GB
Диск10 GB SSD20+ GB SSD
ОСUbuntu 24.04 / Debian 12Ubuntu 24.04

С 1 GB RAM всё запустится и будет работать для одного-двух пользователей, но если планируете держать на том же сервере что-то ещё, закладывайте 2 GB — PostgreSQL съедает оперативку под кэш страниц, и на 1 GB при импорте CSV на пару тысяч строк процесс может упереться в OOM killer.

Для установки Docker с нуля на чистой системе подойдёт инструкция Ubuntu 24.04: установка Docker с нуля — она же годится и для Debian с минимальными правками.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Готовый docker-compose.yml

Ниже — минимальная, но production-пригодная конфигурация: сам Firefly III, отдельный контейнер PostgreSQL, том для загруженных файлов (аттачей и импортов) и cron-контейнер для фоновых задач (напоминания о повторяющихся транзакциях, автоматические правила).

Создайте директорию проекта и файл .env:

mkdir -p ~/firefly-iii && cd ~/firefly-iii
touch .env

Сгенерируйте два случайных значения — APP_KEY (32 байта в base64 с префиксом base64:) и пароль для БД:

echo "APP_KEY=base64:$(openssl rand -base64 32)"
echo "DB_PASS=$(openssl rand -base64 24)"
echo "STATIC_CRON_TOKEN=$(openssl rand -hex 16)"

Впишите результаты в .env:

# .env
APP_ENV=production
APP_KEY=base64:вставьте_сгенерированный_ключ
APP_URL=https://finance.example.com
TZ=Europe/Moscow

DB_HOST=firefly-db
DB_PORT=5432
DB_CONNECTION=pgsql
DB_DATABASE=firefly
DB_USERNAME=firefly
DB_PASSWORD=вставьте_пароль_бд

STATIC_CRON_TOKEN=вставьте_сгенерированный_токен

TRUSTED_PROXIES=**

Теперь сам docker-compose.yml:

services:
  firefly-app:
    image: fireflyiii/core:latest
    container_name: firefly-app
    restart: unless-stopped
    env_file: .env
    volumes:
      - firefly_upload:/var/www/html/storage/upload
    depends_on:
      firefly-db:
        condition: service_healthy
    ports:
      - "127.0.0.1:8080:8080"
    networks:
      - firefly-net

  firefly-db:
    image: postgres:16-alpine
    container_name: firefly-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: firefly
      POSTGRES_USER: firefly
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - firefly_db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U firefly -d firefly"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - firefly-net

  firefly-cron:
    image: alpine:3.20
    container_name: firefly-cron
    restart: unless-stopped
    depends_on:
      - firefly-app
    entrypoint: >
      sh -c "apk add --no-cache curl tzdata >/dev/null &&
      echo '*/15 * * * * curl -s -m 30 http://firefly-app:8080/api/v1/cron/${STATIC_CRON_TOKEN}' | crontab - &&
      crond -f -L /dev/stdout"
    networks:
      - firefly-net

volumes:
  firefly_db:
  firefly_upload:

networks:
  firefly-net:

Обратите внимание: в примере с openssl rand переменная для наглядности названа DB_PASS, а в реальном .env для приложения используйте именно DB_PASSWORD — это имя ждёт и Firefly III, и docker-compose.yml.

Порт приложения намеренно опубликован только на 127.0.0.1:8080 — снаружи Firefly III должен быть доступен исключительно через обратный прокси с HTTPS, никакого прямого HTTP-доступа в открытую сеть быть не должно.

Запуск:

docker compose up -d
docker compose logs -f firefly-app

Первый старт займёт минуту-две — контейнер прогоняет миграции БД. Когда в логах появится строка about listening, идите по http://127.0.0.1:8080 (через SSH-туннель, если ещё нет прокси) и создайте первого пользователя-администратора.

Обратный прокси и HTTPS

Публиковать финансовое приложение без TLS нельзя, поэтому сразу вешаем обратный прокси. Если у вас уже есть Caddy на сервере — конфиг простой:

finance.example.com {
    reverse_proxy 127.0.0.1:8080
}

Caddy сам получит и обновит сертификат Let's Encrypt. Подробности первичной настройки — в статье Caddy с авто-SSL на Ubuntu 24.04: пошаговая установка, а если что-то пошло не так — там же есть разбор частых ошибок Caddy с авто-SSL.

Если предпочитаете nginx:

server {
    listen 443 ssl http2;
    server_name finance.example.com;

    ssl_certificate     /etc/letsencrypt/live/finance.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/finance.example.com/privkey.pem;

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

Не забудьте после этого выставить APP_URL в .env строго на https:// адрес и перезапустить контейнер (docker compose up -d) — иначе Firefly III будет генерировать неправильные ссылки внутри интерфейса и в письмах.

Data Importer: подключение банковских выписок

Ручной ввод каждой транзакции быстро надоедает, поэтому у Firefly III есть отдельный компонент — Data Importer, который умеет читать CSV/CAMT.053-выгрузки и (для части банков ЕС) синхронизироваться по открытому банковскому API через GoCardless. Для банков РФ прямой интеграции нет — работаем через CSV.

Добавьте в тот же docker-compose.yml (или в отдельный файл docker-compose.importer.yml):

services:
  firefly-importer:
    image: fireflyiii/data-importer:latest
    container_name: firefly-importer
    restart: unless-stopped
    environment:
      FIREFLY_III_URL: "http://firefly-app:8080"
      FIREFLY_III_ACCESS_TOKEN: "вставьте_личный_токен_из_UI"
      VANITY_URL: "https://import.example.com"
    ports:
      - "127.0.0.1:8081:8080"
    networks:
      - firefly-net

networks:
  firefly-net:
    external: true

Личный токен создаётся в UI: Profile → OAuth → Personal Access Tokens. Экспортируйте выписку из банка в CSV, зайдите в Data Importer, укажите соответствие колонок (дата, сумма, описание, счёт) — мастер запомнит конфигурацию в виде JSON-профиля, который можно переиспользовать при регулярном импорте.

Бэкапы: что действительно нужно сохранять

Все финансовые данные Firefly III живут в PostgreSQL — том firefly_upload содержит только приложенные файлы (сканы чеков и т.п.), а не транзакции. Значит, приоритет бэкапа — дамп базы:

#!/bin/bash
# /opt/scripts/backup-firefly.sh
BACKUP_DIR="/opt/backups/firefly"
DATE=$(date +%Y%m%d-%H%M%S)
mkdir -p "$BACKUP_DIR"

docker exec firefly-db pg_dump -U firefly firefly | gzip > "$BACKUP_DIR/firefly-db-$DATE.sql.gz"

# том с аттачами
docker run --rm -v firefly-iii_firefly_upload:/data -v "$BACKUP_DIR":/backup alpine \
  tar czf "/backup/firefly-upload-$DATE.tar.gz" -C /data .

# храним последние 14 копий
find "$BACKUP_DIR" -name "firefly-*.gz" -mtime +14 -delete

Добавьте в crontab (crontab -e) ежедневный запуск в тихое время:

0 3 * * * /opt/scripts/backup-firefly.sh >> /var/log/firefly-backup.log 2>&1

Про настройку планировщика подробнее — в статье как установить и настроить cron-задачи на VPS. Если хотите более серьёзную схему с версионированием и дедупликацией (а для финансовых данных это разумно), посмотрите на BorgBackup — есть отдельный разбор BorgBackup в Docker Compose, который можно направить на тот же каталог с дампами. Восстановление дампа — обратная операция:

gunzip -c firefly-db-20260815-030000.sql.gz | docker exec -i firefly-db psql -U firefly -d firefly

Держите хотя бы одну копию бэкапа вне самого сервера — на объектном хранилище или другом VPS. Копия рядом с оригиналом не спасает при потере диска.

Обновление и типичные проблемы

Обновление образа — стандартный докеровский цикл:

docker compose pull
docker compose up -d
docker compose logs -f firefly-app

Firefly III сам прогонит миграции БД при старте новой версии. Перед крупным мажорным обновлением (например, между релизами с разницей в номере минорной версии на 3+) стоит сделать свежий дамп — Laravel-миграции штука надёжная, но откатить их назад без бэкапа не получится.

Частые проблемы, с которыми сталкиваются при первом запуске:

  • 500 Server Error сразу после старта. Почти всегда — неверный или отсутствующий APP_KEY, либо приложение стартовало раньше, чем БД прошла healthcheck. Проверьте docker compose logs firefly-app и убедитесь, что в docker-compose.yml есть depends_on: condition: service_healthy.
  • Ошибки подключения к БД (SQLSTATE[08006]). Обычно рассинхронизация имени сервиса: DB_HOST в .env должен точно совпадать с именем сервиса БД в docker-compose.yml (в примере — firefly-db), а не с localhost.
  • Cron-задачи не выполняются (повторяющиеся транзакции не создаются, правила не срабатывают). Проверьте, что STATIC_CRON_TOKEN в .env и в команде curl контейнера firefly-cron совпадают, и что запрос реально доходит — docker compose logs firefly-cron.
  • После обновления интерфейс генерирует ссылки на http вместо https. Проверьте APP_URL в .env и заголовки X-Forwarded-Proto в конфиге прокси — без них Laravel не понимает, что запрос пришёл по HTTPS.

Если проблема шире конкретно Firefly III и контейнер вообще не поднимается — общий чек-лист есть в статье Docker-контейнер не запускается.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли перенести данные из другого финансового трекера?

Да, через CSV — экспортируйте историю операций из старого приложения (большинство, включая банковские выписки, поддерживают CSV) и заведите импорт через Data Importer, сопоставив колонки вручную один раз.

Работает ли автоматическая синхронизация с российскими банками?

Нет, прямых банковских интеграций для РФ у Firefly III и его Data Importer не предусмотрено — только ручной ввод или CSV-импорт выписок.

Нужен ли отдельный сервер только под Firefly III?

Нет, при 2 GB RAM он спокойно уживается с другими лёгкими сервисами на одном VPS — важно лишь не публиковать порт приложения напрямую наружу и держать всё за одним обратным прокси.

Что будет, если забыть мастер-пароль администратора?

Пароль можно сбросить напрямую через artisan-команду внутри контейнера: docker exec -it firefly-app php artisan firefly-iii:set-user-password, следуя интерактивным подсказкам.

Можно ли вести несколько пользователей (семью) в одном инстансе?

Firefly III однопользовательский по своей модели данных — каждый член семьи должен либо иметь отдельного пользователя с отдельным набором счетов на одном сервере, либо использовать общие учётные данные для входа, если разделение не критично.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →