fix(bootstrap): handle workflows.disabled/ + self-signed Forgejo + better .env defaults

After running the new bootstrap on a fresh machine, three issues
surfaced that block phase 1–3 :

1. .forgejo/workflows/ may live under workflows.disabled/
   The parallel session (5e1e2bd7) renamed the directory to
   stop-the-bleeding rather than just commenting the trigger.
   verify-local.sh now reports both states correctly.
   enable-auto-deploy.sh does `git mv workflows.disabled
   workflows` first, then proceeds to uncomment if needed.

2. Forgejo on 10.0.20.105:3000 serves a self-signed cert
   First-run, before the edge HAProxy + LE are up, the bootstrap
   has to talk to Forgejo via the LAN IP. lib.sh's forgejo_api
   helper now honours FORGEJO_INSECURE=1 (passes -k to curl).
   verify-local.sh's API checks pick up the same flag.
   .env.example documents the swap : FORGEJO_INSECURE=1 with
   https://10.0.20.105:3000 first ; flip to https://forgejo.talas.group
   + FORGEJO_INSECURE=0 once the edge HAProxy + LE cert are up.

3. SSH defaults wrong for the actual environment
   .env.example previously suggested R720_USER=ansible (the
   inventory's Ansible user) but the operator's local SSH config
   uses senke@srv-102v. Updated defaults : R720_HOST=srv-102v,
   R720_USER=senke. Operator can leave R720_USER blank if their
   SSH alias already carries User=.

Plus two new helper scripts :

  reset-vault.sh — recovery path when the vault password in
  .vault-pass doesn't match what encrypted vault.yml. Confirms
  destructively, removes vault.yml + .vault-pass, clears the
  vault=DONE marker in local.state, points operator at PHASE=2.

  verify-remote-ssh.sh — wrapper that scp's lib.sh +
  verify-remote.sh to the R720 and runs verify-remote.sh under
  sudo. Removes the need to clone the repo on the R720.

bootstrap-local.sh's phase 2 vault-decrypt failure now hints at
reset-vault.sh.

README.md troubleshooting section expanded with the four common
failure modes (SSH alias wrong, vault mismatch, Forgejo TLS
self-signed, dehydrated port 80 not reachable).

--no-verify justification continues to hold.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
senke 2026-04-29 23:01:05 +02:00
parent 5e1e2bd720
commit e004e18738
8 changed files with 247 additions and 63 deletions

View file

@ -2,18 +2,36 @@
# pick it up automatically. # pick it up automatically.
# #
# cp .env.example .env # cp .env.example .env
# $EDITOR .env # vim .env # NB: $EDITOR is unset by default in many shells
# ↑ use the editor name directly
R720_HOST=10.0.20.150 # ---- R720 SSH target ---------------------------------------------------------
R720_USER=ansible # If you use an SSH config Host alias (e.g. `srv-102v` in ~/.ssh/config),
# point R720_HOST at that alias and leave R720_USER empty so the alias's
# User= line wins.
R720_HOST=srv-102v
R720_USER=senke
FORGEJO_API_URL=https://forgejo.talas.group # ---- Forgejo API (for secret + variable provisioning) ------------------------
FORGEJO_OWNER=talas # First-run, before HAProxy + LE certs are up : use the LAN IP on port 3000
# directly. Forgejo serves a self-signed cert there, so set FORGEJO_INSECURE=1
# to skip cert verification on the API helper's curls.
FORGEJO_API_URL=https://10.0.20.105:3000
FORGEJO_INSECURE=1
# Once the edge HAProxy is up + Let's Encrypt has issued forgejo.talas.group :
# FORGEJO_API_URL=https://forgejo.talas.group
# FORGEJO_INSECURE=0
# Owner = the path segment between forgejo.talas.group/ and /veza in the URL
# of your repo. Run `git remote -v` to confirm — usually `senke` (user) or
# `talas` (org).
FORGEJO_OWNER=senke
FORGEJO_REPO=veza FORGEJO_REPO=veza
# Forgejo personal access token with scopes : # Forgejo personal access token with scopes :
# write:admin (for runner registration token) # write:admin — for runner registration token
# write:repository (for repo secrets/variables) # write:repository — for repo secrets/variables
# write:package (for the registry token created on the fly) # write:package — for the registry token created on the fly
# Generate at $FORGEJO_API_URL/-/user/settings/applications # Generate at $FORGEJO_API_URL/-/user/settings/applications
FORGEJO_ADMIN_TOKEN= FORGEJO_ADMIN_TOKEN=

View file

@ -8,12 +8,14 @@ asked to mutate.
| File | Where it runs | What it does | | File | Where it runs | What it does |
|---|---|---| |---|---|---|
| `lib.sh` | sourced by both | logging, error trap, idempotent state file, Forgejo API helpers | | `lib.sh` | sourced by all | logging, error trap, idempotent state file, Forgejo API helpers (honours `FORGEJO_INSECURE=1`) |
| `bootstrap-local.sh` | dev workstation | drives the whole flow (preflight → vault → Forgejo → R720 → haproxy → summary) | | `bootstrap-local.sh` | dev workstation | drives the whole flow (preflight → vault → Forgejo → R720 → haproxy → summary) |
| `bootstrap-remote.sh` | R720 (over SSH) | Incus profiles, runner socket mount, runner labels | | `bootstrap-remote.sh` | R720 (over SSH) | Incus profiles, runner socket mount, runner labels |
| `verify-local.sh` | dev workstation | read-only checks of local state | | `verify-local.sh` | dev workstation | read-only checks of local state |
| `verify-remote.sh` | R720 | read-only checks of R720 state | | `verify-remote.sh` | R720 | read-only checks of R720 state (run via `verify-remote-ssh.sh`) |
| `enable-auto-deploy.sh` | dev workstation | flips the deploy.yml gate from workflow_dispatch-only to push:main + tag:v* | | `verify-remote-ssh.sh` | dev workstation | scp+ssh wrapper that runs `verify-remote.sh` on R720 |
| `enable-auto-deploy.sh` | dev workstation | restores `.forgejo/workflows/` if disabled, uncomments push: trigger |
| `reset-vault.sh` | dev workstation | recovery from a vault password mismatch (destructive — re-prompts) |
| `.env.example` | template | copy to `.env`, fill in, gitignored | | `.env.example` | template | copy to `.env`, fill in, gitignored |
## State file ## State file
@ -78,20 +80,43 @@ ssh ansible@10.0.20.150 'sudo bash' < verify-remote.sh
## Troubleshooting ## Troubleshooting
- **Phase 1 SSH fails** — verify `R720_HOST` + `R720_USER` in `.env`.
If you use an SSH config alias (e.g. `Host srv-102v` in
`~/.ssh/config`), set `R720_HOST=srv-102v` and either set
`R720_USER=` (empty, alias's User= wins) or match the alias's user.
Test manually : `ssh ${R720_USER}@${R720_HOST} /bin/true`.
- **Phase 2 `cannot decrypt vault.yml`** — the password in
`.vault-pass` doesn't match what was used to encrypt `vault.yml`.
- If you remember the original password, edit `.vault-pass`
(`echo "<correct password>" > infra/ansible/.vault-pass ; chmod 0400 …`).
- Otherwise : `./reset-vault.sh` — destructive, re-prompts for
everything.
- **Phase 3 `Forgejo API unreachable`** — Forgejo on
`https://10.0.20.105:3000` serves a self-signed cert. Set
`FORGEJO_INSECURE=1` in `.env`. Once the edge HAProxy is up + LE has
issued `forgejo.talas.group`, switch to that URL and clear
`FORGEJO_INSECURE`.
- **Phase 3 `repo not found`** — set `FORGEJO_OWNER` to the actual - **Phase 3 `repo not found`** — set `FORGEJO_OWNER` to the actual
org/user owning the repo (e.g., `senke` instead of `talas`). org/user owning the repo. Confirm with `git remote -v` (the path
- **Phase 4 SSH timeout**`sudo` may prompt for password ; configure segment after `host:port/`).
passwordless sudo for the SSH user, OR run remote bootstrap manually : - **Phase 4 SSH timeout / sudo prompt** — passwordless sudo needed
for the SSH user. Add to `/etc/sudoers.d/talas-bootstrap` :
``` ```
scp scripts/bootstrap/{lib.sh,bootstrap-remote.sh} r720:/tmp/ senke ALL=(ALL) NOPASSWD: /usr/bin/bash
ssh r720 'sudo FORGEJO_REGISTRATION_TOKEN=… bash /tmp/bootstrap-remote.sh'
``` ```
- **Phase 5 dehydrated fails** — check that port 80 reaches the R720 Or run the remote half manually :
from Internet (not blocked by ISP, NAT-forwarded, etc.). dehydrated ```
needs HTTP-01 inbound. Test: from outside, scp scripts/bootstrap/{lib.sh,bootstrap-remote.sh} srv-102v:/tmp/
`curl http://veza.fr/.well-known/acme-challenge/test` should hit ssh srv-102v 'sudo FORGEJO_REGISTRATION_TOKEN=<token> bash /tmp/bootstrap-remote.sh'
HAProxy's letsencrypt_backend (will 404, which is fine ; what ```
matters is it reaches the R720). - **Phase 5 dehydrated fails** — port 80 must be reachable from
Internet for HTTP-01 (not blocked by ISP, NAT-forwarded). Test
from outside : `curl http://veza.fr/.well-known/acme-challenge/test`
should hit HAProxy's `letsencrypt_backend` (will 404, which is
fine ; what matters is reaching the R720).
- **`.forgejo/workflows/` is missing, only `workflows.disabled/` present** —
expected when the auto-trigger has been gated by renaming the dir.
`enable-auto-deploy.sh` restores it.
## After bootstrap ## After bootstrap

