31 января 2026 г.

GitHub, Docker и деплой: база вайб-кодера

Практический набор инструментов и решений, чтобы потратить минимум времени на администрирование сервера и задеплоить свой вайб-проект в паблик. Warp, SSH ключи, Docker, GitHub, Nginx и Let's Encrypt.

Дисклеймер: Это базовые практики, которые помогут задеплоить проект на VPS и обеспечить его работоспособность. Для поддержки продакшн-версий и аудита безопасности инфраструктуры рекомендуется обращаться к профессиональным DevOps-инженерам.

Версии ПО, описанные в статье, актуальные на февраль 2026 года

  • OS Server: Ubuntu 24.04 LTS (Noble Numbat)
  • Docker: Engine 27+, Compose V2 (команда docker compose)
  • Node.js: 22 LTS (Active LTS на 2026)
  • GitHub CLI (gh): v2.50+
  • GitHub Actions: actions/checkout@v4, appleboy/ssh-action@v1.2.0

Термины

  • Git — система контроля версий. Позволяет сохранять историю изменений кода и работать над проектом в команде.
  • VPS (Virtual Private Server) — арендованный виртуальный сервер, "удаленный компьютер", который работает круглосуточно.
  • SSH (Secure Shell) — протокол для безопасного управления сервером через командную строку.
  • Docker — технология упаковки приложения в изолированный контейнер со всем необходимым для запуска. Гарантирует, что "работает у меня — заработает и там".
  • Docker Compose — инструмент для запуска нескольких связанных контейнеров (например, приложение + база данных) одной командой.
  • CI/CD — автоматическая доставка кода: после git push система сама тестирует и обновляет приложение на сервере.
  • Local / Dev / Stage / Prod — окружения. Local — компьютер разработчика, Dev — общий сервер для разработки, Stage — тестовый сервер (копия боевого), Prod — боевой сервер с реальными пользователями.
  • Nginx — быстрый веб-сервер. В данном гайде используется как Reverse Proxy — принимает запросы из интернета и передает их приложению.
  • SSL (Secure Sockets Layer) — технология безопасности, создающая зашифрованное соединение между сервером и браузером (HTTPS). Защищает данные пользователей.

Warp: LLM как DevOps помощник

Warp — это современный терминал, который позволяет доверить работу с командной строкой LLM. Вот что это дает:

  • AI Agent Mode: Можно писать на английском или русском что нужно сделать ("SSH to prod и проверь статус докера"), а Warp генерирует команды и показывает diff перед выполнением
  • Seamless SSH: После подключения по SSH на удаленный сервер, можно дать возможность LLM выполнить на нём команды
  • Command blocks: Весь вывод организован в блоки, которые легко искать и скроллить (удобно при дебаге)
  • Notebooks: Комбинирование Markdown-документации с рабочими SSH-командами

Как это работает в вайб-кодинге: Вместо того чтобы помнить все флаги Docker и Nginx, проблема описывается LLM в Warp: "Деплой не прошел, логи говорят permission denied". Warp генерирует команды для диагностики, пользователь смотрит diff и кликает "run".

Установка: brew install warp на macOS, скачать для Linux/Windows.


SSH ключи

Это нужно сделать один раз. После этого будет работать везде.

Генерация SSH ключа

ssh-keygen -t ed25519 -C "your_email@example.com"
# Где your_email@example.com — email, привязанный к GitHub

Система спросит:

  • Путь для сохранения → Просто Enter (по умолчанию ~/.ssh/id_ed25519)
  • Passphrase → Нужно ввести пароль или оставить пусто (рекомендуется пароль)

Создалось два файла:

  • ~/.ssh/id_ed25519 — приватный ключ (хранить в надежном месте)
  • ~/.ssh/id_ed25519.pub — публичный ключ (тот, что добавляется в GitHub)

Добавление ключа в SSH agent

# Стартуем SSH agent
eval "$(ssh-agent -s)"

