M1: proxy via real coop-cloud/traefik (abra, wildcard/no-ACME); recipe deploy+teardown; M1 CLAIMED
Orchestrator decision: deploy canonical coop-cloud traefik via abra instead of a hand-rolled module. abra packaged in Nix (pinned). custom-html deployed over HTTPS (200) via the gateway and torn down clean. docs/install.md seeded. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
25
modules/abra.nix
Normal file
25
modules/abra.nix
Normal file
@ -0,0 +1,25 @@
|
||||
# abra — the Co-op Cloud CLI used by the harness to deploy/upgrade/backup recipes (M1+).
|
||||
# Packaged from the upstream release binary, pinned by version + hash for reproducibility (D8).
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
abra = pkgs.stdenv.mkDerivation rec {
|
||||
pname = "abra";
|
||||
version = "0.13.0-beta";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://git.coopcloud.tech/toolshed/abra/releases/download/${version}/abra_${version}_linux_amd64.tar.gz";
|
||||
sha256 = "12csk6wp1pk9cspzqfl4a6h5jdz8p055sf0ggxw9k7ljhpd5qvc6";
|
||||
};
|
||||
# Tarball has files at the root (LICENSE, README.md, abra), no common subdir.
|
||||
sourceRoot = ".";
|
||||
nativeBuildInputs = [ pkgs.autoPatchelfHook ];
|
||||
buildInputs = [ pkgs.stdenv.cc.cc.lib ];
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
install -Dm755 abra "$out/bin/abra"
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
environment.systemPackages = [ abra ];
|
||||
}
|
||||
@ -15,6 +15,10 @@
|
||||
|
||||
environment.systemPackages = [ pkgs.docker ];
|
||||
|
||||
# Gateway forwards 80/443 to cc-ci over the public interface (enp5s0); the coop-cloud
|
||||
# traefik stack (deployed via abra, see docs/install.md) publishes these ports.
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
|
||||
# Bring up a single-node swarm + the shared `proxy` overlay network. Idempotent:
|
||||
# safe to re-run every boot/rebuild. advertise-addr 127.0.0.1 is fine for a lone node.
|
||||
systemd.services.swarm-init = {
|
||||
|
||||
@ -1,96 +0,0 @@
|
||||
# Traefik for the test swarm (M1). Runs as a swarm service on the `proxy` overlay so it can
|
||||
# reach recipe service VIPs (a host process couldn't). TLS terminates here using the operator's
|
||||
# pre-issued wildcard cert via the file provider — NO ACME for commoninternet.net (§4.0).
|
||||
# Recipe routers only need `traefik.enable=true` + a Host(...) rule + tls=true; the default
|
||||
# certificate (the wildcard) is served for every *.ci.commoninternet.net host.
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
# Static config. Docker *Swarm* provider (v3) + file provider for the cert.
|
||||
staticCfg = pkgs.writeText "traefik.yml" ''
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":80"
|
||||
websecure:
|
||||
address: ":443"
|
||||
providers:
|
||||
swarm:
|
||||
endpoint: "unix:///var/run/docker.sock"
|
||||
exposedByDefault: false
|
||||
network: proxy
|
||||
file:
|
||||
directory: /etc/traefik/dynamic
|
||||
watch: true
|
||||
log:
|
||||
level: INFO
|
||||
accessLog: {}
|
||||
api:
|
||||
dashboard: false
|
||||
ping: {}
|
||||
'';
|
||||
|
||||
# Dynamic config: serve the pre-issued wildcard as the DEFAULT certificate, so any
|
||||
# *.ci.commoninternet.net router with tls=true is covered without a cert resolver.
|
||||
certsCfg = pkgs.writeText "certs.yml" ''
|
||||
tls:
|
||||
stores:
|
||||
default:
|
||||
defaultCertificate:
|
||||
certFile: /var/lib/ci-certs/live/fullchain.pem
|
||||
keyFile: /var/lib/ci-certs/live/privkey.pem
|
||||
certificates:
|
||||
- certFile: /var/lib/ci-certs/live/fullchain.pem
|
||||
keyFile: /var/lib/ci-certs/live/privkey.pem
|
||||
'';
|
||||
|
||||
stack = pkgs.writeText "traefik-stack.yml" ''
|
||||
version: "3.8"
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.3
|
||||
ports:
|
||||
- target: 80
|
||||
published: 80
|
||||
mode: host
|
||||
- target: 443
|
||||
published: 443
|
||||
mode: host
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- /var/lib/ci-certs/live:/var/lib/ci-certs/live:ro
|
||||
- ${staticCfg}:/etc/traefik/traefik.yml:ro
|
||||
- ${certsCfg}:/etc/traefik/dynamic/certs.yml:ro
|
||||
networks:
|
||||
- proxy
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
restart_policy:
|
||||
condition: any
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
'';
|
||||
in
|
||||
{
|
||||
# Gateway forwards 80/443 to cc-ci over the public interface (enp5s0), so open them.
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
|
||||
systemd.services.traefik-deploy = {
|
||||
description = "Deploy the Traefik swarm stack";
|
||||
after = [ "swarm-init.service" ];
|
||||
requires = [ "swarm-init.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ pkgs.docker ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
set -eu
|
||||
docker stack deploy --detach=true -c ${stack} traefik
|
||||
'';
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user