Tropic Host

Установка и настройка Coolify на VPS: self-hosted альтернатива Vercel, Netlify и Heroku на своем сервере

32 мин чтения
Tropic

Краткий вывод: Миграция на связку Coolify + KVM VPS сокращает инфраструктурные издержки в 4–12 раз по сравнению с Vercel Pro/Enterprise и Heroku Dynos, полностью ликвидируя лимит serverless execution timeout (10–60 секунд), наценку на egress-трафик ($0.15–0.40 за GB) и задержки cold start. За счет прямого контроля над cgroups v2 ядра Linux, сетевым стеком хоста и локального размещения СУБД (PostgreSQL/Redis на loopback-интерфейсе) задержка p99 снижается до значений <10 мс без потери удобства Git push-to-deploy.


Содержание

  1. Аппаратные требования и сайзинг: Почему Coolify на KVM VPS заменяет Vercel и Heroku в 2026 году
  2. Архитектура Coolify: как устроен self-hosted PaaS под капотом
  3. Требования к серверу: сайзинг CPU, RAM и дисков NVMe под билд и рантайм
  4. Сравнительная матрица: Coolify vs Vercel vs Dokku vs CapRover vs Portainer
  5. Пошаговая установка Coolify на чистый сервер Ubuntu 24.04 LTS
  6. Деплой первого проекта из GitHub: Next.js, Node.js или Python приложение
  7. Развертывание баз данных в один клик: PostgreSQL, Redis и автоматические бэкапы
  8. Оптимизация производительности хоста: swapfile на NVMe, prune старых образов и лимиты
  9. Часто задаваемые вопросы (FAQ)

Аппаратные требования и сайзинг: Почему Coolify на KVM VPS заменяет Vercel и Heroku в 2026 году


Архитектурный слом: почему serverless-платформы стали нерентабельны

Популярность Vercel и Heroku держалась на абстракции от инфраструктуры: разработчик пушит код в репозиторий, платформа берет на себя CI/CD, маршрутизацию, выпуск TLS-сертификатов и масштабирование. Однако к 2026 году архитектурный налог этой модели стал блокирующим для растущих сервисов:

  1. Жесткий потолок Execution Timeout: Serverless-функции Vercel принудительно обрывают соединение через 10 секунд (Hobby) или 60–300 секунд (Pro/Enterprise). Для задач потоковой генерации токенов LLM (Server-Sent Events), сборки тяжелых PDF, экспорта данных и фоновых воркеров приходится подключать сторонние оркестраторы (Upstash, AWS SQS, Inngest, Temporal). В Coolify на KVM процесс приложения является долгоживущим демоном внутри контейнера: worker крутится в runtime неограниченное время без наценки за CPU-минуты.
  2. Проблема stateful-соединений и WebSockets: Serverless-архитектура принципиально stateless. Удержание 10 000 постоянных WebSocket-соединений на Vercel либо невозможно архитектурно, либо требует внешних брокеров (Pusher, Ably) с драконовской тарификацией за миллион сообщений. На обычном KVM инстансе за $15–30 приложение на Go/Fastify/Node.js удерживает сотни тысяч активных сокетов через системный вызов ядра epoll, упираясь лишь в лимиты файловых дескрипторов nofile.
  3. Холодный старт и сетевой оверхед к БД: Serverless-лямбды поднимаются «с нуля» при пиковом входящем трафике (cold start 250–1200 мс). Каждая новая лямбда инициирует отдельный TCP-хэндшейк и TLS renegotiation к удаленной базе данных, моментально исчерпывая лимит max_connections СУБД и требуя внешнего пулера вроде PgBouncer. Размещение контейнеров приложения и PostgreSQL внутри одной изолированной Docker bridge-сети на KVM снижает latency обращения к базе данных до <0.2 мс против 20–45 мс между дата-центрами Vercel (AWS us-east-1) и управляемой БД на Neon/Supabase.

Сравнительный анализ: Coolify на KVM против Vercel и Heroku

В таблице сопоставлены ключевые метрики производительности, экономики и инфраструктурного контроля платформ.

Параметр / Метрика Vercel (Pro / Enterprise) Heroku (Standard / Performance Dynos) Coolify на KVM VPS
Базовая стоимость инфраструктуры От $20/мес за место + $40–300+ за перерасход ресурсов $25–50/мес за Eco/Basic; от $250/мес за Performance-M Фиксированная: $12–40/мес (4–8 vCPU, 8–16 GB RAM, NVMe)
Egress-трафик (исходящая полоса) $0.15–0.40 за 1 GB сверх включенного лимита (1 TB) Включен в dyno, но лимитирован пропускной способностью 20–32 TB включено или честный 1 Gbps unmetered
Serverless Timeout / Время жизни процесса 10–60 сек (до 300 сек на Enterprise) 30 сек на HTTP-запрос (router timeout H12) Без ограничений: фоновые процессы, воркеры, демоны
Поддержка WebSockets и SSE Ограничена (требуются внешние сервисы шлюзов) Доступна (с таймаутом бездействия 55 сек) Нативная: постоянные сокеты через встроенный Traefik v3
Сетевая задержка к СУБД (PostgreSQL/Redis) 15–60 мс (cross-region / managed network) 2–5 мс (внутри Private Spaces Heroku) 0.05–0.2 мс (Docker bridge или UNIX-сокет на хосте)
Холодный старт (Cold Start) 250–1500 мс при масштабировании 0 мс на платных Dyno (засыпает на Eco) 0 мс: контейнеры постоянно прогреты в памяти
Контроль системных метрик и ядра Заблокирован (Black-box среда) Заблокирован (изоляция dyno) Полный: sysctl, cgroups v2, swap, OOM killer, eBPF
Вендор-лок и переносимость Критический (Vercel-специфичные API, Edge Middleware) Средний (Procfile, Buildpacks) Нулевой: чистые Dockerfile, Nixpacks или Docker Compose

Экономика self-hosted PaaS: расчет юнит-костов

Рассмотрим типичный продакшн-стек: Next.js фронтенд, Node.js/NestJS API, 2 фоновых воркера BullMQ, PostgreSQL и Redis при нагрузке 8 миллионов запросов в месяц и 2.5 TB исходящего трафика (статический контент, медиа, API payload).

  • Vercel Pro:
  • Базовая подписка (2 разработчика): $40.
  • Fast Data Transfer (1.5 TB сверх лимита 1 TB): $225.
  • Serverless Function Execution (GB-hours перерасход): ~$75.
  • Сторонний PostgreSQL (Neon/Supabase) + Redis (Upstash): ~$60.
  • Итого: ~$400 / месяц.
  • Heroku:
  • 2 × Standard 2X Dynos (API + Workers): $100.
  • Heroku Postgres (Standard-0): $50.
  • Heroku Data for Redis (Premium-0): $60.
  • Итого: ~$210 / месяц (при постоянных рисках поймать Router Error H12 при тяжелых запросах).
  • Coolify на KVM VPS:
  • Аренда KVM VPS (4 vCPU AMD EPYC, 16 GB RAM, 160 GB NVMe, порт 1 Gbps, 20 TB трафика включено): $18 / месяц.
  • Запас по вычислительным ресурсам: 60% CPU idle, потребление RAM стеком — около 4.2 GB из 16 GB доступных.
  • Итого: $18 / месяц. Чистая экономия — более $4 500 в год на одном микропроекте.

Подготовка инфраструктуры: системные требования и тюнинг KVM

Качественная coolify на vps установка и настройка невозможна без предварительного аудита железа. Перед запуском инсталлятора хост должен быть проверен на скрытый оверселлинг гипервизора.

1. Проверка CPU Steal Time (%st)

Запустите мониторинг распределения процессорного времени на пустом сервере:

vmstat 1 5

Анализируйте последнюю колонку st (CPU Steal Time). Если значение %st превышает 3–5%, хостер перегрузил физический сокет процессора шумными соседями. В таких условиях задержки p99 вашего API будут деградировать независимо от оптимизации кода. На чистом KVM параметр st равен 0.

2. Оптимизация сетевого стека и лимитов ядра

Для предотвращения сброса TCP-соединений при пиках трафика и корректной работы Docker-демона внесите параметры в /etc/sysctl.d/99-coolify-perf.conf:

# Максимальный размер очереди соединений ядра (backlog)
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 8192

# Пул динамических портов для исходящих запросов Traefik к бэкендам
net.ipv4.ip_local_port_range = 1024 65535

# Отключение медленного старта TCP после простоя
net.ipv4.tcp_slow_start_after_idle = 0

# Увеличение буферов TCP для высокоскоростного порта 1 Gbps
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

# Лимит структур сокетов в cgroups и дескрипторов файлов
fs.file-max = 2097152

# Разрешение выделения памяти для Redis (Background Save)
vm.overcommit_memory = 1

Примените параметры без перезагрузки:

sysctl --system

3. Базовый сценарий развертывания

