Ir al contenido

Stack de producción

  • Un host Linux con Docker Engine y el Docker Compose plugin.
  • Los puertos 80 y 443 accesibles para sus usuarios (o cualquier otro puerto, definido en .env).
  • Para los certificados Let’s Encrypt: un nombre DNS que apunte al host y los puertos 80 y 443 accesibles desde Internet.

Auditix se publica como tres imágenes (frontend, backend, updater) en el registro de Auditix, rg.fr-par.scw.cloud/auditix, que siempre se despliegan con la misma etiqueta. El archivo compose añade los servicios de los que dependen:

Servicio Función
gateway El único servicio publicado: sirve Auditix en HTTP y HTTPS.
frontend La interfaz web.
backend La aplicación. Aplica por sí misma los cambios de la base de datos al arrancar.
updater Aplica las actualizaciones iniciadas desde Configuración › Plataforma › Actualización. Opcional.
orchestrator Inicia y detiene los contenedores worker que ejecutan el trabajo en segundo plano.
developer La referencia de la API externa, en /developer.
logs Reenvía los registros a los servidores syslog de Configuración › Plataforma › Registros.
rabbitmq Colas del trabajo en segundo plano.
mercure Actualizaciones en tiempo real de la interfaz.
database PostgreSQL: aquí residen todos los datos.

Los servicios updater y orchestrator tienen acceso a Docker. Solo actúan sobre los contenedores de su propia instalación (el proyecto compose desplegado desde la misma carpeta), nunca sobre otros contenedores del host.

  1. Inicie sesión en el registro (omita este paso si el registro es público), con una clave secreta de API de Scaleway autorizada a leer el registro:

    Ventana de terminal
    docker login rg.fr-par.scw.cloud/auditix -u nologin
    # Password: your Scaleway API secret key
  2. Cree la carpeta de instalación:

    Ventana de terminal
    mkdir -p /opt/auditix && cd /opt/auditix
  3. Cree compose.yaml con el contenido que figura más abajo.

  4. Cree .env, legible solo por root (chmod 600 .env), y rellene cada secreto una sola vez con openssl rand -hex 32:

    Ventana de terminal
    # "latest": updated from Settings › Platform › Update. Or a fixed release (vX.Y.Z).
    AUDITIX_VERSION=latest
    HTTP_PORT=80
    HTTPS_PORT=443
    # Generate each once with: openssl rand -hex 32
    APP_SECRET=
    POSTGRES_PASSWORD=
    MERCURE_JWT_SECRET=
    RABBITMQ_PASSWORD=
    GATEWAY_SECRET=
    UPDATER_SECRET=
  5. Arranque:

    Ventana de terminal
    docker compose pull
    docker compose up -d
    docker compose ps # every service should be "healthy"
  6. Inicie sesión en http://<host> con el administrador predeterminado, admin / password. Auditix pide una nueva contraseña antes de nada: hágalo de inmediato, antes de exponer el servicio.

