kampodine 0.3.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.
@@ -12,21 +12,21 @@
12
12
  # 2. apk repositories: ensure the v3.22 community repo (podman lives there)
13
13
  # 3. podman stack: podman podman-docker crun catatonit netavark
14
14
  # aardvark-dns fuse-overlayfs
15
- # 4. /etc/esellar/ (kampodine deploy writes /etc/esellar/env here, 0600 root)
15
+ # 4. /etc/kampodine/ (kampodine deploy writes /etc/kampodine/env here, 0600 root)
16
16
  # 5. /etc/containers/registries.conf (insecure 127.0.0.1:5000; search docker.io)
17
17
  # 6. sysctl net.ipv4.ip_unprivileged_port_start=80 (persisted + applied live)
18
- # 7. OpenRC services /etc/init.d/esellar-api + /etc/init.d/kamal-proxy
18
+ # 7. OpenRC services /etc/init.d/kampodine-api + /etc/init.d/kamal-proxy
19
19
  # (supervise-daemon around plain `podman run`), rc-update'd into the
20
20
  # default runlevel — that IS boot survival (no quadlets, no systemctl)
21
- # 8. esellar-anchor: the blue-green reserved-ip flip's GUEST half — a
22
- # busybox watcher (no container) that polls /etc/esellar/anchor.conf and
21
+ # 8. kampodine-anchor: the blue-green reserved-ip flip's GUEST half — a
22
+ # busybox watcher (no container) that polls /etc/kampodine/anchor.conf and
23
23
  # `ip addr add`s the anchor address at flip time. Started+enabled on every
24
24
  # VM, inert without the conf (flip tooling writes it over ssh).
25
25
  # 9. kamal-proxy image pulled + service UP — the first deploy execs into it
26
26
  # to issue the fresh ACME certificate
27
27
  #
28
- # The esellar-api container is NOT started here: neither its image (pulled by
29
- # the first deploy over the registry tunnel) nor /etc/esellar/env (written by
28
+ # The kampodine-api container is NOT started here: neither its image (pulled by
29
+ # the first deploy over the registry tunnel) nor /etc/kampodine/env (written by
30
30
  # kampodine deploy) exists yet on a fresh VM.
31
31
  #
32
32
  # Idempotent: safe to re-run. apk add is a no-op when satisfied; managed files
@@ -35,42 +35,56 @@
35
35
  # not a restart).
36
36
  #
37
37
  # kampodine vm-prepare --host root@<new-ip>
38
+ # kampodine vm-prepare --profile <name> # host/key from ~/.kampodine/config.json
38
39
  # ... --pull-images # + pre-pull the app image over the registry tunnel
39
- # ... --ssh-key <path> # ssh identity (default: agent / ESPELLAR_SSH_KEY)
40
+ # ... --ssh-key <path> # ssh identity (default: agent / KAMPODINE_SSH_KEY)
40
41
  set -euo pipefail
41
42
 
42
43
  HOST=""
43
44
  DO_PULL=0
44
- SSH_KEY="${ESPELLAR_SSH_KEY:-}"
45
+ SSH_KEY="${KAMPODINE_SSH_KEY:-}"
46
+ PROFILE_FLAG=""
47
+ HOST_FLAG=""
48
+ KEY_FLAG=""
49
+ HERE="$(cd "$(dirname "$0")" && pwd)"
50
+ # shellcheck source=common.sh
51
+ source "$HERE/common.sh"
45
52
 
46
53
  say() { printf '\033[1;32m[vm-prepare]\033[0m %s\n' "$*"; }
47
54
  die() { printf '\033[1;31m[vm-prepare] FAIL:\033[0m %s\n' "$*" >&2; exit 1; }
48
55
  usage() {
49
56
  cat <<'EOF'
50
57
  Usage:
51
- kampodine vm-prepare --host root@<new-ip> [--pull-images] [--ssh-key <path>]
58
+ kampodine vm-prepare --host root@<new-ip> [--pull-images] [--ssh-key <path>] [--profile <name>]
52
59
 
53
60
  Examples:
54
61
  EOF
55
62
  grep '^# kampodine vm-prepare' "$0" | sed 's/^# //'
56
63
  cat <<'EOF'
57
64
 
58
- Host/key resolution: --host | (no env default — explicit flag);
59
- --ssh-key | ESPELLAR_SSH_KEY | ssh-agent / ~/.ssh/config.
65
+ Host/key resolution: --host | --profile <name> | KAMPODINE_PROFILE |
66
+ config defaultProfile; --ssh-key | profile sshKey | KAMPODINE_SSH_KEY |
67
+ ssh-agent / ~/.ssh/config.
60
68
  EOF
61
69
  exit 0
62
70
  }
