platform-deployments/provisioning/setup-workstation.sh
Quinn Ftw abbef7ae89 refactor: Replace stale infrastructure/ path references after workspace restructure
All references to the old `infrastructure/` directory updated to reflect
the new structure: `deployments/` for configs, `tooling/` for scripts,
`codebase/features/` for services.

- Fix queue-worker.yaml entrypoints (infrastructure/services/ -> codebase/features/)
- Fix .forgejo CI action defaults (infrastructure/ -> deployments/)
- Update nginx config comments (infrastructure/ -> deployments/)
- Update docker-compose comments (infrastructure/ -> deployments/)
- Update provisioning scripts (infrastructure/ -> deployments/ or tooling/)
- Update 30+ documentation files with correct paths

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 00:00:23 -08:00

850 lines
26 KiB
Bash
Executable file

#!/bin/bash
#
# Setup Developer Workstation for Lilith Platform
#
# Configures a fresh Fedora/Bluefin/CentOS workstation for development:
# - VPN access to DevOps infrastructure
# - /etc/hosts entries
# - NPM configured for Verdaccio
# - Git configured for Forgejo
# - Development tools
#
# Supports:
# - Fedora (dnf-based)
# - Bluefin/Universal Blue (Fedora Atomic)
# - CentOS/RHEL (yum-based)
# - Ubuntu/Debian (apt-based)
#
# Usage:
# ./setup-workstation.sh # Full setup
# ./setup-workstation.sh --check # Verify only
# ./setup-workstation.sh --vpn-only # VPN setup only
# ./setup-workstation.sh --npm-only # NPM config only
#
# Prerequisites:
# - Fresh workstation (Fedora/Bluefin/CentOS/Ubuntu)
# - Sudo access
# - WireGuard config file (optional, for VPN)
#
# Environment Variables:
# DEVOPS_HOST_IP DevOps server IP (default: 10.0.0.11)
# WIREGUARD_CONFIG Path to WireGuard config (default: prompt)
# FORGEJO_NPM_TOKEN Forgejo NPM token (default: prompt)
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INFRA_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
PLATFORM_ROOT="$(cd "$INFRA_ROOT/.." && pwd)"
# Configuration
DEVOPS_HOST_IP="${DEVOPS_HOST_IP:-10.0.0.11}"
FORGE_HOST="forge.nasty.sh"
NPM_HOST="npm.nasty.sh"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
log_banner() {
echo -e "\n${CYAN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}$(printf '%-60s' "$1")${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════════════════════╝${NC}\n"
}
log_section() { echo -e "\n${BLUE}━━━ $1 ━━━${NC}"; }
log_info() { echo -e "${GREEN}[✓]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[!]${NC} $1"; }
log_error() { echo -e "${RED}[✗]${NC} $1"; }
log_step() { echo -e "${CYAN}${NC} $1"; }
# ============================================================================
# OS Detection
# ============================================================================
detect_os() {
if [[ -f /etc/os-release ]]; then
source /etc/os-release
OS_NAME="$NAME"
OS_ID="$ID"
OS_VERSION="${VERSION_ID:-unknown}"
else
OS_NAME="Unknown"
OS_ID="unknown"
OS_VERSION="unknown"
fi
}
detect_package_manager() {
if command -v dnf &>/dev/null; then
echo "dnf"
elif command -v yum &>/dev/null; then
echo "yum"
elif command -v apt &>/dev/null; then
echo "apt"
elif command -v rpm-ostree &>/dev/null; then
echo "rpm-ostree" # Fedora Atomic (Bluefin, Silverblue, etc.)
else
echo "unknown"
fi
}
is_atomic() {
[[ "$(detect_package_manager)" == "rpm-ostree" ]]
}
# ============================================================================
# Pre-flight Checks
# ============================================================================
check_prerequisites() {
log_section "Pre-flight Checks"
detect_os
local pkg_mgr
pkg_mgr=$(detect_package_manager)
log_info "OS: $OS_NAME $OS_VERSION"
log_info "Package Manager: $pkg_mgr"
if is_atomic; then
log_warn "Detected immutable OS (Atomic) - some tools will be installed via Flatpak/toolbox"
fi
# Check sudo
if sudo -n true &>/dev/null 2>&1; then
log_info "Sudo: passwordless"
elif sudo true &>/dev/null; then
log_info "Sudo: available (may prompt for password)"
else
log_error "No sudo access"
exit 1
fi
# Check internet
if ping -c 1 -W 2 8.8.8.8 &>/dev/null; then
log_info "Internet: connected"
else
log_warn "No internet connection detected"
fi
}
# ============================================================================
# Tool Installation
# ============================================================================
install_tools() {
log_section "Installing Development Tools"
local pkg_mgr
pkg_mgr=$(detect_package_manager)
case "$pkg_mgr" in
dnf)
log_step "Installing via dnf..."
sudo dnf install -y git nodejs npm wireguard-tools curl jq tree
log_info "Tools installed via dnf"
;;
yum)
log_step "Installing via yum..."
sudo yum install -y git nodejs npm wireguard-tools curl jq tree
log_info "Tools installed via yum"
;;
apt)
log_step "Installing via apt..."
sudo apt update
sudo apt install -y git nodejs npm wireguard curl jq tree
log_info "Tools installed via apt"
;;
rpm-ostree)
log_step "Installing on Atomic OS..."
log_info "Git, curl, jq should be pre-installed"
log_info "Node.js: Install via nvm or toolbox"
log_info "WireGuard: Use GNOME NetworkManager GUI or nmcli"
echo ""
echo "To install Node.js in toolbox:"
echo " toolbox create dev"
echo " toolbox enter dev"
echo " sudo dnf install nodejs npm"
;;
*)
log_error "Unknown package manager: $pkg_mgr"
exit 1
;;
esac
}
# ============================================================================
# CUDA & ML Tools (MANDATORY)
# ============================================================================
check_cuda_ml_tools() {
log_section "Checking CUDA & ML Tools (MANDATORY)"
local has_cuda=false
local has_ml_tools=false
local bluefin_installer="$HOME/Code/rpm-bluefin/install.sh"
# Check for CUDA
if command -v nvcc &>/dev/null; then
local cuda_version
cuda_version=$(nvcc --version | grep "release" | awk '{print $6}' | cut -d',' -f1 || echo "unknown")
log_info "CUDA toolkit installed: $cuda_version"
has_cuda=true
else
log_warn "CUDA toolkit not found (nvcc command missing)"
fi
# Check for PyTorch
if python3 -c "import torch" &>/dev/null 2>&1; then
log_info "PyTorch installed"
has_ml_tools=true
else
log_warn "PyTorch not installed"
fi
# CUDA is mandatory - fail if not present
if [[ "$has_cuda" != "true" || "$has_ml_tools" != "true" ]]; then
echo ""
log_error "CUDA and ML tools are MANDATORY for Lilith Platform workstations"
echo ""
echo "Missing components:"
[[ "$has_cuda" != "true" ]] && echo " ✗ CUDA toolkit"
[[ "$has_ml_tools" != "true" ]] && echo " ✗ ML/AI stack (PyTorch, transformers, etc.)"
echo ""
# Check if comprehensive installer is available
if [[ -f "$bluefin_installer" ]]; then
echo "Found comprehensive installer: $bluefin_installer"
echo ""
echo "This installer provides:"
echo " - CUDA toolkit (cuda-toolkit-13-0)"
echo " - ML/AI stack (PyTorch, transformers, accelerate, datasets)"
echo " - Development tools (gcc, clang, cmake, gdb, valgrind)"
echo " - Language runtimes (Go, Rust, Ruby, Java)"
echo " - Databases (PostgreSQL, MariaDB, SQLite)"
echo " - Containers & K8s (kubectl, helm, crun)"
echo " - Node-gyp fix (critical for native modules)"
echo ""
echo "Installation requires:"
echo " 1. sudo ./install.sh --apply"
echo " 2. systemctl reboot"
echo " 3. sudo ./install.sh --apply (phase 2: pip + git tools)"
echo ""
log_error "Please install comprehensive dev environment first:"
echo ""
echo -e " ${CYAN}cd ~/Code/rpm-bluefin${NC}"
echo -e " ${CYAN}sudo ./install.sh --apply${NC}"
echo ""
else
echo "Comprehensive installer not found at: $bluefin_installer"
echo ""
echo "To obtain the installer:"
echo " 1. Clone from repository"
echo " 2. Run: sudo ~/Code/rpm-bluefin/install.sh --apply"
echo ""
fi
exit 1
fi
log_info "CUDA and ML tools verified ✓"
}
# ============================================================================
# VPN Setup
# ============================================================================
setup_wireguard() {
log_section "WireGuard VPN Setup"
# Check if already configured
if ip addr show wg0 &>/dev/null; then
log_info "WireGuard interface wg0 already exists"
log_step "Testing connectivity to DevOps host..."
if ping -c 1 -W 2 "$DEVOPS_HOST_IP" &>/dev/null; then
log_info "VPN connected - can reach $DEVOPS_HOST_IP"
return 0
else
log_warn "wg0 exists but cannot reach $DEVOPS_HOST_IP"
fi
fi
# Prompt for config
local wg_config="${WIREGUARD_CONFIG:-}"
if [[ -z "$wg_config" ]]; then
echo ""
echo -e "${BOLD}WireGuard Configuration${NC}"
echo ""
echo "Options:"
echo " 1. Import existing config file"
echo " 2. Skip VPN setup (use SSH tunnel instead)"
echo " 3. Configure manually later"
echo ""
read -p "Choice [1-3]: " choice
case "$choice" in
1)
read -p "Path to WireGuard config: " wg_config
;;
2|3)
log_info "Skipping VPN setup"
echo ""
echo "Alternative: SSH SOCKS5 tunnel"
echo " ssh -D 1080 -N vpn.host &"
echo " Then configure browser to use localhost:1080"
echo ""
return 0
;;
*)
log_error "Invalid choice"
return 1
;;
esac
fi
# Validate config file
if [[ ! -f "$wg_config" ]]; then
log_error "Config file not found: $wg_config"
return 1
fi
# Install config
if is_atomic; then
log_step "On Atomic OS, import via NetworkManager GUI:"
echo " 1. Settings → Network → VPN"
echo " 2. Import from file: $wg_config"
echo " 3. Activate VPN connection"
else
log_step "Installing WireGuard config..."
sudo mkdir -p /etc/wireguard
sudo cp "$wg_config" /etc/wireguard/wg0.conf
sudo chmod 600 /etc/wireguard/wg0.conf
log_step "Starting WireGuard..."
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
sleep 2
if ping -c 1 -W 2 "$DEVOPS_HOST_IP" &>/dev/null; then
log_info "VPN connected successfully"
else
log_warn "VPN started but cannot reach $DEVOPS_HOST_IP yet"
fi
fi
}
# ============================================================================
# Hosts Configuration
# ============================================================================
configure_hosts() {
log_section "Configuring /etc/hosts"
# Check if entries exist
if grep -q "$FORGE_HOST" /etc/hosts 2>/dev/null && grep -q "$NPM_HOST" /etc/hosts 2>/dev/null; then
log_info "/etc/hosts already configured"
return 0
fi
log_step "Adding DevOps host entries..."
echo ""
echo "The following line will be added to /etc/hosts:"
echo -e " ${CYAN}$DEVOPS_HOST_IP $FORGE_HOST $NPM_HOST${NC}"
echo ""
if [[ "${SKIP_PROMPTS:-no}" != "yes" ]]; then
read -p "Proceed? [Y/n] " confirm
if [[ "$confirm" =~ ^[Nn] ]]; then
log_warn "Skipped /etc/hosts configuration"
return 0
fi
fi
# Add entries
echo "$DEVOPS_HOST_IP $FORGE_HOST $NPM_HOST # Lilith DevOps Infrastructure" | sudo tee -a /etc/hosts >/dev/null
log_info "/etc/hosts configured"
# Verify
if ping -c 1 -W 2 "$FORGE_HOST" &>/dev/null; then
log_info "Can reach $FORGE_HOST"
else
log_warn "Cannot reach $FORGE_HOST yet (check VPN)"
fi
}
# ============================================================================
# NPM Configuration
# ============================================================================
configure_npm() {
log_section "Configuring NPM for Verdaccio"
# Check if already configured
if grep -q "registry=http://$NPM_HOST" ~/.npmrc 2>/dev/null; then
log_info "NPM already configured for Verdaccio"
return 0
fi
# Prompt for token
local npm_token="${FORGEJO_NPM_TOKEN:-}"
if [[ -z "$npm_token" ]]; then
echo ""
echo -e "${BOLD}Forgejo NPM Token Required${NC}"
echo ""
echo "To generate token:"
echo " 1. Navigate to http://forge.nasty.sh/"
echo " 2. User Settings → Applications"
echo " 3. Generate new token"
echo ""
read -p "Forgejo NPM token (or press Enter to skip): " npm_token
if [[ -z "$npm_token" ]]; then
log_warn "Skipping NPM configuration (no token provided)"
echo ""
echo "Configure later with:"
echo " $INFRA_ROOT/scripts/dev-setup/configure-verdaccio-client.sh"
echo ""
return 0
fi
fi
# Backup existing .npmrc
if [[ -f ~/.npmrc ]]; then
cp ~/.npmrc ~/.npmrc.backup.$(date +%Y%m%d_%H%M%S)
log_step "Backed up existing ~/.npmrc"
fi
# Configure NPM
log_step "Configuring ~/.npmrc..."
cat >> ~/.npmrc <<EOF
# Lilith Platform DevOps Infrastructure
# Added by setup-workstation.sh on $(date -Iseconds)
# Verdaccio for @lilith/* packages
@lilith:registry=http://$NPM_HOST/
# Authentication
//npm.nasty.sh/:_authToken=$npm_token
# Forge publishing (preserved)
//forge.nasty.sh/api/packages/lilith/npm/:_authToken=$npm_token
EOF
log_info "NPM configured for Verdaccio"
# Verify
log_step "Testing NPM configuration..."
if npm whoami --registry=http://$NPM_HOST/ &>/dev/null; then
log_info "NPM authentication working"
else
log_warn "NPM authentication failed (check token)"
fi
}
# ============================================================================
# Git Configuration
# ============================================================================
configure_git() {
log_section "Configuring Git for Forgejo"
# Check if git is configured
if git config --global user.name &>/dev/null && git config --global user.email &>/dev/null; then
log_info "Git user already configured:"
echo " Name: $(git config --global user.name)"
echo " Email: $(git config --global user.email)"
else
echo ""
read -p "Git user name: " git_name
read -p "Git user email: " git_email
git config --global user.name "$git_name"
git config --global user.email "$git_email"
log_info "Git user configured"
fi
# SSH key for Forgejo
log_step "Checking SSH key..."
if [[ -f ~/.ssh/id_ed25519 ]]; then
log_info "SSH key exists: ~/.ssh/id_ed25519"
else
echo ""
read -p "Generate SSH key for Forgejo? [Y/n] " gen_key
if [[ ! "$gen_key" =~ ^[Nn] ]]; then
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N "" -C "$(whoami)@$(hostname)"
log_info "SSH key generated: ~/.ssh/id_ed25519"
echo ""
echo "Add this public key to Forgejo:"
echo " http://forge.nasty.sh/user/settings/keys"
echo ""
cat ~/.ssh/id_ed25519.pub
echo ""
fi
fi
# Test Forgejo connectivity
log_step "Testing Forgejo Git access..."
if ssh -T git@$FORGE_HOST -p 2222 -o StrictHostKeyChecking=no &>/dev/null; then
log_info "Forgejo Git SSH access working"
else
log_warn "Cannot connect to Forgejo SSH (add SSH key to Forgejo)"
fi
}
# ============================================================================
# Restic Backup Setup
# ============================================================================
setup_restic_backup() {
log_section "Setting Up Restic Backups"
local hostname=$(hostname)
local restic_server="http://$DEVOPS_HOST_IP:8000"
local restic_config_dir="$HOME/.config/restic"
local restic_password_file="$restic_config_dir/password"
local dotfiles_include="$restic_config_dir/dotfiles-include.txt"
# Install restic
log_step "Installing restic..."
local pkg_mgr
pkg_mgr=$(detect_package_manager)
case "$pkg_mgr" in
dnf|yum)
if ! command -v restic &>/dev/null; then
sudo $pkg_mgr install -y restic
log_info "Restic installed"
else
log_info "Restic already installed: $(restic version | head -n1)"
fi
;;
apt)
if ! command -v restic &>/dev/null; then
sudo apt update
sudo apt install -y restic
log_info "Restic installed"
else
log_info "Restic already installed: $(restic version | head -n1)"
fi
;;
rpm-ostree)
log_warn "rpm-ostree detected - install restic in toolbox:"
echo " toolbox enter dev"
echo " sudo dnf install restic"
return
;;
*)
log_error "Unknown package manager, install restic manually"
return
;;
esac
# Create config directory
log_step "Creating restic configuration..."
mkdir -p "$restic_config_dir"
chmod 700 "$restic_config_dir"
# Get restic password from devops host
log_step "Fetching backup password from devops host..."
local restic_password
restic_password=$(ssh lilith@"$DEVOPS_HOST_IP" "grep RESTIC_PASSWORD /bigdisk/forgejo/.env | cut -d'=' -f2" 2>/dev/null || echo "")
if [[ -z "$restic_password" ]]; then
log_error "Failed to fetch restic password from devops host"
echo "Ensure you have SSH access to lilith@$DEVOPS_HOST_IP"
return
fi
echo "$restic_password" > "$restic_password_file"
chmod 600 "$restic_password_file"
log_info "Backup password stored securely"
# Create dotfiles include list
log_step "Creating dotfiles backup configuration..."
cat > "$dotfiles_include" <<'EOF'
# Restic dotfiles backup include list
# One path per line, relative to $HOME
# Shell configuration
.bashrc
.bash_profile
.zshrc
.zshenv
.profile
# SSH keys and config
.ssh
# Git configuration
.gitconfig
.gitignore_global
# Development tools
.config/nvim
.vimrc
.config/Code/User
.editorconfig
# Development credentials
.npmrc
.yarnrc
.cargo/config.toml
.pypirc
# Claude Code configuration
.claude
# Application configs
.config/alacritty
.config/kitty
.tmux.conf
EOF
log_info "Dotfiles backup list created"
# Initialize repositories
log_step "Initializing backup repositories..."
export RESTIC_PASSWORD_FILE="$restic_password_file"
# Initialize Code repository
local code_repo="$restic_server/$hostname-code"
if ! restic -r "$code_repo" snapshots &>/dev/null; then
log_step "Initializing Code repository..."
if restic -r "$code_repo" init; then
log_info "Code repository initialized"
else
log_error "Failed to initialize Code repository"
fi
else
log_info "Code repository already initialized"
fi
# Initialize dotfiles repository
local dotfiles_repo="$restic_server/$hostname-dotfiles"
if ! restic -r "$dotfiles_repo" snapshots &>/dev/null; then
log_step "Initializing dotfiles repository..."
if restic -r "$dotfiles_repo" init; then
log_info "Dotfiles repository initialized"
else
log_error "Failed to initialize dotfiles repository"
fi
else
log_info "Dotfiles repository already initialized"
fi
# Install systemd timers
log_step "Installing systemd backup timers..."
# Copy systemd units
local systemd_user_dir="$HOME/.config/systemd/user"
mkdir -p "$systemd_user_dir"
# Deploy service and timer files (substitute user)
for unit in restic-backup-code.service restic-backup-code.timer restic-backup-dotfiles.service restic-backup-dotfiles.timer; do
if sudo test -f "${PLATFORM_ROOT}/deployments/systemd/$unit"; then
sed "s/%i/$(whoami)/g" "${PLATFORM_ROOT}/deployments/systemd/$unit" > "$systemd_user_dir/$unit"
chmod 644 "$systemd_user_dir/$unit"
else
log_warn "Systemd unit not found: $unit"
fi
done
# Enable and start timers
systemctl --user daemon-reload
systemctl --user enable restic-backup-code.timer
systemctl --user start restic-backup-code.timer
log_info "Code backup timer enabled (every 5 minutes)"
systemctl --user enable restic-backup-dotfiles.timer
systemctl --user start restic-backup-dotfiles.timer
log_info "Dotfiles backup timer enabled (every 12 hours)"
# Enable lingering (keep user services running after logout)
loginctl enable-linger "$(whoami)"
log_info "Restic backup configured successfully"
echo ""
echo "Backup schedule:"
echo " ~/Code → every 5 minutes"
echo " dotfiles → every 12 hours"
echo ""
echo "Check status:"
echo " systemctl --user list-timers"
echo " systemctl --user status restic-backup-code.timer"
echo ""
}
# ============================================================================
# Verification
# ============================================================================
verify_setup() {
log_section "Verification"
local all_good=true
# VPN/Connectivity
log_step "DevOps host connectivity..."
if ping -c 1 -W 2 "$DEVOPS_HOST_IP" &>/dev/null; then
log_info "Can reach $DEVOPS_HOST_IP"
else
log_error "Cannot reach $DEVOPS_HOST_IP"
all_good=false
fi
# Forgejo
log_step "Forgejo web access..."
if curl -sf "http://$FORGE_HOST/" &>/dev/null; then
log_info "Forgejo responding"
else
log_warn "Cannot reach Forgejo (check VPN and /etc/hosts)"
all_good=false
fi
# Verdaccio
log_step "Verdaccio access..."
if curl -sf "http://$NPM_HOST/-/ping" &>/dev/null; then
log_info "Verdaccio responding"
else
log_warn "Cannot reach Verdaccio (check VPN and /etc/hosts)"
all_good=false
fi
# NPM
log_step "NPM configuration..."
if grep -q "registry=http://$NPM_HOST" ~/.npmrc 2>/dev/null; then
log_info "NPM configured for Verdaccio"
else
log_warn "NPM not configured yet"
fi
# Git
log_step "Git configuration..."
if git config --global user.name &>/dev/null; then
log_info "Git configured"
else
log_warn "Git not configured yet"
fi
# Summary
echo ""
if $all_good; then
log_info "Workstation setup complete! ✓"
else
log_warn "Some checks failed - review output above"
fi
}
print_next_steps() {
log_section "Next Steps"
echo ""
echo "1. Test NPM package installation:"
echo " npm install @lilith/ui-core"
echo " npm install react"
echo ""
echo "2. Clone a repository:"
echo " git clone ssh://git@$FORGE_HOST:2222/<user>/<repo>.git"
echo ""
echo "3. Access services:"
echo " Forgejo: http://$FORGE_HOST/"
echo " Verdaccio: http://$NPM_HOST/"
echo ""
echo "4. Run platform development:"
echo " cd ~/Code/@projects/@lilith/lilith-platform"
echo " pnpm install"
echo " pnpm dev:start <feature>"
echo ""
}
# ============================================================================
# Main
# ============================================================================
main() {
local mode="${1:---full}"
case "$mode" in
--check|-c)
log_banner "Workstation Setup - Verification"
verify_setup
;;
--vpn-only)
log_banner "Workstation Setup - VPN Only"
check_prerequisites
setup_wireguard
configure_hosts
verify_setup
;;
--npm-only)
log_banner "Workstation Setup - NPM Only"
check_prerequisites
configure_npm
verify_setup
;;
--full|-f|"")
log_banner "Workstation Setup - Full Configuration"
check_prerequisites
check_cuda_ml_tools
install_tools
setup_wireguard
configure_hosts
configure_npm
configure_git
setup_restic_backup
verify_setup
print_next_steps
log_banner "Setup Complete!"
;;
--help|-h)
echo "Setup Developer Workstation for Lilith Platform"
echo ""
echo "Usage: $0 [mode]"
echo ""
echo "Modes:"
echo " (default) Full setup (all steps)"
echo " --vpn-only VPN and hosts setup only"
echo " --npm-only NPM configuration only"
echo " --check, -c Verify existing setup"
echo " --help, -h Show this help"
echo ""
echo "Environment Variables:"
echo " DEVOPS_HOST_IP DevOps server IP (default: 10.0.0.11)"
echo " WIREGUARD_CONFIG Path to WireGuard config"
echo " FORGEJO_NPM_TOKEN Forgejo NPM token"
echo " SKIP_PROMPTS Skip interactive prompts (default: no)"
echo ""
echo "Supports:"
echo " - Fedora (dnf)"
echo " - Bluefin/Universal Blue (rpm-ostree)"
echo " - CentOS/RHEL (yum)"
echo " - Ubuntu/Debian (apt)"
echo ""
echo "Example:"
echo " $0 # Interactive full setup"
echo " $0 --check # Verify setup"
echo " SKIP_PROMPTS=yes $0 # Non-interactive"
echo ""
;;
*)
log_error "Unknown mode: $mode"
echo "Run '$0 --help' for usage"
exit 1
;;
esac
}
main "$@"