# Добавляем ключ
ssh-add ~/.ssh/id_ed25519
# Если задавал пароль, нужно ввести его сейчас

Копирование публичного ключа

# Выведет весь ключ в консоль
cat ~/.ssh/id_ed25519.pub

# На macOS удобнее скопировать в буфер сразу:
cat ~/.ssh/id_ed25519.pub | pbcopy

Должен выглядеть так: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... your_email@example.com

Добавление ключа на GitHub

Веб:

  1. Зайти на github.com/settings/ssh
  2. Нажать "New SSH key"
  3. Title — например "My Laptop" (для удобства, если несколько ключей)
  4. Key — вставить скопированный ключ
  5. Key type — выбрать "Authentication"
  6. "Add SSH key"

Или через CLI:

gh ssh-key add ~/.ssh/id_ed25519.pub --type authentication

🤖 Warp Way: Генерация ключей через Warp:

"Сгенерируй новый ed25519 ssh ключ для my@email.com, добавь в агент и скопируй публичный ключ в буфер обмена" "Добавь ssh ключ в github используя gh cli"

Проверка подключения

ssh -T git@github.com

Если виден вывод типа Hi username! You've successfully authenticated... — готово! ✅

После этого:

  • Клонирование репо через SSH: git clone git@github.com:username/repo.git
  • Пуш без пароля: git push
  • Всё работает везде

GitHub

Создание репозитория с gh CLI

Если GitHub.com уже открыт и работа идет через интерфейс — это нормально, но использование CLI часто экономит время.

Установка gh (GitHub CLI, ориентируемся на v2.50+):

# macOS
brew install gh

# Linux (Debian/Ubuntu)
sudo apt install gh

# или скачи отсюда: https://cli.github.com

🤖 Warp Way:

"Установи github cli"

Единоразовая аутентификация:

gh auth login
# Выбрать:
# - GitHub.com
# - SSH (безопаснее, мы это уже настроили)
# - Yes to add SSH key to agent

Создание репо прямо из терминала:

# Самый быстрый способ:
gh repo create my-project --public --source=. --push

# Где:
# --public — делает репо открытым (или --private)
# --source=. — берет текущую папку как исходник
# --push — сразу пушит в GitHub

# Для выбора через интерактивное меню:
gh repo create

Готово. Репо создано, git инициализирован, remote добавлен. За 10 секунд вместо 2 минут в веб-интерфейсе.

Локальная инициализация: git init, git add

Старт нового проекта:

mkdir my-awesome-app
cd my-awesome-app

# Инициализация Git
git init

# Создание файлов (README, код, etc.)
echo "# My Awesome App" > README.md

# Добавление в staging area
git add README.md

# Или добавление всего сразу
git add .

# Коммит
git commit -m "Initial commit"

Важно: Перед git push необходимо убедиться, что репо создан на GitHub (через gh repo create выше).

# Добавление remote (если gh не сделал это автоматически)
git remote add origin git@github.com:username/my-awesome-app.git

# Пуш
git push -u origin main

🤖 Warp Way:

"Инициализируй git репозиторий, добавь все файлы, закоммить как 'Initial commit' и запушь в origin main"

Warp сгенерирует цепочку команд. Останется только нажать Enter.

Docker: упаковать приложение и забыть

Зачем Docker

Один раз создаётся образ — потом одинаково работает на локальной машине, на стейджинге, в продакшене. Это исключает проблемы с различиями версий Node.js и окружения.

Минимум: Dockerfile + compose.yaml

Важно про безопасность: Пароли нельзя хранить в коде. Следует использовать файл .env.

Dockerfile — рецепт сборки образа приложения:

# Берём готовый образ Node (версия 22 LTS - Active в 2026)
FROM node:22-alpine

# Рабочая директория в контейнере
WORKDIR /app

# Копируем package.json и package-lock.json
COPY package*.json ./

# Устанавливаем зависимости
RUN npm install

# Копируем весь код
COPY . .