63
71
 
64
72
  while [[ $# -gt 0 ]]; do
65
73
  case "$1" in
66
- --host) HOST="$2"; shift 2 ;;
74
+ --host) HOST_FLAG="$2"; HOST="$2"; shift 2 ;;
67
75
  --pull-images) DO_PULL=1; shift ;;
68
- --ssh-key) SSH_KEY="$2"; shift 2 ;;
76
+ --ssh-key) KEY_FLAG="$2"; SSH_KEY="$2"; shift 2 ;;
77
+ --profile) PROFILE_FLAG="$2"; shift 2 ;;
69
78
  -h|--help) usage ;;
70
79
  *) die "unknown argument: $1 (--help)" ;;
71
80
  esac
72
81
  done
73
- [[ -n "$HOST" ]] || die "--host root@<ip> required (--help for usage)"
82
+ # profile resolution (flag > KAMPODINE_PROFILE > defaultProfile); the explicit
83
+ # --host/--ssh-key flags always beat the profile
84
+ profile_resolve "$PROFILE_FLAG" "${HOST_FLAG:-}" "${KEY_FLAG:-}"
85
+ SSH_KEY="${KEY_FLAG:-${KAMPODINE_SSH_KEY:-}}"
86
+ [[ -z "$HOST" ]] && HOST="${KAMPODINE_HOST:-}"
87
+ [[ -n "$HOST" ]] || die "--host root@<ip> required (--profile <name> or KAMPODINE_HOST also work; --help for usage)"
74
88
 
75
89
  SSH_ARGS=(-o ConnectTimeout=10 -o BatchMode=yes -o StrictHostKeyChecking=accept-new)
76
90
  [[ -n "$SSH_KEY" ]] && SSH_ARGS+=(-i "$SSH_KEY")
@@ -87,7 +101,7 @@ if [[ "$(uname -s)" == "Darwin" ]]; then
87
101
  fi
88
102
 
89
103
  # --- managed file payloads (built Mac-side, scp'd) ----------------------------
90
- TMPDIR_LOCAL="$(mktemp -d /tmp/esellar-vm-prepare.XXXXXX)"
104
+ TMPDIR_LOCAL="$(mktemp -d /tmp/kampodine-vm-prepare.XXXXXX)"
91
105
  trap 'rm -rf "$TMPDIR_LOCAL"' EXIT
92
106
 
93
107
  cat > "$TMPDIR_LOCAL/registries.conf" <<'REGISTRIES'
@@ -102,17 +116,17 @@ location = "127.0.0.1:5000"
102
116
  insecure = true
103
117
  REGISTRIES
104
118
 
105
- cat > "$TMPDIR_LOCAL/60-esellar.conf" <<'SYSCTL'
119
+ cat > "$TMPDIR_LOCAL/60-kampodine.conf" <<'SYSCTL'
106
120
  # Managed by packages/kampodine/scripts/vm-prepare.sh — do not hand-edit.
107
121
  # OpenRC contract: let unprivileged/container paths bind port 80
108
122
  # (kamal-proxy publishes 80+443; belt-and-braces for a future rootless move).
109
123
  net.ipv4.ip_unprivileged_port_start=80
110
124
  SYSCTL
111
125
 
112
- cat > "$TMPDIR_LOCAL/esellar-api" <<'INITD_API'
126
+ cat > "$TMPDIR_LOCAL/kampodine-api" <<'INITD_API'
113
127
  #!/sbin/openrc-run
114
128
  # Managed by packages/kampodine/scripts/vm-prepare.sh — do not hand-edit.
115
- # KEEP IN SYNC with ansible/roles/container-service/templates/esellar-api.initd.j2
129
+ # KEEP IN SYNC with the golden image's container-service init template
116
130
  # (rendered with role defaults): vm-prepare bootstraps a fresh VM BEFORE the
117
131
  # first ansible converge; ansible owns the file afterwards (drift repair).
