Skip to content

Bind standalone Airflow to loopback by default and stop the whole process group - #2222

Open
jlaneve wants to merge 2 commits into
mainfrom
fix/standalone-loopback-and-group-stop
Open

Bind standalone Airflow to loopback by default and stop the whole process group#2222
jlaneve wants to merge 2 commits into
mainfrom
fix/standalone-loopback-and-group-stop

Conversation

@jlaneve

@jlaneve jlaneve commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

What changed

Loopback binding. Standalone mode runs Airflow with SIMPLE_AUTH_MANAGER_ALL_ADMINS=True, and Airflow's api-server (Airflow 3) and webserver (Airflow 2) default to binding 0.0.0.0. That combination made a local dev instance reachable from other machines on the network. A new airflowrt.ApplyLoopbackDefaults defaults AIRFLOW__API__HOST and AIRFLOW__WEBSERVER__WEB_SERVER_HOST to 127.0.0.1; both airflowrt.BuildEnv and the live path, (*Standalone).buildEnv in airflow/standalone.go, call it. Only the default changed: a user's own setting, from the .env file or the inherited environment, still wins. Airflow ignores whichever key doesn't apply to the running major.

Stop the whole process group. Both airflowrt.StopProcess and the live path, (*Standalone).Stop, polled the master PID, which often exits on SIGTERM before its scheduler/api-server/triggerer children, so those children outlive astro dev stop. Both now poll the process group (new airflowrt.ProcessGroupAlive) and return only once the whole group is gone, still escalating to SIGKILL on timeout. The master is the group leader — Start launches it with Setpgid — so kill(-pid, 0) is a valid group probe. On Windows, where Unix process groups don't apply, the airflowrt fallback checks the single PID — children a dead master leaves behind can still linger there. (v1's standalone mode is a stub on Windows, so its live path is unaffected.)

Review found that airflowrt.BuildEnv and airflowrt.StopProcess have no production callers in this repo — astro dev runs the standalone.go paths — so the fix lands in both places, keeping the shared module and the live path in agreement.

Tests

  • Env defaults include the loopback pins, and overrides from .env and from the inherited environment win — asserted for both airflowrt.BuildEnv and (*Standalone).buildEnv.
  • airflowrt.StopProcess covered without real processes: the signal helpers are package vars the tests stub, so the graceful-wait and force-kill paths run in milliseconds.
  • (*Standalone).Stop covered with a real process group whose master dies on SIGTERM while a TERM-ignoring child lives on ~2s; Stop must outwait the child and leave the group fully dead.
  • go build/go vet/go test in pkg/airflowrt (including a GOOS=windows cross-compile), go build ./... and go test ./airflow/... at the root, golangci-lint on both (no new findings).

Breaking changes

None. Defaults changed; explicit user overrides still win. The airflowrt additions (ApplyLoopbackDefaults, ProcessGroupAlive) are new exports, no signatures changed — the module stays backward compatible.

🤖 Generated with Claude Code

https://claude.ai/code/session_01P6DEdUpFBFaAiPKEu81Wti

jlaneve and others added 2 commits July 21, 2026 17:39
Standalone mode sets SIMPLE_AUTH_MANAGER_ALL_ADMINS=True while Airflow's
api-server/webserver default to binding 0.0.0.0, so a local dev instance
was reachable from other machines on the network. BuildEnv now defaults
AIRFLOW__API__HOST (Airflow 3) and AIRFLOW__WEBSERVER__WEB_SERVER_HOST
(Airflow 2) to 127.0.0.1. A user's own setting, from .env or the
inherited environment, still wins; only the default changed.

StopProcess polled the master PID, which often exits on SIGTERM before
its scheduler/api-server/triggerer children, so those children survived
astro dev stop. It now polls the process group and only returns once the
whole group is gone, escalating to SIGKILL on timeout as before.

The signal helpers are now vars so tests can stub them; the stop path is
covered without real processes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P6DEdUpFBFaAiPKEu81Wti
Review found that airflowrt.BuildEnv and airflowrt.StopProcess have no
production callers: astro dev start/stop run (*Standalone).buildEnv and
(*Standalone).Stop in airflow/standalone.go, which still bound 0.0.0.0
and still polled only the master PID. This wires the fixes into those
paths.

airflowrt now exports ApplyLoopbackDefaults, which both its own BuildEnv
and standalone.go's buildEnv call, so the two host keys are defined once.
It also exports ProcessGroupAlive; standalone.go's Stop polls it instead
of re-reading the master PID. The master is the group leader (Start sets
Setpgid), so kill(-pid, 0) is a valid group probe.

Live-path tests: buildEnv loopback defaults plus .env and inherited-env
overrides, and a Stop test that starts a real process group whose master
dies on SIGTERM while a TERM-ignoring child lives on — Stop must outwait
the child. Also trims repeated comments in the airflowrt seam files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P6DEdUpFBFaAiPKEu81Wti
@jlaneve
jlaneve requested a review from a team as a code owner July 21, 2026 22:12
@coveralls-official

Copy link
Copy Markdown

Coverage Report for CI Build 29872953320

Coverage increased (+0.01%) to 43.894%

Details

  • Coverage increased (+0.01%) from the base build.
  • Patch coverage: 8 of 8 lines across 1 file are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 59029
Covered Lines: 25910
Line Coverage: 43.89%
Coverage Strength: 8.65 hits per line

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant