# Capability: systemd Gestionar units systemd local y remoto via SSH. Cubre: generar texto de unit files (`systemd_generate_unit`, pura), instalar+enable+start (`systemd_install`, `install_systemd_service`), restart/status (`systemd_restart`, `systemd_status`, `services_status`), y auditoria de apps con tag `service`. ## Funciones | ID | Firma | Que hace | |---|---|---| | `install_systemd_service_bash_pipelines` | `install_systemd_service --name --exec [opts] -> json` | Pipeline que registra una app como servicio systemd del sistema: genera el unit, lo instala en /etc/systemd/system/, hace daemon-reload, enable, start y devuelve status. Requiere sudo sin password para systemctl y escritura en /etc/systemd/system/. | | `services_status_go_infra` | `func ServicesStatus(registryRoot string) ([]ServiceStatus, error)` | Lista todas las apps registradas con tag 'service' y reporta su estado: unidad systemd activa, puerto escuchando, y pc_id local. | | `setup_vps_app_go_infra` | `func SetupVPSApp(conn SSHConn, cfg DeployConfig) error` | Orquesta el setup inicial de una app en un VPS remoto: verifica SSH, crea dirs y usuario, sube binario, instala systemd unit y hace health check. | | `systemd_generate_unit_go_infra` | `func SystemdGenerateUnit(name, execStart, workDir, user string, env map[string]string) string` | Genera el texto de un archivo .service de systemd para una app. Incluye restart automático y env vars en orden determinista. | | `systemd_install_go_infra` | `func SystemdInstall(conn SSHConn, unitName, unitContent string) error` | Sube un unit file al host remoto, hace daemon-reload, enable y restart. Idempotente: reemplaza si el unit ya existe. | | `systemd_local_enable_bash_infra` | `systemd_local_enable(name: string) -> json` | Habilita un servicio systemd local con systemctl enable para que arranque automáticamente al boot. Requiere sudo. | | `systemd_local_install_unit_bash_infra` | `systemd_local_install_unit(name: string, unit_content: string) -> json` | Instala un unit file de systemd en /etc/systemd/system/.service y ejecuta daemon-reload. Requiere sudo sin password para install y systemctl. Sobrescribe si el unit ya existe. | | `systemd_local_restart_bash_infra` | `systemd_local_restart(name: string) -> json` | Reinicia un servicio systemd local con systemctl restart. Útil tras actualizar el binario o cambiar el unit. Requiere sudo. | | `systemd_local_start_bash_infra` | `systemd_local_start(name: string) -> json` | Arranca un servicio systemd local con systemctl start. Devuelve el MainPID asignado. Requiere sudo. | | `systemd_local_status_bash_infra` | `systemd_local_status(name: string, log_lines: int = 10) -> json` | Devuelve el estado de un servicio systemd local: active state, sub state, PID, enabled, y las N últimas líneas de journalctl. No requiere sudo. | | `systemd_local_uninstall_bash_infra` | `systemd_local_uninstall(name: string) -> json` | Detiene, deshabilita y elimina el unit file de un servicio systemd local. Idempotente: no falla si el servicio ya está parado o el unit no existe. Requiere sudo. | | `systemd_restart_go_infra` | `func SystemdRestart(conn SSHConn, unitName string) error` | Reinicia un servicio systemd en un host remoto via SSH. | | `systemd_status_go_infra` | `func SystemdStatus(conn SSHConn, unitName string, logLines int) (SystemdServiceStatus, error)` | Consulta el estado de un servicio systemd en un host remoto. Retorna estado activo, sub-estado, PID y logs recientes. | | `tail_journal_bash_infra` | `tail_journal(unit: string, lines: int=100, follow: bool=false, since: string="", priority: string="info") -> void` | Wrapper sobre journalctl con formato consistente. Tail logs de una unidad systemd con coloreado, filtro por prioridad y seguimiento opcional. | ## Ejemplo canonico ### Service local (requiere sudo) ```bash ./fn run install_systemd_service \ --name myapp \ --exec /opt/myapp/myapp \ --workdir /opt/myapp \ --user www-data \ --env "PORT=8080" \ --env "DB_PATH=/var/lib/myapp/db" ``` ### Service remoto via SSH ```bash # 1. Generar unit (pure, sin side effects) unit=$(./fn run systemd_generate_unit \ --name myapp \ --exec-start "/opt/myapp/myapp" \ --work-dir /opt/myapp \ --user deploy \ --env "PORT=8080") # 2. Instalar remoto ./fn run systemd_install --host organic-machine --unit-name myapp --content "$unit" # 3. Status ./fn run systemd_status --host organic-machine --unit myapp.service ``` ### Auditoria de todos los services ```bash ./fn doctor services --json | jq '.[] | {id, active, port_listening}' ``` ## Fronteras - **NO maneja timers ni paths units**. Solo service units. Para cron/timer usa dag_engine (`apps/dag_engine/`, `schedule:` en el YAML del DAG) o cron clasico. - **NO genera socket activation**. Asume que la app abre su propio puerto. - **NO instala unit a nivel usuario (`--user`)** salvo que el caller pase la flag al systemctl. Default es `/etc/systemd/system/`. - Apps en `apps/` que se ejecutan local pero NO son service de larga duracion: NO necesitan systemd. Solo apps con `tags: [service]` en su `app.md`.