Documentación
Todo lo que necesitas para autoalojarlo.
PullPilot gestiona las actualizaciones de las imágenes y servicios Docker de tu homelab — estado, logs y modos de despliegue — desde una sola interfaz. Así lo pones en marcha y lo ajustas.
Instalación rápida
No necesitas .env si usas la ruta por defecto /srv/docker-stacks. El compose oficial define ALLOW_NO_AUTH=true para que el inicio rápido funcione en una LAN de confianza.
$ sudo mkdir -p /srv/docker-stacks
$ mkdir -p ~/pullpilot && cd ~/pullpilot
$ curl -fsSL -o docker-compose.yml https://raw.githubusercontent.com/KN990x/PullPilot/main/docker-compose.yml
$ curl -fsSL -o .env.example https://raw.githubusercontent.com/KN990x/PullPilot/main/.env.example
$ docker compose up -dLuego abre http://tu-servidor-ip:8000 (o el puerto de PULLPILOT_PORT).
Tras el arranque
Cada proyecto es una subcarpeta bajo la raíz de stacks con un docker-compose.yml (o docker-compose.yaml) dentro. Cuando puedas, mantén la carpeta de compose de PullPilot fuera de ese árbol.
/srv/docker-stacks/ # DOCKER_ROOT_PATH por defecto
├── plex/
│ └── docker-compose.yml
├── uptime-kuma/
│ └── docker-compose.yml
└── ...Las carpetas llamadas pullpilot, pullpilot-ui, docker-updater y data se ignoran bajo la raíz de stacks.
Usar otra ubicación de stacks
Crea la carpeta en el host y añade un .env junto a docker-compose.yml apuntando a ella. La ruta debe ser idéntica en el host y dentro del contenedor, porque se monta uno a uno. Tras cualquier cambio en .env, ejecuta docker compose up -d (o docker compose restart).
DOCKER_ROOT_PATH=/absolute/path/to/stacksGuía de uso
Dashboard
Una tarjeta por proyecto — estado, actualización por proyecto e interruptores Full stop y Excluir.
Actualizar todo
Escanea los proyectos no excluidos, ejecuta git pull cuando aplica, recrea contenedores; resumen en el Historial.
Programación
Actualización global diaria por defecto a las 04:00 (hora del contenedor), o define la tuya por proyecto.
Variables de entorno
Una lista única para el .env de Compose. Copia .env.example y sobrescribe solo lo que necesites.
| Variable | Por defecto | Descripción |
|---|---|---|
| DOCKER_ROOT_PATH | /srv/docker-stacks | Misma ruta absoluta de stacks en host y contenedor (bind mount). |
| PROJECTS_ROOT | (de DOCKER_ROOT_PATH) | Avanzado: úsala solo si la ruta dentro del contenedor debe diferir del bind mount. |
| PULLPILOT_PORT | 8000 | Puerto publicado en el host para la interfaz. |
| TZ | UTC | Zona horaria del contenedor. |
| DATA_DIR | /app/data | SQLite y datos de ejecución (el compose oficial usa el volumen pullpilot_data). |
| ALLOW_NO_AUTH | false* | *El compose oficial usa true. Si es false, AUTH_USER y AUTH_PASS son obligatorios o el arranque falla. |
| AUTH_USER / AUTH_PASS | — | Obligatorios cuando ALLOW_NO_AUTH=false. Si ambos están definidos, se exige sesión. |
| SESSION_SECRET | (generado) | Valor fijo ⇒ las sesiones sobreviven a reinicios. Obligatorio si UVICORN_WORKERS > 1. Genéralo con openssl rand -hex 32. |
| SESSION_HTTPS_ONLY | false | Pon true si la app solo se sirve por HTTPS. |
| SESSION_SAME_SITE | lax | SameSite de la cookie: lax, strict o none. Usa none solo con HTTPS — los navegadores exigen Secure. |
| CORS_ORIGINS | (vacío) | Orígenes separados por comas. Vacío suele bastar cuando la SPA la sirve la propia app. |
| HEALTHCHECK_TIMEOUT | 60 | Espera de health tras el despliegue, en segundos. |
| COMMAND_TIMEOUT | 300 | Timeout de comandos externos, en segundos. |
| LOG_LOCALE | es | Idioma de los logs de actualizaciones programadas e historial (es o en). Las actualizaciones lanzadas desde la interfaz siguen Accept-Language. |
| LOGIN_RATE_LIMIT_ENABLED | true | Límite de intentos de login en memoria, por IP. |
| LOGIN_RATE_LIMIT_MAX | 15 | Intentos máximos por ventana. |
| LOGIN_RATE_LIMIT_WINDOW_SEC | 300 | Duración de la ventana del límite, en segundos. |
| TRUST_X_FORWARDED_FOR | false | Usa X-Forwarded-For para el límite de login. Actívalo solo detrás de un proxy de confianza. |
Notas de seguridad
Trata PullPilot como acceso root — el socket de Docker está montado. No expongas el puerto 8000 a internet pública sin TLS, ALLOW_NO_AUTH=false, credenciales robustas y, a ser posible, otra capa de auth (Authelia, Authentik…).
Las actualizaciones y tareas programadas solo se ejecutan bajo la raíz de stacks resuelta. Las rutas fuera de ese árbol se rechazan.
Detrás de un proxy que termina TLS, define SESSION_HTTPS_ONLY=true, y define un SESSION_SECRET fijo para que las sesiones sobrevivan a reinicios.
Usa un solo worker de Uvicorn por instancia — el planificador y el límite de login viven en memoria. Si alguna vez subes UVICORN_WORKERS por encima de 1, tienes que definir SESSION_SECRET para que todos los workers compartan la misma clave de firma.
La imagen publicada es ghcr.io/kn990x/pullpilot. Si todavía apuntas a ghcr.io/kernel-nomad/pullpilot, actualiza tu compose — esa ruta ya no se mantiene.