Coolify управляет локальным Docker-демоном через системный сокет /var/run/docker.sock, автоматически разворачивая Traefik v3 в качестве обратного прокси и панели управления. Установка на чистую ОС (Ubuntu 24.04 LTS / Debian 12) выполняется одним изолированным процессом:

curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash

После завершения инициализации скрипт поднимает следующие сервисы на KVM-ноде: * coolify — бэкенд на Laravel/PHP-FPM, координирующий деплои; * coolify-realtime — сервер очередей и логов на WebSockets; * coolify-proxy — кастомизированный Traefik v3, перехватывающий 80/443 порты, автоматически генерирующий Let's Encrypt SSL-сертификаты и осуществляющий zero-downtime rolling updates при получении вебхука из GitHub/GitLab.

Вы получаете идентичный Vercel UX деплоя, но с полным контролем над процессами, изолированными политиками cgroups v2, и предсказуемой стоимостью инфраструктуры без ограничений по времени выполнения кода.

Архитектура Coolify: как устроен self-hosted PaaS под капотом

Coolify не является монолитным демоном или гипервизором. С точки зрения системной инженерии это легковесный слой оркестрации (Control Plane), развернутый непосредственно поверх хостового Linux-ядра и демона Docker Engine. Платформа трансформирует декларативные конфигурации из веб-интерфейса в низкоуровневые API-вызовы контейнеризации, манипуляции с подсистемами cgroups v2, правилами iptables и конфигурациями обратного прокси.

Когда выполняется базовая процедура — coolify на vps установка и настройка, на сервере разворачивается управляющий стек в директории /data/coolify, состоящий из пяти ключевых изолированных компонентов:

Host VPS (Linux Kernel / cgroups v2)
 ├── Ingress: Traefik (Edge Routing, ACME TLS, Docker Provider)
 ├── Core Control Plane: Laravel Engine + Horizon Queue Worker
 ├── State Storage: PostgreSQL 16 (Метаданные, аудит, схемы)
 ├── Event Broker: Redis 7 (Очереди сборки и кэш)
 └── Telemetry/Logs: Soketi / Node.js (Real-time WebSockets)

Вся координация осуществляется через локальный сокет /var/run/docker.sock. Демон Coolify монтирует сокет внутрь управляющего контейнера, получая эквивалент прав root на хосте для создания сетей, сборки образов и распределения вычислительных квот.

1. Ядро Control Plane и хранение метаданных (PostgreSQL + Redis)

Вся информация о топологии серверов, переменных окружения (.env), ключах развертывания Git, конфигурациях томов и статусах сервисов хранится в инстансе PostgreSQL. База развернута в изолированном контейнере coolify-db со смонтированным persistent volume в /data/coolify/source/db.

Асинхронные операции — опрос репозиториев, клонирование веток, запуск пайплайнов компиляции и сбор метрик телеметрии — делегированы менеджеру очередей на базе Redis и worker-процессам: * Worker Threads: Фоновые задачи разделены по приоритетам. Сборка кода изолирована от задач healthcheck-мониторинга, чтобы зависший процесс npm run build не блокировал опрос живости работающих сервисов. * Realtime Terminal: Потоковый вывод сборщика перехватывается процессом, упаковывается в WebSocket-соединения и передается в браузер инженера без записи промежуточных гигабайтных логов на диск, что сохраняет ресурс IOPS на недорогих NVMe/SSD-накопителях.

2. Сборочный конвейер: Nixpacks против Cloud Native Buildpacks

Главное инженерное отличие Coolify от сырого Docker Compose — автоматическая сборка исходного кода без обязательного наличия Dockerfile. Эту задачу решают встроенные движки:

  1. Nixpacks (по умолчанию): Утилита, разработанная на Rust. При поступлении Webhook-события от Git-репозитория Nixpacks анализирует сигнатуру файловой системы (наличие composer.json, package.json, go.mod, Cargo.toml, requirements.txt). На основе найденных манифестов движок генерирует воспроизводимый сборочный план (nixpacks plan .), выкачивает бинарные пакеты из репозитория Nixpkgs с точной фиксацией хэшей и компилирует легковесный OCI-совместимый образ.
  2. Cloud Native Buildpacks (CNB / Paketo): Альтернативный стандартизированный фреймворк, разделяющий сборку на фазы detect, analyze, build и export.
  3. Raw Dockerfile / Docker Compose: Если в корне проекта обнаружен Dockerfile, Coolify отключает эвристику анализаторов и запускает нативный вызов docker buildx build.

Сборка выполняется во временных контейнерах. Чтобы тяжелая компиляция не вызывала падение хоста по OOM (Out-Of-Memory), Coolify изолирует builder с помощью лимитов ядра через драйвер cgroups:

# Проверка действующих ограничений памяти для процесса сборки в cgroups v2
cat /sys/fs/cgroup/system.slice/docker-<CONTAINER_ID>.scope/memory.max
cat /sys/fs/cgroup/system.slice/docker-<CONTAINER_ID>.scope/memory.current

Если сервер имеет всего 2–4 ГБ RAM, а параллельная сборка на Node.js превышает порог memory.max, ядро активирует подсистему memory.high с замедлением троттлинга или вызывает oom-killer, уничтожая только сборочный контейнер без ущерба для управляющей плоскости и рабочего продакшена.

3. Сетевая топология и динамический Ingress (Traefik)

Для маршрутизации трафика Coolify использует Traefik v2/v3, запущенный в контейнере coolify-proxy. В отличие от Nginx, требующего перезагрузки конфигурации (nginx -s reload) или генерации файлов шаблонов через Lua/Consul-template, Traefik непрерывно слушает события Docker API через сокет:

# Инженерный просмотр подписки на события Docker daemon в реальном времени
docker events --filter 'type=container' --format 'Type={{.Type}} Action={{.Action}} Target={{.Actor.Attributes.name}}'

При старте нового пользовательского приложения Coolify навешивает на его контейнер специфические метки (labels):

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.app-prod.rule=Host(`api.domain.internal`)"
  - "traefik.http.routers.app-prod.entrypoints=websecure"
  - "traefik.http.routers.app-prod.tls.certresolver=letsencrypt"
  - "traefik.http.services.app-prod.loadbalancer.server.port=8080"

Сетевая безопасность реализуется за счет единой внутренней Docker bridge-сети (по умолчанию coolify): * Приложения не пробрасывают порты на внешний интерфейс хоста (отсутствует директива -p 8080:8080). Они слушают трафик исключительно на внутреннем IP-адресе виртуального сетевого моста. * Traefik находится в одной сети с приложениями и пересылает L7-трафик напрямую в виртуальный интерфейс контейнера veth*. Внешний сетевой интерфейс хоста (eth0) держит открытыми только порты 80/tcp (HTTP), 443/tcp (HTTPS) и порт SSH. * Выпуск и продление SSL-сертификатов Let's Encrypt (по протоколам ACME HTTP-01 или DNS-01 challenge) берет на себя Traefik. Приватные ключи и сертификаты автоматически сохраняются в бинарно защищенный файл /data/coolify/proxy/acme.json с правами доступа chmod 600.

4. Взаимодействие с ресурсами хоста и сетевым стеком Linux

При эксплуатации PaaS критически важно контролировать системные параметры ядра хостовой VPS:

  1. Конфликт Docker и UFW/nftables: Демон Docker при старте инжектирует собственные цепочки правил в таблицу iptables (цепочка DOCKER и PREROUTING), минуя стандартные цепочки фильтрации ufw. Публикация любого порта через веб-интерфейс Coolify в обход Traefik открывает порт наружу независимо от состояния локального фаервола. Контроль доступа должен выполняться строго через цепочку DOCKER-USER.
  2. Параметры сетевых сокетов: Для исключения потерь пакетов и скачков задержки (latency p99) при всплесках соединений ядро хоста настраивается через sysctl: bash sysctl -w net.core.somaxconn=4096 sysctl -w net.ipv4.tcp_max_syn_backlog=4096 sysctl -w vm.max_map_count=262144
  3. Метрика CPU Steal Time (%st): На виртуализированных VPS с высокой плотностью соседей показатель %st в выводе утилиты top или vmstat 1 выше 3–5% приводит к таймаутам сборщиков Nixpacks и сбоям healthcheck-проверок Traefik, что провоцирует ошибочный рестарт живых контейнеров механизмом оркестратора.

Требования к серверу: сайзинг CPU, RAM и дисков NVMe под билд и рантайм

Когда планируется coolify на vps установка и настройка, базовой архитектурной ошибкой становится расчет мощностей исключительно под рантайм-потребление контейнеров. В статичном состоянии стек из Coolify core, Traefik, PostgreSQL и двух изолированных веб-сервисов на Go или Node.js потребляет не более 1.2–1.8 GB RAM и минимальное количество процессорного времени (менее 5% vCPU).

