コンテンツにスキップ

本番スタック

  • Docker Engine と Docker Compose プラグインを備えた Linux ホスト。
  • ユーザーがアクセスできるポート 80 と 443(.env で別のポートも設定できます)。
  • Let’s Encrypt の証明書を使う場合:ホストを指す DNS 名と、インターネットからアクセスできるポート 80 と 443。

Auditix は、Auditix レジストリ rg.fr-par.scw.cloud/auditix で 3 つのイメージ(frontend、backend、updater)として公開されており、常に同じタグでデプロイします。compose ファイルは、これらが依存するサービスを追加します。

サービス 役割
gateway 唯一公開されるサービスです。HTTP と HTTPS で Auditix を提供します。
frontend Web インターフェースです。
backend アプリケーション本体です。起動時にデータベースの変更を自動で適用します。
updater 設定 › プラットフォーム › アップデートから開始したアップデートを適用します。省略可能です。
orchestrator バックグラウンド処理を実行するワーカーコンテナーを起動・停止します。
developer 外部 API のリファレンスです(/developer)。
logs ログを設定 › プラットフォーム › ログの syslog サーバーに転送します。
rabbitmq バックグラウンド処理のキューです。
mercure インターフェースのリアルタイム更新です。
database PostgreSQL です。すべてのデータがここに保存されます。

updater サービスと orchestrator サービスは Docker にアクセスできます。ただし、操作するのは自身のインストールのコンテナー(同じフォルダーからデプロイされた compose プロジェクト)だけで、ホスト上の他のコンテナーには一切触れません。

  1. レジストリにログインします(レジストリが公開されている場合はこの手順を省略します)。レジストリの読み取りを許可された Scaleway API シークレットキーを使います。

    ターミナルウィンドウ
    docker login rg.fr-par.scw.cloud/auditix -u nologin
    # Password: your Scaleway API secret key
  2. インストール用フォルダーを作成します。

    ターミナルウィンドウ
    mkdir -p /opt/auditix && cd /opt/auditix
  3. 以下の内容で compose.yaml を作成します。

  4. root だけが読み取れる .env を作成し(chmod 600 .env)、各シークレットを openssl rand -hex 32 で一度だけ生成して設定します。

    ターミナルウィンドウ
    # "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. 起動します。

    ターミナルウィンドウ
    docker compose pull
    docker compose up -d
    docker compose ps # every service should be "healthy"
  6. 既定の管理者 admin / password で http://<host> にログインします。Auditix は何よりも先に新しいパスワードの設定を求めます。サービスを公開する前に、すぐに設定してください。

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:

インストール後の最初のステップ

Section titled “インストール後の最初のステップ”
  1. 設定 › プラットフォーム › 全般で、インスタンス名、タイムゾーン、既定の言語を設定し、外観で既定のテーマとメインカラーを設定します(設定 を参照)。
  2. ライセンス を有効化します。
  3. HTTPS を設定します。
  4. テナント と アカウント を作成します。

アカウントはコマンドラインからも作成できます(Portainer の場合は、backend コンテナーのコンソールから)。

ターミナルウィンドウ
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 で compose.yaml を貼り付けます。
  2. .env の変数をスタックの環境変数に設定し、AUDITIX_VERSION=latest とします。
  3. updater サービスから .:/install ボリュームを削除します。Portainer はスタックのファイルを独自のボリュームに保存するためです。この場合、アップデート前に取得されるバックアップは、updater が作成する <stack>_backups という名前の Docker ボリュームに保存されます。

それ以外の作業は不要です。アップデートでスタックが変更されることはなく、ワーカーはスタックの外で orchestrator サービスによって起動されます。

設定 › プラットフォーム › Web アクセスで、インスタンスのホスト名(DNS がサーバーを指している必要があります)を入力し、証明書を選択します。

  • Let’s Encrypt:無料で、発行と更新が自動で行われます。インターネットからポート 80 と 443 にアクセスできる必要があります。Let’s Encrypt(テスト) を選ぶと、ブラウザーが信頼しない証明書を使って、Let’s Encrypt の上限に達することなく、まず設定を確認できます。
  • 独自の証明書:証明書(PEM)(中間証明書を含む)と秘密鍵(PEM) を貼り付けます。秘密鍵は暗号化して保存され、二度と表示されません。
  • HTTPS なし(HTTP のみ):テスト用、または HTTPS を処理するリバースプロキシの背後で使う場合です。

続いて HTTP を HTTPS にリダイレクトをオンにし、HTTPS が動作することを確認したら 厳格な HTTPS(HSTS) をオンにします。変更は再起動なしで数秒以内に反映されます。設定を誤って HTTPS で Auditix にアクセスできなくなった場合は、サーバーから HTTPS をオフにします。

ターミナルウィンドウ
docker compose exec backend bin/console auditix:web:reset

すでに HTTPS を処理しているリバースプロキシの背後で使う場合は、HTTPS をオフのままにし、X-Forwarded-Proto ヘッダーと X-Forwarded-For ヘッダーを付けて gateway の HTTP ポートに転送します。

orchestrator サービスは、バックグラウンド処理(スケジュールされたタスク、チェック、インポートなど)を行うワーカーコンテナーを、設定 › プラットフォーム › ワーカー › プールの設定に従って起動します。コンテナー数は固定にすることも、待機中のメッセージ数に応じた自動スケーリングにすることもできます。既定のプールでは 2〜4 個のコンテナーが動作します。orchestrator がない場合でも、backend はスケジュールされたタスクを 5 分ごとに実行しますが、それ以外のバックグラウンド処理は行われません。

ワーカーコンテナーは compose プロジェクトに含まれないため、docker compose down では削除されません。インストールを完全に停止するには、次のようにします(auditix はプロジェクト名です)。

ターミナルウィンドウ
docker compose stop orchestrator
docker rm -f $(docker ps -aq --filter label=io.auditix.orchestrator.project=auditix)
docker compose down

すべてのデータは PostgreSQL に保存されています。定期的に、そして手動でアップデートする前には必ずバックアップを取ってください。

ターミナルウィンドウ
docker compose exec -T database pg_dump -U auditix -Fc auditix > auditix-$(date +%F).dump

空のデータベースに復元します。

ターミナルウィンドウ
docker compose exec -T database pg_restore -U auditix -d auditix --clean --if-exists < auditix-YYYY-MM-DD.dump

ログインできる管理者が誰もいない場合は、サーバーから新しいパスワードを設定します。

ターミナルウィンドウ
docker compose exec backend bin/console auditix:user:password admin@example.com