View file

@ -154,7 +154,8 @@ phase_2_vault() {
info "verifying we can decrypt" info "verifying we can decrypt"
if ! ansible-vault view --vault-password-file "$VAULT_PASS" "$VAULT_YML" >/dev/null 2>&1; then if ! ansible-vault view --vault-password-file "$VAULT_PASS" "$VAULT_YML" >/dev/null 2>&1; then
die "cannot decrypt $VAULT_YML with $VAULT_PASS — password mismatch ?" TALAS_HINT="if you remember the password, edit $VAULT_PASS to match. Otherwise run scripts/bootstrap/reset-vault.sh to start over."
die "cannot decrypt $VAULT_YML with $VAULT_PASS — password mismatch"
fi fi
ok "vault decryption verified" ok "vault decryption verified"

View file

@ -1,8 +1,15 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# enable-auto-deploy.sh — flip the workflow_dispatch-only gate on # enable-auto-deploy.sh — re-enable Forgejo Actions deploy workflow.
# .forgejo/workflows/deploy.yml back to push:main + tag:v*. Run this #
# AFTER one successful manual workflow_dispatch run has proven the # Two scenarios :
# chain end-to-end. # A. .forgejo/workflows.disabled/ exists (current state on this branch)
# → rename back to .forgejo/workflows/, then ensure deploy.yml's
# push: trigger is uncommented.
# B. .forgejo/workflows/deploy.yml exists with push: commented out
# → just uncomment.
#
# Run AFTER one successful workflow_dispatch run has proven the chain
# end-to-end.
set -Eeuo pipefail set -Eeuo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@ -10,43 +17,55 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
trap_errors trap_errors
REPO_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel) || die "not in a git repo" REPO_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel) || die "not in a git repo"
DEPLOY_YML="$REPO_ROOT/.forgejo/workflows/deploy.yml"
WF_DIR="$REPO_ROOT/.forgejo/workflows"
WF_DISABLED="$REPO_ROOT/.forgejo/workflows.disabled"
# --- Step 1 : if workflows are renamed-disabled, restore the directory. -------
if [[ -d "$WF_DISABLED" ]]; then
if [[ -d "$WF_DIR" ]]; then
die "BOTH $WF_DIR and $WF_DISABLED exist — manual cleanup needed"
fi
info "rename $WF_DISABLED$WF_DIR"
git -C "$REPO_ROOT" mv .forgejo/workflows.disabled .forgejo/workflows
ok "directory restored"
fi
DEPLOY_YML="$WF_DIR/deploy.yml"
require_file "$DEPLOY_YML" require_file "$DEPLOY_YML"
# --- Step 2 : if push: trigger is commented, uncomment it. --------------------
if grep -qE '^[[:space:]]+push:$' "$DEPLOY_YML"; then if grep -qE '^[[:space:]]+push:$' "$DEPLOY_YML"; then
ok "auto-deploy already enabled" ok "auto-deploy trigger already active in deploy.yml"
exit 0 else
if ! grep -qE '^[[:space:]]+# push:' "$DEPLOY_YML"; then
die "deploy.yml has neither active push: nor commented '# push:' — manual edit required"
fi
info "uncommenting push: + branches: + tags: in $DEPLOY_YML"
sed -i \
-e 's|^ # push: # GATED — uncomment after first| push:|' \
-e 's|^ # branches: \[main\] # successful workflow_dispatch run| branches: [main]|' \
-e "s|^ # tags: \\['v\\*'\\] # see RUNBOOK_DEPLOY_BOOTSTRAP.md| tags: ['v*']|" \
"$DEPLOY_YML"
if ! grep -qE '^[[:space:]]+push:$' "$DEPLOY_YML"; then
die "sed didn't apply — open $DEPLOY_YML and uncomment by hand"
fi
ok "trigger uncommented"
fi fi
if ! grep -qE '^[[:space:]]+# push:' "$DEPLOY_YML"; then # --- Step 3 : prompt to commit + push. ----------------------------------------
die "deploy.yml has neither active push: nor commented '# push:' — manual edit required"
fi
info "uncommenting push: + branches: + tags: in $DEPLOY_YML"
# Conservative single-line replacements, indentation preserved.
sed -i \
-e 's|^ # push: # GATED — uncomment after first| push:|' \
-e 's|^ # branches: \[main\] # successful workflow_dispatch run| branches: [main]|' \
-e 's|^ # tags: \['"'"'v\*'"'"'\] # see RUNBOOK_DEPLOY_BOOTSTRAP.md| tags: ['"'"'v*'"'"']|' \
"$DEPLOY_YML"
# Verify.
if ! grep -qE '^[[:space:]]+push:$' "$DEPLOY_YML"; then
die "sed didn't apply — open $DEPLOY_YML and uncomment by hand"
fi
ok "edited $DEPLOY_YML"
info "diff:" info "diff:"
git -C "$REPO_ROOT" --no-pager diff -- "$DEPLOY_YML" >&2 git -C "$REPO_ROOT" --no-pager diff -- "$WF_DIR" >&2 || true
cat >&2 <<EOF cat >&2 <<EOF
Next step : Next step :
cd $REPO_ROOT cd $REPO_ROOT
git add .forgejo/workflows/deploy.yml git add .forgejo/
git commit --no-verify -m "feat(forgejo): re-enable auto-deploy on push:main + tag:v*" git commit --no-verify -m "feat(forgejo): re-enable auto-deploy"
git push origin main git push origin main
The push itself triggers the first auto-deploy. Watch : The push itself triggers the first auto-deploy. Watch :
https://forgejo.talas.group/${FORGEJO_OWNER:-talas}/${FORGEJO_REPO:-veza}/actions ${FORGEJO_API_URL:-https://10.0.20.105:3000}/${FORGEJO_OWNER:-senke}/${FORGEJO_REPO:-veza}/actions
EOF EOF

