API
Rol de la API
La API de BunkerWeb es el plano de control para gestionar instancias, servicios, bloqueos, plugins, trabajos y configuraciones personalizadas. Se ejecuta como una app FastAPI detrás de Gunicorn y debe mantenerse en una red de confianza. Docs interactivas en /docs (o <API_ROOT_PATH>/docs); el esquema OpenAPI en /openapi.json.
Manténla privada
No expongas la API directamente a Internet. Mantenla en una red interna, restringe IPs de origen y exige autenticación.
Datos rápidos
- Endpoints de salud:
GET /pingyGET /health - Ruta raíz: define
API_ROOT_PATHal usar reverse proxy en subruta para que docs y OpenAPI funcionen - Auth obligatoria: tokens Biscuit, Basic admin o un Bearer de override
- Lista blanca IP por defecto a rangos RFC1918 (
API_WHITELIST_IPS); desactiva solo si el upstream controla el acceso - Rate limiting activado por defecto;
/authsiempre tiene su propio límite
Checklist de seguridad
- Red: mantén el tráfico interno; escucha en loopback o interfaz interna y restringe IPs de origen con
API_WHITELIST_IPS(activo por defecto). - Auth presente: define
API_USERNAME/API_PASSWORD(admin) y, si hace falta,API_ACL_BOOTSTRAP_FILEpara más usuarios/ACL; guarda unAPI_TOKENsolo para emergencias. - Ocultar ruta: con reverse proxy, elige un
API_ROOT_PATHpoco obvio y refléjalo en el proxy. - Rate limiting: déjalo activado salvo que otra capa imponga límites equivalentes;
/authsiempre está limitado. - TLS: termina en el proxy o usa
API_SSL_ENABLED=yescon rutas de cert/clave.
Ejecución
Elige el sabor que encaje con tu entorno.
Layout Compose mínimo con la API detrás de BunkerWeb. Ajusta versiones y contraseñas antes de usar.
x-bw-env: &bw-env
# Usamos un ancla para no repetir ajustes entre servicios
API_WHITELIST_IP: "127.0.0.0/8 10.20.30.0/24" # Ajusta el rango IP correcto para que el scheduler envíe la config a la instancia (API interna de BunkerWeb)
# Opcional: define un token y refléjalo en ambos contenedores (API interna de BunkerWeb)
API_TOKEN: ""
DATABASE_URI: "mariadb+pymysql://bunkerweb:changeme@bw-db:3306/db" # Usa una contraseña más fuerte para la base de datos
services:
bunkerweb:
# Nombre que usará el scheduler para identificar la instancia
image: bunkerity/bunkerweb:1.6.7
ports:
- "80:8080/tcp"
- "443:8443/tcp"
- "443:8443/udp" # Para QUIC / HTTP3
environment:
<<: *bw-env # Reutilizamos el ancla para evitar duplicados
restart: "unless-stopped"
networks:
- bw-universe
- bw-services
bw-scheduler:
image: bunkerity/bunkerweb-scheduler:1.6.7
environment:
<<: *bw-env
BUNKERWEB_INSTANCES: "bunkerweb" # Asegúrate de poner el nombre de instancia correcto
SERVER_NAME: "api.example.com"
MULTISITE: "yes"
USE_REDIS: "yes"
REDIS_HOST: "redis"
DISABLE_DEFAULT_SERVER: "yes"
AUTO_LETS_ENCRYPT: "yes"
api.example.com_USE_TEMPLATE: "api"
api.example.com_USE_REVERSE_PROXY: "yes"
api.example.com_REVERSE_PROXY_URL: "/"
api.example.com_REVERSE_PROXY_HOST: "http://bw-api:8888"
volumes:
- bw-storage:/data # Persistir caché y backups
restart: "unless-stopped"
networks:
- bw-universe
- bw-db
bw-api:
image: bunkerity/bunkerweb-api:1.6.7
environment:
<<: *bw-env
API_USERNAME: "admin"
API_PASSWORD: "Str0ng&P@ss!"
# API_TOKEN: "admin-override-token" # opcional
FORWARDED_ALLOW_IPS: "*" # Cuidado: solo úsalo si el reverse proxy es la única vía
API_ROOT_PATH: "/"
networks:
- bw-universe
- bw-db
bw-db:
image: mariadb:11
# Max allowed packet más grande para evitar problemas con queries grandes
command: --max-allowed-packet=67108864
environment:
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
MYSQL_DATABASE: "db"
MYSQL_USER: "bunkerweb"
MYSQL_PASSWORD: "changeme" # Usa una contraseña más fuerte
volumes:
- bw-data:/var/lib/mysql
restart: "unless-stopped"
networks:
- bw-db
redis: # Redis para persistir reports/bans/stats
image: redis:8-alpine
command: >
redis-server
--maxmemory 256mb
--maxmemory-policy allkeys-lru
--save 60 1000
--appendonly yes
volumes:
- redis-data:/data
restart: "unless-stopped"
networks:
- bw-universe
volumes:
bw-data:
bw-storage:
redis-data:
networks:
bw-universe:
name: bw-universe
ipam:
driver: default
config:
- subnet: 10.20.30.0/24 # Ajusta el rango IP correcto para que el scheduler envíe la config a la instancia
bw-services:
name: bw-services
bw-db:
name: bw-db
docker run -d \
--name bunkerweb-aio \
-e SERVICE_API=yes \
-e API_WHITELIST_IPS="127.0.0.0/8" \
-p 80:8080/tcp -p 443:8443/tcp -p 443:8443/udp \
bunkerity/bunkerweb-all-in-one:1.6.7
Los paquetes DEB/RPM incluyen bunkerweb-api.service, gestionado por /usr/share/bunkerweb/scripts/bunkerweb-api.sh.
- Activar/iniciar:
sudo systemctl enable --now bunkerweb-api.service - Recargar:
sudo systemctl reload bunkerweb-api.service - Logs: journal más
/var/log/bunkerweb/api.log - Escucha por defecto:
127.0.0.1:8888conAPI_WHITELIST_IPS=127.0.0.1 - Archivos de config:
/etc/bunkerweb/api.env(se crea con defaults comentados al primer arranque) y/etc/bunkerweb/api.yml - Fuentes de entorno:
api.env,variables.env,/run/secrets/<VAR>y luego exportadas al proceso Gunicorn
Edita /etc/bunkerweb/api.env para definir API_USERNAME/API_PASSWORD, allowlist, TLS, límites de tasa o API_ROOT_PATH, luego systemctl reload bunkerweb-api.
Autenticación y autorización
/authemite tokens Biscuit. Las credenciales pueden venir por Basic auth, campos de formulario, cuerpo JSON o un header Bearer igual aAPI_TOKEN(override admin).- Los administradores pueden llamar rutas protegidas directamente con HTTP Basic (sin Biscuit).
- Si el Bearer coincide con
API_TOKEN, el acceso es total/admin. Si no, el guard de Biscuit aplica ACL. - El payload de Biscuit incluye usuario, tiempo, IP cliente, host, versión, un rol amplio
role("api_user", ["read", "write"])yadmin(true)o permisos finosapi_perm(resource_type, resource_id|*, permission). - TTL es
API_BISCUIT_TTL_SECONDS(0/off desactiva expiración). Las llaves viven en/var/lib/bunkerweb/.api_biscuit_private_keyy.api_biscuit_public_keysalvo que se pasen conBISCUIT_PRIVATE_KEY/BISCUIT_PUBLIC_KEY. - Los endpoints de auth solo están expuestos cuando existe al menos un usuario de API en la base.
Auth rápido
- Define
API_USERNAMEyAPI_PASSWORD(yOVERRIDE_API_CREDS=yessi necesitas resembrar). - Llama a
POST /authcon Basic; lee.tokende la respuesta. - Usa
Authorization: Bearer <token>en las siguientes llamadas.
Permisos y ACL
- Rol grueso: GET/HEAD/OPTIONS requieren
read; verbos de escritura requierenwrite. - ACL fina se aplica cuando las rutas declaran permisos;
admin(true)omite chequeos. - Tipos de recurso:
instances,global_settings,services,configs,plugins,cache,bans,jobs. - Nombres de permisos:
instances_*:instances_read,instances_update,instances_delete,instances_create,instances_executeglobal_settings_*:global_settings_read,global_settings_updateservices:service_read,service_create,service_update,service_delete,service_convert,service_exportconfigs:configs_read,config_read,config_create,config_update,config_deleteplugins:plugin_read,plugin_create,plugin_deletecache:cache_read,cache_deletebans:ban_read,ban_update,ban_delete,ban_createdjobs:job_read,job_runresource_idsuele ser el segundo componente del path (ej./services/{id}); "*" da acceso global.- Inicializa usuarios no admin y permisos con
API_ACL_BOOTSTRAP_FILEo un/var/lib/bunkerweb/api_acl_bootstrap.jsonmontado. Contraseñas pueden ser texto plano o hash bcrypt.
ACL mínima
{
"users": {
"ci": {
"admin": false,
"password": "Str0ng&P@ss!",
"permissions": {
"services": { "*": { "service_read": true } },
"configs": { "*": { "config_read": true, "config_update": true } }
}
}
}
}
Limitación de velocidad
Activa por defecto con dos cadenas: API_RATE_LIMIT (global, por defecto 100r/m) y API_RATE_LIMIT_AUTH (por defecto 10r/m u off). Acepta notación estilo NGINX (3r/s, 40r/m, 200r/h) o formas verbosas (100/minute, 200 per 30 minutes). Configura mediante:
API_RATE_LIMIT,API_RATE_LIMIT_AUTHAPI_RATE_LIMIT_ENABLED,API_RATE_LIMIT_HEADERS_ENABLEDAPI_RATE_LIMIT_RULES(cadena CSV/JSON/YAML o ruta a archivo)API_RATE_LIMIT_STRATEGY,API_RATE_LIMIT_KEY,API_RATE_LIMIT_EXEMPT_IPS- Almacenamiento en memoria o Redis/Valkey con
USE_REDIS=yesmás ajustesREDIS_*(Sentinel soportado).
Estrategias del limitador (proveídas por limits):
fixed-window(predeterminado): el bucket se reinicia en cada borde de intervalo; más barato y suficiente para límites gruesos.moving-window: ventana deslizante real con timestamps precisos; más suave pero más costosa en operaciones de almacenamiento.sliding-window-counter: híbrido que suaviza con conteos ponderados de la ventana previa; más liviano que moving y más suave que fixed.
Más detalles y trade-offs: https://limits.readthedocs.io/en/stable/strategies.html
CSV en línea
API_RATE_LIMIT_RULES='POST /auth 10r/m, GET /instances* 200r/m, POST|PATCH /services* 40r/m'
Archivo YAML
API_RATE_LIMIT: 200r/m
API_RATE_LIMIT_AUTH: 15r/m
API_RATE_LIMIT_RULES:
- path: "/auth"
methods: "POST"
rate: "10r/m"
- path: "/instances*"
methods: "GET|POST"
rate: "100r/m"
Fuentes de configuración y prioridad
- Variables de entorno (incluyendo
environment:de Docker/Compose) - Secrets en
/run/secrets/<VAR>(Docker) - YAML en
/etc/bunkerweb/api.yml - Archivo env en
/etc/bunkerweb/api.env - Valores predeterminados
Tiempo de ejecución y zona horaria
| Setting | Descripción | Valores aceptados | Predeterminado |
|---|---|---|---|
TZ |
Zona horaria para logs de la API y claims basados en tiempo (p. ej. TTL de Biscuit y marcas de tiempo) | Nombre de base TZ (p. ej. UTC, Europe/Paris) |
unset (default del contenedor, normalmente UTC) |
Desactiva docs o esquema poniendo sus URLs en off|disabled|none|false|0. Define API_SSL_ENABLED=yes con API_SSL_CERTFILE y API_SSL_KEYFILE para terminar TLS en la API. Con reverse proxy, define API_FORWARDED_ALLOW_IPS a las IPs del proxy para que Gunicorn confíe en los X-Forwarded-*.
Referencia de configuración (power users)
Superficie y docs
| Setting | Descripción | Valores aceptados | Predeterminado |
|---|---|---|---|
API_DOCS_URL, API_REDOC_URL, API_OPENAPI_URL |
Rutas para Swagger, ReDoc y OpenAPI; pon off/disabled/none/false/0 para desactivar |
Ruta o off |
/docs, /redoc, /openapi.json |
API_ROOT_PATH |
Prefijo de montaje al usar reverse proxy | Ruta (ej. /api) |
vacío |
API_FORWARDED_ALLOW_IPS |
IPs de proxy confiables para X-Forwarded-* |
IPs/CIDRs separadas por comas | 127.0.0.1 (default de paquete) |
Auth, ACL, Biscuit
| Setting | Descripción | Valores aceptados | Predeterminado |
|---|---|---|---|
API_USERNAME, API_PASSWORD |
Usuario admin inicial | Strings; contraseña fuerte requerida fuera de debug | unset |
OVERRIDE_API_CREDS |
Reaplicar credenciales admin al arranque | yes/no/on/off/true/false/0/1 |
no |
API_TOKEN |
Bearer de override admin | Cadena opaca | unset |
API_ACL_BOOTSTRAP_FILE |
Ruta JSON para usuarios/permisos | Ruta o /var/lib/bunkerweb/api_acl_bootstrap.json montado |
unset |
BISCUIT_PRIVATE_KEY, BISCUIT_PUBLIC_KEY |
Claves Biscuit (hex) si no se usan archivos | Cadenas hex | auto-generadas/persistidas |
API_BISCUIT_TTL_SECONDS |
Vida del token; 0/off desactiva expiración |
Entero en segundos o off/disabled |
3600 |
CHECK_PRIVATE_IP |
Liga Biscuit a la IP cliente (excepto privada) | yes/no/on/off/true/false/0/1 |
yes |
Allowlist
| Setting | Descripción | Valores aceptados | Predeterminado |
|---|---|---|---|
API_WHITELIST_ENABLED |
Alternar middleware de lista blanca | yes/no/on/off/true/false/0/1 |
yes |
API_WHITELIST_IPS |
IPs/CIDRs separadas por espacio/coma | IPs/CIDRs | Rangos RFC1918 en código |
Limitación
| Setting | Descripción | Valores aceptados | Predeterminado |
|---|---|---|---|
API_RATE_LIMIT |
Límite global (cadena estilo NGINX) | 3r/s, 100/minute, 500 per 30 minutes |
100r/m |
API_RATE_LIMIT_AUTH |
Límite de /auth (o off) |
igual que arriba o off/disabled/none/false/0 |
10r/m |
API_RATE_LIMIT_ENABLED |
Activar limitador | yes/no/on/off/true/false/0/1 |
yes |
API_RATE_LIMIT_HEADERS_ENABLED |
Inyectar headers de límite | igual que arriba | yes |
API_RATE_LIMIT_RULES |
Reglas por ruta (CSV/JSON/YAML o ruta) | Cadena o ruta | unset |
API_RATE_LIMIT_STRATEGY |
Algoritmo | fixed-window, moving-window, sliding-window-counter |
fixed-window |
API_RATE_LIMIT_KEY |
Selector de clave | ip, header:<Name> |
ip |
API_RATE_LIMIT_EXEMPT_IPS |
Saltar límites para estas IPs/CIDRs | Separadas por espacio/coma | unset |
API_RATE_LIMIT_STORAGE_OPTIONS |
JSON mezclado en la config de almacenamiento | Cadena JSON | unset |
Redis/Valkey (para rate limits)
| Setting | Descripción | Valores aceptados | Predeterminado |
|---|---|---|---|
USE_REDIS |
Habilitar backend Redis | yes/no/on/off/true/false/0/1 |
no |
REDIS_HOST, REDIS_PORT, REDIS_DATABASE |
Detalles de conexión | Host, int, int | unset, 6379, 0 |
REDIS_USERNAME, REDIS_PASSWORD |
Auth | Cadenas | unset |
REDIS_SSL, REDIS_SSL_VERIFY |
TLS y verificación | yes/no/on/off/true/false/0/1 |
no, yes |
REDIS_TIMEOUT |
Timeout (ms) | Entero | 1000 |
REDIS_KEEPALIVE_POOL |
Keepalive de pool | Entero | 10 |
REDIS_SENTINEL_HOSTS |
Hosts de Sentinel | host:port separados por espacio |
unset |
REDIS_SENTINEL_MASTER |
Nombre de maestro | Cadena | unset |
REDIS_SENTINEL_USERNAME, REDIS_SENTINEL_PASSWORD |
Auth de Sentinel | Cadenas | unset |
Redis de la BD
Si la config de la base de datos de BunkerWeb incluye Redis/Valkey, la API la reutiliza automáticamente para rate limiting incluso sin USE_REDIS en el entorno. Sobrescribe con variables de entorno cuando necesites otro backend.
Listener y TLS
| Setting | Descripción | Valores aceptados | Predeterminado |
|---|---|---|---|
API_LISTEN_ADDR, API_LISTEN_PORT |
Dirección/puerto de Gunicorn | IP o hostname, int | 127.0.0.1, 8888 (script de paquete) |
API_SSL_ENABLED |
Activar TLS en la API | yes/no/on/off/true/false/0/1 |
no |
API_SSL_CERTFILE, API_SSL_KEYFILE |
Rutas de cert y clave PEM | Rutas de archivo | unset |
API_SSL_CA_CERTS |
CA/cadena opcional | Ruta de archivo | unset |
Logging y runtime (defaults de paquete)
| Setting | Descripción | Valores aceptados | Predeterminado |
|---|---|---|---|
LOG_LEVEL, CUSTOM_LOG_LEVEL |
Nivel base / override | debug, info, warning, error, critical |
info |
LOG_TYPES |
Destinos | stderr/file/syslog separados por espacio |
stderr |
LOG_FILE_PATH |
Ubicación del log (si LOG_TYPES incluye file o CAPTURE_OUTPUT=yes) |
Ruta de archivo | /var/log/bunkerweb/api.log si file/capture, si no unset |
LOG_SYSLOG_ADDRESS |
Destino syslog (udp://host:514, tcp://host:514, socket) |
Host:puerto, host con prefijo proto o ruta socket | unset |
LOG_SYSLOG_TAG |
Tag de syslog | Cadena | bw-api |
MAX_WORKERS, MAX_THREADS |
Workers/hilos de Gunicorn | Entero o unset para auto | unset |
CAPTURE_OUTPUT |
Capturar stdout/stderr de Gunicorn hacia los handlers configurados | yes o no |
no |
Superficie de la API (mapa de capacidades)
- Core
GET /ping,GET /health: checks de vida de la propia API.- Auth
POST /auth: emite tokens Biscuit; acepta Basic, formulario, JSON o Bearer de override cuandoAPI_TOKENcoincide.- Instances
GET /instances: lista instancias con metadata de creación/último seen.POST /instances: registra una instancia (hostname/port/server_name/method).GET/PATCH/DELETE /instances/{hostname}: inspeccionar, actualizar campos mutables o borrar instancias gestionadas por la API.DELETE /instances: borrar en masa instancias gestionadas por la API; las ajenas se omiten.- Salud/acciones:
GET /instances/ping,GET /instances/{hostname}/ping,POST /instances/reload?test=yes|no,POST /instances/{hostname}/reload,POST /instances/stop,POST /instances/{hostname}/stop. - Global settings
GET /global_settings: por defecto solo no-defaults; añadefull=truepara todos los ajustes,methods=truepara incluir procedencia.PATCH /global_settings: upsert de globals propiedad de la API; claves de solo lectura se rechazan.- Services
GET /services: lista servicios (incluye borradores por defecto).GET /services/{service}: obtiene no-defaults o config completa (full=true);methods=trueincluye procedencia.POST /services: crea un servicio (draft u online), define variables y actualizaSERVER_NAMEde forma atómica.PATCH /services/{service}: renombrar, actualizar variables, alternar draft.DELETE /services/{service}: eliminar servicio y claves derivadas de config.POST /services/{service}/convert?convert_to=online|draft: cambiar rápido entre draft/online.- Custom configs
GET /configs: lista snippets (servicio por defectoglobal);with_data=trueincrusta contenido imprimible.POST /configs,POST /configs/upload: crea snippets vía JSON o subida de archivo.GET /configs/{service}/{type}/{name}: obtiene snippet;with_data=truepara el contenido.PATCH /configs/{service}/{type}/{name},PATCH .../upload: actualizar o mover snippets gestionados por la API.DELETE /configsoDELETE /configs/{service}/{type}/{name}: eliminar snippets gestionados por la API; los gestionados por plantillas se omiten.- Tipos soportados:
http,server_http,default_server_http,modsec,modsec_crs,stream,server_stream, hooks de CRS/plug-in. - Bans
GET /bans: agrega bans activos desde las instancias.POST /banso/bans/ban: aplica uno o varios bans; payload puede ser objeto, array o JSON como string.POST /bans/unbanoDELETE /bans: eliminar bans globalmente o por servicio.- Plugins (UI)
GET /plugins: lista plugins;with_data=trueincluye los bytes del paquete cuando están disponibles.POST /plugins/upload: instala plugins de UI desde.zip,.tar.gz,.tar.xz.DELETE /plugins/{id}: elimina un plugin por ID.- Cache (artefactos de jobs)
GET /cache: lista archivos de caché con filtros (service,plugin,job_name);with_data=trueincrusta contenido imprimible.GET /cache/{service}/{plugin}/{job}/{file}: obtiene/descarga un archivo de caché específico (download=true).DELETE /cacheoDELETE /cache/{service}/{plugin}/{job}/{file}: borra archivos de caché y notifica al scheduler.- Jobs
GET /jobs: lista jobs, horarios y resúmenes de caché.POST /jobs/run: marca plugins como cambiados para disparar los jobs asociados.
Comportamiento operativo
- Respuestas de error normalizadas a
{"status": "error", "message": "..."}con códigos HTTP adecuados. - Las operaciones de escritura se persisten en la base de datos compartida; las instancias consumen cambios vía sincronización del scheduler o tras un reload.
API_ROOT_PATHdebe coincidir con la ruta del reverse proxy para que/docsy enlaces funcionen.- El arranque falla si no existe un camino de autenticación (sin claves Biscuit, sin usuario admin y sin
API_TOKEN); los errores se registran en/var/tmp/bunkerweb/api.error.