# Какой порт слушает приложение
EXPOSE 3000

# Команда для запуска
CMD ["npm", "start"]

compose.yaml (раньше назывался docker-compose.yml, но V2 рекомендует новое имя) — упрощает запуск локально и на сервере:

# В Docker Compose V2 поле version (например, '3.8') больше не обязательно
services:
  app:
    build: .  # Собираем из Dockerfile
    ports:
      - "3000:3000"  # Локальный порт 3000 → контейнер 3000
    environment:
      NODE_ENV: development
      DATABASE_URL: postgres://postgres:${DB_PASSWORD}@db:5432/myapp
    depends_on:
      - db
    volumes:
      - .:/app  # Горячая перезагрузка (для разработки)
      - /app/node_modules

  db:
    image: postgres:16-alpine # Postgres 16 (Stable)
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: myapp
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Создание файла .env (и добавление его в .gitignore!):

DB_PASSWORD=supersecretpassword123

🤖 Warp Way: Генерация Docker-файлов:

"Создай Dockerfile для приложения Node.js 22 и compose.yaml с базой данных postgres 16"

Запуск:

# Собрать образ и запустить контейнеры
docker compose up -d

# -d = запустить в фоне

# Логи
docker compose logs -f app

# Остановить
docker compose down

🤖 Warp Way:

"Запусти docker compose в фоне" "Следи за логами сервиса app" "Останови все контейнеры docker"

Продвинутый уровень: TypeScript (NestJS / Fastify)

Для TypeScript одного Dockerfile мало — код нужно скомпилировать. Используем Multi-stage build: сборка в одном контейнере, запуск в другом (чистом и легком).

# Stage 1: Сборка
FROM node:22-alpine AS builder
WORKDIR /app

# Копируем конфиги зависимостей
COPY package*.json ./

# Устанавливаем ВСЕ зависимости (включая devDependencies для сборки)
RUN npm ci

# Копируем исходный код
COPY . .

# Собираем TypeScript в JavaScript (папка dist)
RUN npm run build

# Stage 2: Продакшн (лёгкий образ)
FROM node:22-alpine AS runner
WORKDIR /app

COPY package*.json ./

# Устанавливаем ТОЛЬКО продакшн зависимости
RUN npm ci --omit=dev

# Копируем собранное приложение из Stage 1
COPY --from=builder /app/dist ./dist

EXPOSE 3000

# Запускаем (обычно node dist/main.js)
CMD ["node", "dist/main"]

🤖 Warp Way:

"Сгенерируй multi-stage Dockerfile для приложения NestJS используя node:22-alpine с этапами builder и runner"

В чем фишка: Исходники TS и тяжелые dev-пакеты не попадают в итоговый образ. Он весит в 5 раз меньше.


Деплой: из репы на сервер

Подготовка сервера (один раз)

Важно: Сервер должен быть настроен на вход только по SSH ключу. Никаких паролей. Это база безопасности и требование для автоматического деплоя через GitHub Actions.

Ориентируемся на Ubuntu 24.04 LTS. На чистый VPS сначала нужно установить Docker. Одной командой:

curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh # Установит актуальный Docker Engine (v27+)

🤖 Warp Way:

"Установи docker и docker compose на ubuntu используя официальный скрипт"

GitHub Actions

Push в репо → автоматический деплой на сервер. Настраивается один раз.

Что нужно:

  • SSH ключ сервера (без пароля)
  • Адрес сервера
  • Путь, где лежит приложение на сервере

.github/workflows/deploy.yml:

name: Deploy

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest # В 2026 году это обычно Ubuntu 24.04
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy to server
        uses: appleboy/ssh-action@v1.2.0 # Используем фиксированную версию для стабильности (не master)
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SERVER_SSH_KEY }}
          script: |
            # Если папки нет — клонируем, если есть — просто заходим
            if [ ! -d "/var/www/myapp" ]; then
              git clone git@github.com:username/my-project.git /var/www/myapp
            fi
            cd /var/www/myapp
            
            git pull origin main
            # Создаем .env из секретов (если нужно) или убеждаемся что он есть
            docker compose down
            docker compose up -d --build