118
132
  #
@@ -122,7 +136,7 @@ cat > "$TMPDIR_LOCAL/esellar-api" <<'INITD_API'
122
136
  # dies, the WHOLE run restarts against the local :latest (no pull inside the
123
137
  # run — restarts are offline-safe; the registry tunnel is down between deploys).
124
138
  #
125
- # Env: /etc/esellar/env (0600 root, written by kampodine deploy per deploy) is
139
+ # Env: /etc/kampodine/env (0600 root, written by kampodine deploy per deploy) is
126
140
  # the single SECRETS source (podman --env-file reads KEY=VALUE lines directly).
127
141
  # The five CLEAR vars (NODE_ENV, PORT, LIBSQL_TENANT_DIR, LIBSQL_API_MOUNT,
128
142
  # STATIC_SPA_MOUNT) are owned HERE via -e — deploy filters them out of the env
@@ -130,16 +144,16 @@ cat > "$TMPDIR_LOCAL/esellar-api" <<'INITD_API'
130
144
  # (tenant sqlite files) — without the bind mount, tenant data would be
131
145
  # container-ephemeral and lost on every restart.
132
146
 
133
- name="esellar-api"
134
- description="esellar API + SPA container (127.0.0.1:5000/esellar-api:latest on 8080)"
147
+ name="kampodine-api"
148
+ description="kampodine API + SPA container (127.0.0.1:5000/kampodine-api:latest on 8080)"
135
149
 
136
150
  supervisor=supervise-daemon
137
151
  command="/usr/bin/podman"
138
- command_args="run --rm --name esellar-api --network kamal -p 8080:8080"
152
+ command_args="run --rm --name kampodine-api --network kamal -p 8080:8080"
139
153
  command_args="$command_args -v /data/tenants:/data/tenants"
140
154
  command_args="$command_args -e NODE_ENV=production -e PORT=8080"
141
155
  command_args="$command_args -e LIBSQL_TENANT_DIR=/data/tenants -e LIBSQL_API_MOUNT=1 -e STATIC_SPA_MOUNT=1"
142
- command_args="$command_args --env-file /etc/esellar/env 127.0.0.1:5000/esellar-api:latest"
156
+ command_args="$command_args --env-file /etc/kampodine/env 127.0.0.1:5000/kampodine-api:latest"
143
157
 
144
158
  # Respawn forever (blue's restart=always precedent): a crash loop self-heals at
145
159
  # the next deploy's restart; the 10s delay bounds log noise.
@@ -147,26 +161,26 @@ respawn_delay=10
147
161
  respawn_max=0
148
162
 
149
163
  # podman run's OWN stderr (missing image, name conflicts, netavark failures);
150
- # container stdout/stderr go to `podman logs esellar-api`.
151
- supervise_daemon_args="--stderr /var/log/esellar-api-service.log"
164
+ # container stdout/stderr go to `podman logs kampodine-api`.
165
+ supervise_daemon_args="--stderr /var/log/kampodine-service.log"
152
166
 
153
167
  depend() {
154
168
  need net
155
- after esellar-datamount
169
+ after kampodine-datamount
156
170
  }
157
171
 
158
172
  start_pre() {
159
173
  # SIGKILLed runs leave the container name holding port 8080 (--rm only
160
174
  # cleans CLEAN exits) — sweep any leftover before the supervised run.
161
- podman container exists esellar-api 2>/dev/null && podman rm -f esellar-api >/dev/null 2>&1
175
+ podman container exists kampodine-api 2>/dev/null && podman rm -f kampodine-api >/dev/null 2>&1
162
176
  return 0
163
177
  }
164
178
 
165
179
  stop_post() {
166
180
  # supervise-daemon killed the podman client; make sure the container goes
167
181
  # down too (TERM -> graceful shutdown, then a tolerant sweep).
168
- podman stop --time 10 esellar-api >/dev/null 2>&1 || true
169
- podman rm -f --time 0 esellar-api >/dev/null 2>&1 || true
182
+ podman stop --time 10 kampodine-api >/dev/null 2>&1 || true
183
+ podman rm -f --time 0 kampodine-api >/dev/null 2>&1 || true
170
184
  }
171
185
  INITD_API
172
186
 
