feat(cli): add felis setup first-run console with reclaim protection and cfsetup idempotency
- Add `felis setup` TUI for initial Owner provisioning and optional Cloudflare edge - Refactor breakGlass to share console TUI model (runConsoleTUI) with setup mode - Session auth respects configured [auth].admin_hostname; fallback to op.console.<root> - Protect linked Yggdrasil admins from Mojang-priority reclaim (spec §B3) - cfsetup: idempotent Access app/policy creation, better 401/403 errors, GET + lookup - Bootstrap: auto-install cloudflared, symlink /etc/felis/felis.toml - Add sequence diagrams for ping-to-join, claim, and link flows
This commit is contained in:
15 files changed
+957
-126
No files matched your search
+44
-6
@@ -12,8 +12,8 @@
|
||||
# Deployments + in-cluster registry).
|
||||
#
|
||||
# By design it stops short of serving the web panel. After it finishes you run
|
||||
# `felis setup` on the host (a TUI) to create the Owner account; the SysAdmin web
|
||||
# surface only unlocks once Web Zero-Trust is configured. See deploy/README.md.
|
||||
# `felis setup` on the host (a TUI) to create the Owner account and optionally
|
||||
# configure the Cloudflare edge. See deploy/README.md.
|
||||
#
|
||||
# The script is idempotent: re-running it converges rather than duplicating, and
|
||||
# generated secrets are persisted to /etc/felis/secrets.env so reruns reuse them.
|
||||
@@ -154,6 +154,28 @@ install_base() {
|
||||
ok "base tools present"
|
||||
}
|
||||
|
||||
install_cloudflared() {
|
||||
if command -v cloudflared >/dev/null 2>&1; then
|
||||
ok "cloudflared already installed"
|
||||
return 0
|
||||
fi
|
||||
local machine arch url tmp
|
||||
machine="$(uname -m)"
|
||||
case "$machine" in
|
||||
x86_64|amd64) arch="amd64" ;;
|
||||
aarch64|arm64) arch="arm64" ;;
|
||||
armv7l|armv6l) arch="arm" ;;
|
||||
*) die "unsupported architecture for cloudflared: ${machine}" ;;
|
||||
esac
|
||||
url="https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${arch}"
|
||||
tmp="$(mktemp)"
|
||||
log "installing cloudflared (${arch})"
|
||||
curl -fsSL "$url" -o "$tmp"
|
||||
install -m 0755 "$tmp" /usr/local/bin/cloudflared
|
||||
rm -f "$tmp"
|
||||
ok "cloudflared installed ($(cloudflared --version | head -n 1))"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 3. Docker (used only to build & export the felis image; k3s uses containerd)
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -457,16 +479,31 @@ store = "tarLocal"
|
||||
local_path = "/var/lib/felis/archives"
|
||||
|
||||
[auth]
|
||||
admin_hostname = "admin.${FELIS_ROOT_DOMAIN}"
|
||||
panel_hostname = "panel.${FELIS_ROOT_DOMAIN}"
|
||||
admin_hostname = "op.console.${FELIS_ROOT_DOMAIN}"
|
||||
panel_hostname = "console.${FELIS_ROOT_DOMAIN}"
|
||||
EOF
|
||||
}
|
||||
|
||||
ensure_default_config() {
|
||||
local target="${STATE_DIR}/felis.toml"
|
||||
if [ -L "$target" ] && [ "$(readlink "$target")" = "${STATE_DIR}/felis.host.toml" ]; then
|
||||
ok "default host config already points at ${STATE_DIR}/felis.host.toml"
|
||||
return 0
|
||||
fi
|
||||
if [ -e "$target" ] || [ -L "$target" ]; then
|
||||
warn "leaving existing ${target}; setup can use -config ${STATE_DIR}/felis.host.toml if needed"
|
||||
return 0
|
||||
fi
|
||||
ln -s "${STATE_DIR}/felis.host.toml" "$target"
|
||||
ok "default host config: ${target} -> ${STATE_DIR}/felis.host.toml"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 8. Migrate + deploy bundle
|
||||
# ---------------------------------------------------------------------------
|
||||
run_migrations() {
|
||||
write_felis_toml "${STATE_DIR}/felis.host.toml" "127.0.0.1"
|
||||
ensure_default_config
|
||||
log "running database migrations (host binary -> 127.0.0.1)"
|
||||
"$HOST_BIN" migrate up -config "${STATE_DIR}/felis.host.toml"
|
||||
ok "migrations applied"
|
||||
@@ -517,8 +554,8 @@ summary() {
|
||||
kube -n "$CONTROL_NS" get pods -o wide || true
|
||||
echo
|
||||
log "Web is intentionally NOT enabled yet."
|
||||
log "Next: run 'sudo felis setup' on this host to create the Owner account."
|
||||
log "The SysAdmin web surface unlocks only after Web Zero-Trust is configured."
|
||||
log "Next: run 'sudo felis setup' on this host to create the Owner account and configure the web edge."
|
||||
log "Use 'sudo felis breakGlass' only for emergency local Owner recovery/reset."
|
||||
echo
|
||||
}
|
||||
|
||||
@@ -527,6 +564,7 @@ main() {
|
||||
detect_node_ip
|
||||
ensure_swap
|
||||
install_base
|
||||
install_cloudflared
|
||||
load_or_make_secrets
|
||||
install_docker
|
||||
install_k3s
|
||||
|
||||
Reference in new issue
Block a user