Однако Coolify — это полноценный PaaS, берущий на себя функции локального CI/CD-пайплайна. Инфраструктура серверов под его управлением сталкивается с бимодальным распределением нагрузки: длинное плоское плато рантайма и экстремальные пики в момент компиляции артефактов через Docker BuildKit.

       CPU / RAM Usage
         ▲
         │                               [Next.js / Rust Build]
4 GB RAM │                                  ┌─────────────┐
100% CPU │                                  │  BuildKit   │
         │                                  │  Parallel   │
         │                                  │  Workers    │
1.5 GB   │ [Runtime Baseline]               │ (Peak Load) │
 5% CPU  │ ─────────────────────────────────┘             └────────────────────
         └──────────────────────────────────────────────────────────────────────►
                                                                          Time

Разделение профилей нагрузки: BuildKit vs Runtime

1. Фаза компиляции (Build Engine)

Docker BuildKit по умолчанию распределяет задачи сборки на число доступных вычислительных ядер (nproc). * Frontend-стеки (Next.js, Remix, Vite/Svelte): запуск этапа next build параллелит компиляцию бандлов через SWC/esbuild и проверку типов TypeScript (tsc). Одномоментно процесс выделяет пул воркеров по числу vCPU. Если на хосте выделено 2 vCPU, каждый воркер Node.js пытается аллоцировать до 1.5–2 GB памяти под кучу (V8 heap). При компиляции серверных компонентов Next.js суммарный скачок оперативной памяти составляет от 2.5 до 4 GB RAM при утилизации CPU ровно в 100%. * Системные языки (Rust, C++, Go): при компиляции через cargo build --release линковщик (ld, gold или lld) загружает промежуточные объектные файлы целиком в оперативную память. Недостаток 1–2 GB свободного адресного пространства на стадии финишного связывания бинарника немедленно приводит к фатальному завершению процесса сборки.

2. Фаза рантайма (Application Execution)

После упаковки в оптимизированный scratch/distroless-образ или легковесный alpine-контейнер потребление ресурсов стабилизируется. Node.js в production-режиме требует 150–350 MB RAM (в зависимости от размера кэша и наличия SSR), база данных PostgreSQL на старте забирает пул согласно директивам shared_buffers (обычно 128–512 MB), а реверс-прокси Traefik держит baseline в пределах 80–120 MB RAM даже при пропускной способности в сотни RPS.


Опасность работы без Swap и каскадные отказы OOM Killer

Попытка развернуть Coolify на инстансе без активного swap-пространства — прямая гарантия нестабильности хоста. Ядро Linux управляет нехваткой физической памяти через механизм Out-Of-Memory Killer (mm/oom_kill.c).

При компиляции тяжелого проекта аллокатор страниц ядра (page allocator) не находит свободных страниц в зоне ZONE_NORMAL. Если swap отсутствует: 1. Ядро не может сбросить в подкачку неактивные анонимные страницы (anonymous pages), занятые фоновыми сервисами. 2. Происходит мгновенный расчет очков утилизации процесса: $$\text{oom_score} = \frac{\text{resident_pages}}{\text{total_pages}} \times 1000 + \text{oom_score_adj}$$ 3. OOM Killer отправляет сигнал SIGKILL процессу с наивысшим весом. Если контейнер сборщика не был жестко ограничен лимитами cgroups v2 (memory.max), ядро уничтожает не только BuildKit, но и СУБД хоста (postgres), агент dockerd или управляющий демон самого Coolify. В выводе dmesg -T вы увидите характерный след: text [Wed Oct 02 14:22:01 2026] Out of memory: Killed process 38412 (next-server) total-vm:4194304kB, anon-rss:2945120kB [Wed Oct 02 14:22:02 2026] oom_reaper: reaped process 38412 (next-server), now anon-rss:0kB

Настройка отказоустойчивого Swap-файла

Для предотвращения каскадных сбоев необходимо инициализировать swap объемом не менее размера физической памяти хоста (для инстансов до 8 GB RAM) и настроить поведение виртуальной памяти через sysctl:

# Создание swap-файла размером 4GB с жесткими правами доступа
fallocate -l 4G /swapfile || dd if=/dev/zero of=/swapfile bs=1M count=4096
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

# Персистентность в /etc/fstab
echo '/swapfile none swap sw 0 0' >> /etc/fstab

# Тюнинг ядра для снижения агрессивности сброса в подкачку
cat <<EOF > /etc/sysctl.d/99-coolify-memory.conf
vm.swappiness = 15
vm.vfs_cache_pressure = 50
vm.overcommit_memory = 1
EOF

sysctl --system

Параметр vm.swappiness = 15 предотвращает раннее вытеснение рантайм-кода в медленный swap, задействуя подкачку исключительно как амортизационный буфер во время компиляции. vm.overcommit_memory = 1 защищает фоновые вызовы fork() при форке процессов в Redis и Node.js.


Матрица конфигураций: от Minimum до Enterprise Production

При выборе VPS критично учитывать не только объем, но и качество виртуализации. Избегайте хостингов с контейнерной виртуализацией OpenVZ/LXC — требуется исключительно честный KVM с выделенным CPU core quota. Обращайте внимание на метрику CPU Steal Time (%st в top / htop): стабильное значение выше 3% свидетельствует о критическом оверселлинге ноды хостером, что вызовет троттлинг сборщика.

Параметр спецификации Минимальный стек (Sandbox / Pet-проект) Рекомендованный стандарт (Production Base) Высоконагруженный кластер (Multi-Tenant / CI/CD)
Вычислительные ядра (vCPU) 2 ядра (KVM) 4 ядра (High-Frequency $\ge 3.4$ GHz) 8+ ядер (Dedicated / Dedicated vCPU)
Допустимый CPU Steal Time (%st) $< 5\%$ $< 1\%$ $0\%$ (изолированные ядра)
Оперативная память (RAM) 4 GB 8–16 GB 32+ GB ECC RAM
Обязательный Swap 4 GB (NVMe-backed) 4–8 GB 8 GB (в качестве safety-net)
Случайный I/O (4K IOPS) $\ge 2\,500$ IOPS $\ge 8\,000$ IOPS $\ge 25\,000$ IOPS
Дисковая задержка (p99 latency) $< 15$ ms $< 2$ ms $< 0.5$ ms
Емкость накопителя 40 GB NVMe 80–120 GB NVMe 250+ GB NVMe RAID-10
Параллельные сборки (Concurrent) 1 (строго с лимитом nproc=1) 1–2 активных пайплайна 3–5 параллельных билдов

Требования к дисковой подсистеме: NVMe, overlay2 и BuildKit Cache

Развертывание приложений на базе Coolify генерирует экстремальную нагрузку на файловую систему. Использование стандартных SATA SSD или сетевых блочных томов (Ceph, EBS) с низкими лимитами IOPS приведет к возникновению бутылочного горлышка ввода-вывода (I/O Wait).

1. Проблема транзакционного мусора при сборках

Файловая система Docker (overlay2) оперирует слоями. При установке зависимостей (npm ci, pip install, распаковка пакетов Rust) создаются и удаляются сотни тысяч микрофайлов размером менее 4 KB. Диски с низким показателем случайного чтения/записи (4K Random Write) уходят в $100\%$ утилизации дисковой очереди (%util по iostat -xz 1), блокируя ввод-вывод для СУБД. Реляционная база (PostgreSQL/MySQL) в этот момент перестает отвечать на healthcheck-запросы Traefik из-за задержек записи в WAL-лог, в результате чего прокси ошибочно снимает сервис с роутинга и выдает клиентам 502 Bad Gateway.

2. Контроль расхода дискового пространства

Минимальный объем в 40 GB обусловлен структурой хранения данных Coolify: * Дистрибутив Docker-образов самой панели управления, Traefik, локального реестра и системных баз: ~4–6 GB. * Неочищенный кэш Docker BuildKit (/var/lib/docker/buildkit): быстро разрастается до 10–15 GB за счет промежуточных stage-слоев компилятора. * Тома данных приложений (/var/lib/docker/volumes): размер определяется базой данных и пользовательскими загрузками.

Для поддержания стабильности I/O дисковый массив обязан работать с запасом не менее 25% свободного пула, предотвращая фрагментацию экстентов в файловых системах ext4 / xfs. При приближении свободного места к пороговым 10% Docker автоматически переводит внутренние реестры в режим read-only, вызывая полный паралич деплоев.

Сравнительная матрица: Coolify vs Vercel vs Dokku vs CapRover vs Portainer

Выбор слоя абстракции для деплоя — это поиск баланса между контролем над операционной системой и накладными расходами на обслуживание инфраструктуры. Проприетарные serverless-платформы изолируют разработчика от ядра Linux, но выставляют жесткие лимиты на время выполнения процессов и завышенный ценник за сетевой egress. С другой стороны, self-hosted решения требуют прямого понимания работы cgroups v2, управления сокетами демона Docker и тюнинга дискового ввода-вывода (IOPS).

Когда планируется coolify на vps установка и настройка, инженер решает задачу получения developer experience уровня Vercel без привязки к вендору и с предсказуемой стоимостью bare-metal или виртуальных мощностей. Ниже приведено детальное архитектурное сопоставление пяти ключевых платформ.


Сравнительная таблица платформ оркестрации и деплоя

Критерий Coolify (v4) Vercel Dokku CapRover Portainer CE
Базовая архитектура Self-hosted PaaS (Docker Engine + Traefik v3) Проприетарный Serverless / Edge (AWS Lambda base) Self-hosted PaaS (Docker + Herokuish/CNB + Nginx) Self-hosted PaaS (Docker Swarm + Nginx) Container Management UI (Docker / Swarm / K8s)
Интерфейс Реактивный Web UI (Live-логи, метрики, терминал) Web UI / Dashboard вендора CLI-first (Web UI только сторонние/заброшенные) Базовый Web UI Полнофункциональный Web UI для управления контейнерами
Мульти-серверность Да (Push-управление нодами через SSH-туннели) Глобальный Edge (абстрагирован от серверов) Нет (жестко single-host, multi-node не поддерживается) Да (через Docker Swarm кластер и overlay-сеть) Да (Portainer Edge Agent через gRPC/HTTPS)
Интеграция с Git GitHub Apps, GitLab, Gitea, кастомные вебхуки, авто-PR Нативная (GitHub, GitLab, Bitbucket), Instant Previews Git Push over SSH (git push dokku main) Webhooks (GitHub, GitLab, Bitbucket), CLI deploy Git Polling / Webhook на Docker Compose стеки
Билдеры артефактов Nixpacks, Cloud Native Buildpacks, Dockerfile, Compose Проприетарный Vercel Build Pipeline Herokuish, Cloud Native Buildpacks, Dockerfile Dockerfile, Captain-definition, тарболлы Dockerfile, Compose pull / build
Стейтфул сервисы (БД) Автоматизированный запуск Postgres, Redis, MySQL, ClickHouse + S3 бэкапы Нет (только внешние: Neon, PlanetScale, Upstash) Плагины (dokku-postgres, dokku-redis), локальные volume One-Click Apps (шаблоны контейнеров с persistent volume) Ручной запуск через Compose, ручные volume binds
Оверхед на хосте (Control Plane) ~400–700 MB RAM, 1–3% CPU в idle 0 MB (инфраструктура полностью вынесена) ~15–30 MB RAM (только bash/go wrappers, нет постоянных демонов) ~150–300 MB RAM, Docker Swarm overhead ~100–200 MB RAM (Go бинарник + embedded DB)
Сложность Day-2 Ops Средняя (автообновление через cron/UI, мониторинг диска) Нулевая (управление инфраструктурой на вендоре) Низкая/Средняя (Debian-пакеты, bash-скрипты, CLI-отладка) Высокая (Raft-консенсус в Swarm, разборки с оверлейной сетью) Низкая (изолированный контейнер, минимальное вмешательство в ОС)
Модель затрат (TCO) Фиксированная (цена VPS/Dedicated) Pay-as-you-go (крутой рост цены за egress и build minutes) Фиксированная (цена VPS) Фиксированная (цена VPS) Фиксированная (цена VPS)

Архитектурный разбор: ключевые технические различия

1. Модель управления кластером и мульти-нодовость

  • Coolify использует архитектуру Push over SSH. Главный инстанс (Control Plane) не внедряет тяжелые координирующие демоны на подчиненные серверы. Подключение рабочей ноды происходит по SSH-ключу: Coolify деплоит вспомогательные скрипты, валидирует сокет Docker и передает команды на сборку и запуск. При падении мастер-ноды контейнеры на воркерах продолжают исполняться без деградации трафика, так как локальный Traefik хранит маршрутизацию в памяти.
  • CapRover опирается на Docker Swarm. Для отказоустойчивости мастер-нод требуется минимум 3 менеджера для кворума Raft. Если сетевая связность между нодами начинает флапать (джиттер > 150ms или потеря пакетов на дешевых VPS), Swarm входит в состояние split-brain, блокируя развертывание сервисов и обновление VIP-адресов в оверлейной сети ingress.
  • Dokku принципиально ориентирован на один хост. Попытки масштабировать Dokku за пределы одного сервера требуют внешнего распределенного хранилища (Ceph, GlusterFS) и выносного балансировщика, что нивелирует простоту инструмента.
  • Portainer с агентом portainer-edge-agent идеален для мониторинга разнородных сред, но не является классическим PaaS: он не умеет автоматически конфигурировать zero-downtime rolling updates с генерацией SSL-сертификатов на лету без сложной ручной обвязки вокруг Traefik или Nginx Proxy Manager.

2. Ресурсоемкость, cgroups и коллизии при сборках

Главная опасность self-hosted PaaS на недорогих виртуальных машинах — дефицит ресурсов во время билда.

При сборке через Nixpacks или Dockerfile процесс компиляции (например, next build или cargo build) агрессивно потребляет CPU и оперативную память. Если на сервере не настроены лимиты, системный OOM Killer ядра Linux принудительно завершит соседние рабочие контейнеры с кодом завершения 137.

Для предотвращения этого на хостах с Coolify или Dokku критически важно настраивать резервирование памяти и лимиты в /etc/docker/daemon.json:

{
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 65535,
      "Soft": 65535
    }
  },
  "cgroup-parent": "/docker.slice"
}

А также тюнить параметры ядра через sysctl (/etc/sysctl.d/99-paas.conf):

# Предотвращение краха системы при внезапном исчерпании свободных страниц
vm.max_map_count = 262144
vm.overcommit_memory = 1
vm.swappiness = 10
# Снижение задержек на p99 при пиковой нагрузке сетевого стека
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 8192

На виртуальных машинах с высоким показателем CPU Steal Time (%st > 5% в выводе mpstat -P ALL 1) компиляция на стороне хоста затормозит весь I/O. В этом контексте Vercel полностью снимает риск со своего клиента, уводя процесс сборки в изолированные микро-VM на собственной инфраструктуре.

3. Поддержка баз данных и сохранность данных (State Management)

  • Coolify предоставляет встроенный планировщик резервного копирования для PostgreSQL, MySQL и MariaDB с прямой потоковой передачей дампов (pg_dumpall | gzip) в S3-совместимые хранилища (MinIO, AWS S3, Cloudflare R2). Это превращает локальные базы в продакшн-пригодные решения для проектов начального и среднего уровня.
  • Dokku использует модульную экосистему плагинов: bash dokku plugin:install https://github.com/dokku/dokku-postgres.git postgres dokku postgres:create app-db dokku postgres:link app-db my-app Управление происходит исключительно через терминал. Бэкапы настраиваются через cron-задачи самого плагина.
  • Portainer оставляет работу с базами данных полностью на совести инженера: связывание контейнеров через networks, создание named volumes и организацию снапшотов дисков приходится описывать вручную внутри docker-compose.yml.
  • Vercel не поддерживает stateful-контейнеры. Любая попытка поднять базу данных внутри рантайма Vercel исключена архитектурно — платформа форсирует переход на бессерверные решения со сторонней тарификацией за каждый read/write запрос.

4. Безопасность и площадь атаки (Attack Surface)

Эксплуатация self-hosted решений требует повышенного внимания к правам демона Docker. Проброс /var/run/docker.sock внутрь управляющих контейнеров (что необходимо для работы Portainer, Coolify и агентов CapRover) фактически дает веб-интерфейсу права root на хосте. Компрометация панели управления означает полную компрометацию базовой операционной системы.

В Dokku вектор атаки снижен за счет отсутствия открытого во внешний мир HTTP-порта панели управления — весь доступ осуществляется через защищенные SSH-ключи с ограниченной оболочкой (restricted shell).

В Coolify изоляция реализована на уровне взаимодействия сервисов: интерфейс работает в отдельной сети, а проксирование трафика изолировано через Traefik, взаимодействующий с Docker через защищенный сокет-прокси с ограничением доступных API-эндпоинтов на запись.

Пошаговая установка Coolify на чистый сервер Ubuntu 24.04 LTS

Когда выполняется coolify на vps установка и настройка, базовым фундаментом стабильности всей будущей CI/CD-инфраструктуры является низкоуровневая подготовка дистрибутива. Ubuntu 24.04 LTS (Noble Numbat) поставляется с ядром Linux 6.8 и активным контроллером cgroups v2 (/sys/fs/cgroup). Это гарантирует точный учет лимитов памяти и CPU для каждого контейнера, однако стандартные параметры виртуальной памяти и сетевого стека Ubuntu рассчитаны на типовой веб-сервер и вызовут сбои OOM Killer при первой параллельной сборке Docker-образов через BuildKit.

Шаг 1. Предварительный аудит ноды и тюнинг ядра

