521d77f0cc
Build & Push Proxy Image / build (push) Failing after 7m45s
Каждая нода теперь логинится и тянет образ с gitea.netrunner-vpn.com напрямую (secrets.GITEA_REGISTRY_TOKEN, тот же, что и в build.yml).
146 lines
6.9 KiB
YAML
146 lines
6.9 KiB
YAML
# Деплой на прокси-ноды из nodes.json. Список серверов — сам файл в корне
|
||
# репозитория (name/host/proxy_port/decoy_host на каждую ноду), поддерживать
|
||
# его руками при добавлении/выводе серверов.
|
||
#
|
||
# Запуск только вручную (workflow_dispatch) — параметр target: имя ноды из
|
||
# nodes.json (поле "name") или "all" для обновления сразу всех. Job "resolve"
|
||
# фильтрует список по этому параметру и отдаёт job'у "deploy" как matrix —
|
||
# каждая нода тогда видна в прогоне отдельной строкой, с отдельным логом.
|
||
# GH/Gitea Actions не поддерживают выпадающий список (type: choice) с
|
||
# вариантами из файла — только статичные в самом yaml, а список нод меняется
|
||
# независимо от workflow, поэтому просто текстовое поле, значение — точное
|
||
# имя из nodes.json.
|
||
#
|
||
# Каждый деплой пересоздаёт контейнер (pull нового образа + rm + run) — не
|
||
# просто restart, иначе новый образ не подхватится, раз контейнер уже создан
|
||
# со старым слоем.
|
||
#
|
||
# Секреты (общие на все ноды — один master-ключ, как и при первичном
|
||
# провижининге через netrunner-backend, см. NodeService::provision_node_via_ssh):
|
||
# - PROXY_NODES_SSH_KEY — приватный SSH-ключ (root на все ноды)
|
||
# - PROXY_INTERNAL_SECRET — тот же секрет, что и PROXY_INTERNAL_SECRET у бэкенда
|
||
# - GITEA_REGISTRY_TOKEN — тот же, что и в build.yml (Container Registry Gitea,
|
||
# не ghcr.io — каждая нода тянет образ напрямую с gitea.netrunner-vpn.com)
|
||
#
|
||
# Repo Variable (vars.*, не secret — публичный URL, не даёт доступа сам по себе):
|
||
# - BACKEND_URL — публичный адрес control plane (WEB_APP_BASE_URL у бэкенда)
|
||
#
|
||
# Job update-observability-targets (см. ниже) обновляет список scrape-таргетов
|
||
# для центрального Prometheus (netrunner-data/docker-compose.observability.yml,
|
||
# job "netrunner-proxy-nodes") при КАЖДОМ прогоне (независимо от input target,
|
||
# т.к. использует полный nodes.json) — ему нужны СВОИ копии секретов/vars
|
||
# VPS с данными, продублировать в Settings этого репозитория (те же значения,
|
||
# что уже есть в netrunner-data):
|
||
# - vars.DATA_VPS_IP
|
||
# - secrets.DATA_SSH_PRIVATE_KEY
|
||
name: Deploy Proxy Nodes
|
||
|
||
on:
|
||
workflow_dispatch:
|
||
inputs:
|
||
target:
|
||
description: 'Имя ноды из nodes.json ("name"), или "all" — обновить сразу все'
|
||
required: true
|
||
default: "all"
|
||
|
||
jobs:
|
||
resolve:
|
||
runs-on: ubuntu-24.04
|
||
outputs:
|
||
targets: ${{ steps.filter.outputs.targets }}
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Filter nodes.json by input
|
||
id: filter
|
||
run: |
|
||
set -e
|
||
command -v jq >/dev/null || (apt-get update && apt-get install -y jq)
|
||
|
||
target="${{ github.event.inputs.target }}"
|
||
if [ "$target" = "all" ]; then
|
||
filtered=$(jq -c '.' nodes.json)
|
||
else
|
||
filtered=$(jq -c --arg n "$target" '[.[] | select(.name == $n)]' nodes.json)
|
||
fi
|
||
|
||
count=$(echo "$filtered" | jq 'length')
|
||
if [ "$count" -eq 0 ]; then
|
||
echo "Нода '$target' не найдена в nodes.json" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo "targets=$filtered" >> "$GITHUB_OUTPUT"
|
||
|
||
deploy:
|
||
needs: resolve
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
include: ${{ fromJson(needs.resolve.outputs.targets) }}
|
||
runs-on: ubuntu-24.04
|
||
steps:
|
||
- name: Deploy to ${{ matrix.name }} (${{ matrix.host }})
|
||
uses: appleboy/ssh-action@v1
|
||
with:
|
||
host: ${{ matrix.host }}
|
||
username: root
|
||
key: ${{ secrets.PROXY_NODES_SSH_KEY }}
|
||
script: |
|
||
set -e
|
||
echo "🚀 Деплой на ${{ matrix.name }} (${{ matrix.host }}:${{ matrix.proxy_port }})"
|
||
|
||
echo "${{ secrets.GITEA_REGISTRY_TOKEN }}" | docker login gitea.netrunner-vpn.com -u ${{ github.actor }} --password-stdin
|
||
docker pull gitea.netrunner-vpn.com/nineap/netrunner-proxy:latest
|
||
|
||
docker stop netrunner-proxy 2>/dev/null || true
|
||
docker rm netrunner-proxy 2>/dev/null || true
|
||
|
||
docker run -d \
|
||
--name netrunner-proxy \
|
||
--restart always \
|
||
--network host \
|
||
--cap-add NET_ADMIN --cap-add NET_RAW --cap-add DAC_OVERRIDE \
|
||
--device /dev/net/tun:/dev/net/tun \
|
||
-e PROXY_INTERNAL_SECRET="${{ secrets.PROXY_INTERNAL_SECRET }}" \
|
||
gitea.netrunner-vpn.com/nineap/netrunner-proxy:latest \
|
||
./netrunner-proxy \
|
||
--port "${{ matrix.proxy_port }}" \
|
||
--decoy-host "${{ matrix.decoy_host }}" \
|
||
--require-auth \
|
||
--backend-url "${{ vars.BACKEND_URL }}" \
|
||
--health-port 9091 \
|
||
--metrics-port 9093
|
||
|
||
docker image prune -f
|
||
echo "✅ ${{ matrix.name }} обновлена."
|
||
|
||
# Независимо от того, какая конкретно нода деплоилась (target может быть
|
||
# одной нодой, не "all") — список scrape-таргетов всегда генерится из ПОЛНОГО
|
||
# nodes.json, чтобы центральный Prometheus не терял из виду остальные ноды.
|
||
update-observability-targets:
|
||
runs-on: ubuntu-24.04
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Generate targets/nodes.json from nodes.json
|
||
run: node scripts/generate-prometheus-targets.mjs nodes.json > nodes.targets.json
|
||
|
||
- name: Upload to observability VPS
|
||
uses: appleboy/scp-action@v0.1.7
|
||
with:
|
||
host: ${{ vars.DATA_VPS_IP }}
|
||
username: root
|
||
key: ${{ secrets.DATA_SSH_PRIVATE_KEY }}
|
||
source: "nodes.targets.json"
|
||
target: "/root/netrunner-data/observability/targets"
|
||
strip_components: 0
|
||
|
||
- name: Rename to nodes.json (file_sd_configs ждёт именно это имя)
|
||
uses: appleboy/ssh-action@v1
|
||
with:
|
||
host: ${{ vars.DATA_VPS_IP }}
|
||
username: root
|
||
key: ${{ secrets.DATA_SSH_PRIVATE_KEY }}
|
||
script: mv /root/netrunner-data/observability/targets/nodes.targets.json /root/netrunner-data/observability/targets/nodes.json
|