Pular para o conteúdo

Stack de produção

  • Um anfitrião Linux com o Docker Engine e o plugin Docker Compose.
  • As portas 80 e 443 acessíveis aos seus usuários (ou qualquer outra porta, definida em .env).
  • Para certificados Let’s Encrypt: um nome DNS que aponte para o anfitrião, e as portas 80 e 443 acessíveis a partir da Internet.

O Auditix é publicado como três imagens (frontend, backend, updater) no registo Auditix, rg.fr-par.scw.cloud/auditix, sempre implementadas com a mesma tag. O ficheiro compose acrescenta os serviços de que dependem:

Serviço Função
gateway O único serviço publicado: serve o Auditix em HTTP e HTTPS.
frontend A interface web.
backend A aplicação. Aplica ela própria as alterações à base de dados quando arranca.
updater Aplica as atualizações iniciadas a partir de Configurações › Plataforma › Atualização. Opcional.
orchestrator Inicia e para os contentores dos workers que executam o trabalho em segundo plano.
developer A referência da API externa, em /developer.
logs Encaminha os registos para os servidores syslog de Configurações › Plataforma › Registos.
rabbitmq Filas do trabalho em segundo plano.
mercure Atualizações da interface em tempo real.
database PostgreSQL: todos os dados estão aqui.

Os serviços updater e orchestrator têm acesso ao Docker. Só atuam sobre os contentores da sua própria instalação (o projeto compose implementado a partir da mesma pasta), nunca sobre outros contentores do anfitrião.

  1. Inicie sessão no registo (ignore este passo se o registo for público), com uma chave secreta de API Scaleway autorizada a ler o registo:

    Janela do terminal
    docker login rg.fr-par.scw.cloud/auditix -u nologin
    # Password: your Scaleway API secret key
  2. Crie a pasta de instalação:

    Janela do terminal
    mkdir -p /opt/auditix && cd /opt/auditix
  3. Crie compose.yaml com o conteúdo abaixo.

  4. Crie .env, legível apenas pelo root (chmod 600 .env), e preencha cada segredo uma única vez com openssl rand -hex 32:

    Janela do 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:

    Janela do terminal
    docker compose pull
    docker compose up -d
    docker compose ps # every service should be "healthy"
  6. Inicie sessão em http://<host> com o administrador predefinido, admin / password. O Auditix pede uma nova senha antes de mais nada: faça-o imediatamente, antes de expor o serviço.

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. Em Configurações › Plataforma › Geral, defina o Nome da instância, o Fuso horário, o Idioma predefinido e, em Aparência, o Tema predefinido e a Cor principal (consulte Configurações).
  2. Ative a licença.
  3. Configure o HTTPS.
  4. Crie os tenants e as contas.

As contas também podem ser criadas a partir da linha de comandos (com o Portainer, a partir da consola do contentor backend):

Janela do 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: cole o compose.yaml.
  2. Coloque as variáveis do .env nas variáveis de ambiente da stack, com AUDITIX_VERSION=latest.
  3. No serviço updater, remova o volume .:/install: o Portainer guarda os ficheiros de uma stack no seu próprio volume. As cópias de segurança feitas antes das atualizações vão então para um volume Docker chamado <stack>_backups, criado pelo updater.

Não é necessário mais nada: as atualizações nunca alteram a stack, e os workers são iniciados pelo serviço orchestrator, fora da stack.

Em Configurações › Plataforma › Acesso web, indique o Nome de anfitrião da instância (o seu DNS tem de apontar para o servidor) e, em seguida, escolha o Certificado:

  • Let’s Encrypt: gratuito, emitido e renovado automaticamente. As portas 80 e 443 têm de estar acessíveis a partir da Internet. Let’s Encrypt (teste) verifica primeiro a configuração, com certificados em que os navegadores não confiam, sem atingir os limites do Let’s Encrypt.
  • O meu próprio certificado: cole o Certificado (PEM) (com os seus certificados intermédios) e a Chave privada (PEM). A chave é guardada cifrada e nunca mais é mostrada.
  • Sem HTTPS (só HTTP): para um teste, ou atrás de um proxy inverso que trata do HTTPS.

Ative depois Redirecionar HTTP para HTTPS e, quando o HTTPS funcionar, HTTPS estrito (HSTS). As alterações aplicam-se em poucos segundos, sem reinício. Se uma configuração errada tornar o Auditix inacessível em HTTPS, desative o HTTPS a partir do servidor:

Janela do terminal
docker compose exec backend bin/console auditix:web:reset

Atrás de um proxy inverso que já trata do HTTPS, deixe o HTTPS desativado e encaminhe para a porta HTTP do gateway com os cabeçalhos X-Forwarded-Proto e X-Forwarded-For.

O serviço orchestrator inicia os contentores dos workers que fazem o trabalho em segundo plano (tarefas agendadas, verificações, importações…), conforme definido em Configurações › Plataforma › Workers › Pools: um número fixo de contentores, ou um dimensionamento Automático segundo o número de mensagens em espera. O pool predefinido executa de 2 a 4 contentores. Sem o orchestrator, o backend continua a executar as tarefas agendadas a cada cinco minutos, mas nada mais é processado em segundo plano.

Os contentores dos workers não fazem parte do projeto compose, por isso docker compose down não os remove. Para desmontar completamente a instalação (sendo auditix o nome do projeto):

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

Todos os dados estão no PostgreSQL. Faça cópias de segurança regularmente, e sempre antes de uma atualização manual:

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

Restaurar numa base de dados vazia:

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

Quando nenhum administrador consegue iniciar sessão, defina uma nova senha a partir do servidor:

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