commit 0a8c9616259afbf9b0379932577ede2188758897 Author: adminer Date: Tue Jan 13 00:11:31 2026 +0300 Добавить Readme diff --git a/Readme b/Readme new file mode 100644 index 0000000..3e158cf --- /dev/null +++ b/Readme @@ -0,0 +1,311 @@ + +Вот несколько реальных и достаточно популярных подходов в 2025–2026 годах, как организовать доставку **бинарников**, **конфигов** и **systemd**-юнитов на сервер с использованием **Git + Terraform** (без полного перехода на контейнеры). + +| № | Подход | Сложность | Идемпотентность | Скорость деплоя | Рекомендую в 2026 | +|----|--------------------------------------|-----------|------------------|------------------|--------------------| +| 1 | Terraform provisioner + git clone | ★☆☆ | Плохая | Средняя | Нет (только PoC) | +| 2 | Terraform + cloud-init/user-data | ★★☆ | Средняя | Медленно | Иногда (новые VM) | +| 3 | Git → Artifact (zip/tar) → S3/HTTPS → systemd-tmpfiles + remote-exec | ★★★ | Хорошая | Быстро | Да, классика | +| 4 | GitOps через Flux/ArgoCD | ★★★★ | Отличная | Очень быстро | Если уже есть k8s | +| 5 | Git → CI → rsync/scp + webhook/reloader | ★★☆ | Средняя–хорошая | Очень быстро | Самый простой живой вариант сейчас | +| 6 | Git → CI → deb/rpm → apt/yum + systemd | ★★★★ | Отличная | Средняя | Лучший долгосрочный вариант | + +### Самые живые и практичные варианты на сегодня (январь 2026) + +#### Вариант А — Самый простой и быстрый (очень популярен в 2025–2026) + +```bash +# Структура репозитория +my-service/ +├── bin/ +│ └── myapp # ← бинарник +├── config/ +│ └── config.yaml +├── systemd/ +│ └── myapp.service +├── deploy.sh # опционально +└── .github/workflows/deploy.yml +``` + +`.github/workflows/deploy.yml` пример: + +```yaml +name: Deploy to server + +on: + push: + branches: [ main ] + + jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Pack artifact + run: tar czf artifact.tar.gz bin/ config/ systemd/ + + - name: Copy to server + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ secrets.SERVER_IP }} + username: deploy + key: ${{ secrets.SSH_PRIVATE_KEY }} + source: "artifact.tar.gz" + target: "/opt/my-service.new" + + - name: Deploy & restart + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.SERVER_IP }} + username: deploy + key: ${{ secrets.SSH_PRIVATE_KEY }} + script: | + set -e + cd /opt/my-service.new + sudo rm -rf /opt/my-service.old + sudo mv /opt/my-service /opt/my-service.old || true + sudo mv /opt/my-service.new /opt/my-service + sudo cp systemd/myapp.service /etc/systemd/system/ + sudo systemctl daemon-reload + sudo systemctl enable --now myapp.service + ``` + + **Плюсы**: быстро, дёшево, понятно + **Минусы**: не совсем идемпотентно, нет отката версий «из коробки» + + #### Вариант Б — Terraform как оркестратор (очень чистый и воспроизводимый) + + ```hcl + variable "app_version" { default = "v1.2.3" } + + data "http" "release" { + url = "https://github.com/your-org/my-service/releases/download/${var.app_version}/artifact.tar.gz" + } + + resource "null_resource" "deploy" { + triggers = { + version = var.app_version + } + + connection { + type = "ssh" + user = "deploy" + private_key = file("~/.ssh/id_ed25519_deploy") + host = "your-server.example.com" + } + + provisioner "file" { + content = data.http.release.response_body + destination = "/tmp/artifact-${var.app_version}.tar.gz" + } + + provisioner "remote-exec" { + inline = [ + "set -e", + "mkdir -p /opt/my-service", + "tar xzf /tmp/artifact-${var.app_version}.tar.gz -C /opt/my-service", + "sudo cp /opt/my-service/systemd/myapp.service /etc/systemd/system/", + "sudo systemctl daemon-reload", + "sudo systemctl enable --now myapp.service", + "rm -f /tmp/artifact-*.tar.gz" + ] + } + } + ``` + + Или ещё чище — положить артефакт в **S3**/**Artifactory**/**GHCR** и тянуть по https. + + #### Вариант В — Золотой стандарт на 2026 год (если позволяет время и масштаб) + + 1. CI делает deb/rpm-пакет (или tar.gz + manifest.json) + 2. Публикует в Artifactory / Packagecloud / GitHub Releases / S3 + 3. Terraform только управляет инфраструктурой и желаемой версией + 4. На сервере работает **tiny agent** (systemd-таймер + curl + bash) или **ansible-pull**, который раз в 1–5 минут проверяет новую версию и ставит её + + Пример минимального systemd-таймера + сервиса-апдейтера: + + ```ini + # /etc/systemd/system/myapp-updater.timer + [Unit] + Description=Update myapp every 5 minutes + + [Timer] + OnBootSec=3min + OnUnitActiveSec=5min + Unit=myapp-updater.service + + [Install] + WantedBy=timers.target + ``` + + ```ini + # /etc/systemd/system/myapp-updater.service + [Service] + Type=oneshot + ExecStart=/opt/myapp/update.sh + ``` + + ### Краткие рекомендации + + Ситуация | Что выбрать в 2026 + -------------------------------------|------------------------- + Один-два сервера, быстро надо | Вариант А (GitHub Actions + scp + ssh) + Средний проект, много серверов | Вариант Б (Terraform + releases) или Вариант А + Ansible-pull + Хотите «по-взрослому», надолго | deb/rpm + свой маленький apt/yum репозиторий + Уже есть Kubernetes | Flux/ArgoCD + kustomize/helm + git + + Удачи с деплоем! 🚀 + Какой у тебя сейчас масштаб и какие ограничения (деньги, время, команда)? Могу предложить более точный вариант. + ] + } + } + } + } + } + } + + + + +ри 3 людях в команде, нулевом/очень маленьком бюджете и ~10 серверах самая разумная стратегия на 2026 год выглядит так: + +**Цель**: минимизировать время поддержки + количество мест, где может что-то сломаться +**Принцип**: один раз настроил → дальше почти всё через git push + +### Рекомендуемый вариант (топ-1 для вашей ситуации) + +**GitHub Actions → scp/rsync + atomic переключение + systemd** + +Почему именно это: + +- Стоимость ≈ 0 € (GitHub Actions free tier 2000 минут/месяц хватает с огромным запасом) +- Минимум новых технологий +- Работает на любых linux-серверах (даже очень старых) +- Легко откатывать (оставляем предыдущую версию) +- 3 человека реально поддерживают без боли + +#### Структура репозитория (самая практичная) + +``` +my-project/ +├── app/ # исходники +│ └── main.go +├── deploy/ +│ ├── bin/ # сюда кладём готовый бинарник при релизе (опционально) +│ ├── config/ +│ │ └── prod.yaml +│ ├── systemd/ +│ │ └── myapp.service +│ └── versions/ +│ └── current.txt # просто номер версии или git sha +└── .github/workflows/ + └── deploy.yml + ``` + + #### Самый простой и надёжный deploy.yml (2026 версия) + + ```yaml + name: Deploy to all servers + + on: + push: + branches: [ main ] + workflow_dispatch: # можно запускать вручную + + jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.23' # или ваша версия + + - name: Build binary + run: | + GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" \ + -o deploy/bin/myapp ./app + + - name: Pack artifact + run: | + cd deploy + tar czf artifact.tar.gz bin/ config/ systemd/ versions/ + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: deployment-artifact + path: deploy/artifact.tar.gz + + deploy: + needs: build + runs-on: ubuntu-latest + strategy: + matrix: + server: [ "10.10.1.11", "10.10.1.12", "..." ] # ваши 10 ip/доменов + # или лучше через переменные/файл, но для начала так проще + + steps: + - uses: actions/download-artifact@v4 + with: + name: deployment-artifact + + - name: Deploy to ${{ matrix.server }} + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ matrix.server }} + username: deploy + key: ${{ secrets.SSH_PRIVATE_KEY }} + source: "artifact.tar.gz" + target: "/opt/myapp.new" + strip_components: 0 + + - name: Atomic switch & restart + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ matrix.server }} + username: deploy + key: ${{ secrets.SSH_PRIVATE_KEY }} + script: | + set -euo pipefail + cd /opt/myapp.new + sudo tar xzf artifact.tar.gz + + # Проверка что бинарник запускается (очень важно!) + sudo /opt/myapp.new/bin/myapp --version || exit 1 + + sudo rm -rf /opt/myapp.old + sudo mv /opt/myapp /opt/myapp.old 2>/dev/null || true + sudo mv /opt/myapp.new /opt/myapp + + sudo cp /opt/myapp/systemd/myapp.service /etc/systemd/system/ + sudo systemctl daemon-reload + sudo systemctl enable myapp.service + sudo systemctl restart myapp.service + + # Опционально: чистка старых версий через 1 день + # find /opt -maxdepth 1 -name 'myapp.old.*' -mtime +1 -exec rm -rf {} \; + ``` + + ### Альтернативы (если описанное выше по каким-то причинам не подходит) + + | Вариант | Сложность | Время настройки | Стоимость | Подходит если... | + |-------------------------------|-----------|------------------|-----------|-----------------------------------------------| + | GitHub Actions + scp (выше) | ★☆☆ | 1–3 дня | ~0€ | Хотите самый быстрый старт | + | Ansible-pull из git каждые 5 мин | ★★☆ | 3–7 дней | ~0€ | Хотите более идемпотентно и конфиги в git | + | Terraform + null_resource/ssh | ★★★ | 5–14 дней | ~0€ | Уже активно используете terraform для серверов| + | Самопальный tiny-agent (curl+bash+systemd timer) | ★★☆ | 4–10 дней | ~0€ | Очень не любите внешние зависимости | + | Docker + docker-compose pull | ★★☆ | 4–12 дней | ~0€ | Готовы перейти на контейнеры (рекомендую!) | + + ### Краткий совет по приоритетам + + 1. Сделайте сначала **один** сервер по схеме выше (очень быстро) + 2. Добавьте простейшую проверку здоровья после рестарта + `systemctl is-active --quiet myapp && curl -f http://localhost:8080/health || exit 1` + 3. Только после этого масштабируйте на остальные 9 серверов + 4. Параллельно думайте о переходе на **docker + docker compose pull** — это следующий логичный и очень популярный шаг для команд 3–8 человек в 2026 году (даже без kubernetes) + + Если скажете, на каком языке написано приложение и есть ли уже docker — смогу дать ещё более точный вариант. \ No newline at end of file