MAATRIX / Блог / Как установить и настроить Firefly III на VPS

Как установить и настроить Firefly III на VPS

MAATRIX

Банковские приложения показывают траты только по одной карте, а таблицы в Excel надоедает вести уже через неделю. Firefly III — open-source менеджер личных финансов с бюджетами, категориями, повторяющимися транзакциями и отчётами, который вы разворачиваете на собственном сервере: данные о ваших деньгах не уходят ни в какой облачный сервис. Ниже — рабочая установка на VPS через Docker Compose, с HTTPS и бэкапами, которую можно повторить за 20-30 минут.

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

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

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

Что такое Firefly III и зачем он на своём сервере

Firefly III — это веб-приложение на PHP/Laravel: считает баланс по счетам, строит бюджеты по категориям, умеет импортировать выписки из банков (через отдельный модуль Data Importer), показывает графики по месяцам и годам, поддерживает мультивалютность и правила автокатегоризации транзакций.

Почему self-hosted, а не облачный аналог вроде YNAB или готового SaaS:

  • Данные остаются у вас. История трат, зарплата, долги — это чувствительная информация, и держать её на чужом сервере не всегда комфортно.
  • Нет ежемесячной подписки. Плата — только за VPS, а не за каждого пользователя приложения.
  • Полный контроль над бэкапами. Вы сами решаете, где и как часто снимать дамп базы.
  • Можно расширять. Firefly III отдаёт REST API — на нём собирают телеграм-ботов для быстрого добавления трат или интеграции с другими сервисами.

Минус тоже есть: обновления, бэкапы и мониторинг — ваша ответственность, автоматически это никто не сделает. Если это пугает — дальше разберём, как свести ручную работу к минимуму.

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

Firefly III на PHP-FPM + PostgreSQL/MySQL нетребователен к ресурсам. Для личного использования (один-два пользователя, история за несколько лет) достаточно скромной конфигурации:

РесурсМинимумКомфортно
CPU1 vCPU2 vCPU
RAM1 GB2 GB
Диск15 GB SSD25-30 GB SSD (с запасом под бэкапы)
ОСUbuntu 24.04 LTSUbuntu 24.04 LTS

Для семьи с несколькими счетами и активным импортом выписок разумнее взять план с 2 vCPU и 2 GB RAM — при пиковых импортах PHP-FPM и база данных вместе съедают заметно больше памяти, чем в состоянии покоя. Понадобится домен (поддомен вроде finance.example.com) — Firefly III в проде должен работать по HTTPS, потому что через него проходят данные о деньгах.

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

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

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

Установка Docker и подготовка окружения

Если Docker ещё не стоит, это отдельный первый шаг — подробно он разобран в статье про установку Docker на Ubuntu (там же логика подходит и для Ubuntu 24.04, шаги идентичны). Коротко:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
docker --version
docker compose version

Создайте рабочую директорию и файл с переменными окружения — секреты не должны лежать в docker-compose.yml открытым текстом:

mkdir -p ~/firefly-iii && cd ~/firefly-iii
mkdir -p upload

Сгенерируйте APP_KEY — это ключ шифрования Laravel, без него приложение не запустится:

docker run --rm chriswiggins/firefly-iii-key-generator 2>/dev/null \
  || echo "base64:$(openssl rand -base64 32)"

Если контейнер-генератор недоступен, второй вариант с openssl вполне подходит — Firefly III ожидает именно строку в формате base64:....

docker-compose.yml: рабочая конфигурация

Файл .env рядом с compose-файлом:

cat > .env <<'EOF'
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=ЗАМЕНИТЕ_НА_СЛУЧАЙНУЮ_СТРОКУ_32_СИМВОЛА
EOF

STATIC_CRON_TOKEN — токен для запуска фоновых задач Firefly III (пересчёт повторяющихся транзакций и т.п.) через cron, генерируется отдельно: openssl rand -hex 16.

Сам docker-compose.yml:

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

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

  firefly-cron:
    image: alpine:3.20
    restart: unless-stopped
    depends_on:
      - firefly-app
    entrypoint: ["/bin/sh", "-c"]
    command: >
      "echo '0 3 * * * wget -qO- http://firefly-app:8080/api/v1/cron/${STATIC_CRON_TOKEN}' > /etc/crontabs/root &&
       crond -f -L /dev/stdout"

volumes:
  firefly_db_data:
  firefly_upload:

Приложение слушает 127.0.0.1:8080 — наружу порт не торчит, наружу его отдаёт только reverse proxy с SSL. Это осознанное решение: незашифрованный доступ к финансовому приложению по HTTP из интернета — плохая идея.

Запуск:

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

Первый старт занимает 30-60 секунд — приложение накатывает миграции базы данных. Дождитесь строки о готовности сервера, затем Ctrl+C.

SSL и reverse proxy: делаем сайт доступным по HTTPS

Проще всего поднять Caddy — он сам выпускает и продлевает сертификаты Let's Encrypt, конфиг занимает несколько строк. Подробный разбор установки — в статье про Caddy с автоматическим SSL на VPS. Здесь — минимальный Caddyfile именно под Firefly III:

finance.example.com {
    reverse_proxy 127.0.0.1:8080
    encode gzip

    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
    }
}

