Skip to content

build: run one base across the whole stack (debian:trixie-slim) - #731

Merged
frahlg merged 3 commits into
srcfl:masterfrom
HuggeK:debian-base-migration
Aug 4, 2026
Merged

build: run one base across the whole stack (debian:trixie-slim)#731
frahlg merged 3 commits into
srcfl:masterfrom
HuggeK:debian-base-migration

Conversation

@HuggeK

@HuggeK HuggeK commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Warning

#746 is the alternative to this PR plus #728. Merge one route, never both.
#746 keeps core and updater on Alpine and resolves .local in Go. This PR
deliberately leaves .local to #728.

Scope

This is the Debian base root for the container route from #730. It moves the
runtime of core and the updater to debian:trixie-slim, and moves the
optimizer from python:3.12-slim-bookworm to python:3.12-slim-trixie.

The builder stages remain Alpine Go toolchain images; CGO_ENABLED=0 keeps the
Go binaries static. The runtime images use one Debian stable family and one
libc. The optimizer stays on Python/Debian because CVXPY and its solver stack
do not publish the required musllinux wheels.

This PR does not include #728, #733, #714, #746, #776, #777, #779 or #770.
The .local resolver, Debian currency watcher, setup UI, overlapping
container work and host-OS patching stay separate.

Runtime changes

  • Core: debian:trixie-slim with ca-certificates, tzdata, wget and
    libnss-mdns; wget remains because the updater uses it as its readiness
    gate.
  • Updater: debian:trixie-slim with ca-certificates and tzdata; Docker CLI
    27.5.1 and Compose 2.33.0 are copied from the official
    docker:27-cli@sha256:851f91d241214e7c6db86513b270d58776379aacc5eb9c4a87e5b47115e3065c
    multi-arch index. It stays root because it is the only sidecar allowed to
    use the Docker socket.
  • Core and optimizer run as numeric UID/GID 100:101. GID 101 preserves access
    to the optimizer socket and existing bind mounts.
  • The optimizer uses Python 3.12.13, CVXPY 1.9.2 and HiGHS 1.15.1. The image
    retains the solver dependencies and runs a healthcheck as UID/GID 100:101.
  • Core embeds Go timezone data as a second guard; the images also ship system
    CA certificates and zoneinfo.

Validation

Rebased on srcfl/ftw@a520ebbb and pushed as commit f710031e on
2026-08-04. The final PR diff is 10 files, 171 additions and 20 deletions;
there are no resolver, driver, web, Compose or host-update files. The two
review follow-ups are included: the .local documentation names the actual
getent and wget tools in core, and the updater pins the Docker Official
Images multi-arch index digest above.

  • make verify passed: Go tests, 49 optimizer tests, external optimizer tests,
    Compose migration, boundary checks, go vet and native build.
  • make verify-all passed: Linux arm64, Linux amd64 and Windows amd64
    cross-compiles.
  • Core, updater and optimizer each built with Buildx for
    linux/amd64,linux/arm64 as local OCI manifests. The final manifest
    digests were sha256:1dcd1068e67c95497bc1bbdbfdc381c6f0112795ef5c3c78aba34bb411d9bfd0,
    sha256:99cc29d20412c208e9b9bd8fce0284bea6d6c708d2ab2c9ffd526cc1aac89265,
    and sha256:42d1e30d6226805567810953f68bcf339df92ce7b869465073ae878ccc316306.
  • Runtime smoke checks passed on both architectures: Debian package presence,
    CA bundle, zoneinfo, UID/GID, Docker CLI/Compose, and a CLARABEL solve using
    CVXPY/HiGHS dependencies.
  • The pinned 37-driver snapshot was fetched only into the ignored local test
    tree; no generated drivers are part of this PR.

Review and merge order

