Salta ai contenuti

Stack di produzione

  • Un host Linux con Docker Engine e il plugin Docker Compose.
  • Le porte 80 e 443 raggiungibili dai Suoi utenti (o qualsiasi altra porta, impostata in .env).
  • Per i certificati Let’s Encrypt: un nome DNS che punti all’host e le porte 80 e 443 raggiungibili da Internet.

Auditix è pubblicato come tre immagini (frontend, backend, updater) nel registry di Auditix, rg.fr-par.scw.cloud/auditix, sempre distribuite con lo stesso tag. Il file compose aggiunge i servizi su cui si basano:

Servizio Ruolo
gateway L’unico servizio pubblicato: serve Auditix in HTTP e HTTPS.
frontend L’interfaccia web.
backend L’applicazione. Applica da sola le modifiche al database all’avvio.
updater Applica gli aggiornamenti avviati da Impostazioni › Piattaforma › Aggiornamento. Facoltativo.
orchestrator Avvia e arresta i container worker che eseguono le attività in background.
developer Il riferimento dell’API esterna, su /developer.
logs Inoltra i log ai server syslog di Impostazioni › Piattaforma › Log.
rabbitmq Code delle attività in background.
mercure Aggiornamenti in tempo reale dell’interfaccia.
database PostgreSQL: tutti i dati risiedono qui.

I servizi updater e orchestrator hanno accesso a Docker. Agiscono soltanto sui container della propria installazione (il progetto compose distribuito dalla stessa cartella), mai su altri container dell’host.

  1. Acceda al registry (salti questo passaggio se il registry è pubblico), con una chiave segreta API Scaleway autorizzata a leggere il registry:

    Finestra del terminale
    docker login rg.fr-par.scw.cloud/auditix -u nologin
    # Password: your Scaleway API secret key
  2. Crei la cartella di installazione:

    Finestra del terminale
    mkdir -p /opt/auditix && cd /opt/auditix
  3. Crei compose.yaml con il contenuto riportato più sotto.

  4. Crei .env, leggibile solo da root (chmod 600 .env), e compili ogni segreto una sola volta con openssl rand -hex 32:

    Finestra del terminale
    # "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. Avvii:

    Finestra del terminale
    docker compose pull
    docker compose up -d
    docker compose ps # every service should be "healthy"
  6. Acceda a http://<host> con l’amministratore predefinito, admin / password. Auditix chiede una nuova password prima di ogni altra cosa: la imposti subito, prima di esporre il servizio.

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. In Impostazioni › Piattaforma › Generale, imposti il Nome dell’istanza, il Fuso orario, la Lingua predefinita e, in Aspetto, il Tema predefinito e il Colore principale (vedere Impostazioni).
  2. Attivi la licenza.
  3. Configuri HTTPS.
  4. Crei i tenant e gli account.

Gli account possono essere creati anche dalla riga di comando (con Portainer, dalla console del container backend):

Finestra del terminale
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: incolli compose.yaml.
  2. Inserisca le variabili di .env nelle variabili d’ambiente dello stack, con AUDITIX_VERSION=latest.
  3. Nel servizio updater, rimuova il volume .:/install: Portainer conserva i file di uno stack nel proprio volume. I backup eseguiti prima degli aggiornamenti finiscono allora in un volume Docker chiamato <stack>_backups, creato dal programma di aggiornamento.

Non serve nient’altro: gli aggiornamenti non modificano mai lo stack, e i worker vengono avviati dal servizio orchestrator, al di fuori dello stack.

In Impostazioni › Piattaforma › Accesso web, indichi il Nome host dell’istanza (il suo DNS deve puntare al server), poi scelga il Certificato:

  • Let’s Encrypt: gratuito, emesso e rinnovato automaticamente. Le porte 80 e 443 devono essere raggiungibili da Internet. Let’s Encrypt (test) verifica prima la configurazione, con certificati di cui i browser non si fidano, senza incorrere nei limiti di Let’s Encrypt.
  • Il mio certificato: incolli il Certificato (PEM) (con i suoi certificati intermedi) e la Chiave privata (PEM). La chiave viene salvata cifrata e non viene mai più mostrata.
  • Nessun HTTPS (solo HTTP): per un test, o dietro un reverse proxy che gestisce HTTPS.

Attivi poi Reindirizza HTTP a HTTPS e, una volta che HTTPS funziona, HTTPS rigoroso (HSTS). Le modifiche si applicano entro pochi secondi, senza riavvio. Se un’impostazione errata rende Auditix irraggiungibile in HTTPS, disattivi HTTPS dal server:

Finestra del terminale
docker compose exec backend bin/console auditix:web:reset

Dietro un reverse proxy che gestisce già HTTPS, lasci HTTPS disattivato e inoltri il traffico alla porta HTTP del gateway con le intestazioni X-Forwarded-Proto e X-Forwarded-For.

Il servizio orchestrator avvia i container worker che eseguono le attività in background (attività pianificate, controlli, importazioni…), come impostato in Impostazioni › Piattaforma › Worker › Pool: un numero fisso di container, oppure un dimensionamento Automatico in base al numero di messaggi in attesa. Il pool predefinito esegue da 2 a 4 container. Senza l’orchestrator, il backend esegue comunque le attività pianificate ogni cinque minuti, ma nient’altro viene elaborato in background.

I container worker non fanno parte del progetto compose, quindi docker compose down non li rimuove. Per arrestare completamente l’installazione (auditix è il nome del progetto):

Finestra del terminale
docker compose stop orchestrator
docker rm -f $(docker ps -aq --filter label=io.auditix.orchestrator.project=auditix)
docker compose down

Tutti i dati risiedono in PostgreSQL. Ne esegua il backup regolarmente, e sempre prima di un aggiornamento a mano:

Finestra del terminale
docker compose exec -T database pg_dump -U auditix -Fc auditix > auditix-$(date +%F).dump

Ripristino in un database vuoto:

Finestra del terminale
docker compose exec -T database pg_restore -U auditix -d auditix --clean --if-exists < auditix-YYYY-MM-DD.dump

Quando nessun amministratore riesce ad accedere, imposti una nuova password dal server:

Finestra del terminale
docker compose exec backend bin/console auditix:user:password admin@example.com