Author SHA1 Message Date
Bot a15e0100df provision-secrets: add flowagent_* case-entry to the ai) stack (matched pair with ai.yaml's mcpo cutover)
Surgical addition to the existing case "ai)" block only — every other
case, comment, and line in this ~26KB pipeline file is byte-for-byte
unchanged from main. Given this file's documented incident history from
prior full-file rewrites (see header comment), this was hand-verified
against the current main content line-by-line before writing, not
generated fresh.

Adds:
  - 3 new environment: entries (FLOWAGENT_AZURE_CLIENT_ID/TENANT_ID/
    CLIENT_SECRET) via from_secret, alongside the existing ai_* secrets
  - Inside the existing `ai)` case, after the ai.env rewrite block: three
    create_or_update_secret calls provisioning flowagent_azure_client_id,
    flowagent_azure_tenant_id, flowagent_azure_client_secret as native
    Docker Swarm secrets (Pattern C, _FILE convention) — NOT written into
    ai/ai.env, since mcpo's flowagent entry reads them via
    /run/secrets/flowagent_azure_* per flowagent/entrypoint.sh, not env vars
  - A short comment explaining why these three are Pattern C secrets
    inside an otherwise Pattern-B (host .env) stack case

This is the matched-pair companion to the ai.yaml commit in this same PR,
per the FlowAgent progress note's explicit sequencing requirement (both
land together, reviewed, not auto-merged to main).
2026-09-02 16:53:10 -07:00
Bot bcfb24b16d ai.yaml: cut mcpo over to the confirmed-working flowagent-mcpo image + wire flowagent Docker secrets (never touches mcpo-critical)
Image pinned to git.bryanmail.net/homelab/flowagent-mcpo:916164714429 —
the exact sha-tagged image built and smoke-tested clean in mcp-config
pipeline #22 (build-and-push-flowagent + smoke-test-flowagent-image both
success). NOT :latest, for reproducible deploys.

Adds a secrets: block to the mcpo service only, referencing the 3
flowagent_azure_* Docker Swarm secrets (Pattern C, _FILE convention,
consumed by flowagent/entrypoint.sh via /run/secrets/flowagent_azure_*).
Declares those 3 secrets as external at top level, mirroring the existing
vaultwarden_admin_token_v2 pattern in vaultwarden.yaml.

Companion secret-provisioning change lands in the same PR as a separate
commit in .woodpecker/deploy.yml's provision-secrets step (case "ai)").

mcpo-critical (lines defining Proxmox access) is completely untouched —
still stock ghcr.io/open-webui/mcpo:main, no secrets: block, unchanged.

Per FlowAgent MCP progress note: Azure AD App Registration is reported
created with real secrets already in Woodpecker (both mcp-config and
compose-files repos) as of this PR. This is a reviewed PR against a
feature branch, NOT auto-merged to main — deploy only happens after
manual review/merge, per user's explicit request for a manual-revert
safety net on this high-blast-radius shared stack (LiteLLM, Open WebUI,
n8n also live here).
2026-09-02 16:51:31 -07:00
Bot 42d31e38e4 git stack: switch provision-secrets to Pattern B .env rewrite (test phase) + add git to bootstrap-tier guard
ci/woodpecker/push/deploy Pipeline was successful
ci/woodpecker/cron/renovate Pipeline was successful
Context: git hosts the source of truth for every other stack's compose
files, so in a disaster-recovery scenario it must be restorable from a
flat git.yaml + git.env backup alone, with zero dependency on a running
Swarm's Docker secret store (native Docker secrets can't be resolved
until Swarm already exists, which is the circular dependency git.yaml
would otherwise create). Path 2 (documented decision): Pattern B for
git specifically, same mechanism the ai stack already uses.

provision-secrets / git) case:
  - Previously created native Docker secrets (git_db_password,
    git_runner_token, git_mcp_access_token) via create-secrets.sh —
    leftover from an earlier, abandoned Pattern C attempt.
  - Now rewrites only the secret-bearing lines (GITEA__database__PASSWD,
    GITEA_RUNNER_REGISTRATION_TOKEN, GITEA_MCP_ACCESS_TOKEN) via
    grep -v + printf, mirroring the ai) case exactly. Also strips the
    legacy GITEA_ACCESS_TOKEN key name so the test file converges on the
    git.env.example-documented key.
  - TEST PHASE: target is git.env.pipelinetest, NOT git.env. The real
    git.env is never opened for writing by this step. First run seeds
    the test file from the real git.env (to carry over all non-secret
    lines), then only the 3 secret lines are refreshed on every push.
  - Real cutover (pointing git.yaml/stack-deploy at the generated file,
    then retiring git.env.pipelinetest) is a deliberate follow-up step
    after manually diffing the rendered output.

