Coolify на VPS: установка своего PaaS вместо Heroku и Vercel
Coolify на VPS: установка официальным скриптом, домен с TLS для панели, деплой из GitHub, бэкапы в S3 и обновления — свой Heroku и Vercel на сервере.
Статья сверена с Coolify 4.3.23 и актуальна на сентябрь 2026 года. Ветка v4 вышла из беты только в апреле 2026-го, поэтому многие инструкции 2024–2025 годов устарели.
Что такое Coolify и когда он нужен
Coolify — open-source панель под лицензией Apache 2.0, которая превращает сервер в PaaS: по git push собирает образ, запускает контейнер, выпускает сертификат Let's Encrypt и направляет домен на приложение. В комплекте базы данных, бэкапы, превью-деплои и каталог из трёхсот с лишним сервисов, среди них n8n, Uptime Kuma и Forgejo.
Внутри обычный Docker: панель, её PostgreSQL, Redis и сервис живых обновлений работают в контейнерах, а на каждом сервере с приложениями стоит прокси coolify-proxy на Traefik или Caddy. Серверами, включая собственный, Coolify управляет по SSH.
- Подходит для нескольких приложений и баз на одном-двух серверах, когда нужны деплой по push, превью и общий интерфейс вместо SSH.
- Проще без Coolify, если приложение одно и меняется редко: хватит Docker Compose и деплоя из Git.
- Проще без Coolify, если инфраструктура должна жить в git: настройки Coolify хранятся в её базе, а у Kamal 2 или compose-файлов — в репозитории.
Сколько ресурсов нужно
Официальный минимум — 2 ядра, 2 ГБ памяти и 10 ГБ диска. Сама панель лёгкая: в замере на 4.3.23 её контейнеры в простое заняли около 300 МБ, но на сервере с 1 ГБ сборка небольшого Node-приложения забрала почти всю память и больше гигабайта swap.
- 2 vCPU и 4 ГБ — панель, база и несколько лёгких сервисов, сборки по одной.
- 4 vCPU и 8 ГБ — несколько приложений на Node.js или Python с PostgreSQL и сборками на месте.
- Диск от 40 ГБ: образы, кэш сборок и локальные бэкапы растут быстрее данных.
Главный потребитель CPU и памяти — сборки. В одном из issues пересборка Next.js заняла 3,6 ГБ памяти и повесила панель на сервере с 8 ГБ без swap. Лимиты ресурсов приложения на сборку не действуют, только на запущенный контейнер. На небольшом сервере поставьте Number of concurrent builds в Configuration → Advanced сервера равным 1 вместо 2, добавьте swap, а частые сборки вынесите с продакшена (шаг 10).
В пакет ForestsNet Cloud входит только исходящий трафик: docker pull, git clone и загрузка зависимостей при сборке не считаются, а исходящий — это ответы приложений, выгрузка бэкапов и push образов с build-сервера. Другие задачи разработчика — в обзоре VPS.
Что понадобится
- VPS с Ubuntu 24.04 или 22.04 LTS либо Debian 12 без своего веб-сервера и других Docker-проектов: порты 80 и 443 займёт прокси, а очистка Coolify удаляет чужие образы.
- Вход по SSH под root по ключу: из статьи «Усиление SSH» подходит
PermitRootLogin prohibit-password, но неno. - Домен с A-записями на IP сервера:
coolify.example.comдля панели и*.apps.example.comдля приложений, см. статьи о привязке домена и о DNS-записях. - Репозиторий на GitHub и S3-совместимое хранилище вне сервера.
Шаг 1. Подготовьте сервер
Обновите систему по чеклисту базовой защиты. При 4 ГБ памяти и меньше добавьте swap: сборку он не ускорит, но поможет пережить её пик.
apt update && apt -y upgrade
fallocate -l 4G /swapfile && chmod 600 /swapfile
mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstabШаг 2. Установите Coolify официальным скриптом
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bashСкрипт ставит Docker Engine через get.docker.com (Docker из snap не поддерживается), пишет в /etc/docker/daemon.json ротацию логов и пул адресов, создаёт /data/coolify с секретами в /data/coolify/source/.env, добавляет свой SSH-ключ в authorized_keys root и запускает контейнеры.
Лучше сразу закрепить версию и выключить автообновление (почему — в разделе про обновления):
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | AUTOUPDATE=false bash -s 4.3.23Сохраните /data/coolify/source/.env вне сервера: APP_KEY из него шифрует ключи и пароли в базе Coolify, и без него бэкап панели бесполезен.
Шаг 3. Создайте администратора и переведите панель на домен
Откройте http://IP:8000 и сразу зарегистрируйтесь: первый пользователь получает root-доступ к серверу, после этого регистрация закрывается. До этого страницу может занять кто угодно.
Включите 2FA в Profile, затем в Settings → Configuration → General впишите в URL адрес https://coolify.example.com. Coolify проверит DNS, прокси выпустит сертификат. Убедитесь, что по HTTPS работают панель, живые логи деплоя и терминал. Кириллические домены вводите в Punycode, вида xn--....
Шаг 4. Закройте порты 8000, 6001 и 6002
Через ufw их не закрыть: Docker публикует порты своими правилами iptables в обход него, подробнее — в статье о файрволе ufw. Официальный способ — привязать порты к 127.0.0.1 в docker-compose.custom.yml, который обновления не трогают:
cat > /data/coolify/source/docker-compose.custom.yml <<'EOF'
services:
coolify:
ports: !override
- "127.0.0.1:${APP_PORT:-8000}:8080"
soketi:
ports: !override
- "127.0.0.1:${SOKETI_PORT:-6001}:6001"
- "127.0.0.1:6002:6002"
EOF
cd /data/coolify/source
docker compose --env-file .env -f docker-compose.yml -f docker-compose.prod.yml \
-f docker-compose.custom.yml config -q && echo OK
curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh | bash -s 4.3.23Последняя команда перезапускает Coolify с новым файлом, подставьте в неё свою версию. С другой машины curl -m 5 http://IP:8000 отвечать больше не должен.
Шаг 5. Настройте wildcard-домен для приложений
В Servers → localhost → General укажите Wildcard Domain https://apps.example.com: кнопка Generate Domain будет выдавать приложениям адреса https://<id>.apps.example.com, а свой домен вписывается в Domains приложения.
Каждый поддомен получает свой сертификат, а Let's Encrypt выдаёт не больше 50 сертификатов на домен за 7 дней. При десятках приложений и превью выпустите один wildcard-сертификат через DNS-01: в Servers → Proxy → Configuration замените флаги httpchallenge на dnschallenge с токеном DNS-провайдера и добавьте роутер для *.apps.example.com в Dynamic Configurations.
Адреса sslip.io, которые Coolify генерирует без wildcard-домена, годятся только для проверки по HTTP. Для TLS нужен свой домен: на серверах ForestsNet Cloud домен и сертификат должны принадлежать вам.
Шаг 6. Подключите GitHub
Подключайте GitHub после перехода на домен: GitHub App запоминает адрес вебхуков при создании, и приложение, созданное по http://IP:8000, после закрытия порта молча перестанет запускать деплой.
В Sources → + Add выберите GitHub App, Automated Installation и endpoint https://coolify.example.com. Оставьте Preview Deployments, если нужны превью, и дайте приложению доступ только к нужным репозиториям.
Шаг 7. Разверните приложение
В проекте нажмите + New → Private Repository (with GitHub App) и выберите сервер, репозиторий, ветку и Build Pack.
Способ сборки
- Nixpacks сам определяет язык — удобно для старта, но Railway его больше не развивает.
- Railpack — преемник Nixpacks, в Coolify с 4.1 в статусе beta; перед переходом сравните образы.
- Dockerfile — предсказуемый выбор для продакшена: тот же образ, что локально и в CI.
- Docker Compose — для нескольких сервисов, но без rolling updates и build-сервера, а health checks задаются в compose-файле.
- Static раздаёт готовые файлы через nginx, Docker Image разворачивает образ из registry без сборки.
Порт и адрес
Ports Exposes — порт внутри контейнера, на первый из них прокси шлёт трафик домена; домен вида https://app.example.com:3000 ведёт на порт 3000 и наружу ничего не открывает. Приложение должно слушать 0.0.0.0, иначе будет 502. Port Mappings для веб-приложений не используйте: такой порт открыт в интернет в обход ufw и отключает rolling updates.
Переменные окружения
У переменной два независимых флажка, Build Variable и Runtime Variable, по умолчанию включены оба. Секретам, нужным только в работе, снимите Build Variable: аргументы сборки остаются в метаданных образа. А NEXT_PUBLIC_* и VITE_* вшиваются при сборке, и после их изменения нужен новый деплой, а не перезапуск.
Health check
В Configuration → Healthcheck задайте проверку вроде GET /health. Она выполняется внутри контейнера через curl или wget, которых часто нет в образах на Alpine и distroless. Поля Return Code и Response Text не сравниваются, важен только код выхода.
Без проверки rolling update переключит трафик сразу после старта контейнера, даже если приложение ещё не поднялось. С проверкой старый контейнер работает, пока новый не станет healthy; на завершение по SIGTERM даётся 30 секунд.
Шаг 8. Базы данных и бэкапы
+ New → Database создаёт PostgreSQL, MySQL, MariaDB, MongoDB, Redis, KeyDB, Dragonfly или ClickHouse. Приложение ходит к базе по внутреннему адресу в сети Docker, публичный порт не нужен. Об устройстве СУБД — в статьях про PostgreSQL и Redis.
Расписание и S3
Добавьте бакет в S3 Storages и проверьте подключение, затем в базе откройте Backups → + Add: расписание cron, S3 и сроки хранения, отдельные для локальных копий и S3. Встроенные бэкапы есть у PostgreSQL, MySQL, MariaDB, MongoDB и ClickHouse, но не у Redis, KeyDB и Dragonfly. Остановленную базу Coolify пропускает.
Зелёному статусу не верьте на слово: в issues описаны бакеты, пустые неделями при письмах об успехе, а после обновления до 4.1.2 бэкап самой панели молча перестал запускаться. Оба бага исправлены, но бакет проверяйте сами.
С версии 4.3 бэкапятся и тома — архивами tar.gz, но без кнопки восстановления, а архив тома под записью бывает несогласованным.
Проверьте восстановление
Раз в месяц создайте временную базу той же версии, залейте в неё свежий дамп через Configuration → Import Backup и проверьте на ней приложение. Ручные дампы — в статье о бэкапах баз данных.
Бэкап самой Coolify
Проекты, переменные и ключи живут в coolify-db, её ежедневный бэкап включается в Settings → Backup. В S3 уходит только дамп, а для восстановления на новом сервере нужны ещё APP_KEY из .env и каталог /data/coolify/ssh/keys — их копируйте отдельно, например через restic.
Шаг 9. Включите превью-деплои
Превью включаются в Configuration → Advanced: на каждый pull request Coolify разворачивает копию и удаляет её после закрытия PR. Адрес задаёт Preview URL Template, по умолчанию {{pr_id}}.{{domain}}: PR №42 приложения app.example.com получит 42.app.example.com, и нужна запись *.app.example.com. Удобнее держать все превью под одним доменом — шаблон {{pr_id}}.preview.example.com и wildcard-сертификат из шага 5.
- Каждое превью — ещё одна сборка и ещё один контейнер, закладывайте ресурсы.
- Дайте превью свои переменные и отдельную базу: код из PR выполняется на вашем сервере.
- Не включайте Allow Public PR Deployments, иначе превью запустит PR из любого форка.
Шаг 10. Вынесите сборки с продакшен-сервера
Пора, если деплой тормозит продакшен или заканчивается OOM.
GitHub Actions. Workflow собирает образ и кладёт его в GHCR, а Coolify разворачивает приложение типа Docker Image по вызову API. Включите API Access в Settings → Configuration → Advanced, создайте в Keys & Tokens токен с правом deploy и вызывайте вебхук последним шагом, после тестов. Собирать можно и на своём self-hosted runner.
curl --fail -X POST "https://coolify.example.com/api/v1/deploy?uuid=<uuid>&force=false" \
-H "Authorization: Bearer $COOLIFY_TOKEN"Build-сервер. Чистый сервер добавляется в Servers с отметкой Use it as a build server? и не может запускать приложения. На нём нужен docker login в registry, а в приложении — поле Docker Image и Use a Build Server?; для приватного registry залогиньтесь и на продакшене. Архитектура серверов должна совпадать, Compose-приложения режим не поддерживают. Если build-сервер недоступен, Coolify соберёт образ на продакшене, в логе будет «No suitable build server found».
Несколько серверов. У каждого сервера свой прокси, и DNS приложения должен вести на его сервер. Одно приложение можно развернуть на нескольких серверах через registry и внешний балансировщик, но не с постоянными томами и не в Compose. Docker Swarm в Coolify устарел и уйдёт в v5.
Обновления и безопасность
Обновления
Автообновление после установки включено и срабатывает каждую ночь в 00:00, когда новые образы тянут все инстансы разом: в одном из issues обновление 37 ночей подряд упиралось в лимит registry, а в логе при этом значился успех. Выключите автообновление в Settings → Configuration → Updates и обновляйтесь вручную: release notes, бэкап инстанса, ни одного идущего деплоя, затем кнопка в панели или скрипт с явной версией:
curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh | bash -s 4.3.23Без версии скрипт запишет в .env значение latest, и проверка обновлений сломается. Откат — тем же скриптом со старой версией, если новая не меняла схему базы, иначе — бэкап инстанса.
Что ломалось в 2026 году:
- 4.2–4.3: API деплоя принимает только POST, старые вебхуки с GET получают 405; роль Member стала только для чтения; у compose-сервисов с точками и дефисами в имени сменились имена роутеров Traefik.
- Патч-версии 4.3.19 и 4.3.22: Sentinel стал обязательным, из интерфейса и API убрали host-path у томов.
- Docker 29 при старом Traefik: сайты отвечают «No available server», в логах прокси
client version 1.24 is too old. Прокси Coolify сама не обновляет — поменяйте образ на Traefik 3.6.1 или новее в Servers → Proxy до обновления Docker.
Безопасность
Coolify хранит SSH-ключи с root-доступом ко всем подключённым серверам, и взлом панели — это взлом всей инфраструктуры. За 2025–2026 годы для неё опубликовали 70 уязвимостей, 21 критическую, в основном инъекции команд, дававшие пользователю панели root на серверах. В январе 2026 года Censys насчитал около 52 тысяч панелей в открытом интернете. Почти всё закрыли ещё до 4.0.0, но раскрывали уязвимости через 2–5 месяцев после исправления, так что отставать от релизов опасно.
Минимум:
- порты 8000, 6001 и 6002 закрыты, панель только по HTTPS, у всех аккаунтов 2FA;
- в команде только те, кому вы доверили бы root; API выключен или ограничен токенами с минимальными правами и Allowed IPs;
- у баз нет публичных портов;
- исправления безопасности ставятся за пару дней, релизы и advisories — в подписке;
- SSH закрыт по чеклисту и fail2ban, а новый порт SSH прописан и в настройках сервера в Coolify.
Сервисы из каталога тоже нужно обновлять: у автора статьи, переведённой на Хабре, Umami десять дней майнил Monero через уязвимость Next.js, хотя исправление вышло за неделю до взлома.
Dokploy как альтернатива
Dokploy — ближайший аналог: панель поверх Docker и Traefik с базами, бэкапами в S3 и превью. Требует от 2 ГБ памяти и 30 ГБ диска, занимает порты 80, 443 и 3000:
curl -sSL https://dokploy.com/install.sh | sh- Swarm в основе: установщик всегда инициализирует Docker Swarm, приложения работают как сервисы с репликами.
- Compose в центре: основной сценарий — compose-проекты и стеки.
- Версия 0.x: актуальна 0.30.8, за 2025–2026 годы — 60 security advisories, 34 критических, так что ниже 0.29.13 не оставайтесь. SSO и аудит — по коммерческой лицензии.
- Порт 3000 после настройки домена закрывают командой
docker service update --publish-rm "published=3000,target=3000,mode=host" dokploy, а порты Swarm 2377, 7946 и 4789 — файрволом.
Dokploy удобнее, когда нужны реплики на нескольких нодах и Compose как основной формат, Coolify — когда важнее стабильная ветка 4.x, чистая Apache 2.0 и rolling updates без Swarm.
Диагностика
- Панель не открывается по домену — не обновился DNS, закрыт порт 80 или нет сертификата. Зайдите через SSH-туннель и смотрите Servers → Proxy → Logs.
- 502 Bad Gateway — приложение слушает
127.0.0.1или порт не совпадает с Ports Exposes. - 503 «No available server» — контейнер unhealthy (в образе нет
curlилиwget, проверка смотрит не на тот порт) или старый Traefik после обновления Docker. - 504 на больших загрузках и долгих запросах — у Traefik таймаут чтения 60 секунд, его поднимают в конфигурации прокси.
- Сертификат TRAEFIK DEFAULT CERT — Let's Encrypt не прошёл проверку: закрыт порт 80, домен проксирует Cloudflare, AAAA-запись ведёт в нерабочий IPv6 или сработал лимит (ошибка 429 в логах прокси).
- Бесконечный редирект за Cloudflare — режим SSL Flexible вместо Full (strict), см. статью «Cloudflare перед VPS».
- Сервер замирает при деплое — сборка съела память и CPU, лимиты на неё не действуют: одна сборка за раз, swap или build-сервер. Разбор нагрузки — в статье «Высокая нагрузка на сервер».
- Push не запускает деплой — GitHub App шлёт вебхуки на старый адрес. Проверьте Recent Deliveries на GitHub и смените Webhook URL на
https://coolify.example.com/webhooks/source/github/events. - Деплой падает с «no space left on device» — диск заняли образы и кэш сборок. Включите Servers → Docker Cleanup (по умолчанию раз в сутки или при заполнении диска на 80%), но не Delete Unused Volumes: в неиспользуемых томах бывают данные. Остальное — в статье «Закончилось место на диске».
Источники
- Документация Coolify: установка, файрвол, домены, wildcard-сертификаты, health checks, бэкапы баз, бэкап инстанса, build-серверы, обновление, модель безопасности
- GitHub Coolify: install.sh, релизы, security advisories, CVE-2026-86117
- Issues Coolify: сборка Next.js, пустой S3, бэкап coolify-db, автообновление, install.sh, Docker 29 и Traefik
- Замер Coolify на 1 ГБ, The Hacker News об уязвимостях, лимиты Let's Encrypt
- Хабр: Coolify на своём VPS, майнер в Umami
- Dokploy: установка, GitHub