package infra import "fmt" // SetupVPSApp orquesta el setup inicial de una app en un VPS remoto. // Pasos: verificar SSH → crear dirs/usuario → rsync código → generar unit → instalar systemd → health check. func SetupVPSApp(conn SSHConn, cfg DeployConfig) error { // 1. Verificar conectividad SSH if err := SSHCheck(conn); err != nil { return fmt.Errorf("setup_vps_app: ssh check: %w", err) } // 2. Preparar directorios y usuario en el VPS if err := VPSSetupApp(conn, cfg.AppName, cfg.RemoteDir, cfg.ServiceUser); err != nil { return fmt.Errorf("setup_vps_app: vps setup: %w", err) } // 3. Subir binario o archivos de la app if err := uploadAppFiles(conn, cfg); err != nil { return fmt.Errorf("setup_vps_app: upload: %w", err) } // 4. Generar unit de systemd execStart := fmt.Sprintf("%s/%s", cfg.RemoteDir, cfg.BinaryName) unit := SystemdGenerateUnit(cfg.AppName, execStart, cfg.RemoteDir, cfg.ServiceUser, cfg.Env) // 5. Instalar y arrancar servicio if err := SystemdInstall(conn, cfg.AppName, unit); err != nil { return fmt.Errorf("setup_vps_app: systemd install: %w", err) } // 6. Health check (si hay endpoint configurado) if cfg.HealthPath != "" && cfg.Port > 0 { url := fmt.Sprintf("http://%s:%d%s", conn.Host, cfg.Port, cfg.HealthPath) if err := HealthCheckHTTP(url, 30, 2000); err != nil { return fmt.Errorf("setup_vps_app: health check: %w", err) } } return nil } // uploadAppFiles sube el binario compilado al VPS via SCP. func uploadAppFiles(conn SSHConn, cfg DeployConfig) error { localBinary := fmt.Sprintf("%s/%s", cfg.LocalDir, cfg.BinaryName) remoteBinary := fmt.Sprintf("%s/%s", cfg.RemoteDir, cfg.BinaryName) if err := SSHUpload(conn, localBinary, remoteBinary); err != nil { return err } // Hacer ejecutable _, stderr, code, err := SSHExec(conn, fmt.Sprintf("chmod +x %s", remoteBinary)) if err != nil { return err } if code != 0 { return fmt.Errorf("chmod: %s", stderr) } return nil }