Add SOPS + .env automation after ansible/run

This commit is contained in:
sascha 2026-04-22 21:20:19 +02:00
parent 6f9e1a47dd
commit 8fe5bbd069

67
app.py
View file

@ -431,6 +431,72 @@ async def ansible_run(request: Request, _=Depends(_verify)):
except Exception as e: except Exception as e:
log.warning(f"Hawser token sync failed for {hostname}: {e}") log.warning(f"Hawser token sync failed for {hostname}: {e}")
# NEW: SOPS + .env handling for Git-centric deployments
try:
log.info(f"Checking for SOPS .env setup for {hostname}")
# Get SOPS age public key from automation1
rc4, age_pub, _ = _ssh(AUTOMATION1, "cat ~/.config/sops/age/keys.txt | grep '^# public key' | awk '{print $4}'", timeout=10)
age_pub = age_pub.strip() if rc4 == 0 else None
if age_pub:
# Check if compose.yaml exists in /app-config/github/{hostname}/
rc5, compose_check, _ = _ssh(AUTOMATION1, f"test -f /app-config/github/{hostname}/compose.yaml && echo 'found' || echo 'missing'", timeout=10)
if compose_check.strip() == "found":
log.info(f"Found compose.yaml for {hostname}, generating .env")
# Generate secrets
import secrets as sec
secret_key = base64.b64encode(sec.token_bytes(32)).decode()
admin_pw = sec.token_urlsafe(16)
db_pw = sec.token_urlsafe(16)
# Store in vault cache
_vault_cache[f"{hostname}_secret_key"] = secret_key
_vault_cache[f"{hostname}_admin_password"] = admin_pw
_vault_cache[f"{hostname}_db_password"] = db_pw
# Build .env content
env_lines = ["# Auto-generated by Butler", f"TZ=Europe/Berlin", "PUID=1000", "PGID=1000"]
# Detect service type from hostname
if "paperless" in hostname.lower():
env_lines.extend([
f"PAPERLESS_ADMIN_USER=admin",
f"PAPERLESS_ADMIN_PASSWORD={admin_pw}",
f"PAPERLESS_SECRET_KEY={secret_key}",
f"PAPERLESS_URL=http://{vm_ip}:8000",
"PAPERLESS_TIME_ZONE=Europe/Berlin",
"PAPERLESS_OCR_LANGUAGE=deu",
"PAPERLESS_REDIS=redis://redis:6379",
"PAPERLESS_DBHOST=postgres",
"PAPERLESS_DBPORT=5432",
"PAPERLESS_DBNAME=paperless",
"PAPERLESS_DBUSER=paperless",
f"PAPERLESS_DBPASS={db_pw}",
"POSTGRES_DB=paperless",
"POSTGRES_USER=paperless",
f"POSTGRES_PASSWORD={db_pw}",
])
env_content = "\\n".join(env_lines) + "\\n"
# Write .env to automation1
env_tmp = f"/tmp/{hostname}.env"
_ssh(AUTOMATION1, f"printf '%s' '{env_content}' > {env_tmp}", timeout=10)
# Encrypt with SOPS
enc_tmp = f"/tmp/{hostname}.env.enc"
_ssh(AUTOMATION1, f"cd /tmp && SOPS_AGE_RECIPIENT={age_pub} sops --encrypted-regex 'PASSWORD|SECRET_KEY|_PASS' --encrypt {env_tmp} > {enc_tmp}", timeout=30)
# Copy to VM
_ssh(AUTOMATION1, f"scp -o StrictHostKeyChecking=no {env_tmp} sascha@{vm_ip}:/app-config/github/{hostname}/.env 2>/dev/null || true", timeout=15)
_ssh(AUTOMATION1, f"scp -o StrictHostKeyChecking=no {enc_tmp} sascha@{vm_ip}:/app-config/github/{hostname}/.env.enc 2>/dev/null || true", timeout=15)
log.info(f"SOPS .env setup completed for {hostname}")
except Exception as e:
log.warning(f"SOPS .env setup failed for {hostname}: {e}")
return {"status": "ok" if rc == 0 else "error", "rc": rc, "output": out[-1000:]} return {"status": "ok" if rc == 0 else "error", "rc": rc, "output": out[-1000:]}
@app.get("/ansible/status/{job_id}") @app.get("/ansible/status/{job_id}")
@ -562,3 +628,4 @@ async def proxy(service: str, path: str, request: Request, _=Depends(_verify)):