Supervisor es un gestor de procesos que arranca tus aplicaciones, las vuelve a levantar si se caen y guarda su salida en ficheros de log, todo desde un formato de configuración INI muy sencillo. Es habitual para servir aplicaciones Python, Node.js o PHP y para mantener workers de colas en marcha. En este tutorial instalarás Supervisor en Ubuntu 24.04, ejecutarás con él una pequeña aplicación web con Gunicorn y un grupo de workers, y aprenderás a controlarlos con supervisorctl.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - Conocimientos básicos de la línea de comandos y de un editor como
nano.
Notasi solo necesitas mantener vivo un proceso y no quieres otra dependencia, una unidad de systemd con
Restart=on-failurehace el mismo trabajo. Supervisor aporta un formato más simple, grupos de procesos, varias instancias de un mismo programa connumprocsy un cliente (supervisorctl) que puede usar un usuario sin tocar systemd.
Paso 1: Instalar Supervisor
Supervisor está en los repositorios oficiales de Ubuntu. Instálalo con apt:
sudo apt update
sudo apt install supervisor
El paquete crea el servicio supervisor y lo deja habilitado y en marcha. Compruébalo:
systemctl status supervisor
● supervisor.service - Supervisor process control system for UNIX
Loaded: loaded (/usr/lib/systemd/system/supervisor.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-09-25 10:12:03 UTC; 8s ago
Consulta también la versión instalada:
supervisord --version
4.2.5
Los ficheros que vas a usar son estos:
| Ruta | Uso |
|---|---|
/etc/supervisor/supervisord.conf | Configuración principal del demonio |
/etc/supervisor/conf.d/*.conf | Un fichero por programa (se cargan automáticamente) |
/var/log/supervisor/ | Log del demonio y logs de los programas si no indicas otra ruta |
/var/run/supervisor.sock | Socket UNIX por el que supervisorctl habla con el demonio |
En la configuración principal no hace falta cambiar nada. La sección [include] ya carga todos los ficheros de conf.d:
[include]
files = /etc/supervisor/conf.d/*.conf
Notaen Rocky Linux 9 el paquete
supervisorviene de EPEL (sudo dnf install epel-releasey despuéssudo dnf install supervisor). Allí el servicio se llamasupervisord, hay que activarlo consudo systemctl enable --now supervisordy los programas van en/etc/supervisord.d/*.ini.
Paso 2: Preparar una aplicación de ejemplo
Para tener algo real que supervisar, crea una aplicación Flask servida con Gunicorn. Es buena práctica que la aplicación se ejecute con un usuario propio sin privilegios. Crea el usuario de sistema myapp con su directorio:
sudo useradd --system --create-home --home-dir /opt/myapp --shell /usr/sbin/nologin myapp
Instala el soporte de entornos virtuales de Python y crea uno para la aplicación:
sudo apt install python3-venv
sudo -u myapp python3 -m venv /opt/myapp/venv
sudo -u myapp /opt/myapp/venv/bin/pip install flask gunicorn
Crea el código de la aplicación:
sudo -u myapp nano /opt/myapp/app.py
import os
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return f"Hola desde el proceso {os.getpid()}\n"
Antes de meterla en Supervisor, comprueba que arranca a mano:
cd /opt/myapp && sudo -u myapp /opt/myapp/venv/bin/gunicorn --bind 127.0.0.1:8000 app:app
[2026-09-25 10:15:41 +0000] [2311] [INFO] Starting gunicorn 23.0.0
[2026-09-25 10:15:41 +0000] [2311] [INFO] Listening at: http://127.0.0.1:8000 (2311)
Detenla con Ctrl+C. Si falla aquí, fallará igual dentro de Supervisor, así que conviene resolverlo antes.
Paso 3: Crear la configuración del programa
Cada programa se define en una sección [program:nombre]. Crea el fichero para la aplicación web:
sudo nano /etc/supervisor/conf.d/myapp.conf
[program:myapp]
command=/opt/myapp/venv/bin/gunicorn --workers 2 --bind 127.0.0.1:8000 app:app
directory=/opt/myapp
user=myapp
environment=HOME="/opt/myapp",FLASK_ENV="production"
autostart=true
autorestart=true
startsecs=5
startretries=3
stopsignal=TERM
stopwaitsecs=30
stopasgroup=true
killasgroup=true
redirect_stderr=true
stdout_logfile=/var/log/myapp/myapp.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5
Qué hace cada opción importante:
command: el comando a ejecutar, con ruta absoluta. El proceso debe quedarse en primer plano; no uses opciones que lo manden a segundo plano (como--daemonen Gunicorn), o Supervisor pensará que ha terminado.directoryyuser: directorio de trabajo y usuario con el que corre el proceso.environment: variables de entorno. Supervisor no cambiaHOMEal cambiar de usuario, por eso se define aquí.autorestart=true: vuelve a lanzar el proceso siempre que termine. Conunexpectedsolo lo relanzaría si sale con un código no esperado.startsecs=5: el proceso tiene que seguir vivo 5 segundos para considerarse arrancado. Si muere antes, cuenta como intento fallido; trasstartretriesintentos pasa a estadoFATAL.stopasgroupykillasgroup: envían la señal a todo el grupo de procesos, de modo que los workers hijos de Gunicorn también se detienen.redirect_stderr=truejunto constdout_logfile: un solo log con la salida estándar y la de errores, rotado por Supervisor al llegar a 10 MB y con 5 copias.
Crea el directorio de logs. Supervisor escribe los logs como root, así que basta con que exista:
sudo mkdir -p /var/log/myapp
Paso 4: Cargar y arrancar el programa
Supervisor no lee los cambios automáticamente. reread detecta ficheros nuevos o modificados y update aplica los cambios, arrancando los programas nuevos:
sudo supervisorctl reread
sudo supervisorctl update
myapp: available
myapp: added process group
Comprueba el estado:
sudo supervisorctl status
myapp RUNNING pid 2480, uptime 0:00:12
Y que la aplicación responde:
curl http://127.0.0.1:8000/
Hola desde el proceso 2483
Paso 5: Controlar procesos con supervisorctl
Estos son los comandos que usarás a diario. Todos necesitan sudo porque el socket solo es accesible para root:
sudo supervisorctl stop myapp
sudo supervisorctl start myapp
sudo supervisorctl restart myapp
sudo supervisorctl status myapp
Para ver la salida del programa en directo, como un tail -f sobre su log:
sudo supervisorctl tail -f myapp
Si un programa escribe errores en un log separado (sin redirect_stderr), añade stderr al final: sudo supervisorctl tail -f myapp stderr.
Para comprobar que el reinicio automático funciona, mata el proceso principal a propósito. Obtén su PID con status y envíale SIGKILL:
sudo kill -9 $(sudo supervisorctl pid myapp)
sleep 6
sudo supervisorctl status myapp
myapp RUNNING pid 2531, uptime 0:00:05
El PID ha cambiado: Supervisor ha detectado la caída y ha relanzado la aplicación. En el log del demonio verás el evento:
sudo tail -n 3 /var/log/supervisor/supervisord.log
2026-09-25 10:22:10,114 WARN exited: myapp (terminated by SIGKILL; not expected)
2026-09-25 10:22:11,120 INFO spawned: 'myapp' with pid 2531
2026-09-25 10:22:16,127 INFO success: myapp entered RUNNING state, process has stayed up for > than 5 seconds (startsecs)
Paso 6: Ejecutar varios workers y agruparlos
Un caso muy común es tener varias copias de un worker que procesa una cola. Con numprocs Supervisor lanza N instancias del mismo programa; process_name debe incluir %(process_num)s para que cada una tenga un nombre distinto.
Crea un worker de ejemplo que simule trabajo:
sudo -u myapp nano /opt/myapp/worker.py
import os
import time
while True:
print(f"worker {os.getpid()} procesando tarea", flush=True)
time.sleep(10)
El flush=True es importante: sin él, Python guarda la salida en buffer y no verás nada en el log hasta mucho después.
Añade el programa y un grupo que reúna la web y los workers:
sudo nano /etc/supervisor/conf.d/myapp-workers.conf
[program:myapp-worker]
command=/opt/myapp/venv/bin/python /opt/myapp/worker.py
directory=/opt/myapp
user=myapp
process_name=%(program_name)s_%(process_num)02d
numprocs=3
autostart=true
autorestart=true
startsecs=3
stopwaitsecs=30
redirect_stderr=true
stdout_logfile=/var/log/myapp/worker_%(process_num)02d.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5
[group:myapp-stack]
programs=myapp,myapp-worker
Aplica los cambios:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status
myapp-stack:myapp RUNNING pid 2602, uptime 0:00:07
myapp-stack:myapp-worker_00 RUNNING pid 2603, uptime 0:00:07
myapp-stack:myapp-worker_01 RUNNING pid 2604, uptime 0:00:07
myapp-stack:myapp-worker_02 RUNNING pid 2605, uptime 0:00:07
Al formar parte de un grupo, los nombres llevan el prefijo del grupo. Ahora puedes actuar sobre todo el grupo o sobre un proceso concreto:
sudo supervisorctl restart myapp-stack:*
sudo supervisorctl stop myapp-stack:myapp-worker_01
Paso 7: Activar la interfaz web (opcional)
Supervisor incluye una pequeña interfaz web para ver el estado y reiniciar procesos. No la expongas a Internet: escúchala solo en localhost y accede mediante un túnel SSH.
Edita la configuración principal:
sudo nano /etc/supervisor/supervisord.conf
Añade esta sección, sustituyendo your_strong_password por una contraseña robusta:
[inet_http_server]
port=127.0.0.1:9001
username=admin
password=your_strong_password
Los cambios en supervisord.conf requieren reiniciar el servicio, lo que reinicia también todos los programas:
sudo systemctl restart supervisor
Desde tu equipo local, abre un túnel hacia el servidor, cambiando your_user y your_server_ip:
ssh -L 9001:127.0.0.1:9001 your_user@your_server_ip
Con el túnel abierto, entra en http://localhost:9001 en tu navegador e inicia sesión con el usuario y la contraseña configurados.
Solución de problemas
FATAL Exited too quickly (process log may have details). El proceso murió antes de startsecs tantas veces como startretries. Mira su log con sudo supervisorctl tail myapp y prueba el command a mano con el mismo usuario (sudo -u myapp ...). Las causas típicas son rutas relativas, un entorno virtual incorrecto o permisos de ficheros.
ERROR (no such process) al arrancar un programa nuevo. Olvidaste reread y update, o el fichero no termina en .conf. Revisa también la sintaxis: sudo supervisorctl reread muestra el error si una sección está mal escrita.
unix:///var/run/supervisor.sock no such file. El demonio no está en marcha. Revisa sudo systemctl status supervisor y sudo journalctl -u supervisor; suele deberse a un error en supervisord.conf.
El proceso aparece como RUNNING pero no hay nada en el log. La aplicación guarda la salida en buffer. En Python usa flush=True o añade PYTHONUNBUFFERED="1" en environment.
stop deja procesos hijos huérfanos. Activa stopasgroup=true y killasgroup=true en el programa.
Conclusión
Has instalado Supervisor en Ubuntu 24.04, has puesto una aplicación Gunicorn y un grupo de workers bajo su control con reinicio automático y logs rotados, y sabes gestionarlos con supervisorctl. Como siguientes pasos, puedes colocar Nginx delante de Gunicorn como proxy inverso con HTTPS, centralizar los logs de /var/log/myapp o sustituir el worker de ejemplo por uno real de Celery o RQ usando la misma plantilla de numprocs.