Перед запуском инсталляционных скриптов подключитесь к VPS по SSH с правами root и зафиксируйте метрики гипервизора. Проверьте показатель CPU Steal Time (%st):

top -b -n 1 | grep '%Cpu'

Если значение %st регулярно превышает 2–3%, нода делит физические ядра с шумными соседями; компиляция сложного Rust/Node.js проекта внутри контейнера приведет к просадке latency p99 и тайм-аутам демона Docker. Также проверьте доступную дисковую подсистему через тест прямой записи (I/O latency):

fio --name=direct-io --ioengine=libaio --iodepth=16 --rw=randwrite --bs=4k --direct=1 --size=256M --numjobs=1 --runtime=10 --group_reporting

При показателе IOPS ниже 1500 дисковый ввод-вывод станет узким горлышком для баз данных PostgreSQL, развернутых внутри Coolify.

Обновите пакетную базу и установите системные утилиты:

apt-get update && apt-get upgrade -y
apt-get install -y --no-install-recommends \
    curl \
    wget \
    git \
    jq \
    ca-certificates \
    gnupg \
    lsb-release \
    socat \
    htop \
    net-tools

Если объем оперативной памяти VPS составляет 2–4 ГБ, выделите 4 ГБ swap-пространства. Это защитит системный демон Coolify и вспомогательную СУБД от принудительного сброса по out of memory:

fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab

Скорректируйте сетевые параметры и лимиты маппинга памяти ядра, создав конфигурационный файл /etc/sysctl.d/99-coolify-host.conf:

# Разрешение трансляции сетевых пакетов для Docker bridge
net.ipv4.ip_forward = 1

# Предотвращение исчерпания виртуальной памяти СУБД и поисковыми движками
vm.max_map_count = 262144

# Снижение агрессивности вытеснения страниц памяти в swap для удержания low latency
vm.swappiness = 10

# Расширение очереди входящих сокетов для Traefik под нагрузкой
net.core.somaxconn = 65535

# Максимальное количество файловых дескрипторов
fs.file-max = 2097152

Примените параметры на лету:

sysctl --system

Шаг 2. Настройка фаервола и сетевые порты

Coolify требует прямого проброса конкретных портов. Настройте фаервол ufw, разрешив управляющий трафик:

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp comment 'SSH'
ufw allow 80/tcp comment 'Traefik HTTP'
ufw allow 443/tcp comment 'Traefik HTTPS'
ufw allow 8000/tcp comment 'Coolify UI Initial Setup'
ufw allow 6001/tcp comment 'Coolify Realtime WebSockets'
ufw --force enable

Обратите внимание: Docker напрямую модифицирует цепочки iptables (в частности PREROUTING и DOCKER), минуя стандартную цепочку ufw INPUT. После завершения первичной конфигурации и привязки домена порт 8000 должен быть исключен из публичного доступа, оставив вход только через обратный прокси Traefik на портах 80/443.

Шаг 3. Запуск инсталлятора и анатомия контейнеров

Развертывание выполняется официальным Bash-скриптом:

curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash

Под капотом установочный скрипт выполняет строгую последовательность операций: 1. Проверяет наличие прав UID 0 и архитектуру CPU (x86_64 или aarch64). 2. Удаляет конфликтующие snap-версии Docker, подключает официальный репозиторий download.docker.com и разворачивает пакеты docker-ce, docker-ce-cli, containerd.io и плагин docker-compose-plugin. 3. Создает директорию /data/coolify с базовой структурой: * /data/coolify/source — манифесты docker-compose.yml, исходный код панели управления. * /data/coolify/ssh — внутренние SSH-ключи для управления локальным хостом и удаленными серверами. * /data/coolify/proxy — конфигурация Traefik v3, динамические правила маршрутизации и файл сертификатов acme.json. * /data/coolify/databases — персистентное хранилище внутренней СУБД. 4. Генерирует криптографические ключи (APP_KEY, пароли баз данных) в файле /data/coolify/source/.env. 5. Инициализирует и запускает Docker Compose стек в фоновом режиме.

По окончании работы скрипта проверьте статус сервисов:

docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

В выводе должны присутствовать пять ключевых сервисов со статусом healthy / Up: * coolify — бэкенд на базе Laravel 11 / PHP 8.3 FPM с фоновыми воркерами Laravel Horizon для очередей задач. * coolify-realtime — сервис WebSockets (Soketi) на порту 6001, транслирующий логи сборки в реальном времени. * coolify-db — PostgreSQL 16, хранилище метаданных проектов, переменных окружения и зашифрованных секретов. * coolify-redis — Redis 7, брокер очередей для выполнения задач сборки и кеширования состояний. * coolify-proxy — Traefik v3, принимающий внешний трафик через порты 80 и 443 и маршрутизирующий его к контейнерам по Docker socket (/var/run/docker.sock).

Шаг 4. Первичная авторизация и создание root-пользователя

После запуска стека откройте браузер и перейдите по адресу:

http://<IP_ВАШЕГО_СЕРВЕРА>:8000
  1. На стартовом экране мастера настройки заполните регистрационные поля root-пользователя: имя, email и пароль. Пароль хешируется с использованием bcrypt (cost 12) и сохраняется в таблице users базы coolify-db.
  2. После входа отобразится onboarding-мастер выбора конфигурации. Выберите архитектуру Self-hosted / Localhost — это зарегистрирует текущий VPS как целевой сервер сборки (localhost), связав его через сгенерированный внутренний SSH-ключ (/data/coolify/ssh/keys/[email protected]).
  3. Панель управления автоматически выполнит валидацию подключения к демону Docker и локальной файловой системе.

Шаг 5. Привязка Wildcard DNS и автоматизация Let's Encrypt

Чтобы развертывать приложения и превью-ветки без ручного добавления записей на каждый микросервис, настройте Wildcard DNS.

В панели управления вашим DNS-провайдером (Cloudflare, Route53, Selectel) добавьте две A-записи, направленные на внешний IPv4-адрес вашего VPS:

Тип: A    Имя: coolify.yourdomain.com       Значение: 198.51.100.10    TTL: 300
Тип: A    Имя: *.apps.coolify.yourdomain.com Значение: 198.51.100.10    TTL: 300

Важно: Если используется Cloudflare, временно отключите проксирование (серый значок облака, режим DNS Only), чтобы избежать сбоев при валидации HTTP-01 вызова Let's Encrypt через Traefik.

Далее перенесите саму панель Coolify на защищенный HTTPS-протокол: 1. В левом навигационном меню перейдите в Settings -> Instance Settings -> вкладка General. 2. В поле Instance's Domain введите целевой FQDN панели: https://coolify.yourdomain.com. 3. Нажмите кнопку Save.

