IPv6 environments
Environments can opt into IPv6 on their Docker network via the create-time
IPV6_ENABLED parameter (DEV-2590). This page covers the opt-in model, the
agent onboarding required, and the security implications.
Opt-in model (create-time only)
-
IPV6_ENABLEDis a Create-Environment parameter, default off. It is stored once inmeta.jsonasipv6_enabled(boolean) and is immutable for the env’s life — Update-Environment has no IPv6 parameter by design. -
To change IPv6 on an existing env, clone or re-create it with the box ticked.
CLONE_FROMreproduces the services / DB / versions / variables; it does not copyipv6_enabled, so you set it explicitly on the new env. -
Rationale for create-only: it removes the two failure modes a mutable toggle would introduce — a static checkbox re-defaulting to unticked on every unrelated Update build (silently dropping a saved IPv6 setting), and the Docker "network needs to be recreated" error that changing
enable_ipv6on an already-deployed network throws (deploy runsdocker compose upwith no precedingdown). A create-only, immutable flag makes the injected network block deterministic across every redeploy.
meta.ipv6_enabled is not a supported manual-edit surface.
Hand-editing it on a deployed env re-introduces the network-recreate error on
the next compose up.
|
What happens on deploy
When ipv6_enabled is true, deployEnvStep:
-
Runs an IPv6 preflight on the chosen
DEPLOY_RUNNER(fail-closed — any failing or inconclusive check aborts the deploy before any container starts):-
kernel IPv6 enabled (
net.ipv6.conf.all.disable_ipv6 == 0); -
operator attestation — the node-scoped Node Property
QA_AGENT_IPV6_READY == true(read via the Jenkins node API, never the pipelineenv.global, so a global value cannot attest all agents at once); -
a subnet-less
docker network create --ipv6capability probe (exercises the same daemondefault-address-poolspathcompose upuses), cleaned up immediately; -
best-effort removal of a stale same-name
<env>_defaultnetwork only when no containers are attached.
-
-
Overrides the compose
defaultnetwork withenable_ipv6: true(no explicit subnet — the daemon auto-assigns a unique /64 per env). Services are not given per-servicenetworks:keys; they stay ondefault, which now carries IPv6.
Legacy fixed-port envs (legacy_ports=true, pre-Phase-3) cannot use IPv6: the
deploy fails fast if the combination is ever reached (it is unreachable via the
create-only flag, since new envs are always legacy_ports=false).
Agent onboarding checklist
Perform on each agent that should serve IPv6 envs, then set the attestation:
-
Enable IPv6 in the host kernel (
net.ipv6.conf.all.disable_ipv6 = 0). -
Configure the Docker daemon (
/etc/docker/daemon.json):{ "ipv6": true, "ip6tables": true, "default-address-pools": [ { "base": "fd00:qa::/48", "size": 64 } ] }Restart the daemon.
ip6tables: trueis required for cross-env isolation and published-port filtering; the pipeline trusts the attestation for it rather than probing (the agent user has docker-socket access only, not root). -
Set the Node Property
QA_AGENT_IPV6_READY=true(Manage Jenkins → Nodes → agent → Configure → Node Properties → Environment variables). Set it only after the daemon is configured. This attestation doubles as the operator’s acknowledgement of the exposure note below.
Security: host-side port exposure
All service ports publish as bare HOST:CONTAINER (no 127.0.0.1 bind). On a
daemon with ipv6+ip6tables, Docker installs IPv6 DNAT rules, so every
published port becomes reachable on the agent’s IPv6 addresses — bypassing an
IPv4-only host firewall. This repo does not manage host firewalling. Only
onboard internet-facing agents for IPv6 after extending their IPv6 firewall
rules to match the intended exposure.