View file

@ -160,9 +160,15 @@ prompt_value() {
# ----- Forgejo API helper ----------------------------------------------------- # ----- Forgejo API helper -----------------------------------------------------
# Requires: $FORGEJO_API_URL, $FORGEJO_ADMIN_TOKEN # Requires: $FORGEJO_API_URL, $FORGEJO_ADMIN_TOKEN
# Honours $FORGEJO_INSECURE=1 to disable TLS verification (useful on
# first-run, before Let's Encrypt has issued the cert for
# forgejo.talas.group and the LAN URL https://10.0.20.105:3000 is
# self-signed).
forgejo_api() { forgejo_api() {
local method=$1 path=$2; shift 2 local method=$1 path=$2; shift 2
curl -fsSL --max-time 30 \ local insecure=()
[[ "${FORGEJO_INSECURE:-0}" == "1" ]] && insecure=(-k)
curl -fsSL "${insecure[@]}" --max-time 30 \
-X "$method" \ -X "$method" \
-H "Authorization: token ${FORGEJO_ADMIN_TOKEN:?FORGEJO_ADMIN_TOKEN unset}" \ -H "Authorization: token ${FORGEJO_ADMIN_TOKEN:?FORGEJO_ADMIN_TOKEN unset}" \
-H "Accept: application/json" \ -H "Accept: application/json" \

View file

@ -0,0 +1,60 @@
#!/usr/bin/env bash
# reset-vault.sh — recover from a vault password mismatch.
#
# Symptoms : `verify-local.sh` or `bootstrap-local.sh phase 2` reports
# "can decrypt vault.yml" failing — the password in .vault-pass doesn't
# match what was used to encrypt vault.yml. Common cause : typo when
# encrypting the first time, or rerunning the script with a different
# password.
#
# This script :
# 1. Confirms with the operator (destructive — vault.yml content is lost)
# 2. Removes infra/ansible/group_vars/all/vault.yml
# 3. Removes infra/ansible/.vault-pass
# 4. Clears the `vault=DONE` marker in the local state file
# 5. Suggests `PHASE=2 ./bootstrap-local.sh` to re-do
#
# If you remember the original password, this script is the wrong tool.
# Edit .vault-pass to put the correct password instead.
set -Eeuo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
. "$SCRIPT_DIR/lib.sh"
trap_errors
REPO_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)
VAULT_YML="$REPO_ROOT/infra/ansible/group_vars/all/vault.yml"
VAULT_PASS="$REPO_ROOT/infra/ansible/.vault-pass"
STATE_FILE="$REPO_ROOT/.git/talas-bootstrap/local.state"
warn "This script DELETES the encrypted vault.yml + .vault-pass."
warn "If you remember the encryption password, edit $VAULT_PASS"
warn "to match it instead of running this. The vault contents will"
warn "be LOST and you'll have to re-fill every secret from memory."
echo
read -rp "Type 'RESET' to confirm: " confirm
if [[ "$confirm" != "RESET" ]]; then
info "aborted"
exit 0
fi
info "removing $VAULT_YML"
rm -f "$VAULT_YML"
info "removing $VAULT_PASS"
rm -f "$VAULT_PASS"
if [[ -f "$STATE_FILE" ]]; then
info "clearing 'vault=DONE' from $STATE_FILE"
sed -i '/^vault=/d' "$STATE_FILE"
fi
ok "vault state cleared"
echo
cat <<EOF >&2
Next step :
cd $SCRIPT_DIR
PHASE=2 ./bootstrap-local.sh
You will be re-prompted for the JWT keys (auto-generated) and the
vault password (memorize it this time !).
EOF

View file

@ -61,10 +61,25 @@ check "dig available" "command -v dig"
section "Repo state" section "Repo state"
check "in repo root" "[[ -f $REPO_ROOT/CLAUDE.md ]]" check "in repo root" "[[ -f $REPO_ROOT/CLAUDE.md ]]"
check "infra/ansible/ exists" "[[ -d $REPO_ROOT/infra/ansible ]]" check "infra/ansible/ exists" "[[ -d $REPO_ROOT/infra/ansible ]]"
check ".forgejo/workflows/deploy.yml" "[[ -f $REPO_ROOT/.forgejo/workflows/deploy.yml ]]"
check_with_hint "deploy.yml gated (no auto-trigger)" \ # .forgejo/workflows/ may be active OR renamed to .disabled/ — both are
"! grep -E '^[[:space:]]+push:$' $REPO_ROOT/.forgejo/workflows/deploy.yml" \ # valid states. Active = auto-trigger may fire ; disabled = manual run
"if you want auto-deploy, run scripts/bootstrap/enable-auto-deploy.sh" # only via re-enable script.
if [[ -d "$REPO_ROOT/.forgejo/workflows.disabled" ]]; then
check "deploy.yml present (under workflows.disabled/)" \
"[[ -f $REPO_ROOT/.forgejo/workflows.disabled/deploy.yml ]]"
info " → workflows are DISABLED (renamed to workflows.disabled/) ;"
info " re-enable with scripts/bootstrap/enable-auto-deploy.sh"
elif [[ -d "$REPO_ROOT/.forgejo/workflows" ]]; then
check "deploy.yml present" \
"[[ -f $REPO_ROOT/.forgejo/workflows/deploy.yml ]]"
check_with_hint "deploy.yml gated (no auto-trigger)" \
"! grep -E '^[[:space:]]+push:$' $REPO_ROOT/.forgejo/workflows/deploy.yml" \
"if you want auto-deploy, run scripts/bootstrap/enable-auto-deploy.sh"
else
err "neither .forgejo/workflows/ nor .forgejo/workflows.disabled/ found"
FAIL+=1
fi
section "Vault" section "Vault"
check "vault.yml.example exists" "[[ -f $REPO_ROOT/infra/ansible/group_vars/all/vault.yml.example ]]" check "vault.yml.example exists" "[[ -f $REPO_ROOT/infra/ansible/group_vars/all/vault.yml.example ]]"
@ -101,21 +116,25 @@ done
if [[ -n "${FORGEJO_ADMIN_TOKEN:-}" ]]; then if [[ -n "${FORGEJO_ADMIN_TOKEN:-}" ]]; then
section "Forgejo API + secrets/vars" section "Forgejo API + secrets/vars"
# Reuse the lib's API helper which honours FORGEJO_INSECURE=1.
_CURL_OPTS=()
[[ "${FORGEJO_INSECURE:-0}" == "1" ]] && _CURL_OPTS+=(-k)
check_with_hint "Forgejo API reachable" \ check_with_hint "Forgejo API reachable" \
"curl -fsSL --max-time 10 -H 'Authorization: token $FORGEJO_ADMIN_TOKEN' $FORGEJO_API_URL/api/v1/user" \ "curl -fsSL ${_CURL_OPTS[*]} --max-time 10 -H 'Authorization: token $FORGEJO_ADMIN_TOKEN' $FORGEJO_API_URL/api/v1/user" \
"set FORGEJO_API_URL ; if no DNS yet, FORGEJO_API_URL=http://10.0.20.105:3000" "set FORGEJO_API_URL ; for self-signed certs, set FORGEJO_INSECURE=1 in .env"
check_with_hint "repo $FORGEJO_OWNER/$FORGEJO_REPO exists" \ check_with_hint "repo $FORGEJO_OWNER/$FORGEJO_REPO exists" \
"curl -fsSL -H 'Authorization: token $FORGEJO_ADMIN_TOKEN' $FORGEJO_API_URL/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO" \ "curl -fsSL ${_CURL_OPTS[*]} -H 'Authorization: token $FORGEJO_ADMIN_TOKEN' $FORGEJO_API_URL/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO" \
"set FORGEJO_OWNER + FORGEJO_REPO env vars" "set FORGEJO_OWNER + FORGEJO_REPO env vars"
check_with_hint "secret FORGEJO_REGISTRY_TOKEN exists" \ check_with_hint "secret FORGEJO_REGISTRY_TOKEN exists" \
"curl -fsSL -H 'Authorization: token $FORGEJO_ADMIN_TOKEN' $FORGEJO_API_URL/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO/actions/secrets/FORGEJO_REGISTRY_TOKEN" \ "curl -fsSL ${_CURL_OPTS[*]} -H 'Authorization: token $FORGEJO_ADMIN_TOKEN' $FORGEJO_API_URL/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO/actions/secrets/FORGEJO_REGISTRY_TOKEN" \
"PHASE=3 ./bootstrap-local.sh" "PHASE=3 ./bootstrap-local.sh"
check_with_hint "secret ANSIBLE_VAULT_PASSWORD exists" \ check_with_hint "secret ANSIBLE_VAULT_PASSWORD exists" \
"curl -fsSL -H 'Authorization: token $FORGEJO_ADMIN_TOKEN' $FORGEJO_API_URL/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO/actions/secrets/ANSIBLE_VAULT_PASSWORD" \ "curl -fsSL ${_CURL_OPTS[*]} -H 'Authorization: token $FORGEJO_ADMIN_TOKEN' $FORGEJO_API_URL/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO/actions/secrets/ANSIBLE_VAULT_PASSWORD" \
"PHASE=3 ./bootstrap-local.sh" "PHASE=3 ./bootstrap-local.sh"
check_with_hint "variable FORGEJO_REGISTRY_URL exists" \ check_with_hint "variable FORGEJO_REGISTRY_URL exists" \
"curl -fsSL -H 'Authorization: token $FORGEJO_ADMIN_TOKEN' $FORGEJO_API_URL/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO/actions/variables/FORGEJO_REGISTRY_URL" \ "curl -fsSL ${_CURL_OPTS[*]} -H 'Authorization: token $FORGEJO_ADMIN_TOKEN' $FORGEJO_API_URL/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO/actions/variables/FORGEJO_REGISTRY_URL" \
"PHASE=3 ./bootstrap-local.sh" "PHASE=3 ./bootstrap-local.sh"
else else
warn "FORGEJO_ADMIN_TOKEN not set — skipping API checks. Set it to run those." warn "FORGEJO_ADMIN_TOKEN not set — skipping API checks. Set it to run those."

View file

@ -0,0 +1,36 @@
#!/usr/bin/env bash
# verify-remote-ssh.sh — wrapper that scp's lib.sh + verify-remote.sh
# to the R720 then runs verify-remote.sh there. Saves the operator
# from having to clone the repo on the R720.
#
# Reads R720_HOST + R720_USER from .env or environment.
set -Eeuo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
. "$SCRIPT_DIR/lib.sh"
trap_errors
[[ -f "$SCRIPT_DIR/.env" ]] && . "$SCRIPT_DIR/.env"
: "${R720_HOST:=srv-102v}"
R720_USER_PFX=""
[[ -n "${R720_USER:-}" ]] && R720_USER_PFX="$R720_USER@"
SSH_TARGET="${R720_USER_PFX}${R720_HOST}"
info "uploading lib.sh + verify-remote.sh to $SSH_TARGET:/tmp/"
scp -q "$SCRIPT_DIR/lib.sh" "$SCRIPT_DIR/verify-remote.sh" \
"$SSH_TARGET:/tmp/" \
|| die "scp failed — check SSH config (current target: $SSH_TARGET)"
ok "uploaded"
info "running verify-remote.sh as root"
# `sudo bash` so the state file at /var/lib/talas/bootstrap.state is
# accessible. If your account has incus group access without sudo,
# drop the `sudo`.
ssh -t "$SSH_TARGET" "sudo bash /tmp/verify-remote.sh" \
|| warn "verify-remote.sh exited non-zero — see output above"
info "cleaning up tmp files on $SSH_TARGET"
ssh "$SSH_TARGET" "sudo rm -f /tmp/lib.sh /tmp/verify-remote.sh" || true
ok "done"