diff --git a/.env.example b/.env.example index 7a1c078..882367d 100644 --- a/.env.example +++ b/.env.example @@ -120,7 +120,10 @@ COOKIE_SECURE=true # ===================================================================== # === DEPLOYMENT & REPOSITORY SETTINGS === # ===================================================================== -GHCR_TOKEN=ghp_ТВОЙ_ТОКЕН_ОТ_ГИТХАБА_ДЛЯ_ДОСТУПА_К_РЕЕСТРУ +# Токен Gitea (право write:package) — нужен самому бэкенду в рантайме для +# провижининга новых нод (см. NodeService::provision_node_via_ssh, шлёт этот +# же токен на ноду, чтобы она тоже могла тянуть образ с Gitea Registry). +GITEA_REGISTRY_TOKEN=CHANGE_ME_GITEA_REGISTRY_TOKEN VPS_IP=CHANGE_ME_VPS_IP DEPLOY_DIR=/root/netrunner-core BINARY_NAME=netrunner-control-plane diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 760a669..dbbe450 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -1,9 +1,13 @@ # Копия .github/workflows/build.yml для Gitea Actions. Отличие от оригинала: -# логин на ghcr.io использует secrets.GHCR_TOKEN (настоящий GitHub PAT с -# правами write:packages), а не secrets.GITHUB_TOKEN — автотокен Gitea валиден -# только для самого Gitea (API/пакеты этого инстанса), на ghcr.io им не -# залогиниться. Секрет GHCR_TOKEN нужно завести отдельно в настройках этого -# репозитория/организации в Gitea. +# реестр — встроенный Container Registry самой Gitea (gitea.netrunner-vpn.com), +# не ghcr.io — секрет secrets.GITHUB_TOKEN там валиден только на самом +# GitHub. Логин — токеном Gitea с правом write:package +# (secrets.GITEA_REGISTRY_TOKEN), один и тот же токен используется во всех +# репозиториях, где собираются образы (netrunner-backend/netrunner-landing/ +# netrunner-proxy) — пакеты в Gitea принадлежат аккаунту, не конкретному +# репозиторию, заводить по секрету на каждый репозиторий не нужно, но +# значение нужно продублировать в Settings каждого из них (Gitea не даёт +# организационных секретов на уровне всего аккаунта для personal-репозиториев). name: Build & Push Image on: @@ -13,12 +17,12 @@ on: workflow_dispatch: env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository_owner }}/netrunner-control-plane + REGISTRY: gitea.netrunner-vpn.com + IMAGE_NAME: nineap/netrunner-control-plane jobs: build: - name: Build and push to GHCR + name: Build and push to Gitea Registry runs-on: ubuntu-24.04 permissions: contents: read @@ -30,12 +34,12 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Log in to GHCR + - name: Log in to Gitea Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} - password: ${{ secrets.GHCR_TOKEN }} + password: ${{ secrets.GITEA_REGISTRY_TOKEN }} - name: Extract metadata (tags, labels) id: meta @@ -76,12 +80,12 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Log in to GHCR + - name: Log in to Gitea Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} - password: ${{ secrets.GHCR_TOKEN }} + password: ${{ secrets.GITEA_REGISTRY_TOKEN }} - name: Build and push uses: docker/build-push-action@v6 @@ -90,9 +94,7 @@ jobs: file: ./Dockerfile.caddy push: true # Захардкожено, не ${{ github.repository_owner }}: он резолвится в - # "nineAp" (смешанный регистр), Docker такие теги отклоняет — та же - # причина, по которой deploy.yml тоже хардкодит "nineap" для - # основного образа вместо репозиторного контекста. + # "nineAp" (смешанный регистр), Docker такие теги отклоняет. tags: ${{ env.REGISTRY }}/nineap/netrunner-caddy-cloudflare:latest cache-from: type=gha,scope=caddy cache-to: type=gha,mode=max,scope=caddy diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 1e53702..0687c73 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,5 +1,6 @@ -# Копия .github/workflows/deploy.yml для Gitea Actions. secrets.GHCR_TOKEN -# здесь уже был настоящим PAT (не автотокеном), менять не пришлось. +# Копия .github/workflows/deploy.yml для Gitea Actions. Образы тянутся из +# встроенного Container Registry самой Gitea (gitea.netrunner-vpn.com), не +# ghcr.io — secrets.GITEA_REGISTRY_TOKEN, не GHCR_TOKEN/GITHUB_TOKEN. # Триггер workflow_run (авто-деплой после успешной сборки) поддерживается не # во всех версиях Gitea Actions — если deploy-dev не срабатывает автоматически # после build, проверить версию Gitea или временно дергать деплой вручную @@ -22,7 +23,7 @@ on: workflow_dispatch: inputs: image_tag: - description: "Тег образа в GHCR для прод-деплоя" + description: "Тег образа в Gitea Registry для прод-деплоя" required: true default: "latest" @@ -37,8 +38,8 @@ jobs: ref: ${{ github.event.workflow_run.head_sha }} # Копируем compose-файл + Caddyfile (примонтированный конфиг, не образ — - # сам Caddy-образ, как и образ бэкенда, дев-сервер тянет из GHCR, собран - # в build.yml::build-caddy. Собирать xcaddy прямо на VPS один раз уже не + # сам Caddy-образ, как и образ бэкенда, дев-сервер тянет из Gitea Registry, + # собран в build.yml::build-caddy. Собирать xcaddy прямо на VPS один раз уже не # уложилось в таймаут SSH-деплоя и уронило весь прогон). - name: Sync compose file to Dev VPS uses: appleboy/scp-action@v0.1.7 @@ -56,7 +57,7 @@ jobs: host: ${{ vars.DEV_VPS_IP }} username: root key: ${{ secrets.DEV_SSH_PRIVATE_KEY }} - envs: "DB_PASSWORD,CF_API_TOKEN,JWT_SECRET,ARGON_SALT,TON_MASTER_WALLET,PROXY_INTERNAL_SECRET,CRYPTOBOT_API_TOKEN,TELOXIDE_TOKEN,BOT_USERNAME" + envs: "DB_PASSWORD,CF_API_TOKEN,JWT_SECRET,ARGON_SALT,TON_MASTER_WALLET,PROXY_INTERNAL_SECRET,CRYPTOBOT_API_TOKEN,TELOXIDE_TOKEN,BOT_USERNAME,GITEA_REGISTRY_TOKEN" script: | set -e cd /root/netrunner-core @@ -72,6 +73,10 @@ jobs: ARGON_SALT=${ARGON_SALT} TON_MASTER_WALLET=${TON_MASTER_WALLET} PROXY_INTERNAL_SECRET=${PROXY_INTERNAL_SECRET} + # Нужен самому бэкенду в рантайме, не только CI — см. + # NodeService::provision_node_via_ssh (шлёт этот же токен на новую + # ноду, чтобы она тоже могла тянуть образ с gitea.netrunner-vpn.com). + GITEA_REGISTRY_TOKEN=${GITEA_REGISTRY_TOKEN} CRYPTOBOT_API_TOKEN=${CRYPTOBOT_API_TOKEN} CRYPTOBOT_TESTNET=true BOT_ENABLED=true @@ -87,11 +92,11 @@ jobs: EOF chmod 600 .env - export IMAGE="ghcr.io/nineap/netrunner-control-plane:latest" - export CADDY_IMAGE="ghcr.io/nineap/netrunner-caddy-cloudflare:latest" + export IMAGE="gitea.netrunner-vpn.com/nineap/netrunner-control-plane:latest" + export CADDY_IMAGE="gitea.netrunner-vpn.com/nineap/netrunner-caddy-cloudflare:latest" echo "🚀 Deploying ${IMAGE} to DEV" - echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin + echo "${{ secrets.GITEA_REGISTRY_TOKEN }}" | docker login gitea.netrunner-vpn.com -u ${{ github.actor }} --password-stdin docker compose -f docker-compose.dev-remote.yml pull docker compose -f docker-compose.dev-remote.yml up -d --remove-orphans @@ -109,6 +114,7 @@ jobs: CRYPTOBOT_API_TOKEN: ${{ secrets.DEV_CRYPTOBOT_API_TOKEN }} TELOXIDE_TOKEN: ${{ secrets.DEV_TELOXIDE_TOKEN }} BOT_USERNAME: ${{ vars.DEV_BOT_USERNAME }} + GITEA_REGISTRY_TOKEN: ${{ secrets.GITEA_REGISTRY_TOKEN }} deploy-prod: name: Pull & restart on Prod VPS @@ -133,7 +139,7 @@ jobs: host: ${{ vars.VPS_IP }} username: root key: ${{ secrets.SSH_PRIVATE_KEY }} - envs: "DB_PASSWORD,DATA_VPS_IP,JWT_SECRET,ARGON_SALT,TON_MASTER_WALLET,GRAFANA_PUBLIC_URL,PROXY_INTERNAL_SECRET,CRYPTOBOT_API_TOKEN,TELOXIDE_TOKEN,BOT_USERNAME,WEB_APP_BASE_URL" + envs: "DB_PASSWORD,DATA_VPS_IP,JWT_SECRET,ARGON_SALT,TON_MASTER_WALLET,GRAFANA_PUBLIC_URL,PROXY_INTERNAL_SECRET,CRYPTOBOT_API_TOKEN,TELOXIDE_TOKEN,BOT_USERNAME,WEB_APP_BASE_URL,GITEA_REGISTRY_TOKEN" script: | set -e cd /root/netrunner-core @@ -156,6 +162,9 @@ jobs: BOT_USERNAME=${BOT_USERNAME} WEB_APP_BASE_URL=${WEB_APP_BASE_URL} PROXY_INTERNAL_SECRET=${PROXY_INTERNAL_SECRET} + # Нужен самому бэкенду в рантайме, не только CI — см. + # NodeService::provision_node_via_ssh. + GITEA_REGISTRY_TOKEN=${GITEA_REGISTRY_TOKEN} PORT=8080 SUBSCRIPTION_CHECK_INTERVAL=1800 NODE_HEALTH_CHECK_INTERVAL=60 @@ -168,10 +177,10 @@ jobs: EOF chmod 600 .env - export IMAGE="ghcr.io/nineap/netrunner-control-plane:${{ github.event.inputs.image_tag }}" + export IMAGE="gitea.netrunner-vpn.com/nineap/netrunner-control-plane:${{ github.event.inputs.image_tag }}" echo "🚀 Deploying ${IMAGE}" - echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin + echo "${{ secrets.GITEA_REGISTRY_TOKEN }}" | docker login gitea.netrunner-vpn.com -u ${{ github.actor }} --password-stdin # Тянем свежий образ, прогоняем миграции (one-shot) и поднимаем сервисы. docker compose -f docker-compose.prod.yml pull @@ -193,3 +202,4 @@ jobs: TELOXIDE_TOKEN: ${{ secrets.TELOXIDE_TOKEN }} BOT_USERNAME: ${{ vars.BOT_USERNAME }} WEB_APP_BASE_URL: ${{ vars.WEB_APP_BASE_URL }} + GITEA_REGISTRY_TOKEN: ${{ secrets.GITEA_REGISTRY_TOKEN }} diff --git a/docker-compose.dev-remote.yml b/docker-compose.dev-remote.yml index acfc467..d363867 100644 --- a/docker-compose.dev-remote.yml +++ b/docker-compose.dev-remote.yml @@ -6,7 +6,7 @@ services: # One-shot: применяет миграции и завершается. Требует только DATABASE_URL. migrate: - image: ${IMAGE:-ghcr.io/nineap/netrunner-control-plane:latest} + image: ${IMAGE:-gitea.netrunner-vpn.com/nineap/netrunner-control-plane:latest} container_name: netrunner-migrate-dev command: ["./netrunner-control-plane", "--migrate"] environment: @@ -19,7 +19,7 @@ services: - netrunner_grid_dev app: - image: ${IMAGE:-ghcr.io/nineap/netrunner-control-plane:latest} + image: ${IMAGE:-gitea.netrunner-vpn.com/nineap/netrunner-control-plane:latest} container_name: netrunner-app-dev-remote restart: always ports: @@ -85,7 +85,7 @@ services: # компиляция xcaddy (Go, тянет много модулей) на этой машине один раз уже # не уложилась в таймаут SSH-деплоя и уронила весь прогон. caddy: - image: ${CADDY_IMAGE:-ghcr.io/nineap/netrunner-caddy-cloudflare:latest} + image: ${CADDY_IMAGE:-gitea.netrunner-vpn.com/nineap/netrunner-caddy-cloudflare:latest} container_name: netrunner-caddy-dev restart: always ports: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 32872dd..55dd994 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -14,7 +14,7 @@ services: # One-shot: применяет миграции и завершается. Требует только DATABASE_URL. migrate: - image: ${IMAGE:-ghcr.io/nineap/netrunner-control-plane:latest} + image: ${IMAGE:-gitea.netrunner-vpn.com/nineap/netrunner-control-plane:latest} container_name: netrunner-migrate command: ["./netrunner-control-plane", "--migrate"] environment: @@ -24,7 +24,7 @@ services: - netrunner_grid app: - image: ${IMAGE:-ghcr.io/nineap/netrunner-control-plane:latest} + image: ${IMAGE:-gitea.netrunner-vpn.com/nineap/netrunner-control-plane:latest} container_name: netrunner-app restart: always ports: diff --git a/src/modules/nodes/service.rs b/src/modules/nodes/service.rs index a979438..33bbe87 100644 --- a/src/modules/nodes/service.rs +++ b/src/modules/nodes/service.rs @@ -153,8 +153,8 @@ impl NodeService { let sess = Self::connect_ssh(ip, "root", password)?; // 3. Подготавливаем команды автоматизации - let gh_token = std::env::var("GHCR_TOKEN").map_err(|_| { - AppError::Internal("GHCR_TOKEN не задан — провижининг ноды невозможен".into()) + let gh_token = std::env::var("GITEA_REGISTRY_TOKEN").map_err(|_| { + AppError::Internal("GITEA_REGISTRY_TOKEN не задан — провижининг ноды невозможен".into()) })?; // Секрет и публичный URL этого же бэкенда — нода должна ходить именно // сюда для проверки токенов/лимитов (--require-auth), а не работать diff --git a/templates/init_node.sh b/templates/init_node.sh index 0c9b877..647a5b0 100644 --- a/templates/init_node.sh +++ b/templates/init_node.sh @@ -10,11 +10,11 @@ if ! command -v docker &> /dev/null; then sh get-docker.sh fi -echo "[*] Step 3: Logging into ghcr.io via Control Plane token..." -echo "$GH_TOKEN" | docker login ghcr.io -u nineap --password-stdin +echo "[*] Step 3: Logging into Gitea Registry via Control Plane token..." +echo "$GH_TOKEN" | docker login gitea.netrunner-vpn.com -u nineap --password-stdin echo "[*] Step 4: Pulling the latest Netrunner image..." -docker pull ghcr.io/nineap/netrunner-proxy:latest +docker pull gitea.netrunner-vpn.com/nineap/netrunner-proxy:latest echo "[*] Step 5: Starting Netrunner Proxy at port ${NODE_PORT}..." # NODE_PORT/SNI_DOMAIN/BACKEND_URL/PROXY_INTERNAL_SECRET подставляет @@ -34,7 +34,7 @@ docker run -d \ --cap-add DAC_OVERRIDE \ --device /dev/net/tun:/dev/net/tun \ -e PROXY_INTERNAL_SECRET="$PROXY_INTERNAL_SECRET" \ - ghcr.io/nineap/netrunner-proxy:latest \ + gitea.netrunner-vpn.com/nineap/netrunner-proxy:latest \ ./netrunner-proxy \ --port "$NODE_PORT" \ --decoy-host "$SNI_DOMAIN" \