Установка Actual Budget на VPS через Docker Compose
Пошаговое руководство по развертыванию Actual Budget на собственном сервере. Вы настроите Docker Compose, настроите HTTPS для Web Crypto API и обеспечите сохранность данных.
Что вы создаете
Actual Budget — это приложение для ведения бюджета методом конвертов с возможностью самостоятельного размещения. Это стандартное решение для тех, кто ищет альтернативу YNAB с возможностью хостинга на собственном оборудовании. Сервер представляет собой один контейнер, один том данных и один HTTPS-адрес. Все функции, необходимые для ведения бюджета, стабильно работают на самом бюджетном VPS, так как сервер в основном занимается хранением и синхронизацией файлов.
Перед началом работы важно понять архитектуру системы. Сам бюджет представляет собой базу данных SQLite, которая хранится в браузере и в каждом мобильном приложении. Сервер, который вы собираетесь установить, является точкой синхронизации: он хранит список счетов, файлы бюджета и журнал изменений, обеспечивающий согласованность данных между телефоном и ноутбуком. Именно поэтому приложение продолжает работать при недоступности сервера, а потеря сервера не приводит к потере бюджета, если хотя бы у одного клиента осталась его копия.
Зачем серверу нужен HTTPS
Actual требует использования HTTPS, и это не формальность. Браузеры предоставляют доступ к Web Crypto API — интерфейсу, который Actual использует для сквозного шифрования — только в так называемом безопасном контексте (secure context). Безопасный контекст — это https:// или http://localhost. Если открыть приложение по адресу http://203.0.113.10:5006 в браузере на другом устройстве, эти функции будут недоступны, так как браузер не предоставит их странице. Официальные мобильные сборки также отклоняют подключение к серверу по протоколу http://.
Существует два рабочих варианта настройки. Первый — установить настоящий сертификат для доменного имени перед контейнером; именно этот способ описан в данном руководстве. Второй — использовать самоподписанный сертификат с помощью ACTUAL_HTTPS_KEY и ACTUAL_HTTPS_CERT, как указано в документации проекта, и принимать предупреждение браузера на каждом устройстве. Получение бесплатного сертификата от Let's Encrypt занимает пять минут, поэтому рекомендуется выбрать первый вариант.
Установка Actual Budget с помощью Docker Compose
Если сервер новый, сначала установите Docker. Если синтаксис файлов Compose вам в новинку, руководство Основы Docker Compose для VPS содержит описание полей, используемых ниже.
sudo install -d -m 755 /opt/actual
sudo install -d -m 700 /opt/actual/dataСоздайте файл /opt/actual/docker-compose.yml:
services:
actual:
image: actualbudget/actual-server:latest
container_name: actual
restart: unless-stopped
ports:
- '127.0.0.1:5006:5006'
volumes:
- ./data:/dataВ этом файле важны три детали.
Используется образ actualbudget/actual-server:latest, опубликованный проектом в Docker Hub и зеркалируемый в ghcr.io/actualbudget/actual. Для маломощных устройств предусмотрен тег latest-alpine.
Контейнер записывает все данные в каталог /data. Внутри него находятся server-files, где хранятся account.sqlite с вашими данными для входа и токенами сессий, а также user-files, где хранятся сами файлы бюджета. Обязательно смонтируйте этот путь, иначе при выполнении docker compose pull ваш бюджет будет удален. Вы можете изменить расположение с помощью ACTUAL_DATA_DIR, но значения по умолчанию достаточно.
Порт опубликован только на 127.0.0.1. Обычная запись 5006:5006 открывает доступ через все сетевые интерфейсы, а Docker создает свои правила раньше правил ufw, поэтому приложение окажется доступным из интернета даже при политике запрета по умолчанию. Подробнее об этой особенности рассказано в статье почему опубликованные порты Docker обходят ufw. Привязка к loopback означает, что обращаться к приложению сможет только обратный прокси-сервер, запущенный на том же узле.
Запустите контейнер:
cd /opt/actual
docker compose up --detach
docker compose logs -f actualЛог стабилизируется, когда сервер сообщит о прослушивании порта 5006. Проверьте работу локально, прежде чем настраивать DNS:
curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:5006/Код 200 означает, что приложение работает. curl: (7) Failed to connect означает, что контейнер не запущен, а docker compose ps покажет, что он завершил работу. Чаще всего это происходит из-за проблем с правами доступа к смонтированному тому, что будет видно по строке EACCES в логе.
Настройка сертификата и доменного имени
Направьте A-запись на ваш VPS, budget.example.com, и дождитесь завершения разрешения DNS. Затем установите nginx и выпустите сертификат. Руководство Certbot в Ubuntu 24.04 с nginx содержит подробную информацию о выпуске и таймере автоматического обновления.
Блок проксирования:
server {
listen 443 ssl;
http2 on;
server_name budget.example.com;
ssl_certificate /etc/letsencrypt/live/budget.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/budget.example.com/privkey.pem;
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:5006;
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;
}
}client_max_body_size — это параметр, который часто забывают настроить. Файл бюджета передается целиком при полной синхронизации. По умолчанию nginx ограничивает тело запроса 1 МБ, поэтому при превышении этого размера синхронизация завершается с ошибкой 413 Request Entity Too Large в журнале доступа nginx, а приложение отображает общую ошибку синхронизации. У сервера есть собственные ограничения: ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB по умолчанию равно 20, а ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB — 50, поэтому установите лимит в nginx выше того значения, которое применимо к вашей конфигурации.
Перезагрузите конфигурацию и проверьте работу:
sudo nginx -t && sudo systemctl reload nginx
curl -fsS -o /dev/null -w '%{http_code}\n' https://budget.example.com/Первый запуск: пароль и первый файл бюджета
Откройте https://budget.example.com в браузере. На первом экране потребуется установить пароль сервера. Этот единственный пароль защищает весь сервер, поэтому создайте длинный случайный пароль и сохраните его в надежном месте, например, в собственном менеджере паролей Vaultwarden. Создавать учетные записи пользователей не нужно. Сервер Actual спроектирован с использованием одного пароля, поэтому предоставление доступа к бюджету означает передачу этого пароля.
Затем создайте файл бюджета. Actual предложит включить сквозное шифрование. Соглашайтесь: сервер будет хранить только зашифрованные данные, что является правильным решением для финансовых сведений на арендованном оборудовании. Учитывайте риски: пароль шифрования не передается на сервер, поэтому в случае его потери файл будет безвозвратно утерян, а сбросить его невозможно. Запишите пароль, прежде чем переходить к следующему экрану.
Установите начальные балансы на основе текущих данных вашего банка, вместо импорта истории за несколько лет. Метод конвертного бюджетирования работает с деньгами, которые у вас есть сейчас, поэтому отсутствие истории не создает никаких неудобств.
Импорт транзакций
Здесь честность важнее энтузиазма, так как процесс импорта — основная причина, по которой пользователи отказываются от самостоятельного хостинга систем бюджетирования.
Ручной ввод — это базовый метод, который работает всегда. Для метода конвертов это, по сути, и есть главная цель, так как ввод каждой покупки заставляет вас обращать на неё внимание.
Импорт файлов справляется с большими объёмами данных. Actual считывает форматы CSV, QIF, OFX и QFX, а каждый банк поддерживает как минимум один из них. Выполняйте импорт для каждого счёта на экране счёта, один раз настройте соответствие столбцов, и Actual запомнит эту схему для данного счёта.
Существует автоматическая синхронизация с банками, для которой требуется сторонний сервис, так как сервер не может взаимодействовать с банками напрямую. Actual поддерживает SimpleFIN Bridge для банков Северной Америки, Enable Banking для Европы, Akahu для Новой Зеландии и Pluggy.ai для Бразилии. GoCardless по-прежнему поддерживается, но новые аккаунты не принимает. Вы самостоятельно регистрируетесь у провайдера, создаёте учётные данные и добавляете их на сервер. По состоянию на июль 2026 года SimpleFIN Bridge стоит 15 долларов США в год за подключение до 25 финансовых учреждений, у остальных сервисов другие тарифы.
Перед использованием этой функции примите два ограничения. Учётные данные API хранятся на сервере и не защищены сквозным шифрованием, так как сервер должен использовать их для работы. Actual не выполняет автоматический опрос: синхронизация запускается нажатием кнопки, а не фоновой задачей.
Резервное копирование, так как это просто файлы
Все важные данные находятся в /opt/actual/data. Нет необходимости в этапе экспорта или создании дампа базы данных с помощью скриптов.
Единственная сложность — SQLite. Копирование account.sqlite во время записи данных сервером может привести к захвату незавершенной транзакции, и вы узнаете об этом только при попытке восстановления. Остановите контейнер на несколько секунд, пока выполняется копирование:
cd /opt/actual
docker compose stop
restic -r sftp:backup@backup.example.com:/srv/restic backup /opt/actual/data
docker compose startНастройте расписание для этой задачи, используя подход из резервного копирования restic на VPS, где описаны настройка репозитория, хранение и процедура восстановления. Обязательно протестируйте восстановление. Резервная копия, которую вы никогда не восстанавливали, — это лишь предположение.
Клиентские резервные копии Actual — это отдельный механизм, о котором стоит знать. Браузер хранит недавние копии файла бюджета, доступные через меню файла. Это позволяет решить проблему «я случайно удалил категорию», не затрагивая сервер.
Обновление сервера
cd /opt/actual
docker compose pull
docker compose up --detachCompose пересоздает контейнер из нового образа и повторно подключает тот же том, поэтому данные сохраняются. Обновите также клиенты. Ожидается, что версии сервера и приложения будут близки; клиент, версия которого значительно старше версии сервера, может отказаться от синхронизации, выдав сообщение о несовпадении версий. Перед переходом на мажорную версию сделайте резервную копию, так как миграции выполняются при первом запуске, а путь для отката на предыдущую версию отсутствует.
Что может сломаться и что вы увидите
Приложение загружается, но синхронизация не завершается. Проверьте журнал доступа nginx на наличие 413. Это означает, что значение client_max_body_size слишком мало. Ошибка 502 указывает на то, что nginx работает, а контейнер — нет.
Параметры шифрования отсутствуют или мобильное приложение отклоняет URL. Страница открыта не в безопасном контексте. В адресной строке будет отображаться http:// с IP-адресом или именем хоста, отличным от localhost. Исправьте сертификат, вместо того чтобы пытаться обойти проблему.
Сообщение о том, что файл бюджета несовместим с этой версией. Версии клиента и сервера разошлись. Обновите обе части до одного релиза и перезагрузите приложение.
Контейнер постоянно перезапускается. Прочитайте docker compose logs actual. Ошибка прав доступа к /data означает, что пользователь контейнера не имеет прав на запись в смонтированную директорию. Ошибка «адрес уже используется» означает, что порт 5006 на интерфейсе loopback уже занят другим процессом.
Первая загрузка кажется медленной. При открытии весь файл бюджета загружается в браузер. Это одна большая передача данных, после которой чтение происходит локально. Это не проблема производительности сервера, и увеличение объема оперативной памяти не ускорит процесс.
FAQ
Нужно ли Actual Budget использовать HTTPS для работы?
Да, на практике это необходимо. Сквозное шифрование Actual использует API Web Crypto браузера, а браузеры предоставляют к нему доступ только в безопасном контексте, то есть https:// или http://localhost. При использовании обычного HTTP с другого компьютера эти функции недоступны, а официальные мобильные приложения отклоняют URL сервера без HTTPS. Используйте сертификат Let's Encrypt для реального доменного имени или самоподписанный сертификат с ACTUAL_HTTPS_KEY и ACTUAL_HTTPS_CERT, если вы работаете только в настольном браузере.
Может ли Actual импортировать банковские транзакции автоматически?
Только через сторонний сервис, на который вы подписываетесь самостоятельно: SimpleFIN Bridge в Северной Америке, Enable Banking в Европе, Akahu в Новой Зеландии или Pluggy.ai в Бразилии. GoCardless поддерживается, но новые аккаунты не принимает. Эти учетные данные API хранятся на вашем сервере и не защищены сквозным шифрованием. Синхронизация также выполняется вручную: вы нажимаете кнопку, фоновый опрос не производится. Для импорта файлов CSV, QIF, OFX и QFX сторонние сервисы не требуются.
Что именно нужно копировать для резервной копии?
Примонтированный каталог данных, который в этом руководстве обозначен как /opt/actual/data. Он содержит server-files/account.sqlite с данными для входа и сессиями, а также user-files с файлами бюджета. Остановите контейнер перед копированием, так как при копировании активной базы данных SQLite можно получить поврежденный файл из-за незавершенной записи. Никакие другие данные на сервере не сохраняются.
Что произойдет, если я потеряю пароль шифрования?
Файл восстановить невозможно. Пароль никогда не передается на сервер, в этом и заключается смысл сквозного шифрования, поэтому функции сброса или технической поддержки не существует. Сохраните пароль в менеджере паролей сразу после создания файла и держите копию в месте, не зависящем от этого сервера.
Какие требования к серверу у Actual Budget?
Минимальные. Контейнер отдает статические ресурсы и файлы, а расчеты бюджета выполняются в браузере. Одно общее ядро vCPU и 1 ГБ оперативной памяти обеспечивают стабильную работу, а каталог данных для семейного бюджета с историей за несколько лет занимает всего несколько десятков мегабайт. Нагрузка на диск зависит от ваших резервных копий и других контейнеров, а не от Actual.