feat(P2): podman traefik reconciler + TLS model fix (REQ-172)
Replace internal/traefik/install.go binary+systemd installer with a
podman-container reconciler (R-024). The reconciler is idempotent:
inspect → start-if-stopped → pull+run-if-absent.
Container run flags (research-validated):
--restart=unless-stopped (not always; research Topic 6)
--network host (binds 127.0.0.1:8080/8443 on host/LXC loopback)
-v /etc/traefik/traefik.yml:ro (overrides baked default; C-58)
-v /etc/traefik/dynamic:ro (orca writes atomically via SSH-push)
-v /etc/orca/step-ca-root.crt:ro (future mTLS; v0.14 uses tls:{})
No :Z SELinux flag (research Topic 7)
C-50: ensurePodmanLocal/Remote installs podman if absent.
C-57: removeLegacySystemdUnitLocal/Remote stops+disables+removes
the v0.13 orca-traefik.service + /usr/local/bin/traefik before
starting the podman container (upgrade path).
upgrade.go cutover rewritten to use the reconciler.
TLS model fix (research Topic 4): drop certResolver: orca from
dynamic config (traefik v3.3 only supports acme/tailscale resolvers,
not CA-file-based). Emit tls: {} instead. Real mTLS via dynamic
tls.certificates + clientAuth.caFiles deferred to v0.15 (grill
G-003, confidence 0.55 < 0.60).
Callsites updated:
init.go: installTraefikLocal → ensureTraefikContainerLocal
linux/bootstrap.go: traefik.InstallRemote → EnsureTraefikContainerRemote
proxmox/bootstrap.go: same
traefik_install.go: wrapper updated
Tests: internal/traefik/install_test.go (new) — ImageRef, podmanRunArgs,
container-running/stopped/absent paths, legacy systemd removal (C-57).
---ci---
project: orca
phase: 2
milestone: v0.14
status: execute
---/ci---
This commit is contained in:
+14
-13
@@ -48,13 +48,13 @@ const DefaultSSHPort = 22
|
||||
|
||||
// Options configures a Linux worker bootstrap run.
|
||||
type Options struct {
|
||||
Host string
|
||||
SSHUser string
|
||||
SSHKeyPath string
|
||||
OrcaUser string
|
||||
SSHPort int
|
||||
HostKeyFingerprint string
|
||||
Logger *slog.Logger
|
||||
Host string
|
||||
SSHUser string
|
||||
SSHKeyPath string
|
||||
OrcaUser string
|
||||
SSHPort int
|
||||
HostKeyFingerprint string
|
||||
Logger *slog.Logger
|
||||
}
|
||||
|
||||
// Result is the outcome of a successful bootstrap.
|
||||
@@ -157,8 +157,8 @@ func BootstrapLinux(ctx context.Context, opts Options) (*Result, error) {
|
||||
}
|
||||
opts.Logger.Info("linux bootstrap: user created", "user", opts.OrcaUser)
|
||||
|
||||
// Step 4d: Install Traefik on the remote host (REQ-165, Phase B).
|
||||
// Traefik is the data-plane ingress; SSH is control plane only.
|
||||
// Step 4d: Ensure orca-traefik podman container on the remote host
|
||||
// (REQ-172, R-024). Replaces v0.13 binary+systemd install.
|
||||
sshExecFn := func(cmd string) ([]byte, error) {
|
||||
session, err := client.NewSession()
|
||||
if err != nil {
|
||||
@@ -167,8 +167,10 @@ func BootstrapLinux(ctx context.Context, opts Options) (*Result, error) {
|
||||
defer session.Close()
|
||||
return session.CombinedOutput(cmd)
|
||||
}
|
||||
if err := traefik.InstallRemote("", sshExecFn); err != nil {
|
||||
opts.Logger.Warn("linux bootstrap: traefik install failed", "err", err)
|
||||
ctx, cancelContainer := context.WithTimeout(ctx, 120*time.Second)
|
||||
defer cancelContainer()
|
||||
if err := traefik.EnsureTraefikContainerRemote(ctx, "", sshExecFn); err != nil {
|
||||
opts.Logger.Warn("linux bootstrap: traefik container ensure failed", "err", err)
|
||||
}
|
||||
|
||||
// Step 5: Create the drift-events directory.
|
||||
@@ -188,7 +190,7 @@ func BootstrapLinux(ctx context.Context, opts Options) (*Result, error) {
|
||||
|
||||
return &Result{
|
||||
NodeName: opts.Host,
|
||||
NodeAddress: fmt.Sprintf("%s:8443", opts.Host),
|
||||
NodeAddress: fmt.Sprintf("%s:8443", opts.Host),
|
||||
HostKeyFingerprint: hostKeyFP,
|
||||
}, nil
|
||||
}
|
||||
@@ -226,5 +228,4 @@ func pinnedHostKeyCallback(expectedSHA256Base64 string, capturedKey *ssh.PublicK
|
||||
return cb, nil
|
||||
}
|
||||
|
||||
|
||||
var _ = security.WriteAtomic
|
||||
|
||||
Reference in New Issue
Block a user