This PR remains draft. It needs a new independent review after the rebase,
including confirmation of the cross-repo Home Assistant add-on follow-up
(srcfl/home-assistant-addons#6), before merge. After this root lands, rebase
#728 and #733 separately; keep #714 after the resolver and human web review.

🤖 Generated with Claude Code

@HuggeK

HuggeK commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Cross-repo follow-up: the Home Assistant add-on builds FROM ${FTW_OPTIMIZER_FROM}, so it inherits this base automatically — but its CI fixtures pin python:3.12-slim-bookworm and would keep certifying the add-on against a base that no longer ships.

Handled in srcfl/home-assistant-addons#6, which is marked blocked by this PR. Verified there on the real new base: fixtures build, the add-on image builds on top of them, and scripts/smoke.sh passes.

@HuggeK

HuggeK commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Alternative route now available as #746 — one alpine:3.22 base for core + updater, with .local resolved natively in Go (no avahi). Merge one route or the other, not both.

Headline from building both in one session: the Alpine route consolidates only two of three images. cvxpy publishes no musllinux wheels at all (newest is 0.4.10), and neither do clarabel, osqp or ecos, so the optimizer cannot leave Debian.

Because python:3.12-slim-trixie is built from debian:trixie-slim (both first layer f2ec4de8…), this PR is the only one of the two that genuinely gets the whole stack onto one base — and once the optimizer is deployed the disk difference between the routes is 4.6 MB, not the ~83 MB the per-image sizes suggest. Full numbers in #746.

@frahlg
frahlg force-pushed the debian-base-migration branch from 6720ec1 to f710031 Compare August 4, 2026 09:25
@frahlg
frahlg marked this pull request as ready for review August 4, 2026 09:42
@frahlg
frahlg merged commit 8d39cd9 into srcfl:master Aug 4, 2026
15 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 01792f464b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread go/cmd/ftw/main.go
// without tzdata. The failure it guards against is invisible — production
// code reads time.Local, and the tzdata tests skip rather than fail — so the
// ~450 KB is worth it.
_ "time/tzdata"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Initialize Local from the embedded zone data

When /etc/localtime is unavailable and TZ is unset—as it is in the checked Compose configuration—importing time/tzdata does not protect time.Local: Unix initialization reads /etc/localtime and otherwise falls directly back to UTC, while embedded data is only consulted when loading a named zone. The exact missing-tzdata scenario described here therefore still silently mis-times code using time.Local; explicitly load/configure a named local zone rather than relying on this blank import.

Useful? React with 👍 / 👎.

Comment thread Dockerfile
Comment on lines +49 to +50
# major versions on some future rebuild. The `debian base currency` workflow
# watches for a new stable and files an issue, so the bump stays deliberate.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the promised Debian currency watcher

There is no debian base currency workflow—or any equivalent Debian-stable check—under .github/workflows in this commit. Because trixie is deliberately pinned, a future Debian stable release will not produce the tracking issue promised here, leaving the base on the old suite without the stated notification; either include the watcher or remove this assurance until it lands.

Useful? React with 👍 / 👎.

Comment thread docs/operations.md
Comment on lines +204 to +206
This makes the container's own tooling agree with the host. Whether the FTW
process itself resolves a device's `.local` name is a separate question,
answered by `internal/mdnsresolve`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Replace the reference to the nonexistent resolver

The added troubleshooting guidance directs operators to internal/mdnsresolve, but a repo-wide search finds no such package or generated artifact. During an actual .local failure this leaves readers without the promised explanation; document the current static-core behavior and workaround, or land the resolver before referring to it.

AGENTS.md reference: AGENTS.md:L139-L140

Useful? React with 👍 / 👎.

HuggeK added a commit to HuggeK/ftw that referenced this pull request Aug 5, 2026
srcfl#731 landed the base move itself, so this branch keeps only the part that
was never in it: a check that notices when the pinned codename stops being
what Debian calls stable.

Dependabot cannot cover this. It orders numeric tags, and `trixie` is a
codename with no numeric component — the same is true of the suite half of
`python:3.12-slim-trixie`. It bumps the interpreter and leaves the suite
alone. This reads Debian's own Release file for `stable` instead of a
registry tag listing, and also fails when the three images stop agreeing on
one suite, which is the whole reason they were aligned.

Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>
frahlg added a commit to srcfl/home-assistant-addons that referenced this pull request Aug 7, 2026
* build: follow Core and Optimizer onto the trixie base

@
srcfl/ftw#731 moves the whole FTW stack onto Debian 13 "trixie". This repo
inherits that automatically -- the add-on image is built FROM the Optimizer
image -- so the change that matters here is the test fixtures, which stood in
for Core and Optimizer on bookworm and would have gone on testing a base that
no longer ships.

Also say, once, why libnss-mdns is not installed here even though Core has it:
it only forwards to avahi-daemon over a Unix socket, and Supervisor gives an
add-on no way to bind an arbitrary host path. FTW resolves ".local" in-process
instead, which is what host_network is for. Documented in DOCS.md for operators
who hit a name that will not resolve.

Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>
@

* docs: correct how `.local` resolves under Supervisor

Tested on a pilot HA green instead of reasoning about it, and the earlier
text was wrong in the way that matters. `.local` does not need anything
from FTW here: Supervisor points every app at its own CoreDNS, which
carries an mdns plugin backed by systemd-resolved, and that answers over
ordinary unicast DNS. A lookup failure names it — "on 172.30.32.3:53".

The avahi paragraph stands but for a further reason: HA OS runs no avahi
at all. Its multicast plugin is mdns-repeater, a packet relay with no
query API, so there is no socket to bind even in principle.

Evidence: srcfl/ftw#728 (comment).

Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>

* docs: say what `.local` resolution depends on, and what it does not

Someone reading the previous version could reasonably ask which plugin
they have to install. The answer is none, and that is worth stating
rather than leaving implied.

Supervisor hard-codes five built-in services and starts them itself
(supervisor/plugins/manager.py: cli, dns, audio, observer, multicast).
They are not add-ons — an app cannot install one, and cannot declare a
dependency on one either. A failure there becomes a repairable system
issue Supervisor raises on its own.

The one real host requirement is systemd-resolved, which HA OS always
has and which the Supervised installer's first step sets up. A host
that skipped it resolves no .local names, so that case is called out
with its workaround.

Also documents the resolver address in the failure message, since
seeing 172.30.32.3 is what separates "device is not there" from
"resolution never got that far".

Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>

* docs: qualify local-name network failures

Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>

---------

Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
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.

2 participants