name: auditix
# Every service hands its output to Docker's syslog driver, towards the log collector, which
# forwards it to the syslog servers of Settings › Platform › Logs.
x-logging: &logging
driver: syslog
options:
syslog-address: udp://127.0.0.1:15013
syslog-format: rfc5424
tag: "{{.Name}}"
services:
# The only published service. HTTPS and the certificate are set in Settings › Platform › Web
# access; the gateway reads them from the backend.
gateway:
logging: *logging
image: traefik:v3.7
command:
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.forwardedHeaders.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1/32
- --entrypoints.websecure.forwardedHeaders.trustedIPs=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1/32
- --providers.http.endpoint=http://backend:8080/internal/gateway
- --providers.http.pollInterval=5s
- --providers.http.headers.X-Gateway-Secret=${GATEWAY_SECRET:?Set GATEWAY_SECRET in .env}
- --certificatesresolvers.letsencrypt.acme.storage=/data/acme.json
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
- --certificatesresolvers.letsencrypt-staging.acme.storage=/data/acme-staging.json
- --certificatesresolvers.letsencrypt-staging.acme.httpchallenge.entrypoint=web
- --certificatesresolvers.letsencrypt-staging.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
- --ping=true
- --global.checkNewVersion=false
- --global.sendAnonymousUsage=false
ports:
- "${HTTP_PORT:-80}:80"
- "${HTTPS_PORT:-443}:443"
volumes:
- gateway:/data
healthcheck:
test: ["CMD", "traefik", "healthcheck", "--ping"]
interval: 10s
timeout: 3s
retries: 6
depends_on:
backend:
condition: service_healthy
restart: unless-stopped
frontend:
logging: *logging
image: rg.fr-par.scw.cloud/auditix/frontend:${AUDITIX_VERSION:-latest}
environment:
BACKEND_URL: http://backend:8080
depends_on:
backend:
condition: service_healthy
restart: unless-stopped
backend:
logging: *logging
image: rg.fr-par.scw.cloud/auditix/backend:${AUDITIX_VERSION:-latest}
environment: &backend-environment
APP_SECRET: ${APP_SECRET:?Set APP_SECRET in .env}
DATABASE_URL: postgresql://auditix:${POSTGRES_PASSWORD}@database:5432/auditix?serverVersion=18&charset=utf8
MERCURE_URL: http://mercure/.well-known/mercure
MERCURE_JWT_SECRET: ${MERCURE_JWT_SECRET:?Set MERCURE_JWT_SECRET in .env}
MESSENGER_TRANSPORT_DSN: amqp://auditix:${RABBITMQ_PASSWORD:?Set RABBITMQ_PASSWORD in .env}@rabbitmq:5672/%2f
GATEWAY_SECRET: ${GATEWAY_SECRET}
UPDATER_SECRET: ${UPDATER_SECRET:-}
LOGS_COLLECTOR_HOST: logs
# Never published: the internal API is only for the frontend; integrations use the
# external API (/api/v1) through the gateway.
volumes:
- logs-config:/app/var/logs-collector
depends_on:
database:
condition: service_healthy
rabbitmq:
condition: service_healthy
restart: unless-stopped
# Applies the updates started from Settings › Platform › Update. The only service with access to
# Docker: it only acts on the services of this file (its own compose project), never on other
# containers of the host. Optional: without it, update by hand (see Update below).
updater:
logging: *logging
image: rg.fr-par.scw.cloud/auditix/updater:${AUDITIX_VERSION:-latest}
environment:
BACKEND_URL: http://backend:8080
UPDATER_SECRET: ${UPDATER_SECRET:?Set UPDATER_SECRET in .env}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
# The installation directory: the backups taken before updates in backups/, and its .env
# when AUDITIX_VERSION is a fixed release.
- .:/install
depends_on:
backend:
condition: service_healthy
restart: unless-stopped
# Runs the background work: starts and stops the worker containers (the backend image, started
# with the "worker" command) as the pools of Settings › Platform › Workers ask, a fixed number or
# following the backlog of their queues. Same image as the updater; it only acts on the worker
# containers it creates for this installation. Without it, no worker runs (see Scale the workers).
orchestrator:
logging: *logging
image: rg.fr-par.scw.cloud/auditix/updater:${AUDITIX_VERSION:-latest}
entrypoint: ["auditix-orchestrator"]
environment:
BACKEND_URL: http://backend:8080
UPDATER_SECRET: ${UPDATER_SECRET:?Set UPDATER_SECRET in .env}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
backend:
condition: service_healthy
restart: unless-stopped
# The developer portal: the reference of the external API, at /developer.
developer:
logging: *logging
image: scalarapi/api-reference:0.6.12
environment:
BASE_PATH: /developer/scalar
API_REFERENCE_CONFIG: '{"sources":[{"url":"/api/v1/openapi.json","title":"Auditix API"}],"theme":"none","withDefaultFonts":false,"customCss":"@import url(\"/theme/developer\");","favicon":"/icon.svg","metaData":{"title":"Auditix API"},"defaultHttpClient":{"targetKey":"shell","clientKey":"curl"},"showDeveloperTools":"never","agent":{"disabled":true},"mcp":{"disabled":true}}'
restart: unless-stopped
# The log collector: forwards the logs to the syslog servers of the settings.
logs:
image: timberio/vector:0.59.0-alpine
command: ["--config-dir", "/etc/vector/auditix", "--watch-config"]
ports:
- "127.0.0.1:15013:5514/udp"
volumes:
- logs-config:/etc/vector/auditix:ro
depends_on:
backend:
condition: service_healthy
restart: unless-stopped
# Queues of the background work.
rabbitmq:
logging: *logging
image: rabbitmq:4.3-management-alpine
hostname: rabbitmq
environment:
RABBITMQ_DEFAULT_USER: auditix
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD}
volumes:
- rabbitmq:/var/lib/rabbitmq
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
interval: 10s
timeout: 10s
retries: 12
restart: unless-stopped
# Real-time updates. Not published: the browsers reach it through the gateway.
mercure:
logging: *logging
image: dunglas/mercure:v1.1
environment:
SERVER_NAME: ":80"
MERCURE_TRUSTED_ISSUERS: auditix
MERCURE_PUBLISHER_JWT_KEY: ${MERCURE_JWT_SECRET}
MERCURE_PUBLISHER_JWT_ALG: HS256
MERCURE_SUBSCRIBER_JWT_KEY: ${MERCURE_JWT_SECRET}
MERCURE_SUBSCRIBER_JWT_ALG: HS256
MERCURE_EXTRA_DIRECTIVES: |
resource_identifier http://mercure/.well-known/mercure
cookie_name auditix_live
transport bolt {
path /data/mercure.db
size 1000
cleanup_frequency 0.3
}
heartbeat 15s
volumes:
- mercure:/data
restart: unless-stopped
database:
logging: *logging
image: postgres:18-alpine
environment:
POSTGRES_DB: auditix
POSTGRES_USER: auditix
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}
volumes:
- database:/var/lib/postgresql
healthcheck:
test: ["CMD", "pg_isready", "-U", "auditix", "-d", "auditix"]
interval: 5s
timeout: 3s
retries: 10
restart: unless-stopped
volumes:
database:
gateway:
logs-config:
mercure:
rabbitmq:
  1. En Configuración › Plataforma › General, defina el Nombre de la instancia, la Zona horaria, el Idioma predeterminado y, en Apariencia, el Tema predeterminado y el Color principal (consulte Configuración).
  2. Active la licencia.
  3. Configure HTTPS.
  4. Cree los tenants y las cuentas.

