Зачем cloud-init, если есть руки
Ручная настройка по SSH работает ровно до второго сервера. cloud-init выполняет конфигурацию при первом старте VPS — пользователи, ключи, пакеты, — и тот же файл поднимет идентичный сервер через год. У всех крупных провайдеров поле «user data» есть прямо в форме создания сервера.
Минимальный конфиг: отдельный пользователь deploy с ключом вместо пароля, запрет root-логина, свежие пакеты.
#cloud-config
users:
- name: deploy
groups: [sudo, docker]
ssh_authorized_keys:
- ssh-ed25519 AAAA… you@laptop
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_pwauth: false
disable_root: true
package_update: true
package_upgrade: true
Docker: официальный репозиторий и лимиты логов
Ставьте Docker из официального репозитория, а не из пакетов дистрибутива — там версии отстают на полгода. И сразу ограничьте логи: контейнер, который пишет в stdout без лимита, за пару месяцев съест весь диск. Это самая частая причина «сервер внезапно умер» из тех, что мы разбираем.
// /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": { "max-size": "10m", "max-file": "3" }
}
systemctl restart docker — уже запущенные контейнеры сохранят старый лог-драйвер до пересоздания.Firewall: три порта, не больше
Наружу смотрят только 22, 80 и 443. Всё остальное — базы, метрики, панели — доступно через SSH-туннель или VPN. Важный нюанс: Docker пишет правила напрямую в iptables в обход ufw, поэтому порт, опубликованный через -p 5432:5432, будет открыт всему интернету, что бы ни говорил ufw. Публикуйте порты только на 127.0.0.1.
$ ufw default deny incoming
$ ufw allow 22/tcp comment 'ssh'
$ ufw allow 80,443/tcp comment 'web'
$ ufw enable
# порты наружу — только через 127.0.0.1:
ports: ["127.0.0.1:5432:5432"]
Чек-лист перед продакшеном
Сервер готов, когда на каждый пункт можно ответить «да» — и показать, где это лежит в коде:
Некогда настраивать самому?
Настроим VPS под Docker под ключ — от 8 400 ₽, с cloud-init-конфигом, который останется у вас.