feat: add interactive CLI setup wizard for server configuration and log file registration

This commit is contained in:
2026-06-25 20:41:52 +02:00
parent 0415e905af
commit 22e6812d4b
Executable
+223
View File
@@ -0,0 +1,223 @@
#!/bin/sh
# ──────────────────────────────────────────────────────────────────────
# Nadir interactive setup — generates config.yaml
#
# Run this script on a fresh box after placing the nadir binary, before
# `nadir install`. It asks about server settings, TLS mode, and log-file
# tracking, then writes the configuration file and prints the next steps.
#
# Everything in here is a question with a default answer in brackets.
# Press Enter to accept the default.
# ──────────────────────────────────────────────────────────────────────
set -e
# ── helpers ──────────────────────────────────────────────────────────
prompt() {
printf "%s [%s]: " "$1" "$2"
read -r val
echo "${val:-$2}"
}
prompt_yn() {
while :; do
printf "%s (y/n) [%s]: " "$1" "$2"
read -r val
val=$(printf "%s" "${val:-$2}" | tr '[:upper:]' '[:lower:]')
case "$val" in
y|yes) return 0 ;;
n|no) return 1 ;;
*) printf " please answer y or n.\n" >&2 ;;
esac
done
}
prompt_multi() {
desc="$1"
label="$2"
result=""
printf "%s\n" "$desc"
printf " Enter one %s at a time, then press Enter on an empty line when done.\n" "$label"
while :; do
printf " > "
read -r val
[ -z "$val" ] && break
result="${result} - ${val}
"
done
echo "$result"
}
# ── preamble ─────────────────────────────────────────────────────────
if [ "$(id -u)" -ne 0 ]; then
echo "This script should usually be run as root so the config file ends"
echo "up owned by root (the server runs as root). Continue anyway? (y/n) [y]"
if ! prompt_yn "Continue without root?" "y"; then
echo "Aborted."
exit 1
fi
fi
echo
echo "╔══════════════════════════════════════════════════════════╗"
echo "║ Nadir — interactive setup ║"
echo "╚══════════════════════════════════════════════════════════╝"
echo
# ── 1. admin username ───────────────────────────────────────────────
SUGGESTED_USER="${SUDO_USER:-$USER}"
if [ -z "$SUGGESTED_USER" ] || [ "$SUGGESTED_USER" = "root" ]; then
SUGGESTED_USER="admin"
fi
ADMIN_USER=$(prompt "Admin username (system user assigned the admin role)" "$SUGGESTED_USER")
# ── 2. config path ───────────────────────────────────────────────────
DEFAULT_CONFIG="${CONFIG_PATH:-$HOME/.config/nadir/config.yaml}"
CONFIG_PATH=$(prompt "Config file path" "$DEFAULT_CONFIG")
# ── 3. hostname ──────────────────────────────────────────────────────
HOSTNAME=$(prompt "Bind address (use 127.0.0.1 for local-only, or a Tailscale/Netbird IP)" "127.0.0.1")
# ── 4. port ──────────────────────────────────────────────────────────
PORT=$(prompt "Port" "9999")
# ── 5. TLS mode ──────────────────────────────────────────────────────
echo
echo "How should clients connect to nadir?"
echo " 1) Plain HTTP (unsecure — local-only or dev)"
echo " 2) HTTPS with a self-signed certificate (nadir generates cert + key)"
echo " 3) Behind a TLS-terminating reverse proxy (trust_proxy mode)"
printf "Choose [1-3] [1]: "
read -r tls_mode
tls_mode="${tls_mode:-1}"
SECURE_TLS="false"
TRUST_PROXY_LINE="# trust_proxy: false"
CERT_LINE="# tls_cert: /var/lib/nadir/tls/cert.pem"
KEY_LINE="# tls_key: /var/lib/nadir/tls/key.pem"
case "$tls_mode" in
2)
echo " → HTTPS with self-signed certificate"
SECURE_TLS="true"
CERT_LINE="tls_cert: /var/lib/nadir/tls/cert.pem"
KEY_LINE="tls_key: /var/lib/nadir/tls/key.pem"
;;
3)
echo " → Behind reverse proxy (trust_proxy)"
SECURE_TLS="true"
TRUST_PROXY_LINE="trust_proxy: true"
;;
*)
echo " → Plain HTTP"
SECURE_TLS="false"
;;
esac
# ── 6. release repo ──────────────────────────────────────────────────
RELEASE_REPO=$(prompt "Gitea release repo (for auto-updates, or leave blank to disable)" "")
# ── 7. log files ─────────────────────────────────────────────────────
echo
if prompt_yn "Track log files (add entries to log_files allowlist)?" "n"; then
echo
echo "For each service (e.g. nginx, ssh, auth), you'll list the paths"
echo "nadir is allowed to serve. Add as many services as you like."
echo
LOG_FILES_SECTION="log_files:"
LOG_FILES_BODY=""
while :; do
service=$(prompt " Service name (e.g. nginx, sshd) — empty line to stop" "")
[ -z "$service" ] && break
paths=$(prompt_multi "" "log path for $service")
LOG_FILES_BODY="${LOG_FILES_BODY}
${service}:"
# indentation inside prompt_multi already includes leading spaces
IFS='
'
for line in $paths; do
LOG_FILES_BODY="${LOG_FILES_BODY}
${line}"
done
echo
done
if [ -n "$LOG_FILES_BODY" ]; then
LOG_FILES_SECTION="${LOG_FILES_SECTION}${LOG_FILES_BODY}"
else
LOG_FILES_SECTION="# log_files:"
fi
else
LOG_FILES_SECTION="# log_files:"
fi
# ── write config ─────────────────────────────────────────────────────
CONFIG_DIR=$(dirname "$CONFIG_PATH")
mkdir -p "$CONFIG_DIR"
cat > "$CONFIG_PATH" <<CONFIGEOF
# Nadir configuration - config.yaml
# Generated by install.sh
server:
secure_tls: ${SECURE_TLS}
${TRUST_PROXY_LINE}
${CERT_LINE}
${KEY_LINE}
hostname: ${HOSTNAME}
port: ${PORT}
release_repo: ${RELEASE_REPO}
roles:
admin:
"*": ["*"]
auditor:
"*": ["read"]
assignments:
${ADMIN_USER}: [admin]
dashboard: [auditor]
${LOG_FILES_SECTION}
CONFIGEOF
chmod 600 "$CONFIG_PATH"
echo
echo "╔══════════════════════════════════════════════════════════╗"
echo "║ Configuration written to: ║"
echo "$CONFIG_PATH"
echo "╚══════════════════════════════════════════════════════════╝"
echo
echo "Next steps:"
echo
echo " 1. Make sure the nadir binary is installed:"
echo " sudo cp ./nadir /usr/local/bin/nadir"
echo " sudo chmod +x /usr/local/bin/nadir"
echo
echo " 2. Run the service installer:"
echo " sudo nadir install"
echo
echo " 3. If you chose TLS mode, nadir will generate a self-signed"
echo " certificate automatically during install."
echo
echo " 4. Check status:"
echo " nadir status"
echo
# If a SUDO_USER exists, chown the config directory so the user can
# read it without root.
if [ -n "${SUDO_USER}" ] && [ "${SUDO_USER}" != "root" ]; then
chown "${SUDO_USER}:${SUDO_USER}" "$CONFIG_DIR" 2>/dev/null || true
chown "${SUDO_USER}:${SUDO_USER}" "$CONFIG_PATH" 2>/dev/null || true
fi