#!/bin/bash # # Deploy Forgejo DevOps Stack # Wrapper around the reconciliation system for manual invocation # # Host resolution via roles.yaml - to change target, update: # infrastructure/hosts/roles.yaml → roles.devops.host_id # # Usage: # ./deploy-devops-stack.sh # Full deploy (via reconciler) # ./deploy-devops-stack.sh --status # Check status # ./deploy-devops-stack.sh --logs # View logs # ./deploy-devops-stack.sh --restart # Restart services # ./deploy-devops-stack.sh --check # Dry-run, show drift # set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" INFRA_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" RECONCILE_DIR="$INFRA_DIR/reconciliation" FORGEJO_DIR="$INFRA_DIR/docker/forgejo" # Load utilities source "$SCRIPT_DIR/../lib/colors.sh" source "$SCRIPT_DIR/../lib/logger.sh" source "$SCRIPT_DIR/../lib/hosts.sh" log_init "DEVOPS" # Resolve target from role hosts_init || { echo "ERROR: Failed to initialize host resolution"; exit 1; } TARGET_HOST=$(get_role_host "devops") TARGET_IP=$(get_role_ip "devops") REMOTE_DIR="/bigdisk/forgejo" log_info "Target: $TARGET_HOST ($TARGET_IP) via role 'devops'" # ============================================================================ # Helper Functions # ============================================================================ check_ssh() { log_step "Checking SSH connectivity to $TARGET_HOST..." if ! ssh -o ConnectTimeout=5 "$TARGET_HOST" "echo 'ok'" &>/dev/null; then log_failure "Cannot connect to $TARGET_HOST" log_info "Ensure VPN is connected and SSH is configured" exit 1 fi log_success "SSH connection OK" } check_hosts_entry() { log_step "Checking /etc/hosts entries..." local missing=() if ! grep -q "forge.nasty.sh" /etc/hosts 2>/dev/null; then missing+=("forge.nasty.sh") fi if [ ${#missing[@]} -gt 0 ]; then log_warn "Missing /etc/hosts entries: ${missing[*]}" log_info "Add to /etc/hosts:" echo -e "${COLOR_CYAN} $TARGET_IP forge.nasty.sh${COLOR_NC}" echo "" else log_success "Hosts entries OK" fi } remote_docker() { ssh "$TARGET_HOST" "cd $REMOTE_DIR && docker compose $*" } show_status() { log_section "Stack Status" log_step "Container status:" remote_docker ps || true echo "" log_step "Service URLs (VPN required):" echo -e " ${COLOR_CYAN}Forgejo:${COLOR_NC} http://forge.nasty.sh/" echo -e " ${COLOR_CYAN}SSH Clone:${COLOR_NC} ssh://git@forge.nasty.sh:2222//.git" } show_logs() { log_section "Container Logs" local service="${1:-}" if [ -n "$service" ]; then remote_docker logs -f --tail=100 "$service" else remote_docker logs -f --tail=50 fi } restart_stack() { log_section "Restarting Stack" log_step "Stopping containers..." remote_docker down log_step "Reconciling and restarting..." "$RECONCILE_DIR/reconcile" --host "$TARGET_HOST" --service devops-stack log_success "Stack restarted" } pull_images() { log_section "Pulling Latest Images" remote_docker pull log_success "Images updated" } # ============================================================================ # Main # ============================================================================ main() { local action="${1:-deploy}" case "$action" in --status|-s) check_ssh show_status ;; --logs|-l) check_ssh show_logs "${2:-}" ;; --restart|-r) log_banner "Forgejo - Restart" check_ssh restart_stack ;; --pull|-p) log_banner "Forgejo - Pull Images" check_ssh pull_images ;; --check|-c) log_banner "Forgejo - Check Drift" check_ssh "$RECONCILE_DIR/reconcile" --host "$TARGET_HOST" --service devops-stack --check ;; deploy|--deploy|-d|"") log_banner "Forgejo - Deploy" check_ssh check_hosts_entry # Use reconciler for deployment "$RECONCILE_DIR/reconcile" --host "$TARGET_HOST" --service devops-stack show_status ;; --help|-h) echo "Usage: $0 [action]" echo "" echo "Actions:" echo " (default) Deploy stack via reconciler" echo " --check, -c Dry-run, show drift without fixing" echo " --status, -s Show container status" echo " --logs, -l View logs (optionally: -l )" echo " --restart, -r Restart all services" echo " --pull, -p Pull latest images" echo " --help, -h Show this help" echo "" echo "Services: nginx, forgejo, db, runner" echo "" echo "The reconciler handles:" echo " - Docker installation check" echo " - Secret generation (first run)" echo " - Config sync from repo" echo " - Container lifecycle" ;; *) log_error "Unknown action: $action" echo "Run '$0 --help' for usage" exit 1 ;; esac } main "$@"