deploy / bootstrap-tier guard:
  - Added git to the traefik|woodpecker|postgresql|secrets guard list.
    git.yaml changes now sync to the host but require a manual
    `stack-deploy.sh git` run, same as the other foundational stacks —
    prevents an auto-deploy of a bad git.yaml change from taking down
    Gitea before a human can look at it (Gitea itself is what every
    other pipeline needs to trigger a fix).
2026-09-02 00:02:36 -07:00
AVB 16a01a9ea5 Merge pull request 'Remove orphaned mcpo/ mirror (migrated to homelab/mcp-config)' (#13) from remove-orphaned-mcpo-mirror into main
ci/woodpecker/push/deploy Pipeline failed
ci/woodpecker/cron/renovate Pipeline was successful
Reviewed-on: #13
2026-08-29 20:57:58 -07:00
2 changed files with 64 additions and 7 deletions
+49 -6
View File
@@ -179,6 +179,12 @@ steps:
from_secret: ai_open_webui_database_url
AI_OAUTH_CLIENT_SECRET:
from_secret: ai_oauth_client_secret
FLOWAGENT_AZURE_CLIENT_ID:
from_secret: flowagent_azure_client_id
FLOWAGENT_AZURE_TENANT_ID:
from_secret: flowagent_azure_tenant_id
FLOWAGENT_AZURE_CLIENT_SECRET:
from_secret: flowagent_azure_client_secret
commands:
- apk add --no-cache openssh-client
- mkdir -p ~/.ssh
@@ -221,10 +227,36 @@ steps:
ssh -o StrictHostKeyChecking=no root@$${SWARM_MANAGER_IP} "source /tmp/cs.sh
create_or_update_secret 'gamma_auth_token' '$${GAMMA_AUTH_TOKEN}'";;
git)
ssh -o StrictHostKeyChecking=no root@$${SWARM_MANAGER_IP} "source /tmp/cs.sh
create_or_update_secret 'git_db_password' '$${GIT_DB_PASSWORD}'
create_or_update_secret 'git_runner_token' '$${GIT_RUNNER_TOKEN}'
create_or_update_secret 'git_mcp_access_token' '$${GIT_MCP_ACCESS_TOKEN}'";;
# PATTERN B, DELIBERATE (see decision notes) — git hosts the source
# of truth for every other stack's compose files, so it must be
# restorable from a flat git.yaml + git.env backup alone, with zero
# dependency on a running Swarm's Docker secret store. Native Docker
# secrets (Pattern C) can't satisfy that: they only exist inside an
# already-running Swarm, which is exactly the circular dependency
# this stack can't have. Mirrors the ai) case's grep -v + printf
# rewrite-in-place approach, never sed (values may contain slash,
# dollar sign, ampersand).
#
# TEST PHASE: target is git.env.pipelinetest, NOT the real git.env.
# The real file is never opened for writing by this step. First run
# seeds the test file from the real git.env (carries over all
# non-secret lines untouched); every push after that only refreshes
# the 3 secret lines below. Also strips the legacy GITEA_ACCESS_TOKEN
# key name so the test file converges on the git.env.example-
# documented GITEA_MCP_ACCESS_TOKEN key. Cutover to the real file —
# and pointing git.yaml/stack-deploy at it — is a deliberate,
# separate follow-up after manually diffing this render.
ssh -o StrictHostKeyChecking=no root@$${SWARM_MANAGER_IP} "FILE=/volume1/docker/compose-files/git.env.pipelinetest
TMP=\$FILE.tmp.\$\$
[ -f \$FILE ] || cp /volume1/docker/compose-files/git.env \$FILE
grep -vE '^(GITEA__database__PASSWD|GITEA_RUNNER_REGISTRATION_TOKEN|GITEA_MCP_ACCESS_TOKEN|GITEA_ACCESS_TOKEN)=' \$FILE > \$TMP 2>/dev/null || touch \$TMP
{ cat \$TMP
printf 'GITEA__database__PASSWD=%s\n' '$${GIT_DB_PASSWORD}'
printf 'GITEA_RUNNER_REGISTRATION_TOKEN=%s\n' '$${GIT_RUNNER_TOKEN}'
printf 'GITEA_MCP_ACCESS_TOKEN=%s\n' '$${GIT_MCP_ACCESS_TOKEN}'
} > \$FILE
rm -f \$TMP
echo ' [OK] git.env.pipelinetest updated - real git.env untouched'";;
homeassistant)
ssh -o StrictHostKeyChecking=no root@$${SWARM_MANAGER_IP} "source /tmp/cs.sh
create_or_update_secret 'homeassistant_frigate_rtsp_password' '$${HOMEASSISTANT_FRIGATE_RTSP_PASSWORD}'
@@ -279,6 +311,13 @@ steps:
# unresolved at compose-render time (empty), silently breaking Bedrock auth.
# All other migrated vars in ai.yaml use plain (unprefixed) names, so only
# these two lines need the AI_ prefix.
#
# FLOWAGENT NOTE (added alongside the ai.yaml mcpo image/secrets cutover):
# the 3 flowagent_azure_* values are provisioned as native Docker secrets
# below (Pattern C, matches every other _FILE-convention stack), NOT written
# into ai/ai.env — mcpo's flowagent entry reads them via
# /run/secrets/flowagent_azure_* (see mcp-config/flowagent/entrypoint.sh),
# not via env var, so they don't belong in this stack's Pattern B .env block.
ssh -o StrictHostKeyChecking=no root@$${SWARM_MANAGER_IP} "FILE=/volume1/docker/compose-files/ai/ai.env
TMP=\$FILE.tmp.\$\$
grep -vE '^(AI_AWS_ACCESS_KEY_ID|AI_AWS_SECRET_ACCESS_KEY|LITELLM_MASTER_KEY|LITELLM_SALT_KEY|POSTGRES_PASSWORD|DATABASE_URL|WEBUI_SECRET_KEY|OPEN_WEBUI_DATABASE_URL|OAUTH_CLIENT_SECRET)=' \$FILE > \$TMP 2>/dev/null || touch \$TMP
@@ -294,7 +333,11 @@ steps:
printf 'OAUTH_CLIENT_SECRET=%s\n' '$${AI_OAUTH_CLIENT_SECRET}'
} > \$FILE
rm -f \$TMP
echo ' [OK] ai/ai.env secrets updated'";;
echo ' [OK] ai/ai.env secrets updated'
source /tmp/cs.sh
create_or_update_secret 'flowagent_azure_client_id' '$${FLOWAGENT_AZURE_CLIENT_ID}'
create_or_update_secret 'flowagent_azure_tenant_id' '$${FLOWAGENT_AZURE_TENANT_ID}'
create_or_update_secret 'flowagent_azure_client_secret' '$${FLOWAGENT_AZURE_CLIENT_SECRET}'";;
entertainment)
ssh -o StrictHostKeyChecking=no root@$${SWARM_MANAGER_IP} "source /tmp/cs.sh
create_or_update_secret 'entertainment_discord_token' '$${ENTERTAINMENT_DISCORD_TOKEN}'
@@ -352,7 +395,7 @@ steps:
# Bootstrap-tier guard: file synced to host, deploy is MANUAL
case "$STACK" in
traefik|woodpecker|postgresql|secrets)
traefik|woodpecker|postgresql|secrets|git)
echo " [BOOTSTRAP] $STACK: file synced. Deploy is MANUAL."
echo " Run: bash /volume1/docker/compose-files/deploy/stack-deploy.sh $STACK"
continue ;;
+15 -1
View File
@@ -127,7 +127,7 @@ services:
labels:
- traefik.enable=false
mcpo:
image: ghcr.io/open-webui/mcpo:main
image: git.bryanmail.net/homelab/flowagent-mcpo:916164714429
command:
- --config
- /app/config/config.json
@@ -141,6 +141,13 @@ services:
- /volume1/docker/mcpo/data:/mcpo_data
- /volume1/docker/cronicle/ssh_keys:/app/ssh_keys:ro
- /volume1/docker/mcpo/uv-cache:/app/uv-cache
secrets:
- source: flowagent_azure_client_id
target: flowagent_azure_client_id
- source: flowagent_azure_tenant_id
target: flowagent_azure_tenant_id
- source: flowagent_azure_client_secret
target: flowagent_azure_client_secret
networks:
- traefik_backend
deploy:
@@ -173,6 +180,13 @@ services:
- traefik.http.middlewares.n8n.headers.STSPreload=true
- traefik.http.routers.n8n.middlewares=forwardAuth-authentik@file, crowdsec@file
- traefik.swarm.network=traefik_backend
secrets:
flowagent_azure_client_id:
external: true
flowagent_azure_tenant_id:
external: true
flowagent_azure_client_secret:
external: true
networks:
traefik_backend:
external: true