🤖 Warp Way:

"Создай workflow github action для деплоя на сервер через ssh при пуше в ветку main используя appleboy/ssh-action"

Что сделать один раз в GitHub:

  1. Settings → Secrets and variables → Actions
  2. Добавить секреты:
    • SERVER_HOST — IP сервера
    • SERVER_USER — пользователь (обычно root или ubuntu)
    • SERVER_SSH_KEY — весь приватный SSH ключ (результат cat ~/.ssh/id_rsa на сервере)

Готово. Теперь каждый git push main деплоит приложение автоматически.

SSH + git pull (для собственного сервера)

Проще, чем Actions. Достаточно зайти на сервер и обновить приложение.

На сервере один раз:

# Клонируем репо
git clone git@github.com:username/my-app.git /var/www/myapp
cd /var/www/myapp

# Собираем Docker образ
docker compose build

# Запускаем
docker compose up -d

🤖 Warp Way:

"Клонируй https://github.com/username/my-app.git в /var/www/myapp и запусти docker compose в фоне"

После этого, для обновления:

# С локальной машины:
git push origin main

# На сервере (или через Warp AI):
cd /var/www/myapp
git pull origin main
docker compose down
docker compose up -d --build

Одна команда для быстрого обновления:

ssh user@server.com "cd /var/www/myapp && git pull && docker compose down && docker compose up -d --build"

🤖 Warp Way: Удаленное управление сервером:

"Зайди по SSH на user@server.com, перейди в /var/www/myapp, подтяни изменения из git и перезапусти docker compose с пересборкой"

Warp сам соберет сложную команду в одну строку.


Nginx и SSL сертификаты

Зачем Nginx

Nginx — это обратный прокси (reverse proxy). Приложение работает на порту 3000, а Nginx слушает порты 80 и 443, принимает трафик и пробрасывает его приложению. Плюсы:

  • HTTPS/SSL в одном месте
  • Возможность держать несколько приложений на одном сервере
  • Кэширование, сжатие, раздача статики

Базовая конфигурация Nginx

Важно: Для Ubuntu 24.04 (Nginx 1.24) используется старый синтаксис listen ... http2. Для более свежих версий Nginx (1.25+) нужно писать http2 on;.

/etc/nginx/sites-available/myapp:

server {
    listen 80;
    server_name example.com www.example.com;

    # Перенаправляем HTTP на HTTPS (дальше про это)
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    # SSL сертификаты (дальше про как их получить)
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Пробрасываем трафик приложению на порту 3000
    location / {
        proxy_pass http://localhost:3000;
        
        # Важные заголовки
        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;
    }
}

Активация конфигурации:

# Создаём symlink
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp

# Проверяем синтаксис
sudo nginx -t

# Перезагружаем Nginx
sudo systemctl reload nginx

🤖 Warp Way (включить сайт):

"Включи сайт nginx myapp, создав симлинк из sites-available, проверь конфиг и перезагрузи сервис"

🤖 Warp Way (создать конфиг): Автоматическая генерация конфига:

"Сгенерируй конфиг nginx для домена example.com с проксированием на localhost:3000, http2 и заголовками безопасности. Сохрани его в /etc/nginx/sites-available/myapp"

Он выдаст готовый блок кода или команду cat <<EOF ....

Let's Encrypt и Certbot — бесплатные SSL сертификаты

Установка Certbot:

sudo apt update
sudo apt install certbot python3-certbot-nginx # Версия из репозитория Ubuntu 24.04

🤖 Warp Way:

"Установи certbot для nginx"

Получение сертификата:

sudo certbot --nginx -d example.com -d www.example.com

🤖 Warp Way:

"Запроси ssl сертификат для example.com используя certbot"

