- Historial pasa a Librería: pestañas Leyendo, Siguiendo, Terminados, En el dispositivo y listas propias (Favoritos, Pendientes, Abandonados por defecto) - Recomendaciones en el inicio según tus géneros más leídos (populares de MangaDex) - Descarga anticipada de los N capítulos siguientes (opcionalmente en HD) al pasar la mitad de uno - PWA: manifest, iconos y service worker; capítulos guardados en el dispositivo para leer sin conexión, progreso offline sincronizado después - Seguridad: baneo de IP tras 6 intentos fallidos (configurable), IP real detrás de proxies de confianza, CSP y cabeceras, cookie Secure/HSTS en HTTPS, login sin diferencias de tiempo, registro cerrado por defecto, contraseñas de 8+, protección SSRF en el proxy de imágenes, errores 500 genéricos - Ajustes: sección Seguridad con IPs bloqueadas, intentos recientes y la IP vista por el servidor - LeerCapitulo: reintentos ante caídas (522/5xx), copia anterior si sigue caído y mensaje claro Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
57 lines
2.3 KiB
YAML
57 lines
2.3 KiB
YAML
# Todo lo que depende de la máquina va en .env (ver .env.example).
|
|
# Sin .env también arranca: puerto 3352 en todas las interfaces, descargas en ./mangas.
|
|
services:
|
|
manga-reader:
|
|
build: .
|
|
image: manga-reader:local
|
|
container_name: manga-reader
|
|
restart: unless-stopped
|
|
# Dueño de ./data y de la carpeta de mangas en el host (id -u / id -g).
|
|
user: "${PUID:-1000}:${PGID:-1000}"
|
|
environment:
|
|
- TZ=${TZ:-America/El_Salvador}
|
|
- PORT=3352
|
|
- DATA_DIR=/app/data
|
|
- MANGA_DIR=/mangas
|
|
# Cada cuántas horas se buscan capítulos nuevos de los mangas seguidos.
|
|
- CHECK_INTERVAL_HOURS=${CHECK_INTERVAL_HOURS:-3}
|
|
# URL con la que se abre la web desde las notificaciones.
|
|
- PUBLIC_URL=${PUBLIC_URL:-http://localhost:3352}
|
|
# Registro de cuentas nuevas. Con la base vacía el primer usuario siempre puede registrarse.
|
|
- ALLOW_SIGNUP=${ALLOW_SIGNUP:-false}
|
|
# Baneo de IP: tras BAN_MAX_FAILS intentos fallidos en BAN_WINDOW_MIN minutos, BAN_HOURS horas.
|
|
- BAN_MAX_FAILS=${BAN_MAX_FAILS:-6}
|
|
- BAN_WINDOW_MIN=${BAN_WINDOW_MIN:-60}
|
|
- BAN_HOURS=${BAN_HOURS:-24}
|
|
- BAN_IGNORE=${BAN_IGNORE:-}
|
|
# Detrás de un proxy inverso (Caddy, Nginx, Cloudflare Tunnel…): cabecera con la IP real del
|
|
# cliente, p. ej. x-forwarded-for o cf-connecting-ip. Vacío = conexión directa.
|
|
- REAL_IP_HEADER=${REAL_IP_HEADER:-}
|
|
volumes:
|
|
# SQLite con usuarios, sesiones, historial, estadísticas y clave del proxy de imágenes.
|
|
- ./data:/app/data
|
|
# Mangas descargados: <Título>/Capitulo NNNN.cbz + cover.jpg
|
|
- ${MANGA_DIR_HOST:-./mangas}:/mangas
|
|
# GPU para el reescalado HD (Real-ESRGAN por Vulkan). Sin /dev/dri en el host, borra estas líneas
|
|
# y el reescalado queda desactivado. RENDER_GID = grupo "render" del host (getent group render).
|
|
devices:
|
|
- /dev/dri:/dev/dri
|
|
group_add:
|
|
- "${RENDER_GID:-render}"
|
|
ports:
|
|
# 0.0.0.0 no depende de que la IP de la LAN o de Tailscale existan al arrancar.
|
|
# Para limitarlo a una interfaz: BIND_IP=192.168.1.141 en .env.
|
|
- "${BIND_IP:-0.0.0.0}:${HOST_PORT:-3352}:3352"
|
|
read_only: true
|
|
tmpfs:
|
|
- /tmp
|
|
cap_drop:
|
|
- ALL
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|