Files
bellsystems-cp/backend/admin/router.py
bonamin 6eda151f06 fix: configure gitea webhook auto-deploy and fix provisioning NVS flash
- Add deploy-host.sh script for webhook-triggered docker redeploy
- Mark deploy-host.sh executable in .gitignore / git config
- Update docker-compose.yml and nginx.conf for auto-pull setup
- Fix vite.config.js and admin router for deployment environment
- Fix NVS generator CRC seed to match ESP-IDF esp_rom_crc32_le

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 09:14:58 +02:00

54 lines
1.8 KiB
Python

import asyncio
import hashlib
import hmac
import logging
from fastapi import APIRouter, HTTPException, Request
from config import settings
logger = logging.getLogger("admin.deploy")
router = APIRouter(prefix="/api/admin", tags=["admin"])
@router.post("/deploy")
async def deploy(request: Request):
"""Gitea webhook endpoint — pulls latest code and rebuilds Docker containers.
Gitea webhook configuration:
URL: https://<your-domain>/api/admin/deploy
Secret token: value of DEPLOY_SECRET env var
Content-Type: application/json
Trigger: Push events only (branch: main)
Add to VPS .env:
DEPLOY_SECRET=<random-strong-token>
DEPLOY_PROJECT_PATH=/home/bellsystems/bellsystems-cp
"""
if not settings.deploy_secret:
raise HTTPException(status_code=503, detail="Deploy secret not configured on server")
# Gitea sends the HMAC-SHA256 of the request body in X-Gitea-Signature
sig_header = request.headers.get("X-Gitea-Signature", "")
body = await request.body()
expected_sig = hmac.new(
key=settings.deploy_secret.encode(),
msg=body,
digestmod=hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(sig_header, expected_sig):
raise HTTPException(status_code=403, detail="Invalid webhook signature")
logger.info("Auto-deploy triggered via Gitea webhook")
# Write a trigger file to the host-mounted project path.
# A host-side watcher service (bellsystems-deploy-watcher) polls for this
# file and runs deploy-host.sh as the bellsystems user when it appears.
trigger_path = f"{settings.deploy_project_path}/.deploy-trigger"
with open(trigger_path, "w") as f:
f.write("deploy\n")
logger.info("Auto-deploy trigger file written")
return {"ok": True, "message": "Deploy started"}