Certbot:

  1. Проверяет владение доменом (HTTP challenge на порт 80)
  2. Получает сертификат от Let's Encrypt
  3. Автоматически обновляет Nginx конфиг с SSL директивами
  4. Спрашивает email для напоминаний о продлении

После выполнения:

  • Сертификат в /etc/letsencrypt/live/example.com/
  • Nginx конфиг обновлён (HTTP → HTTPS redirect)
  • HTTPS работает

Проверка возобновления сертификата:

sudo systemctl list-timers | grep certbot
# Должен быть активный таймер

# Тест возобновления (безопасно)
sudo certbot renew --dry-run

Сертификаты Let's Encrypt действуют 90 дней, но Certbot продлевает их автоматически.

Дополнительно: безопасность

1. Firewall (UFW) Не стоит оставлять лишние порты открытыми. Рекомендуется закрыть всё, кроме SSH и веба:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

🤖 Warp Way:

"Включи фаервол ufw, разрешив только ssh и http/https трафик"

2. Security Headers Добавляем заголовки в конфиг Nginx:

server {
    listen 443 ssl http2;
    server_name example.com;
    
    # ... SSL и proxy_pass ...

    # Безопасность
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
}

🤖 Warp Way:

"Добавь заголовки безопасности (X-Frame-Options, X-Content-Type-Options и т.д.) в файл конфигурации nginx"

Проверка SSL:

# Локально
curl https://example.com

# Или через SSL Labs (https://www.ssllabs.com/ssltest/)

🤖 Warp Way:

"Проверь детали ssl сертификата для example.com используя curl"


Real-world flow: собираем всё вместе

Сценарий: создание Node.js приложения с базой данных.

Инициализация проекта:

mkdir my-app && cd my-app
git init
echo "# My App" > README.md
npm init -y
gh repo create my-app --public --source=. --push

🤖 Warp Way:

"Создай новую папку my-app, инициализируй npm проект, git репозиторий и создай публичный репозиторий github с пушем в origin"

Создание Dockerfile и compose.yaml (как выше с Node + PostgreSQL).

На сервере:

git clone git@github.com:username/my-app.git /var/www/my-app
cd /var/www/my-app
docker compose up -d

🤖 Warp Way:

"Клонируй https://github.com/username/my-app в /var/www/my-app и запусти docker compose в фоне"

Настройка Nginx и SSL (как выше).

Каждый раз при пуше кода:

git push origin main
# На сервере (если используются GitHub Actions, это происходит автоматически):
cd /var/www/my-app && git pull && docker compose down && docker compose up -d --build

🤖 Warp Way:

"Запушь изменения в main и зайди по ssh на сервер, чтобы подтянуть изменения и перезапустить docker compose с пересборкой"


Частые проблемы и решения

Docker контейнер не стартует:

docker compose logs app  # Смотреть логи

🤖 Warp: > "Покажи последние логи контейнера app и объясни ошибки"

Nginx не видит приложение:

# Проверка, что приложение слушает на 3000
docker compose ps  # Контейнер должен быть UP
curl http://localhost:3000  # С сервера

🤖 Warp: > "Проверь, слушается ли порт 3000 и запущен ли docker контейнер"

SSL сертификат истек:

sudo certbot renew  # Обновить сейчас (обычно автоматически)

🤖 Warp: > "Обнови все сертификаты certbot вручную"

Git не пушится (permission denied):

# Проверка SSH ключа
ssh -T git@github.com
# Если ошибка — см. раздел про SSH ключи

🤖 Warp: > "Проверь ssh соединение с github"


Итого

  • Warp — терминал, который понимает команды на английском
  • gh CLI — создание репо за 10 секунд
  • SSH ключи — один раз настроить, потом забыть
  • Docker — одна команда docker compose up, и всё работает везде
  • GitHub Actions — push в репо, и приложение деплоится автоматически
  • Nginx + Let's Encrypt — HTTPS за 5 минут

Полезные ссылки