Установка Actual Budget на свой VPS через Docker
Пошаговое руководство по развертыванию Actual Budget с помощью Docker Compose. Разберем настройку HTTPS, подключение томов данных, импорт банковских выписок и создание бэкапов.
Что вы создаете
Actual Budget — это приложение для ведения бюджета методом конвертов с возможностью самостоятельного хостинга. Это стандартный выбор для тех, кто ищет альтернативу YNAB, которую можно развернуть на собственных мощностях. Сервер состоит из одного контейнера, одного тома данных и одного HTTPS-имени. Все функции, необходимые для ведения бюджета, стабильно работают на самом дешевом VPS, так как сервер в основном занимается хранением и синхронизацией файлов.
Перед началом работы важно понять архитектуру системы. Сам бюджет представляет собой базу данных SQLite, которая хранится в браузере и в каждом мобильном приложении. Сервер, который вы собираетесь установить, выступает в роли точки синхронизации: он хранит список счетов, файлы бюджета и журнал изменений, позволяющий синхронизировать данные между телефоном и ноутбуком. Именно поэтому приложение продолжает работать при недоступности сервера, а потеря сервера не приводит к потере бюджета, если хотя бы у одного клиента осталась его копия.
Зачем серверу нужен HTTPS
Actual требует использования HTTPS, и это не формальность. Браузеры предоставляют доступ к Web Crypto API — интерфейсу, который Actual использует для сквозного шифрования — только в так называемом безопасном контексте (secure context). Безопасным контекстом считается https:// или http://localhost. Если открыть приложение по адресу http://203.0.113.10:5006 в браузере на другом устройстве, эти функции будут недоступны, так как браузер не предоставит их странице. Официальные мобильные сборки также отклоняют URL сервера, использующие обычный 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 добавляет свои правила в iptables раньше, чем ufw, поэтому приложение окажется доступно из интернета даже при политике deny-all в брандмауэре. Подробности этого поведения описаны в статье почему опубликованные порты Docker обходят ufw. Привязка к loopback означает, что обращаться к приложению сможет только reverse proxy, запущенный на том же сервере.
Запустите сервис:
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 в access log 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 предложит включить сквозное шифрование. Соглашайтесь: сервер будет хранить только зашифрованные данные, что является правильным решением для финансовых сведений на арендованном оборудовании. У этого есть важная особенность: пароль шифрования никогда не передается на сервер, поэтому, если вы его потеряете, файл будет утрачен без возможности восстановления. Запишите его, прежде чем переходить к следующему экрану.
Установите начальные балансы на основе текущих данных вашего банка, а не импортируйте историю за несколько лет. Метод конвертного бюджетирования работает с деньгами, которые у вас есть сейчас, поэтому отсутствие истории никак не повлияет на результат.
Импорт транзакций
Здесь честность важнее энтузиазма, так как процесс импорта — основная причина, по которой пользователи отказываются от self-hosted систем бюджетирования.
Ручной ввод — это базовый метод, который работает всегда. Для конвертного метода бюджетирования это, по сути, ключевой момент: ввод покупки вручную заставляет вас осознать трату.
Импорт файлов справляется с большими объемами данных. 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 пересоздаёт контейнер из нового образа и подключает к нему тот же том, поэтому данные сохраняются. Обновите также клиенты. Версии сервера и приложения должны оставаться близкими. Клиент, который намного старше сервера, может отказаться синхронизироваться и вывести сообщение о несовпадении версий. Перед переходом на новую основную версию создайте резервную копию: при первом запуске выполняются миграции, а обратного пути к предыдущей версии нет. Actual не так чувствителен к плавающему тегу latest, поскольку его состояние хранится в каталоге с файлами. Для приложения с полноценной базой данных это не подходит. В материале самостоятельное размещение Chatwoot описаны закрепление тегов и дамп перед обновлением, которые требуются в таком случае.
Что может пойти не так и что вы увидите
Приложение загружается, но синхронизация не завершается. Проверьте лог доступа nginx на наличие 413. Это означает, что параметр client_max_body_size установлен слишком низко. Ошибка 502, напротив, указывает на то, что nginx работает, а контейнер — нет.
Отсутствуют параметры шифрования или мобильное приложение отклоняет URL. Страница не находится в безопасном контексте. В адресной строке будет отображаться http:// с IP-адресом или именем хоста, отличным от localhost. Исправьте сертификат, вместо того чтобы пытаться обойти проблему.
Сообщение о том, что файл бюджета несовместим с этой версией. Версии клиента и сервера разошлись. Обновите обе части до одного релиза и перезагрузите приложение.
Контейнер постоянно перезапускается. Прочитайте docker compose logs actual. Ошибка прав доступа к /data означает, что пользователь контейнера не имеет прав на запись в примонтированный каталог. Ошибка «address-in-use» означает, что порт 5006 на loopback уже занят другим процессом.
Первая загрузка кажется медленной. При открытии весь файл бюджета загружается в браузер. Это одна большая передача данных, после которой чтение происходит локально. Это не проблема производительности сервера, и увеличение объема оперативной памяти не ускорит процесс.
FAQ
Нужен ли Actual Budget HTTPS для работы?
Да, на практике нужен. Сквозное шифрование Actual использует Web Crypto API браузера, а браузеры предоставляют доступ к нему только в защищенном контексте, то есть через 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 GB оперативной памяти обеспечивают стабильную работу, а каталог данных для семейного бюджета с историей за несколько лет занимает десятки мегабайт. Нагрузка на диск зависит от ваших резервных копий и других контейнеров, а не от Actual. Если вы выбираете конфигурацию сервера для запуска более требовательных приложений, ориентируйтесь на фотосервер — он обычно определяет нижнюю границу ресурсов. Проверьте сколько оперативной памяти на самом деле нужно PhotoPrism и Immich перед выбором тарифа. Та же логика применима к медиа-стеку: план определяет транскодирование, в то время как фронтенд для браузера, такой как Halcyon, превращающий библиотеку Jellyfin в интерактивный видеомагазин 90-х, потребляет ресурсов не больше, чем Actual.