Las cuentas también se pueden crear desde la línea de comandos (con Portainer, desde la consola del contenedor backend):

Ventana de terminal
docker compose exec backend bin/console auditix:user:create jane@example.com \
--first-name=Jane --last-name=Doe --platform-admin --tenant="My company"
  1. Stacks › Add stack › Web editor: pegue compose.yaml.
  2. Ponga las variables de .env en las variables de entorno del stack, con AUDITIX_VERSION=latest.
  3. En el servicio updater, quite el volumen .:/install: Portainer guarda los archivos de un stack en su propio volumen. Las copias de seguridad realizadas antes de las actualizaciones van entonces a un volumen Docker llamado <stack>_backups, creado por el updater.

No hace falta nada más: las actualizaciones nunca modifican el stack, y los workers los inicia el servicio orchestrator, fuera del stack.

En Configuración › Plataforma › Acceso web, indique el Nombre de host de la instancia (su DNS debe apuntar al servidor) y elija el Certificado:

  • Let’s Encrypt: gratuito, emitido y renovado automáticamente. Los puertos 80 y 443 deben ser accesibles desde Internet. Let’s Encrypt (prueba) comprueba antes la configuración, con certificados en los que los navegadores no confían, sin alcanzar los límites de Let’s Encrypt.
  • Mi propio certificado: pegue el Certificado (PEM) (con sus certificados intermedios) y la Clave privada (PEM). La clave se guarda cifrada y no se vuelve a mostrar nunca.
  • Sin HTTPS (solo HTTP): para una prueba, o detrás de un proxy inverso que gestiona HTTPS.

Active después Redirigir HTTP a HTTPS y, una vez que HTTPS funcione, HTTPS estricto (HSTS). Los cambios se aplican en pocos segundos, sin reinicio. Si una configuración errónea deja Auditix inaccesible por HTTPS, desactive HTTPS desde el servidor:

Ventana de terminal
docker compose exec backend bin/console auditix:web:reset

Detrás de un proxy inverso que ya gestiona HTTPS, deje HTTPS desactivado y reenvíe al puerto HTTP del gateway con las cabeceras X-Forwarded-Proto y X-Forwarded-For.

El servicio orchestrator inicia los contenedores worker que realizan el trabajo en segundo plano (tareas programadas, comprobaciones, importaciones…), según lo definido en Configuración › Plataforma › Workers › Pools: un número fijo de contenedores, o un escalado Automático en función del número de mensajes en espera. El pool predeterminado ejecuta de 2 a 4 contenedores. Sin el orchestrator, el backend sigue ejecutando las tareas programadas cada cinco minutos, pero no se procesa nada más en segundo plano.

Los contenedores worker no forman parte del proyecto compose, por lo que docker compose down no los elimina. Para detener la instalación por completo (siendo auditix el nombre del proyecto):

Ventana de terminal
docker compose stop orchestrator
docker rm -f $(docker ps -aq --filter label=io.auditix.orchestrator.project=auditix)
docker compose down

Todos los datos residen en PostgreSQL. Haga copias de seguridad con regularidad, y siempre antes de una actualización manual:

Ventana de terminal
docker compose exec -T database pg_dump -U auditix -Fc auditix > auditix-$(date +%F).dump

Restauración en una base de datos vacía:

Ventana de terminal
docker compose exec -T database pg_restore -U auditix -d auditix --clean --if-exists < auditix-YYYY-MM-DD.dump

Cuando ningún administrador puede iniciar sesión, defina una nueva contraseña desde el servidor:

Ventana de terminal
docker compose exec backend bin/console auditix:user:password admin@example.com