Coolify на лету выполнит следующую цепочку действий: * Добавит метки traefik.http.routers.coolify.rule=Host(\coolify.yourdomain.com`)иtraefik.http.routers.coolify.tls=trueв манифест управления прокси. * Traefik перехватит запрос, сформирует ACME HTTP-01 challenge и отправит запрос в Let's Encrypt CA. * После успешной валидации токена сертификат сохранится с правами0600в/data/coolify/proxy/acme.json, а входящий HTTP-трафик на порт 80 будет автоматически отдавать301 Moved Permanently` на порт 443 с заголовками HSTS.

Проверьте корректность TLS-рукопожатия из терминала:

curl -Iv https://coolify.yourdomain.com

В ответе должен возвращаться заголовок HTTP/2 200 (или 302 для редиректа на дашборд), а эмитент сертификата должен соответствовать Let's Encrypt Authority.

После успешной верификации закройте прямой доступ к установочному порту 8000:

ufw delete allow 8000/tcp

Теперь панель полностью изолирована за Traefik-прокси, готова к деплою баз данных и микросервисов с автоматическим выпуском сертификатов по маске *.apps.coolify.yourdomain.com.

Деплой первого проекта из GitHub: Next.js, Node.js или Python приложение

После завершения базового развертывания платформы следующий шаг практической эксплуатации связки «Coolify на VPS: установка и настройка» — организация отказоустойчивого CI/CD конвейера для рабочих нагрузок. Архитектура Coolify исключает необходимость ручного написания сложных пайплайнов GitHub Actions для типовых сервисов: оркестратор берет на себя получение webhook-событий, изолированную сборку через Nixpacks или Dockerfile, регистрацию сервиса во внутреннем сервис-дискавери и бесшовную маршрутизацию входящего трафика через Traefik.


1. Подключение Git-провайдера: GitHub App против Personal Access Token

При интеграции исходного кода критически важно правильно выбрать модель авторизации. Использование персональных токенов (PAT) или Deploy Keys создает эксплуатационные риски: PAT требует избыточных глобальных привилегий на аккаунт, а Deploy Keys требуют раздельной ротации на каждый репозиторий.

Рекомендуемый стандарт — интеграция через GitHub App. Она обеспечивает: * Гранулярное разграничение прав доступа исключительно на уровне выбранных репозиториев; * Автоматическую конфигурацию Webhook URL и криптографического секрета проверки подписи (X-Hub-Signature-256); * Автономную ротацию кратковременных токенов инсталляции (installation tokens) со временем жизни 1 час.

Процедура интеграции:

  1. В панели Coolify перейдите в Sources → Add New Source → GitHub App.
  2. Укажите системное имя источника и нажмите Register GitHub App. Платформа сформирует редирект на github.com/settings/apps/new с предзаполненным манифестом.
  3. В манифесте проверяются минимально необходимые скоупы:
  4. Repository permissions: Contents: Read-only — доступ к коду и коммитам.
  5. Repository permissions: Metadata: Read-only — чтение базовой структуры.
  6. Repository permissions: Pull requests: Read-only — генерация Preview Deployments для PR.
  7. Repository permissions: Webhooks: Read and write — подписка на push-события.
  8. После сохранения GitHub вернет App ID, Client ID, сгенерирует закрытый RSA-ключ (.private-key.pem) и секрет вебхука. Coolify сохранит эти артефакты в зашифрованном виде внутри локальной базы PostgreSQL.

Для GitLab или self-hosted инстансов (GitLab CE/EE) используется Personal Access Token или Deploy Token с правами read_repository и api (для автоматического создания system hook на стороне GitLab).


2. Сборка артефакта через Nixpacks: анатомия процесса

Coolify использует Nixpacks от Railway как движок сборки по умолчанию. В отличие от Buildpacks, Nixpacks генерирует легковесный OCI-образ за счет использования пакетного менеджера Nix, формируя воспроизводимое окружение без необходимости вести ручной Dockerfile.

Движок анализирует файлы проекта в строгой последовательности: * Наличие package.json / pnpm-lock.yaml / bun.lockb → Node.js провайдер. * Наличие requirements.txt / pyproject.toml / Pipfile → Python провайдер. * Наличие go.mod → Go провайдер.

Сборка проходит через 4 детерминированные фазы: 1. Setup: установка бинарных зависимостей уровня ОС из Nix-репозитория (например, openssl, libpqxx, vips для Sharp в Next.js). 2. Install: выкачивание зависимостей уровня языка (pnpm install --frozen-lockfile или pip install --no-cache-dir). 3. Build: компиляция ассетов (npm run build, next build, python manage.py collectstatic). 4. Start: запуск супервизора приложения (node server.js или uvicorn main:app --host 0.0.0.0 --port 8000).

Тонкая настройка: nixpacks.toml

Если приложению требуются системные библиотеки (например, libpq-dev для сборки psycopg2 в Python или графические библиотеки libvips для Next.js Image Optimization), создайте в корне репозитория файл nixpacks.toml:

[phases.setup]
nixPkgs = ["nodejs_20", "pnpm-9_x", "vips", "pkg-config"]

[phases.install]
cmds = ["pnpm install --frozen-lockfile"]

[phases.build]
cmds = ["pnpm run build"]

[start]
cmd = "node .next/standalone/server.js"

Контроль ресурсов ядра и лимиты памяти (OOM Killer)

Сборка SSR-фреймворков (Next.js, Remix, Nuxt) вызывает резкие пики потребления RAM из-за работы Webpack/Turbopack и минификаторов Terser. Если на VPS выделено 2–4 ГБ памяти, компилятор гарантированно вызовет аварийное завершение процесса ядром Linux (Out of Memory: Kill process).

Диагностика сбоя в системном логе хоста:

dmesg -T | grep -E -i "oom[-_]killer|killed process"

Если процесс скомпрометирован OOM, примените конфигурацию в Coolify в блоке Resources: * Ограничьте аппетит компилятора Node.js через переменную окружения: bash NODE_OPTIONS="--max-old-space-size=1536" * Задайте резервный swap через sysctl на хосте, снизив интенсивность сброса страниц памяти в диск: bash sysctl -w vm.swappiness=10 sysctl -w vm.vfs_cache_pressure=50


3. Конфигурация переменных окружения (Build-time vs Runtime)

Распространенная архитектурная ошибка при деплое фронтенд- и фулстек-приложений — смешивание этапов внедрения переменных окружения.

В Coolify переменные разделены аппаратно: * Build-time Variables (Available at build time): вшиваются непосредственно в статические JS-бандлы на этапе выполнения next build или vite build (например, NEXT_PUBLIC_API_URL, PUBLIC_KEY). Если чекбокс сборки не установлен, компилятор подставит undefined. * Runtime Variables: передаются в окружение контейнера в момент его старта (docker run -e ...). Доступны серверному коду (Node.js, FastAPI, Django) через process.env.DATABASE_URL или os.environ.get("DATABASE_URL"). Никогда не отмечайте чувствительные переменные (секреты БД, приватные ключи) как build-time, иначе они могут утечь в открытый клиентский бандл.

Формат хранения переменных в интерфейсе Coolify поддерживает синтаксис экранирования и многострочные значения (RSA-ключи, сертификаты):

NODE_ENV=production
DATABASE_URL=postgresql://app_user:StrongPassword789@postgres-internal:5432/production_db
REDIS_URL=redis://default:CacheTokenSecure@redis-internal:6379/0
SECRET_KEY_BASE=base64:4e9bf433a0db6701f53d2bf2cb02ad3d5c589b27daebc2106

4. Сетевая топология, маршрутизация портов и Traefik

Coolify полностью абстрагирует системного администратора от ручного редактирования конфигураций NGINX. Маршрутизация строится на Docker Labels и динамическом чтении событий Docker socket демоном Traefik.

Правила привязки портов

  1. Категорический запрет на Host Port Mapping: В настройках сервиса нельзя пробрасывать порт на хост через Ports Exposes (e.g. 3000:3000). Публикация порта напрямую через 0.0.0.0:3000 открывает сервис в обход Traefik, делая его уязвимым для сканирования и лишая защиты SSL/TLS.
  2. Параметр Port в Coolify UI: Указывается только внутренний порт, который слушает приложение внутри контейнера.
  3. Next.js: 3000
  4. Python (Uvicorn / FastAPI): 8000
  5. Node.js (Express / Fastify): 3000 или 8080

Traefik автоматически считывает сгенерированные метки контейнера и конфигурирует виртуальный хост:

# Демонстрация меток, автоматически генерируемых Coolify для Traefik
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.app-http.rule=Host(`app.example.com`)"
  - "traefik.http.routers.app-http.entrypoints=http"
  - "traefik.http.routers.app-http.middlewares=redirect-to-https"
  - "traefik.http.routers.app-https.rule=Host(`app.example.com`)"
  - "traefik.http.routers.app-https.entrypoints=https"
  - "traefik.http.routers.app-https.tls=true"
  - "traefik.http.routers.app-https.tls.certresolver=letsencrypt"
  - "traefik.http.services.app.loadbalancer.server.port=3000"

Для выдачи сертификата Let's Encrypt в поле Domains достаточно указать FQDN: https://app.example.com. Сервер проверяет наличие A/AAAA-записи в DNS, после чего Traefik по ACME-протоколу через challenge-запрос получает и монтирует SSL-сертификат в рантайм.


5. Автоматический деплой по Git Push и Healthcheck проверки

По умолчанию после подключения GitHub App в репозитории активируется Webhook. При выполнении:

git add .
git commit -m "feat(api): optimize connection pooling"
git push origin main

GitHub отправляет POST-запрос с полезной нагрузкой на эндпоинт Coolify:

POST /webhooks/source/github/events HTTP/1.1
Host: coolify.example.com
X-GitHub-Event: push
X-Hub-Signature-256: sha256=d58d9b8e4e9f73f8e0d9...
Content-Type: application/json

Coolify выполняет HMAC-валидацию сигнатуры по сохраненному секрету, сопоставляет ветку из payload (refs/heads/main) с настройкой приложения и ставит задачу сборки в очередь Redis/Horizon.

Реализация Zero-Downtime Deployment

Чтобы исключить разрыв сетевых соединений (502 Bad Gateway) в момент переключения контейнеров, обязательно активируйте Healthcheck в конфигурации сервиса.

Пример системного эндпоинта для FastAPI (main.py):

from fastapi import FastAPI, Response, status
import psycopg

app = FastAPI()

@app.get("/healthz")
def health_check():
    # Проверка доступности критических зависимостей (DB, Cache)
    try:
        # Проверка соединения с базой данных
        return {"status": "healthy", "engine": "nixpacks"}
    except Exception:
        return Response(status_code=status.HTTP_503_SERVICE_UNAVAILABLE)

В настройках Coolify укажите: * Health Check Path: /healthz * Interval: 5s * Timeout: 3s * Retries: 3 * Start Period: 15s (время на холодный старт рантайма)

Traefik переключит входящий поток трафика со старого контейнера на новый только тогда, когда новый экземпляр вернет HTTP-код 200 OK заданное число раз подряд. Старый контейнер получит сигнал SIGTERM, завершит активные транзакции в течение grace-периода (stop_signal_timeout = 20s) и только после этого будет остановлен демоном Docker. Это гарантирует нулевую деградацию метрики latency p99 во время непрерывного релиза.

Развертывание баз данных в один клик: PostgreSQL, Redis и автоматические бэкапы

При развертывании stateful-сервисов через веб-интерфейсы разработчики часто забывают, что абстракция PaaS не отменяет физику дисковых подсистем и ограничений ядра Linux. Когда выполняется coolify на vps установка и настройка, платформа разворачивает базы данных в виде изолированных Docker-контейнеров, подключенных к внутренней overlay- или bridge-сети. Создание инстанса PostgreSQL 16, MySQL 8.4 или Redis 7 занимает один клик, но эксплуатация под реальной нагрузкой требует понимания того, как Coolify организует хранилище, аллоцирует ресурсы через cgroups v2 и выполняет сброс данных на диск.

Архитектура персистентных томов и дисковый I/O

По умолчанию при создании PostgreSQL или MySQL в Coolify монтирует именованный Docker-том (Named Volume), физически расположенный по пути /var/lib/docker/volumes/<uuid>_data/_data. Для сред с высокими транзакционными требованиями (OLTP свыше 1 500 TPS) стандартное размещение на общем корневом разделе с файловой системой Ext4 чревато деградацией latency p99 из-за конкуренции за операции ввода-вывода с системными логами и другими контейнерами.

Если хост использует отдельный NVMe-накопитель под базы данных, смонтированный в /mnt/nvme-data, стандартный Named Volume внутри Coolify необходимо заменить на bind-mount в расширенных настройках сервиса (пункт Storage):

volumes:
  - /mnt/nvme-data/postgres-production/data:/var/lib/postgresql/data:rw

На уровне ядра ОС для хоста с базами данных критически важно настроить поведение подсистемы виртуальной памяти. Если страница памяти модифицирована (dirty page), ядро сбрасывает ее по таймауту или достижению лимита. Стандартные настройки Ubuntu Server 24.04 (vm.dirty_ratio = 20, vm.dirty_background_ratio = 10) на VPS с 32 ГБ RAM приводят к тому, что фоновый сброс начинается только при накоплении 3.2 ГБ «грязных» страниц, вызывая резкий скачок I/O wait и заморозку транзакций (fsync latency spikes).

Отрегулируйте параметры в /etc/sysctl.d/99-databases.conf:

# Начинать сброс на диск при накоплении 64 МБ грязных страниц
vm.dirty_background_bytes = 67108864
# Жестко блокировать процессы записи при накоплении 256 МБ
vm.dirty_bytes = 268435456

# Защита от OOM Killer при fork() процессов Redis и фоновых воркеров
vm.overcommit_memory = 1

# Увеличение очереди соединений для сокетов PostgreSQL и Redis
net.core.somaxconn = 4096

Примените изменения без перезагрузки:

sysctl --system

Тюнинг PostgreSQL 16: уход от дефолтов

Стандартный образ postgres:16-alpine, который Coolify подтягивает из Docker Hub, рассчитан на запуск в минимальных средах: параметр shared_buffers там равен 128 МБ, а work_mem — 4 МБ. Запуск production-нагрузки на таких параметрах приведет к постоянному чтению с диска вместо буферного кэша и сбросу промежуточных сортировок во временные файлы на диск (work_mem exhaustion).

Coolify позволяет передавать флаги инициализации сервера через поле Docker Run Flags или путем переопределения команды запуска. Для VPS с 8 ГБ RAM и 4 vCPU выделите под СУБД 4 ГБ оперативной памяти и передайте оптимизированную конфигурацию через аргументы запуска в интерфейсе сервиса:

postgres -c shared_buffers=2GB \
         -c effective_cache_size=6GB \
         -c maintenance_work_mem=512MB \
         -c work_mem=16MB \
         -c min_wal_size=1GB \
         -c max_wal_size=8GB \
         -c checkpoint_completion_target=0.9 \
         -c checkpoint_timeout=15min \
         -c wal_buffers=64MB \
         -c default_statistics_target=100 \
         -c random_page_cost=1.1 \
         -c effective_io_concurrency=200

Значение random_page_cost = 1.1 актуально исключительно для NVMe/SSD накопителей (для HDD оставляют 4.0), чтобы планировщик запросов не избегал индексного сканирования (Index Scan) в пользу последовательного чтения (Seq Scan).

Параллельно ограничьте лимиты cgroups в конфигурации контейнера Coolify, чтобы внезапная утечка памяти в аналитическом запросе не привела к аварийной остановке самого демона Coolify или Traefik:

deploy:
  resources:
    limits:
      cpus: '3.5'
      memory: 5120M
    reservations:
      memory: 2048M

Redis 7: персистентность без просадки TPS

При выборе Redis внутри Coolify по умолчанию разворачивается инстанс без строгой настройки персистентности. Для кэша это приемлемо, но если Redis используется как брокер сообщений (Celery, BullMQ) или хранилище сессий, требуется гибридный режим: периодические снимки RDB плюс журнал AOF (Append-Only File).

В секции Environment Variables или через монтирование кастомного redis.conf укажите:

appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
save 900 1
save 300 10
save 60 10000
maxmemory 1536mb
maxmemory-policy allkeys-lru

Параметр no-appendfsync-on-rewrite yes предотвращает блокировку основного потока вызовом fsync() во время выполнения тяжелых фоновых операций BGSAVE или BGREWRITEAOF. Если на VPS фиксируется ненулевой процент CPU Steal Time (%st > 1.5% в утилите top или vmstat 1), совмещение AOF-сброса и фоновой перезаписи неизбежно вызовет рост latency p99 до сотен миллисекунд.

Обязательно отключите Transparent Huge Pages на уровне хоста — данная оптимизация ядра фрагментирует память при вызове fork():

echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

Для персистентности этой настройки добавьте указанные строки в /etc/rc.local или оформите в виде отдельного systemd-юнита.

Настройка автоматических бэкапов в S3 / MinIO / Backblaze B2

Отказоустойчивость СУБД в рамках одного VPS не имеет смысла без внешнего резервного копирования. Coolify содержит встроенный бэкап-модуль, работающий поверх утилит pg_dumpall, pg_dump или mysqldump, с нативной поддержкой отправки снапшотов в любые S3-совместимые объектные хранилища.

Для настройки автоматического экспорта перейдите в свойства базы данных: вкладка Backups -> Configurations.

  1. Schedule (Cron-синтаксис): Рекомендуется выставлять время наименьшей активности приложения, например 0 3 * * * (ежедневно в 03:00 UTC).
  2. S3 Storage Target: Выберите предварительно зарегистрированный S3-профиль.
  3. Backblaze B2: Endpoint: s3.<region>.backblazeb2.com, Signature Version: v4.
  4. MinIO (self-hosted): Endpoint: https://minio.internal.domain:9000. Убедитесь, что бакет не является публичным.
  5. AWS S3: Укажите стандартизированный регион (например, eu-central-1) и IAM-ключи с минимально необходимым набором прав (s3:PutObject, s3:GetObject, s3:ListBucket).
  6. Retention Policy (Глубина хранения): Задайте срок жизни ротации, например, 30 дней. Coolify автоматически удаляет устаревшие объекты по маске database-dump-*.sql.gz, предотвращая переполнение бакета.

Механизм создания бэкапа внутри Coolify работает следующим образом: фоновый процесс агента запускает временный контейнер, который подключается к сети нужной СУБД, выполняет потоковый дамп через UNIX-pipe с архивацией на лету:

docker exec -i <coolify_postgres_container_id> pg_dump -U postgres -d production_db -Fc | gzip -9 > /var/lib/coolify/backups/dump.sql.gz

Использование кастомного формата -Fc (PostgreSQL Custom Format) вместо сырого SQL-дампа позволяет восстанавливать данные в параллельном режиме через pg_restore -j 4, а также избирательно извлекать отдельные схемы или таблицы без разворачивания всей базы.

Для валидации целостности созданного бэкапа протестируйте ручное скачивание и проверку структуры дампа прямо с целевого хоста через AWS CLI:

# Проверка наличия и размера файла в бакете
aws --endpoint-url https://s3.eu-central-1.wasabisys.com s3 ls s3://company-production-backups/coolify/postgres/

# Тестовая проверка заголовка сжатого дампа без полной распаковки на диск
aws --endpoint-url https://s3.eu-central-1.wasabisys.com s3 cp s3://company-production-backups/coolify/postgres/latest.sql.gz - | gzip -d | pg_restore -l | head -n 25

Если утилита pg_restore -l без ошибок выводит оглавление архивных TOC-записей (Table of Contents), процедура создания и выгрузки бэкапа считается валидной, а сервис — готовым к эксплуатации.

Оптимизация производительности хоста: swapfile на NVMe, prune старых образов и лимиты

Когда завершена базовая связка «coolify на vps установка и настройка», хост-система часто остается с дефолтными параметрами дистрибутива (Ubuntu 22.04/24.04 или Debian 12). На инстансах начального и среднего звена (2–4 vCPU, 4–8 GB RAM) первый же деплой тяжелого SPA (Next.js, Nuxt) или компиляция backend-монолита на Go/Rust через Nixpacks/BuildKit гарантированно упираются в исчерпание физической памяти.

Ядро Linux реагирует на нехватку страниц памяти бескомпромиссно: подсистема mm/oom_kill.c вычисляет процесс с наихудшим показателем oom_score (куда суммируются используемые rss и размер страниц swap) и посылает сигнал SIGKILL (-9). В результате падает либо сам процесс сборки с кодом ошибки Exit code 137, либо, что опаснее, фоновые контейнеры PostgreSQL или Traefik/Caddy.

Предотвращение OOM Killer: инициализация swapfile и тюнинг ядра

На хостах с быстрыми NVMe-накопителями подкачка выполняет роль защитного демпфера: она не предназначена для постоянного обслуживания горячей памяти приложений (это уничтожило бы latency p99 дискового I/O), но удерживает ядро от вызова OOM Killer при кратковременных пиках аллокации (компиляция webpack, запуск rustc).

Выделение файла подкачки 4GB

Создание swapfile через fallocate выполняется мгновенно, поскольку системный вызов выделяет блоки без фактической записи нулей. Если виртуальный сервер использует файловую систему с Copy-on-Write (Btrfs) или старые версии XFS, используйте утилиту dd для предотвращения ошибок фрагментации:

# Выделение пространства 4GB
fallocate -l 4G /swapfile || dd if=/dev/zero of=/swapfile bs=1M count=4096 status=progress

# Назначение строгих прав (чтение/запись только root)
chmod 600 /swapfile

# Инициализация структуры swap-пространства
mkswap /swapfile

# Активация файла подкачки в пространстве ядра
swapon /swapfile

# Фиксация в fstab для автомонтирования при ребуте
echo '/swapfile none swap sw 0 0' | tee -a /etc/fstab

Проверьте успешность инициализации через swapon --show или системный вызов free -m.

Конфигурация подсистемы виртуальной памяти (sysctl)

Поведение ядра Linux по умолчанию (vm.swappiness = 60) рассчитано на настольные системы и слишком агрессивно сбрасывает неактивные анонимные страницы на диск, провоцируя ненужные дисковые прерывания. Для production-хоста Coolify требуется тонкая калибровка:

  1. vm.swappiness = 10 — ядро обращается к диску только тогда, когда объем свободной физической памяти падает ниже критического порога (high водяной знак подсистемы kswapd).
  2. vm.vfs_cache_pressure = 50 — удерживает в оперативной памяти структуры кэша файловой системы (dentry и inode). Сборка современных проектов оперирует десятками тысяч мелких файлов в директориях node_modules или .cargo; сохранение метаданных в RAM радикально снижает время I/O ожидания (iowait).
  3. vm.overcommit_memory = 1 — эвристический оверкоммит, необходимый для корректного форка процессов баз данных (в частности, Redis BGSAVE), исключающий фатальные сбои при копировании страниц памяти по схеме Copy-on-Write.

Создайте конфигурационный файл ядра:

cat << 'EOF' > /etc/sysctl.d/99-coolify-performance.conf
# Тюнинг подсистемы виртуальной памяти под сборки Docker/Nixpacks
vm.swappiness = 10
vm.vfs_cache_pressure = 50
vm.overcommit_memory = 1

# Расширение очередей сетевого стека для Traefik/Caddy
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 16384
EOF

# Применение параметров без перезагрузки ноды
sysctl --system

Автоматическая очистка дискового пространства и Docker Layers

Механизм Docker BuildKit, используемый в Coolify, агрессивно кэширует слои образов в директории /var/lib/docker/overlay2. При регулярном CI/CD пайплайне диск объемом 40–80 GB забивается dangling-образами и промежуточными кэшами компиляции за 1–2 недели. Заполнение раздела на 100% переводит файловую систему в режим read-only, парализуя все запущенные базы данных.

Команда docker system prune -af --volumes чрезмерно деструктивна, так как удаляет неименованные тома, где могут находиться временные данные инстансов. Очистку слоев и builder-кэша необходимо автоматизировать через изолированный systemd-таймер с фильтрацией по времени устаревания.

1. Создание сервиса очистки

cat << 'EOF' > /etc/systemd/system/coolify-docker-prune.service
[Unit]
Description=Automated Docker Prune for Coolify Host
After=docker.service
Requires=docker.service

[Service]
Type=oneshot
# Удаление неиспользуемых образов старше 168 часов (7 дней)
ExecStart=/usr/bin/docker image prune -a --force --filter "until=168h"
# Очистка BuildKit кэша старше 72 часов
ExecStart=/usr/bin/docker builder prune --force --filter "until=72h"
# Удаление неиспользуемых сетей (за исключением bridge, host, none)
ExecStart=/usr/bin/docker network prune --force
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

2. Конфигурация расписания выполнения (Systemd Timer)

Запуск сборщика мусора во время активного рабочего дня может вызвать просадку по IOPS дисковой подсистемы и замедлить деплои. Назначьте выполнение на 03:30 UTC:

cat << 'EOF' > /etc/systemd/system/coolify-docker-prune.timer
[Unit]
Description=Run Coolify Docker Prune daily at 03:30 UTC

[Timer]
OnCalendar=*-*-* 03:30:00
RandomizedDelaySec=600
Persistent=true

[Install]
Timers.target
EOF

# Активация таймера
systemctl daemon-reload
systemctl enable --now coolify-docker-prune.timer

Проверить статус расписания можно командой systemctl list-timers coolify-docker-prune.timer.

Лимиты ресурсов: изоляция на уровне cgroups v2

Отсутствие жестких границ потребления памяти и процессора позволяет сбойному приложению (например, утечка памяти в Node.js сервере) монополизировать ресурсы ноды. На хостах с ядром Linux 5.8+ по умолчанию активна версия cgroups v2, обеспечивающая тотальный контроль над иерархией контроллеров memory и cpu.

В панели Coolify (раздел General -> Resources) или напрямую в кастомном docker-compose.yml каждого сервиса необходимо задавать две метрики: жесткий лимит (limits) и гарантированный резерв (reservations).

version: '3.8'

services:
  backend-service:
    image: my-registry/app:latest
    deploy:
      resources:
        limits:
          # cgroups v2: memory.max. При превышении процесс внутри контейнера получит OOM-kill,
          # не затрагивая соседние контейнеры и хост-систему
          memory: 1024M
          # cgroups v2: cpu.max. Квота 1.5 ядра (150000 мкс на период 100000 мкс)
          # Защищает ноду от взрывного роста %st (CPU Steal Time) у соседа по гипервизору
          cpus: '1.5'
        reservations:
          # cgroups v2: memory.min / memory.low. Ядро гарантирует, что 256MB RAM 
          # никогда не будут вытеснены в swap даже при пиковой нагрузке
          memory: 256M
          cpus: '0.25'
    restart: always
  • limits.memory (memory.max в /sys/fs/cgroup): верхняя планка. Как только контейнер пересекает 1024 MB, ядро сначала пытается инициировать реклейм страниц (сброс page cache), и если это не дает результата — OOM Killer уничтожает процесс внутри изолированного пространства cgroup, возвращая код контейнера 137.
  • reservations.memory (memory.low): защитный порог. Подсистема управления виртуальной памятью хоста не трогает зарезервированные 256 MB при фоновом сбросе страниц через kswapd.
  • limits.cpus (cpu.max): предотвращает монополизацию процессорных циклов бесконечными циклами или утечками пула потоков. Ограничение в 1.5 ядра гарантирует, что системные демоны (dockerd, sshd, coolify-proxy) всегда получат процессорное время без деградации времени ответа сетевого стека.

Часто задаваемые вопросы (FAQ)

Подходит ли Coolify для продакшн-нагрузок?

Да, Coolify управляет нативными Docker-контейнерами через Traefik. Падение самой панели Coolify никак не влияет на работу уже запущенных сервисов и сайтов.

Можно ли управлять несколькими серверами из одной панели Coolify?

Да, Coolify поддерживает мульти-серверную архитектуру: вы можете развернуть панель управления на одном базовом VPS и подключать другие удаленные серверы по SSH как воркер-ноды.

Как перенести проекты с Vercel на Coolify?

Для Next.js приложений достаточно указать в next.config.js параметр output: 'standalone', после чего Coolify соберет минималистичный легковесный контейнер без необходимости править код.

Что делать, если зависает сборка проекта из-за нехватки RAM?

Подключите swap-файл размером 4–8 GB на NVMe диске и ограничьте количество параллельных потоков сборки в переменных окружения.