1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# Despliegue de producción de Kesto (SRS §8).
#
# La clave maestra y los secretos NO viven aquí: entran por el entorno del
# host (`.env` del despliegue o gestor de secretos). Copia `.env.example` a
# `.env` y rellénalo antes de `podman compose up -d`.
services:
kesto:
image: ghcr.io/atareao/kesto:latest
container_name: kesto-app
restart: always
ports:
- "8080:8080"
# Secretos OPCIONALES por `.env`: solo entran si el operador los
# descomenta ahí. NO se cablean en `environment:` porque una `OIDC_*`
# presente pero VACÍA se lee como «presente» (src/config.rs::resolve_auth
# deduce el modo de la mera presencia de las tres): declararlas aquí con
# valor por defecto vacío forzaría el modo OIDC y rompería el arranque por
# defecto, que debe ser `Disabled`.
env_file:
- .env
environment:
RUST_LOG: info,kesto=debug
DATABASE_URL: sqlite:///app/data/kesto.db
BIND_ADDRESS: 0.0.0.0:8080
# Obligatoria siempre. Sin ella el arranque falla (src/config.rs).
KESTO_MASTER_KEY: ${KESTO_MASTER_KEY:?falta KESTO_MASTER_KEY}
volumes:
# Socket del daemon para el `exec` de bollard, en solo lectura.
- /var/run/docker.sock:/var/run/docker.sock:ro
# Fuentes de copia de ejemplo del §8, en solo lectura.
- /var/www:/backup_sources/var_www:ro
- /etc/nginx:/backup_sources/nginx_config:ro
# Persistencia interna (SQLite) de la aplicación.
- kesto_data:/app/data
# En un host estándar el socket del daemon es `root:docker` con modo
# `srw-rw----`, y el proceso corre como uid/gid 10001: sin el grupo del
# daemon no puede abrirlo. El gid DEPENDE DEL HOST y se pasa por `DOCKER_GID`
# (`getent group docker`) sin editar este fichero. El defecto es el propio gid
# del proceso (10001): inofensivo, y mantiene el arranque en dev (sin daemon)
# sin configurar nada. En local lo cubre `just run` con `--userns=keep-id`.
group_add:
volumes:
kesto_data:
# ---
# Ejemplo de fuente SQLite (§4): un servicio autoalojado cuya base vive DENTRO
# de su propio contenedor (Vaultwarden, Miniflux, Immich…). NO se monta en
# Kesto ni se lee del host: se declara como target `sqlite` con
# `container_name` —el contenedor donde vive el fichero— y `db_path` —la ruta
# absoluta del `.db` dentro de él—, sin `db_user`, `db_password`, `db_name` ni
# `host_path`. Kesto copia con `sqlite3 <db_path> .dump` por el socket del
# daemon (consistente en caliente: válido con WAL y sin parar el servicio).
#
# El contenedor del target DEBE traer el binario `sqlite3`: si su imagen no lo
# incluye, añade una capa que lo instale (`apk add --no-cache sqlite` /
# `apt-get install -y sqlite3`) o usa una imagen que ya lo traiga.
#
# Alta equivalente por API (el panel hace lo mismo en Ajustes → Fuentes):
#
# curl -fsS -X POST http://localhost:8080/api/v1/targets \
# -H 'content-type: application/json' \
# -d '{"name":"vaultwarden","target_type":"sqlite",
# "container_name":"vaultwarden","db_path":"/data/db.sqlite"}'
#
# services:
# vaultwarden:
# image: vaultwarden/server:latest
# container_name: vaultwarden
# restart: always
# volumes:
# - vaultwarden_data:/data # aquí vive /data/db.sqlite
#
# volumes:
# vaultwarden_data: