@celilo/e2e 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/bin/cele2e +14 -0
  2. package/bin/e2e-cache-images +57 -0
  3. package/bin/e2e-shell +36 -13
  4. package/bin/e2e-status +8 -2
  5. package/bin/e2e-up +5 -5
  6. package/completions/install-zsh-completion.sh +78 -0
  7. package/config/dns/iamtheinternet.org.zone +1 -1
  8. package/config/routing/docker-image-preload.service +14 -0
  9. package/config/routing/docker-image-preload.sh +24 -0
  10. package/config/routing/management-routes.sh +40 -28
  11. package/docker/Dockerfile.management +7 -5
  12. package/docker/Dockerfile.target-machine +20 -0
  13. package/docker/Dockerfile.target-machine-docker +11 -19
  14. package/docker/Dockerfile.target-technitium +97 -0
  15. package/netapps/authentik.netapp +0 -0
  16. package/netapps/caddy.netapp +0 -0
  17. package/netapps/greenwave.netapp +0 -0
  18. package/netapps/homebridge.netapp +0 -0
  19. package/netapps/iptables.netapp +0 -0
  20. package/netapps/knot-unbound-internal.netapp +0 -0
  21. package/netapps/namecheap.netapp +0 -0
  22. package/netapps/technitium.netapp +0 -0
  23. package/netapps/test-ansible-output.netapp +0 -0
  24. package/package.json +7 -1
  25. package/simulators/greenwave/state.ts +7 -12
  26. package/src/cli/build.ts +204 -0
  27. package/src/cli/command-registry.ts +99 -0
  28. package/src/cli/command-tree-parser.ts +52 -0
  29. package/src/cli/completion.ts +171 -0
  30. package/src/cli/index.ts +203 -0
  31. package/src/cli/scaffold.ts +109 -0
  32. package/src/container-manager.ts +16 -4
  33. package/src/docker-compose-generator.ts +12 -10
  34. package/src/network-builder.ts +21 -0
  35. package/src/parse-line.ts +136 -0
  36. package/src/runner.ts +81 -88
  37. package/src/types.ts +4 -0
  38. package/bin/cache-docker-images +0 -46