@@ -174,7 +188,7 @@ cat > "$TMPDIR_LOCAL/kamal-proxy" <<'INITD_PROXY'
174
188
  #!/sbin/openrc-run
175
189
  # Managed by packages/kampodine/scripts/vm-prepare.sh — do not hand-edit.
176
190
  # KEEP IN SYNC with ansible/roles/container-service/templates/kamal-proxy.initd.j2
177
- # (see the esellar-api header for the vm-prepare/ansible split).
191
+ # (see the kampodine-api header for the vm-prepare/ansible split).
178
192
  #
179
193
  # TLS edge (kamal-proxy, Let's Encrypt HTTP-01 on :80). Publishes 80+443; the
180
194
  # LE certs + host->target registrations persist in the kamal-proxy-config named
@@ -182,7 +196,7 @@ cat > "$TMPDIR_LOCAL/kamal-proxy" <<'INITD_PROXY'
182
196
  # the first deploy survives container recreation AND reboots. Start-fresh:
183
197
  # nothing is carried from the retired blue VM. Target registration happens at
184
198
  # deploy time (kampodine deploy: podman exec kamal-proxy kamal-proxy deploy
185
- # esellar-api --host=$PROXY_HOST --target=esellar-api:8080 --tls
199
+ # kampodine-api --host=$PROXY_HOST --target=kampodine-api:8080 --tls
186
200
  # --health-check-path=/api/auth/ok).
187
201
 
188
202
  name="kamal-proxy"
@@ -212,19 +226,19 @@ stop_post() {
212
226
  }
213
227
  INITD_PROXY
214
228
 
215
- cat > "$TMPDIR_LOCAL/esellar-anchor.sh" <<'ANCHOR_WATCHER'
229
+ cat > "$TMPDIR_LOCAL/kampodine-anchor.sh" <<'ANCHOR_WATCHER'
216
230
  #!/bin/sh
217
- # KEEP IN SYNC with ansible/roles/container-service/files/esellar-anchor.sh
231
+ # KEEP IN SYNC with ansible/roles/container-service/files/kampodine-anchor.sh
218
232
  # (vm-prepare rendered-content convention: vm-prepare bootstraps a fresh VM
219
233
  # BEFORE the first ansible converge; ansible owns the file afterwards).
220
234
  #
221
- # esellar-anchor.sh — guest half of the blue-green reserved-ip flip.
235
+ # kampodine-anchor.sh — guest half of the blue-green reserved-ip flip.
222
236
  #
223
237
  # OCI assigns the reserved PUBLIC ip to a SECONDARY private ip ("the anchor")
224
238
  # on the instance VNIC, but this image has NO oracle-cloud-agent: nothing
225
239
  # configures that private ip inside the guest, so packets to the reserved ip
226
240
  # die until the address exists on the interface. `kampodine bluegreen flip` writes
227
- # /etc/esellar/anchor.conf over ssh at flip time; this watcher polls it and
241
+ # /etc/kampodine/anchor.conf over ssh at flip time; this watcher polls it and
228
242
  # runs `ip addr add` within one interval. The unit is enabled+started on every
229
243
  # VM by default and is INERT without the conf — a VM that never flips never
230
244
  # touches its addresses.
@@ -236,13 +250,13 @@ cat > "$TMPDIR_LOCAL/esellar-anchor.sh" <<'ANCHOR_WATCHER'
236
250
  # ADD-ONLY BY DESIGN: this script NEVER removes or flushes addresses (rollback
237
251
  # cleanup is the flip tool's explicit ssh job). Idempotent: a present address
238
252
  # is a no-op. Only state TRANSITIONS are logged (bounded log noise), to
239
- # stdout — supervise-daemon tees it to /var/log/esellar-anchor.log.
253
+ # stdout — supervise-daemon tees it to /var/log/kampodine-anchor.log.
240
254
 
241
- CONF="/etc/esellar/anchor.conf"
242
- INTERVAL="${ESPELLAR_ANCHOR_INTERVAL:-5}"
255
+ CONF="/etc/kampodine/anchor.conf"
256
+ INTERVAL="${KAMPODINE_ANCHOR_INTERVAL:-5}"
243
257
  STATE="boot" # last logged transition (boot | idle | added | error)
244
258
 
245
- log() { printf '%s esellar-anchor: %s\n' "$(date '+%Y-%m-%dT%H:%M:%S%z')" "$*"; }
259
+ log() { printf '%s kampodine-anchor: %s\n' "$(date '+%Y-%m-%dT%H:%M:%S%z')" "$*"; }
246
260
 
247
261
  # supervise-daemon SIGTERMs on stop — die cleanly with the current tick.
248
262
  trap 'exit 0' TERM INT
@@ -283,33 +297,33 @@ while :; do
283
297
  done
284
298
  ANCHOR_WATCHER
285
299
 
286
- cat > "$TMPDIR_LOCAL/esellar-anchor" <<'INITD_ANCHOR'
300
+ cat > "$TMPDIR_LOCAL/kampodine-anchor" <<'INITD_ANCHOR'
287
301
  #!/sbin/openrc-run
288
302
  # Managed by packages/kampodine/scripts/vm-prepare.sh — do not hand-edit.
289
- # KEEP IN SYNC with ansible/roles/container-service/templates/esellar-anchor.initd.j2
290
- # (rendered with role defaults — see the esellar-api header for the
303
+ # KEEP IN SYNC with ansible/roles/container-service/templates/kampodine-anchor.initd.j2
304
+ # (rendered with role defaults — see the kampodine-api header for the
291
305
  # vm-prepare/ansible split).
292
306
  #
293
307
  # Guest half of the blue-green reserved-ip flip: supervise-daemon runs the
294
- # esellar-anchor.sh watcher, which polls /etc/esellar/anchor.conf (written by
308
+ # kampodine-anchor.sh watcher, which polls /etc/kampodine/anchor.conf (written by
295
309
  # `kampodine bluegreen flip` over ssh at flip time) and `ip addr add`s the
296
310
  # anchor address when it appears. Started+enabled on EVERY vm by default and
297
311
  # INERT without the conf: a VM that never flips never touches its addresses —
298
- # unlike the container units, there is no esellar_start_containers gate.
299
- # Transitions land in /var/log/esellar-anchor.log.
312
+ # unlike the container units, there is no kampodine_start_containers gate.
313
+ # Transitions land in /var/log/kampodine-anchor.log.
300
314
 
301
- name="esellar-anchor"
315
+ name="kampodine-anchor"
302
316
  description="Blue-green reserved-ip anchor address watcher (guest half of the flip)"
303
317
 
304
318
  supervisor=supervise-daemon
305
- command="/usr/local/sbin/esellar-anchor.sh"
319
+ command="/usr/local/sbin/kampodine-anchor.sh"
306
320
 
307
321
  # Respawn forever: the watcher itself never exits (trap TERM/INT -> exit 0 on
308
322
  # stop), so a respawn means the script died abnormally — retry gently.
309
323
  respawn_delay=5
310
324
  respawn_max=0
311
325
 
312
- supervise_daemon_args="--stdout /var/log/esellar-anchor.log --stderr /var/log/esellar-anchor.log"
326
+ supervise_daemon_args="--stdout /var/log/kampodine-anchor.log --stderr /var/log/kampodine-anchor.log"
313
327
 