Перед этим убедитесь, что A-запись домена finance.example.com указывает на IP вашего VPS — без этого Let's Encrypt не сможет подтвердить владение доменом и выпустить сертификат. Если предпочитаете nginx с certbot вместо Caddy — логика та же: proxy_pass на 127.0.0.1:8080, сертификат на домен, редирект с 80 на 443.

Не забудьте открыть порты 80 и 443 в файрволе — как это сделать безопасно, разобрано в статье про настройку UFW на VPS. Порт 8080 наружу открывать не нужно — он и так слушает только 127.0.0.1.

Первый запуск, бюджеты и импорт выписок

Откройте https://finance.example.com — Firefly III предложит создать первого пользователя (в self-hosted версии это одновременно и админ). Пароль указывайте длинный и уникальный — это единственная точка входа ко всей финансовой истории.

После входа стоит настроить в таком порядке:

  1. Валюта по умолчанию — Settings → Currencies (для рублёвых счетов добавьте RUB, если её нет в списке по умолчанию).
  2. Счета (Accounts) — заведите все реальные счета: карты, наличные, накопительные. Для каждого укажите начальный баланс на дату старта учёта.
  3. Категории (Categories) — продукты, транспорт, подписки и т.д. Можно начать с 8-10 категорий, остальное добавится по ходу.
  4. Бюджеты (Budgets) — месячные лимиты по категориям, с прогресс-баром расхода.
  5. Правила (Rules) — автоматическая категоризация по описанию транзакции (например, все траты с "Яндекс.Такси" в категорию "Транспорт").

Для регулярного ввода трат с телефона удобнее не веб-интерфейс, а Firefly III API + сторонний телеграм-бот или мобильный клиент — но это уже отдельная настройка сверх базовой установки.

Импорт банковских выписок

Ручной ввод каждой транзакции реалистичен только первую неделю. Для импорта данных есть отдельный контейнер Data Importer — он читает CSV/CAMT.053-выписки и раскладывает их по счетам через API основного приложения.

Добавьте в docker-compose.yml:

  firefly-importer:
    image: fireflyiii/data-importer:latest
    restart: unless-stopped
    depends_on:
      - firefly-app
    environment:
      FIREFLY_III_URL: "http://firefly-app:8080"
      VANITY_URL: "https://finance.example.com"
    ports:
      - "127.0.0.1:8081:8080"

После docker compose up -d импортер доступен на 127.0.0.1:8081 — пробросьте на него ещё один поддомен через Caddy тем же способом, что и основное приложение. Для авторизации импортера в основном Firefly III нужен Personal Access Token — он создаётся в Settings → Profile → OAuth → Personal Access Tokens.

Российские банки в большинстве своём не поддерживают формат CAMT.053, но почти все дают выгрузку в CSV или Excel из личного кабинета — под неё в Data Importer настраивается кастомный маппинг колонок (дата, сумма, описание, счёт).

Бэкапы и обновления

Firefly III хранит всё в PostgreSQL — бэкап сводится к дампу базы. Простой скрипт для cron на хосте (не внутри контейнера):

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

docker exec firefly-iii-firefly-db-1 pg_dump -U firefly firefly \
  | gzip > "$BACKUP_DIR/firefly_${DATE}.sql.gz"

# храним последние 14 бэкапов, старое удаляем
find "$BACKUP_DIR" -name "firefly_*.sql.gz" -mtime +14 -delete
chmod +x /root/scripts/firefly-backup.sh
crontab -e
# добавить строку:
0 4 * * * /root/scripts/firefly-backup.sh

Готовые дампы имеет смысл дополнительно копировать за пределы сервера — если сам VPS выйдет из строя, локальный бэкап на нём же не поможет. Общий подход к бэкапам Docker-томов и переносу их за пределы сервера разобран в статье про бэкап Docker volume на VPS — том firefly_upload (вложения к транзакциям — сканы чеков и т.п.) стоит бэкапить тем же способом.

Обновление до новой версии:

cd ~/firefly-iii
docker compose pull
docker compose up -d

Firefly III сам прогоняет миграции базы при старте новой версии. Перед крупным мажорным обновлением (смена первой цифры версии) стоит на всякий случай снять свежий дамп вручную — так, как показано выше.

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

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

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

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

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

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

Можно ли обойтись без домена и SSL, только по IP?

Технически да, но не стоит: Firefly III передаёт логин, пароль и финансовые данные, и без HTTPS всё это идёт открытым текстом. Даже бесплатный поддомен и сертификат Let's Encrypt снимают этот риск полностью.

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

В открытой версии — один аккаунт-владелец на инстанс, но можно завести несколько "бюджетных" ролей внутри интерфейса и делиться доступом к одному логину в рамках семьи. Полноценная мультипользовательская модель с раздельными правами — коммерческая функция у сторонних форков, в базовой версии её нет.

Насколько сложен импорт из российских банков?

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

Что будет, если сервер отключат или заблокируют?

Данные останутся целы, пока цел бэкап базы данных вне сервера — поэтому регулярная выгрузка дампа за пределы VPS (в объектное хранилище, на другой сервер, локально к себе) обязательна, а не опциональна.

Нужен ли мощный сервер, если добавлять транзакции каждый день годами?

История в тысячи транзакций для PostgreSQL — незначительный объём, даже минимальная конфигурация с 1 GB RAM тянет это без проблем. Расти по ресурсам имеет смысл только если параллельно добавляете тяжёлые интеграции (свой бот с очередями, аналитику поверх API).

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

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

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