Stop handing StackPilot's own settings to the stacks it deploys (0.66.3)
CI / check (push) Successful in 13m48s
CI / build-and-push (push) Successful in 4m5s

docker compose ran with StackPilot's whole environment, and compose
resolves ${VAR} from the calling environment before a stack's own .env.
A stack whose compose file says SECRET_KEY: ${SECRET_KEY} therefore ran
with StackPilot's SECRET_KEY instead of the one in its .env — and with
its own again whenever it was started from a shell. AnsiblePilot hit
exactly this: credentials saved under one key became unreadable under
the other, twice.

config.child_env() is os.environ minus every StackPilot setting
(SECRET_KEY, DATA_DIR, STACKS_DIR, PORT, ...); the docker CLI and git
subprocesses now get that instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
menzeljandClaude Opus 5 committed 2026-09-19 13:49:52 +02:00
1 parent 34458c702c
commit 052a85067b
7 files changed
+44 -7

No files matched your search

+2 -2
View File
@@ -39,7 +39,7 @@ from typing import Optional
from sqlmodel import Session
from config import settings
from config import child_env, settings
from models.git_source import GitSource, SyncResult
from services import compose_service, crypto_service, stack_lock_service
@@ -124,7 +124,7 @@ def _auth_env(source: GitSource) -> tuple[dict, Optional[str]]:
with their whole stack.
"""
env = {
**os.environ,
**child_env(),
# No interactive prompting: a private repo without credentials must fail
# fast rather than hang forever waiting on a terminal that is not there.
"GIT_TERMINAL_PROMPT": "0",
+4 -3
View File
@@ -31,7 +31,7 @@ from typing import Optional
import httpx
from sqlmodel import Session, select
from config import settings
from config import child_env, settings
from models.registry import Registry
from services import crypto_service
@@ -186,9 +186,10 @@ def cli_env() -> dict:
Points DOCKER_CONFIG at our generated file rather than writing into
``~/.docker``, so what StackPilot manages stays separate from anything the
image ships or an operator put there by hand.
image ships or an operator put there by hand. StackPilot's own settings are
left out: compose would otherwise interpolate them into the stacks.
"""
return {**os.environ, "DOCKER_CONFIG": docker_config_dir()}
return {**child_env(), "DOCKER_CONFIG": docker_config_dir()}
# --------------------------------------------------------------------------- #