314
328
  depend() {
315
329
  need net
@@ -366,7 +380,7 @@ say "sshd hardening: ensure drop-in + Include + restart (golden image predates t
366
380
  vm 'grep -q "^Include /etc/ssh/sshd_config.d/\*.conf" /etc/ssh/sshd_config || sed -i "1i Include /etc/ssh/sshd_config.d/*.conf" /etc/ssh/sshd_config' \
367
381
  || die "could not ensure the sshd_config Include line"
368
382
  vm 'mkdir -p /etc/ssh/sshd_config.d && chmod 700 /etc/ssh/sshd_config.d'
369
- scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/sshd-hardening.conf" "$HOST:/etc/ssh/sshd_config.d/99-esellar-hardening.conf"
383
+ scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/sshd-hardening.conf" "$HOST:/etc/ssh/sshd_config.d/99-kampodine-hardening.conf"
370
384
  vm 'rc-service sshd restart' || die "sshd restart failed after hardening ensure"
371
385
 
372
386
  say "gate: sshd hardening effective"
@@ -404,50 +418,50 @@ PODSTACK_GATE
404
418
  vm 'rc-update show boot | grep -q cgroups || rc-update add cgroups boot' || die "rc-update cgroups failed"
405
419
  vm 'rc-service cgroups status >/dev/null 2>&1 || rc-service cgroups start' || die "cgroups start failed"
406
420
 
407
- # --- 3. /etc/esellar + managed config files ------------------------------------
408
- say "creating /etc/esellar (env file lands here via kampodine deploy, 0600 root)…"
409
- vm 'mkdir -p /etc/esellar && chmod 700 /etc/esellar'
421
+ # --- 3. /etc/kampodine + managed config files ------------------------------------
422
+ say "creating /etc/kampodine (env file lands here via kampodine deploy, 0600 root)…"
423
+ vm 'mkdir -p /etc/kampodine && chmod 700 /etc/kampodine'
410
424
 
411
425
  say "writing /etc/containers/registries.conf (insecure 127.0.0.1:5000; search docker.io)…"
412
426
  vm 'mkdir -p /etc/containers'
413
427
  scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/registries.conf" "$HOST:/etc/containers/registries.conf"
414
428
 
415
- say "writing /etc/sysctl.d/60-esellar.conf + applying live…"
416
- scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/60-esellar.conf" "$HOST:/etc/sysctl.d/60-esellar.conf"
429
+ say "writing /etc/sysctl.d/60-kampodine.conf + applying live…"
430
+ scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/60-kampodine.conf" "$HOST:/etc/sysctl.d/60-kampodine.conf"
417
431
  vm_sh <<'SYSCTL_APPLY' || die "sysctl ensure/apply failed"
418
432
  rc-update show boot | grep -Eq '^[[:space:]]*sysctl[[:space:]]*\|' || rc-update add sysctl boot
419
433
  sysctl -w net.ipv4.ip_unprivileged_port_start=80 > /dev/null
420
434
  SYSCTL_APPLY
421
435
 
422
436
  # --- 4. OpenRC services (canonical: ansible container-service templates) --------
423
- say "ensuring the 'kamal' podman network (deploy's proxy re-point resolves esellar-api:8080 by network DNS)…"
437
+ say "ensuring the 'kamal' podman network (deploy's proxy re-point resolves kampodine-api:8080 by network DNS)…"
424
438
  # shellcheck disable=SC2016
425
439
  vm 'podman network exists kamal 2>/dev/null || podman network create kamal' \
426
440
  || die "podman network create kamal failed"
427
- say "installing OpenRC services esellar-api + kamal-proxy (supervise-daemon around podman run)…"
428
- scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/esellar-api" "$HOST:/etc/init.d/esellar-api"
441
+ say "installing OpenRC services kampodine-api + kamal-proxy (supervise-daemon around podman run)…"
442
+ scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/kampodine-api" "$HOST:/etc/init.d/kampodine-api"
429
443
  scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/kamal-proxy" "$HOST:/etc/init.d/kamal-proxy"
430
- vm 'chmod 755 /etc/init.d/esellar-api /etc/init.d/kamal-proxy'
444
+ vm 'chmod 755 /etc/init.d/kampodine-api /etc/init.d/kamal-proxy'
431
445
 
432
- # --- 4b. esellar-anchor (blue-green flip guest half — watcher, no container) ----
446
+ # --- 4b. kampodine-anchor (blue-green flip guest half — watcher, no container) ----
433
447
  # Ships on EVERY vm: started + enabled now, INERT until a flip writes
434
- # /etc/esellar/anchor.conf over ssh (ansible container-service owns both files
448
+ # /etc/kampodine/anchor.conf over ssh (ansible container-service owns both files
435
449
  # afterwards — drift repair keeps them in sync).
436
- say "installing the esellar-anchor watcher service (blue-green flip guest half)…"
450
+ say "installing the kampodine-anchor watcher service (blue-green flip guest half)…"
437
451
  # /usr/local/sbin does NOT exist on the golden image (fresh Alpine ships no
438
452
  # /usr/local hierarchy; the alpine-base role creates it — vm-prepare runs
439
453
  # BEFORE any ansible)
440
454
  vm 'mkdir -p /usr/local/sbin' || die "mkdir /usr/local/sbin failed"
441
- scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/esellar-anchor.sh" "$HOST:/usr/local/sbin/esellar-anchor.sh"
442
- scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/esellar-anchor" "$HOST:/etc/init.d/esellar-anchor"
443
- vm 'chmod 755 /usr/local/sbin/esellar-anchor.sh /etc/init.d/esellar-anchor' || die "chmod esellar-anchor files failed"
444
- vm 'sh -n /usr/local/sbin/esellar-anchor.sh' || die "esellar-anchor.sh does not parse (busybox sh)"
445
- vm 'sh -n /etc/init.d/esellar-anchor' || die "/etc/init.d/esellar-anchor does not parse"
446
- vm 'rc-update show default | grep -qE "^[[:space:]]*esellar-anchor[[:space:]]*\\|" || rc-update add esellar-anchor default' \
447
- || die "rc-update add esellar-anchor default failed"
448
- vm 'rc-service esellar-anchor start' || die "rc-service esellar-anchor start failed"
449
-
450
- for SVC in esellar-api kamal-proxy; do
455
+ scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/kampodine-anchor.sh" "$HOST:/usr/local/sbin/kampodine-anchor.sh"
456
+ scp -q "${SSH_ARGS[@]}" "$TMPDIR_LOCAL/kampodine-anchor" "$HOST:/etc/init.d/kampodine-anchor"
457
+ vm 'chmod 755 /usr/local/sbin/kampodine-anchor.sh /etc/init.d/kampodine-anchor' || die "chmod kampodine-anchor files failed"
458
+ vm 'sh -n /usr/local/sbin/kampodine-anchor.sh' || die "kampodine-anchor.sh does not parse (busybox sh)"
459
+ vm 'sh -n /etc/init.d/kampodine-anchor' || die "/etc/init.d/kampodine-anchor does not parse"
460
+ vm 'rc-update show default | grep -qE "^[[:space:]]*kampodine-anchor[[:space:]]*\\|" || rc-update add kampodine-anchor default' \
461
+ || die "rc-update add kampodine-anchor default failed"
462
+ vm 'rc-service kampodine-anchor start' || die "rc-service kampodine-anchor start failed"
463
+
464
+ for SVC in kampodine-api kamal-proxy; do
451
465
  vm "rc-update show default | grep -qE '^[[:space:]]*${SVC}[[:space:]]*\\|' || rc-update add ${SVC} default" \
452
466
  || die "rc-update add $SVC default failed"
453
467
  done
@@ -456,7 +470,7 @@ done
456
470
  # re-runs after a deploy must not bounce production.
457
471
  # shellcheck disable=SC2016
458
472
  vm_sh <<'UNIT_DRIFT' || true
459
- for SVC in esellar-api kamal-proxy esellar-anchor; do
473
+ for SVC in kampodine-api kamal-proxy kampodine-anchor; do
460
474
  if rc-service "$SVC" status > /dev/null 2>&1; then
461
475
  echo "RUNNING: $SVC (unit file was overwritten — rc-service $SVC restart to apply, on your call)"
462
476
  fi
@@ -483,26 +497,26 @@ if [[ $DO_PULL -eq 1 ]]; then
483
497
  # installs it later; vm-prepare runs BEFORE any ansible)
484
498
  vm 'busybox wget -q -O /dev/null http://127.0.0.1:5000/v2/' || {
485
499
  pkill -f "ssh.*-R 5000" 2>/dev/null || true; sleep 1
486
- nohup ssh -R 5000:127.0.0.1:5000 -N -o ServerAliveInterval=30 -o ExitOnForwardFailure=yes "$HOST" >/tmp/esellar-tunnel.log 2>&1 &
500
+ nohup ssh -R 5000:127.0.0.1:5000 -N -o ServerAliveInterval=30 -o ExitOnForwardFailure=yes "$HOST" >/tmp/kampodine-tunnel.log 2>&1 &
487
501
  sleep 3
488
502
  }
489
- vm 'busybox wget -q -O /dev/null http://127.0.0.1:5000/v2/' || die "registry tunnel did not come up (/tmp/esellar-tunnel.log)"
490
- vm 'podman pull --tls-verify=false 127.0.0.1:5000/esellar-api:latest' || die "app image pull failed"
503
+ vm 'busybox wget -q -O /dev/null http://127.0.0.1:5000/v2/' || die "registry tunnel did not come up (/tmp/kampodine-tunnel.log)"
504
+ vm 'podman pull --tls-verify=false 127.0.0.1:5000/kampodine-api:latest' || die "app image pull failed"
491
505
  else
492
506
  say "skipping app-image pre-pull (pass --pull-images, or let the first deploy pull)"
493
507
  fi
494
508
 
495
- # --- 7. converge esellar-api ONLY if a previous deploy left image + env ---------
509
+ # --- 7. converge kampodine-api ONLY if a previous deploy left image + env ---------
496
510
  # On a truly fresh VM neither exists — the FIRST DEPLOY provides both and
497
511
  # starts the service. Re-runs of this script after a deploy heal drift.
498
- say "esellar-api start check (needs image + /etc/esellar/env — first deploy provides both)…"
512
+ say "kampodine-api start check (needs image + /etc/kampodine/env — first deploy provides both)…"
499
513
  # shellcheck disable=SC2016
500
- vm_sh <<'API_CONVERGE' || die "esellar-api start failed (image + env present — investigate: podman logs esellar-api)"
501
- if [ -f /etc/esellar/env ] && podman image exists 127.0.0.1:5000/esellar-api:latest; then
502
- rc-service esellar-api start
503
- echo "esellar-api started (image + env present)"
514
+ vm_sh <<'API_CONVERGE' || die "kampodine-api start failed (image + env present — investigate: podman logs kampodine-api)"
515
+ if [ -f /etc/kampodine/env ] && podman image exists 127.0.0.1:5000/kampodine-api:latest; then
516
+ rc-service kampodine-api start
517
+ echo "kampodine-api started (image + env present)"
504
518
  else
505
- echo "esellar-api deferred: no image and/or /etc/esellar/env yet (normal on a fresh VM — first deploy handles it)"
519
+ echo "kampodine-api deferred: no image and/or /etc/kampodine/env yet (normal on a fresh VM — first deploy handles it)"
506
520
  fi
507
521
  API_CONVERGE
508
522
 
@@ -522,16 +536,16 @@ vm 'grep -q "127.0.0.1:5000" /etc/containers/registries.conf && grep -q "insecur
522
536
  || die "registries.conf incomplete (127.0.0.1:5000 insecure + docker.io search)"
523
537
 
524
538
  say "gate: services enabled in the default runlevel"
525
- vm 'rc-update show default | grep -qE "^[[:space:]]*esellar-api[[:space:]]*\\|"' || die "esellar-api not in the default runlevel"
539
+ vm 'rc-update show default | grep -qE "^[[:space:]]*kampodine-api[[:space:]]*\\|"' || die "kampodine-api not in the default runlevel"
526
540
  vm 'rc-update show default | grep -qE "^[[:space:]]*kamal-proxy[[:space:]]*\\|"' || die "kamal-proxy not in the default runlevel"
527
541
  vm 'rc-service kamal-proxy status >/dev/null' || die "kamal-proxy service not started"
528
542
 
529
- say "gate: esellar-anchor watcher running + INERT (no anchor conf on a fresh VM)"
530
- vm 'rc-update show default | grep -qE "^[[:space:]]*esellar-anchor[[:space:]]*\\|"' || die "esellar-anchor not in the default runlevel"
531
- vm 'rc-service esellar-anchor status >/dev/null' || die "esellar-anchor service not started"
532
- vm '! test -e /etc/esellar/anchor.conf' || die "/etc/esellar/anchor.conf already exists on a fresh VM (wrong machine?)"
533
- vm 'grep -q "no anchor conf" /var/log/esellar-anchor.log' \
534
- || die "esellar-anchor is started but never logged its idle transition (watcher loop not running?)"
543
+ say "gate: kampodine-anchor watcher running + INERT (no anchor conf on a fresh VM)"
544
+ vm 'rc-update show default | grep -qE "^[[:space:]]*kampodine-anchor[[:space:]]*\\|"' || die "kampodine-anchor not in the default runlevel"
545
+ vm 'rc-service kampodine-anchor status >/dev/null' || die "kampodine-anchor service not started"
546
+ vm '! test -e /etc/kampodine/anchor.conf' || die "/etc/kampodine/anchor.conf already exists on a fresh VM (wrong machine?)"
547
+ vm 'grep -q "no anchor conf" /var/log/kampodine-anchor.log' \
548
+ || die "kampodine-anchor is started but never logged its idle transition (watcher loop not running?)"
535
549
 
536
550
  # --- summary ---------------------------------------------------------------------
537
551
  IP="${HOST#*@}"