package/bin/cele2e ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env bash
2
+ # cele2e — E2E test CLI for Celilo-deployed applications.
3
+
4
+ # Resolve symlinks to find the actual package directory
5
+ SOURCE="${BASH_SOURCE[0]}"
6
+ while [ -L "$SOURCE" ]; do
7
+ DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
8
+ SOURCE="$(readlink "$SOURCE")"
9
+ [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE"
10
+ done
11
+ SCRIPT_DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
12
+ PKG_DIR="$(dirname "$SCRIPT_DIR")"
13
+
14
+ exec bun "$PKG_DIR/src/cli/index.ts" "$@"
@@ -0,0 +1,57 @@
1
+ #!/bin/bash
2
+ #
3
+ # Save application Docker images to the local cache for e2e acceleration.
4
+ #
5
+ # The cached tarballs are mounted into app-zone target machines and
6
+ # pre-loaded at startup, avoiding slow pulls from ghcr.io / docker.io
7
+ # during every test run.
8
+ #
9
+ # Run once after pulling new image versions. The cache directory is
10
+ # gitignored — each developer maintains their own copy.
11
+ #
12
+ # Usage:
13
+ # ./e2e/bin/e2e-cache-images
14
+ #
15
+
16
+ set -e
17
+
18
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
+ E2E_DIR="$(dirname "$SCRIPT_DIR")"
20
+ CACHE_DIR="$E2E_DIR/docker-image-cache"
21
+
22
+ mkdir -p "$CACHE_DIR"
23
+
24
+ BOLD='\033[1m'
25
+ GREEN='\033[0;32m'
26
+ DIM='\033[2m'
27
+ NC='\033[0m'
28
+
29
+ # Images used by deployed modules in the app zone.
30
+ # Update versions here when bumping module image versions.
31
+ declare -A IMAGES=(
32
+ ["docker.io_library_postgres_15-alpine"]="docker.io/library/postgres:15-alpine"
33
+ ["docker.io_library_redis_alpine"]="docker.io/library/redis:alpine"
34
+ ["ghcr.io_goauthentik_server_2024.2.2"]="ghcr.io/goauthentik/server:2024.2.2"
35
+ )
36
+
37
+ echo -e "${BOLD}Pulling and caching application images...${NC}"
38
+ echo ""
39
+
40
+ for filename in "${!IMAGES[@]}"; do
41
+ image="${IMAGES[$filename]}"
42
+ tarball="$CACHE_DIR/${filename}.tar"
43
+
44
+ printf " %-50s " "$image"
45
+ START=$(date +%s)
46
+
47
+ docker pull "$image" > /dev/null 2>&1
48
+ docker save "$image" -o "$tarball"
49
+
50
+ END=$(date +%s)
51
+ SIZE=$(du -h "$tarball" | cut -f1)
52
+ echo -e "${GREEN}✔${NC} ${DIM}$((END - START))s ${SIZE}${NC}"
53
+ done
54
+
55
+ echo ""
56
+ echo -e "${GREEN}Images cached to $CACHE_DIR${NC}"
57
+ echo "These will be pre-loaded into app-zone containers on next e2e run."
package/bin/e2e-shell CHANGED
@@ -2,26 +2,49 @@
2
2
  # Connect to a running E2E container.
3
3
  #
4
4
  # Usage:
5
- # ./bin/e2e-shell # Shell into management machine
5
+ # ./bin/e2e-shell # Shell into management (interactive or test project)
6
6
  # ./bin/e2e-shell caddy # Shell into caddy container
7
- # ./bin/e2e-shell fw-main # Shell into fw-main
8
- # ./bin/e2e-shell namecheap-dns # Shell into namecheap-dns
7
+ # ./bin/e2e-shell authentik # Shell into authentik container (test project)
9
8
 
10
9
  set -e
11
- PROJECT_NAME="conductor-e2e-interactive"
12
10
  CONTAINER="${1:-management}"
13
11
 
14
- # Check if network is running
15
- if ! docker compose -p "$PROJECT_NAME" ps --status running 2>/dev/null | grep -q "$CONTAINER"; then
16
- echo "Container '$CONTAINER' is not running."
17
- echo "Available containers:"
18
- docker compose -p "$PROJECT_NAME" ps --format ' {{.Name}} ({{.Status}})' 2>/dev/null || echo " No E2E network running. Start with: ./bin/e2e-up"
12
+ # Resolve project name: prefer interactive project, fall back to any running test project
13
+ resolve_project() {
14
+ # 1. Interactive project (e2e-up)
15
+ if docker compose -p celilo-e2e-interactive ps --status running 2>/dev/null | grep -q "$CONTAINER"; then
16
+ echo "celilo-e2e-interactive"
17
+ return
18
+ fi
19
+
20
+ # 2. Test run project: find any celilo-e2e-* container matching the name
21
+ local container_id
22
+ container_id=$(docker ps --filter "name=${CONTAINER}" --filter "name=celilo-e2e-" --format '{{.Names}}' | head -1)
23
+ if [ -n "$container_id" ]; then
24
+ # Extract project from container name: celilo-e2e-<project>-<service>-1
25
+ # We don't need the compose project name — just exec directly
26
+ echo "_direct:${container_id}"
27
+ return
28
+ fi
29
+
30
+ echo ""
31
+ }
32
+
33
+ PROJECT=$(resolve_project)
34
+
35
+ if [ -z "$PROJECT" ]; then
36
+ echo "Container '$CONTAINER' is not running in any celilo-e2e project."
37
+ echo ""
38
+ echo "Running celilo-e2e containers:"
39
+ docker ps --filter "name=celilo-e2e-" --format ' {{.Names}} ({{.Status}})' 2>/dev/null || echo " none"
19
40
  exit 1
20
41
  fi
21
42
 
22
- # Use zsh for management (has conductor aliases + completion), bash for others
23
- if [ "$CONTAINER" = "management" ]; then
24
- docker compose -p "$PROJECT_NAME" exec "$CONTAINER" zsh -li
43
+ SHELL_CMD="bash"
44
+
45
+ if [[ "$PROJECT" == _direct:* ]]; then
46
+ FULL_NAME="${PROJECT#_direct:}"
47
+ exec docker exec -it "$FULL_NAME" $SHELL_CMD
25
48
  else
26
- docker compose -p "$PROJECT_NAME" exec "$CONTAINER" bash
49
+ exec docker compose -p "$PROJECT" exec "$CONTAINER" $SHELL_CMD
27
50
  fi
package/bin/e2e-status CHANGED
@@ -1,10 +1,16 @@
1
1
  #!/bin/bash
2
2
  # Show status of the E2E test network.
3
3
 
4
- PROJECT_NAME="conductor-e2e-interactive"
4
+ PROJECT_NAME="${CELILO_E2E_PROJECT:-celilo-e2e-interactive}"
5
5
 
6
6
  echo "=== Containers ==="
7
- docker compose -p "$PROJECT_NAME" ps 2>/dev/null || { echo "No E2E network running."; exit 0; }
7
+ if ! docker compose -p "$PROJECT_NAME" ps 2>/dev/null | grep -q .; then
8
+ echo "No E2E network running (project: $PROJECT_NAME)."
9
+ echo ""
10
+ echo "Start one with: cele2e up or cele2e run --keep"
11
+ exit 0
12
+ fi
13
+ docker compose -p "$PROJECT_NAME" ps
8
14
 
9
15
  echo ""
10
16
  echo "=== DNS Check ==="
package/bin/e2e-up CHANGED
@@ -15,7 +15,7 @@ set -e
15
15
  SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
16
16
  cd "$SCRIPT_DIR"
17
17
 
18
- PROJECT_NAME="conductor-e2e-interactive"
18
+ PROJECT_NAME="celilo-e2e-interactive"
19
19
 
20
20
  # Parse args
21
21
  PRESET="infrastructure"
@@ -148,13 +148,13 @@ echo " letsencrypt: 100.64.0.100 (Pebble ACME)"
148
148
  echo " apt-cache: 100.64.0.2 (apt proxy → real internet)"
149
149
  echo ""
150
150
  echo "Commands:"
151
- echo " ./bin/e2e-shell Reconnect to management"
152
- echo " ./bin/e2e-shell <container> Shell into any container"
153
- echo " ./bin/e2e-down Tear everything down"
151
+ echo " cele2e shell Reconnect to management"
152
+ echo " cele2e shell <container> Shell into any container"
153
+ echo " cele2e down Tear everything down"
154
154
  echo " docker compose -p $PROJECT_NAME ps List containers"
155
155
  echo ""
156
156
  echo "Dropping you into the management machine..."
157
- echo "(use 'conductor <cmd>' or 'c <cmd>' — tab completion works)"
157
+ echo "(use 'celilo <cmd>' — tab completion works)"
158
158
  echo ""
159
159
 
160
160
  docker compose -p "$PROJECT_NAME" exec management zsh -li
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # cele2e - Zsh Completion Installer
4
+
5
+ set -e
6
+
7
+ RED='\033[0;31m'
8
+ GREEN='\033[0;32m'
9
+ YELLOW='\033[1;33m'
10
+ BLUE='\033[0;34m'
11
+ NC='\033[0m'
12
+
13
+ COMPLETION_FILE="_cele2e"
14
+ COMPLETION_DIR="$HOME/.zsh/completions"
15
+ ZSHRC="$HOME/.zshrc"
16
+
17
+ echo -e "${BLUE}🧪 cele2e - Zsh Completion Installer${NC}\n"
18
+
19
+ if ! command -v zsh &> /dev/null; then
20
+ echo -e "${RED}✗ zsh not found${NC}"; exit 1
21
+ fi
22
+ echo -e "${GREEN}✓${NC} zsh detected"
23
+
24
+ if ! command -v cele2e &> /dev/null; then
25
+ echo -e "${RED}✗ cele2e not found in PATH${NC}"
26
+ echo -e " Run: bun install -g ~/hobby/infra/packages/e2e"; exit 1
27
+ fi
28
+ echo -e "${GREEN}✓${NC} Found cele2e CLI"
29
+
30
+ echo -e "${YELLOW}→${NC} Generating completion script..."
31
+ GENERATED=$(cele2e completion zsh 2>/dev/null)
32
+ if [[ -z "$GENERATED" ]]; then
33
+ echo -e "${RED}✗ Failed to generate completion script${NC}"; exit 1
34
+ fi
35
+ echo -e "${GREEN}✓${NC} Completion script generated"
36
+
37
+ mkdir -p "$COMPLETION_DIR"
38
+ echo -e "${YELLOW}→${NC} Installing completion script..."
39
+ echo "$GENERATED" > "$COMPLETION_DIR/$COMPLETION_FILE"
40
+ chmod 644 "$COMPLETION_DIR/$COMPLETION_FILE"
41
+ echo -e "${GREEN}✓${NC} Installed to $COMPLETION_DIR/$COMPLETION_FILE"
42
+
43
+ [[ -f "$ZSHRC" ]] || touch "$ZSHRC"
44
+
45
+ if grep -q "fpath=.*\.zsh/completions" "$ZSHRC"; then
46
+ echo -e "${GREEN}✓${NC} Completion directory already in fpath"
47
+ else
48
+ echo -e "${YELLOW}→${NC} Adding completion directory to .zshrc..."
49
+ if grep -qn "autoload.*compinit" "$ZSHRC"; then
50
+ COMPINIT_LINE=$(grep -n "autoload.*compinit" "$ZSHRC" | head -1 | cut -d: -f1)
51
+ sed -i '' "${COMPINIT_LINE}i\\
52
+ # cele2e completions\\
53
+ fpath=(~/.zsh/completions \$fpath)\\
54
+
55
+ " "$ZSHRC"
56
+ else
57
+ echo -e "\n# cele2e completions\nfpath=(~/.zsh/completions \$fpath)\nautoload -Uz compinit && compinit" >> "$ZSHRC"
58
+ fi
59
+ echo -e "${GREEN}✓${NC} fpath configured"
60
+ fi
61
+
62
+ if ! grep -q "autoload.*compinit" "$ZSHRC"; then
63
+ echo "autoload -Uz compinit && compinit" >> "$ZSHRC"
64
+ fi
65
+
66
+ echo -e "${YELLOW}→${NC} Clearing completion cache..."
67
+ rm -rf "$HOME"/.zcompdump*
68
+ echo -e "${GREEN}✓${NC} Cache cleared"
69
+
70
+ echo ""
71
+ echo -e "${GREEN}✅ Installation complete!${NC}"
72
+ echo ""
73
+ echo "To activate:"
74
+ echo -e " ${BLUE}exec zsh${NC}"
75
+ echo ""
76
+ echo "Try it out:"
77
+ echo -e " ${BLUE}cele2e <TAB>${NC}"
78
+ echo -e " ${BLUE}cele2e run <TAB>${NC}"
@@ -2,7 +2,7 @@ $ORIGIN iamtheinternet.org.
2
2
  $TTL 300
3
3
 
4
4
  @ IN SOA ns1.iamtheinternet.org. admin.iamtheinternet.org. (
5
- 2024010778 300 60 604800 300
5
+ 2024010821 300 60 604800 300
6
6
  )
7
7
 
8
8
  @ IN NS ns1.iamtheinternet.org.
@@ -0,0 +1,14 @@
1
+ [Unit]
2
+ Description=Pre-load cached Docker images for e2e acceleration
3
+ After=docker.service
4
+ Requires=docker.service
5
+ ConditionPathIsDirectory=/docker-image-cache
6
+
7
+ [Service]
8
+ Type=oneshot
9
+ ExecStart=/usr/local/bin/docker-image-preload.sh
10
+ RemainAfterExit=yes
11
+ StandardOutput=journal
12
+
13
+ [Install]
14
+ WantedBy=multi-user.target
@@ -0,0 +1,24 @@
1
+ #!/bin/bash
2
+ # Load pre-cached Docker images for e2e acceleration.
3
+ # Runs at container startup via docker-image-preload.service.
4
+ # Gracefully skips if /docker-image-cache is empty or not mounted.
5
+
6
+ # Wait for the Docker daemon to accept connections (up to 30s)
7
+ for i in $(seq 1 30); do
8
+ if docker info > /dev/null 2>&1; then
9
+ break
10
+ fi
11
+ sleep 1
12
+ done
13
+
14
+ if ! docker info > /dev/null 2>&1; then
15
+ echo "docker-image-preload: Docker not ready after 30s, skipping"
16
+ exit 0
17
+ fi
18
+
19
+ shopt -s nullglob
20
+ for tar in /docker-image-cache/*.tar; do
21
+ echo "docker-image-preload: loading $(basename "$tar")"
22
+ docker load -i "$tar"
23
+ done
24
+ echo "docker-image-preload: done"
@@ -28,26 +28,43 @@ ip route add 10.0.10.0/24 via 192.168.0.254 # dmz via fw-main
28
28
  ip route add 10.0.20.0/24 via 192.168.0.254 # app via fw-main
29
29
  ip route add 10.0.30.0/24 via 192.168.0.254 # secure via fw-main
30
30
 
31
- # DNS — use the simulated resolver
32
- echo "nameserver 100.100.0.1" > /etc/resolv.conf
31
+ # DNS — Technitium internal resolver (split-horizon) with public fallback.
32
+ # Technitium at 192.168.0.10 is authoritative for iamtheinternet.org internally,
33
+ # resolving www/auth to Caddy's DMZ IP (10.0.10.10) rather than the public WAN IP.
34
+ # Fall back to the simulated public resolver if Technitium is not yet up.
35
+ printf 'nameserver 192.168.0.10\nnameserver 100.100.0.1\n' > /etc/resolv.conf
33
36
 
34
37
  # Create celilo data directory (Linux default: /var/lib/celilo/)
35
38
  mkdir -p /var/lib/celilo/modules
36
39
 
37
- # Dependencies come from the host bind mount (node_modules/)
38
- # If missing, run 'cd apps/celilo && bun install' on the host first.
39
- cd /celilo/apps/celilo
40
- if [ ! -d node_modules/@clack ]; then
41
- echo "WARNING: node_modules not found. Run 'cd apps/celilo && bun install' on the host."
40
+ # If the monorepo is mounted at /celilo, use it for shell completions (dev mode).
41
+ # Otherwise use the globally installed CLI from npm.
42
+ if [ -d /celilo/apps/celilo ]; then
43
+ CELILO_SRC="/celilo/apps/celilo/src/cli/index.ts"
44
+ CELILO_CMD="bun run $CELILO_SRC"
45
+
46
+ # Warn if node_modules are missing (developer forgot to bun install)
47
+ if [ ! -d /celilo/apps/celilo/node_modules/@clack ]; then
48
+ echo "WARNING: /celilo/apps/celilo/node_modules not found. Run 'cd apps/celilo && bun install' on the host."
49
+ fi
50
+
51
+ # Generate zsh completions from source
52
+ mkdir -p /root/.zsh/completions
53
+ bun run "$CELILO_SRC" completion zsh > /root/.zsh/completions/_celilo 2>/dev/null || true
54
+
55
+ START_DIR="/celilo/apps/celilo"
56
+ else
57
+ CELILO_CMD="celilo"
58
+ START_DIR="/root"
59
+
60
+ # Generate zsh completions from npm-installed CLI
61
+ mkdir -p /root/.zsh/completions
62
+ celilo completion zsh > /root/.zsh/completions/_celilo 2>/dev/null || true
42
63
  fi
43
64
 
44
- # Generate zsh completion script from celilo
45
- mkdir -p /root/.zsh/completions
46
- bun run /celilo/apps/celilo/src/cli/index.ts completion zsh > /root/.zsh/completions/_celilo 2>/dev/null || true
47
-
48
- # Shell setup: aliases and completion for zsh
49
- cat > /root/.zshrc << 'ZSHRC'
50
- export PATH="/root/.bun/bin:$PATH"
65
+ # Shell setup
66
+ cat > /root/.zshrc << ZSHRC
67
+ export PATH="/root/.bun/bin:/usr/local/bin:\$PATH"
51
68
 
52
69
  # Simulated network overrides
53
70
  export DDNS_ENDPOINT="http://100.64.0.55:8080/update"
@@ -69,27 +86,22 @@ bindkey '^R' history-incremental-search-backward
69
86
  # Prompt
70
87
  PROMPT='%F{cyan}celilo%f:%F{yellow}%~%f# '
71
88
 
72
- # Commands
73
- celilo() { bun run /celilo/apps/celilo/src/cli/index.ts "$@"; }
74
- c() { celilo "$@"; }
89
+ # Commands — celilo shim in /usr/local/bin prefers source when /celilo is mounted
90
+ alias c='celilo'
75
91
  alias ll='ls -la'
76
92
 
77
- # Tab completion — use celilo's built-in zsh completion generator
78
- fpath=(~/.zsh/completions $fpath)
93
+ # Tab completion
94
+ fpath=(~/.zsh/completions \$fpath)
79
95
  autoload -Uz compinit && compinit -u
80
96
 
81
- # Also bind `c` to the same completion
82
- compdef _celilo c
83
-
84
- cd /celilo/apps/celilo
97
+ cd $START_DIR
85
98
  ZSHRC
86
99
 
87
- # Also set up bash aliases (for non-zsh shells)
88
- cat > /root/.bashrc << 'BASHRC'
89
- export PATH="/root/.bun/bin:$PATH"
90
- alias celilo='bun run /celilo/apps/celilo/src/cli/index.ts'
100
+ # Bash fallback (for non-zsh shells)
101
+ cat > /root/.bashrc << BASHRC
102
+ export PATH="/root/.bun/bin:/usr/local/bin:\$PATH"
91
103
  alias c='celilo'
92
- cd /celilo/apps/celilo
104
+ cd $START_DIR
93
105
  BASHRC
94
106
 
95
107
  echo "Management machine ready"
@@ -17,18 +17,20 @@ RUN chsh -s /bin/zsh root
17
17
 
18
18
  # Trust the E2E forward proxy CA (for transparent HTTPS interception)
19
19
  COPY config/proxy/squid-ca.crt /usr/local/share/ca-certificates/e2e-proxy-ca.crt
20
+ # Trust Pebble's test CA (so bun fetch() trusts certs issued by the simulated Let's Encrypt)
21
+ COPY config/pebble/pebble-ca.crt /usr/local/share/ca-certificates/pebble-ca.crt
20
22
  RUN update-ca-certificates
21
23
 
22
24
  # Point apt at the simulated apt cache proxy (for runtime apt usage)
23
25
  RUN echo 'Acquire::http::Proxy "http://100.64.0.2:3142";' > /etc/apt/apt.conf.d/00proxy
24
26
 
25
- # Install celilo CLI from npm — provides the fallback `celilo` command
26
- RUN bun add -g @celilo/cli@0.1.4
27
+ # Install celilo CLI from npm. bun installs the bin to /usr/local/bin/celilo
28
+ # on the oven/bun base image. We rename it so our shim can fall back to it.
29
+ RUN bun add -g @celilo/cli@0.1.5 \
30
+ && mv /usr/local/bin/celilo /usr/local/bin/celilo-npm
27
31
 
28
32
  # Shim: prefer /celilo source when mounted (dev loop), fall back to npm install.
29
- # This means `celilo ...` runs the monorepo's source code during e2e tests
30
- # instead of the pinned npm version — critical for iterating on fixes.
31
- RUN printf '#!/bin/bash\nif [ -d /celilo/apps/celilo ]; then\n exec bun run /celilo/apps/celilo/src/cli/index.ts "$@"\nfi\nexec /root/.bun/bin/celilo "$@"\n' > /usr/local/bin/celilo \
33
+ RUN printf '#!/bin/bash\nif [ -d /celilo/apps/celilo ]; then\n exec bun run /celilo/apps/celilo/src/cli/index.ts "$@"\nfi\nexec /usr/local/bin/celilo-npm "$@"\n' > /usr/local/bin/celilo \
32
34
  && chmod +x /usr/local/bin/celilo
33
35
 
34
36
  # Standard modules pre-packaged as .netapp files — built by e2e-build.
@@ -57,5 +57,25 @@ RUN (cd /lib/systemd/system/sysinit.target.wants/ && \
57
57
  # Re-enable the services we actually need
58
58
  RUN systemctl enable ssh target-setup
59
59
 
60
+ # --- Caddy pre-installation ---
61
+ # Temporarily disable apt proxy (not available during docker build)
62
+ RUN rm -f /etc/apt/apt.conf.d/00proxy
63
+
64
+ # Install Caddy (same steps as the Ansible role, but at image build time so
65
+ # the role finds it already installed and skips the slow cloudsmith.io downloads)
66
+ RUN apt-get update && apt-get install -y \
67
+ debian-keyring \
68
+ debian-archive-keyring \
69
+ apt-transport-https \
70
+ && rm -rf /var/lib/apt/lists/*
71
+ RUN curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \
72
+ gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
73
+ RUN curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \
74
+ tee /etc/apt/sources.list.d/caddy-stable.list
75
+ RUN apt-get update && apt-get install -y caddy && rm -rf /var/lib/apt/lists/*
76
+
77
+ # Re-enable apt proxy for runtime
78
+ RUN echo 'Acquire::http::Proxy "http://100.64.0.2:3142";' > /etc/apt/apt.conf.d/00proxy
79
+
60
80
  STOPSIGNAL SIGRTMIN+3
61
81
  ENTRYPOINT ["/sbin/init"]
@@ -1,6 +1,6 @@
1
- # Target machine with Docker pre-installed and authentik images pre-pulled.
2
- # Used for app-zone machines that will run Docker Compose workloads.
3
- # This avoids a 10+ minute Docker pull during e2e test deploy time.
1
+ # Target machine with Docker pre-installed.
2
+ # Used for app-zone machines that run Docker Compose workloads (e.g. authentik).
3
+ # Docker itself is baked in; application images are pulled at deploy time by each module.
4
4
 
5
5
  FROM ubuntu:22.04
6
6
 
@@ -87,22 +87,14 @@ RUN mkdir -p /etc/docker && \
87
87
 
88
88
  RUN systemctl enable docker
89
89
 
90
- # Pre-cached image loading service:
91
- # At first boot, if /docker-image-cache/*.tar exists, load them into Docker.
92
- # This avoids multi-minute pulls during e2e test deploy.
93
- RUN echo '#!/bin/bash\n\
94
- set -e\n\
95
- if ls /docker-image-cache/*.tar 1>/dev/null 2>&1; then\n\
96
- for img in /docker-image-cache/*.tar; do\n\
97
- echo "Loading cached Docker image: $img"\n\
98
- docker load < "$img"\n\
99
- done\n\
100
- fi\n' > /usr/local/bin/load-cached-images.sh && \
101
- chmod +x /usr/local/bin/load-cached-images.sh
102
-
103
- RUN printf '[Unit]\nDescription=Load pre-cached Docker images\nAfter=docker.service\nRequires=docker.service\n\n[Service]\nType=oneshot\nExecStart=/usr/local/bin/load-cached-images.sh\nRemainAfterExit=yes\n\n[Install]\nWantedBy=multi-user.target\n' \
104
- > /etc/systemd/system/load-docker-cache.service && \
105
- systemctl enable load-docker-cache
90
+ # Pre-load cached Docker images on startup (e2e acceleration)
91
+ # /docker-image-cache is bind-mounted from the host by the compose generator.
92
+ # The service is a no-op if the directory is absent or empty.
93
+ COPY config/routing/docker-image-preload.sh /usr/local/bin/docker-image-preload.sh
94
+ RUN chmod +x /usr/local/bin/docker-image-preload.sh
95
+ COPY config/routing/docker-image-preload.service /etc/systemd/system/docker-image-preload.service
96
+ RUN systemctl enable docker-image-preload
97
+
106
98
 
107
99
  STOPSIGNAL SIGRTMIN+3
108
100
  ENTRYPOINT ["/sbin/init"]
@@ -0,0 +1,97 @@
1
+ # Target machine with Technitium DNS Server pre-installed.
2
+ # Based on target-machine; Technitium is installed at image build time so the
3
+ # Ansible role finds it already present and skips the download step.
4
+
5
+ FROM ubuntu:22.04
6
+
7
+ ENV DEBIAN_FRONTEND=noninteractive
8
+
9
+ RUN apt-get update && apt-get install -y \
10
+ systemd \
11
+ systemd-sysv \
12
+ openssh-server \
13
+ iproute2 \
14
+ iputils-ping \
15
+ net-tools \
16
+ dnsutils \
17
+ procps \
18
+ python3 \
19
+ python3-apt \
20
+ sqlite3 \
21
+ jq \
22
+ sudo \
23
+ curl \
24
+ ca-certificates \
25
+ && rm -rf /var/lib/apt/lists/*
26
+
27
+ # Trust the E2E forward proxy CA (for transparent HTTPS interception)
28
+ COPY config/proxy/squid-ca.crt /usr/local/share/ca-certificates/e2e-proxy-ca.crt
29
+ # Trust Pebble's test CA (so Caddy/ACME clients trust the simulated Let's Encrypt)
30
+ COPY config/pebble/pebble-ca.crt /usr/local/share/ca-certificates/pebble-ca.crt
31
+ RUN update-ca-certificates
32
+
33
+ RUN mkdir -p /run/sshd && \
34
+ sed -i 's/#PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config && \
35
+ sed -i 's/#PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
36
+
37
+ # Enable SSH service
38
+ RUN systemctl enable ssh
39
+
40
+ # Point apt at the simulated apt cache proxy
41
+ RUN echo 'Acquire::http::Proxy "http://100.64.0.2:3142";' > /etc/apt/apt.conf.d/00proxy
42
+
43
+ # E2E network setup service (runs at boot to configure routing, DNS, SSH keys)
44
+ COPY config/routing/target-setup.sh /usr/local/bin/target-setup.sh
45
+ RUN chmod +x /usr/local/bin/target-setup.sh
46
+
47
+ COPY config/routing/target-setup.service /etc/systemd/system/target-setup.service
48
+ RUN systemctl enable target-setup
49
+
50
+ # Clean up unnecessary systemd services that slow down boot
51
+ RUN (cd /lib/systemd/system/sysinit.target.wants/ && \
52
+ ls | grep -v systemd-tmpfiles-setup | xargs rm -f 2>/dev/null); \
53
+ rm -f /lib/systemd/system/multi-user.target.wants/*; \
54
+ rm -f /etc/systemd/system/*.wants/*; \
55
+ rm -f /lib/systemd/system/local-fs.target.wants/*; \
56
+ rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
57
+ rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
58
+ rm -f /lib/systemd/system/basic.target.wants/*; \
59
+ true
60
+
61
+ # Re-enable the services we actually need
62
+ RUN systemctl enable ssh target-setup
63
+
64
+ # --- Technitium pre-installation (manual — installer requires running systemd) ---
65
+ # The official install.sh checks for systemd at runtime and fails during docker build.
66
+ # Instead: install ASP.NET Core runtime, download binaries, write the service file.
67
+ # Ansible tasks check for /opt/technitium/dns/DnsServerApp.dll and skip the download.
68
+
69
+ # Temporarily lift the apt proxy (not available at build time)
70
+ RUN rm -f /etc/apt/apt.conf.d/00proxy
71
+
72
+ # ASP.NET Core 8.0 runtime via Microsoft package feed
73
+ RUN curl -sSL https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb \
74
+ -o /tmp/ms-prod.deb && \
75
+ dpkg -i /tmp/ms-prod.deb && \
76
+ rm /tmp/ms-prod.deb && \
77
+ apt-get update && \
78
+ apt-get install -y aspnetcore-runtime-8.0 && \
79
+ rm -rf /var/lib/apt/lists/*
80
+
81
+ # Download and extract Technitium portable package
82
+ RUN mkdir -p /opt/technitium/dns && \
83
+ curl -sSL https://download.technitium.com/dns/DnsServerPortable.tar.gz \
84
+ -o /tmp/technitium.tar.gz && \
85
+ tar -xzf /tmp/technitium.tar.gz -C /opt/technitium/dns && \
86
+ rm -f /tmp/technitium.tar.gz
87
+
88
+ # Register systemd service (same unit the installer creates)
89
+ RUN printf '[Unit]\nDescription=Technitium DNS Server\nAfter=network.target\n\n[Service]\nExecStart=/usr/bin/dotnet /opt/technitium/dns/DnsServerApp.dll\nRestart=on-failure\nRestartSec=10\n\n[Install]\nWantedBy=multi-user.target\n' \
90
+ > /etc/systemd/system/dns.service && \
91
+ systemctl enable dns
92
+
93
+ # Re-enable apt proxy for runtime
94
+ RUN echo 'Acquire::http::Proxy "http://100.64.0.2:3142";' > /etc/apt/apt.conf.d/00proxy
95
+
96
+ STOPSIGNAL SIGRTMIN+3
97
+ ENTRYPOINT ["/sbin/init"]
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file