- docker
- docker compose >= 2.20 (HTTPS mode uses the
!overrideYAML tag andservice_completed_successfully)
Run following command from repository root directory:
docker compose -f .github/docker/docker-compose.yml up -d --waitCentreon web should be accessible at http://localhost:4000/centreon
The stack runs in HTTP mode by default. HTTPS mode is opt-in via the docker-compose.tls.yml overlay — production-faithful, using the official Centreon HTTPS Apache vhost (packaging/src/centreon-apache-https.conf) that customer deployments run.
# HTTP (default)
docker compose -f .github/docker/docker-compose.yml up -d --wait
# → http://localhost:4000/centreon
# HTTPS
docker compose \
-f .github/docker/docker-compose.yml \
-f .github/docker/docker-compose.tls.yml \
up -d --wait
# → https://localhost:4443/centreon (cert is self-signed)In HTTPS mode, both :80 and :443 are mapped. :80 runs the production :80 → :443 redirect block; :443 serves the API/UI. This mirrors the production deployment shape where a user typing http://centreon.example.com/ is redirected to https://.
| Service | HTTP mode | HTTPS mode |
|---|---|---|
web |
4000:80 |
4000:80 + 4443:443 |
remote-server |
4001:80 |
4001:80 + 4444:443 |
Following the redirect from the host fails because the production template's redirect target preserves the request port (%{HTTP_HOST} → localhost:4000, which is HTTP-only on the host side) — this is the upstream template's behavior. To validate:
- Redirect emission:
curl -I http://localhost:4000/centreon/returns302 Foundwith the expectedLocation: https://localhost:4000/centreon/. - Full chain at production-default ports (inside the container):
docker compose exec -T web curl -kL http://localhost/centreon/api/latest/platform/versionsfollows:80 → :443 → 200.
The overlay adds:
certgenone-shot — issues a Root CA + multi-SAN leaf cert into thecertsnamed volume on firstup(coveringweb,remote-server,db,db-remote,localhost,127.0.0.1). CA persists acrossupcycles;docker compose down -vwipes it.web/remote-server— install the CA into the OS trust store, drop the official Apache HTTPS vhost (same cipher list, HSTS,X-Frame-Options, cookie hardening, FCGI tophp-fpm:9042,:80 → :443redirect as production — only cert paths differ), write/usr/share/centreon/.envwithDATABASE_SSL_*keys for the PHP-sideDatabaseTLSResolver, and patch the gorgone DB DSN withmysql_ssl=1;mysql_ssl_ca_file=…;mysql_ssl_verify_server_cert=1(RHEL images only, see the trixie note below).db/db-remote— offer TLS via--ssl-cert/--ssl-keybut do not enforce it (no--require-secure-transport=ON). Clients that opt in (PHP viaDatabaseTLSResolver, themysqlCLI via the[client]drop-in) negotiate TLS; the install wizard's legacy plaintext path keeps working. See Known limitations for the rationale and how the smoke workflow guards against silent regression to all-plaintext.- Centreon Broker — the install-time
db_ssl_*JSON keys (existing Centreon support) are emitted automatically whenDATABASE_SSL_ENABLED=1is in.env.
# Copy the CA out of the running stack
docker compose -f .github/docker/docker-compose.yml -f .github/docker/docker-compose.tls.yml \
cp web:/etc/pki/centreon-tls/rootCA.pem /tmp/centreon-dev-ca.pem
# Verified curl (no -k)
curl --cacert /tmp/centreon-dev-ca.pem https://localhost:4443/centreon/api/latest/platform/versions
# OS trust store (Linux example)
sudo cp /tmp/centreon-dev-ca.pem /usr/local/share/ca-certificates/centreon-dev-ca.crt
sudo update-ca-certificatesNote
HTTPS mode needs DatabaseTLSResolver in the WEB_IMAGE. This class is part of centreon-web since the 26.07 develop/unstable line (added by #9237). If you point WEB_IMAGE at an older build, the 04-tls.sh entrypoint hook fails fast with a copy-pasteable error so the misconfig is loud rather than silent.
Note
DB TLS is offered, not enforced (no --require-secure-transport=ON). The Centreon install wizard (legacy PHP path) connects to the DB before Symfony Dotenv has populated $_ENV, so DatabaseTLSResolver reads no DATABASE_SSL_* keys and PDO falls back to plaintext. Enforcing secure transport server-side rejects those wizard connections with a misleading "Access denied (using password: YES)" on MariaDB 10.x and the install fails before creating the schema. The pattern mirrors centreon/centreon#10620's configure_db_tls() in unattended.sh. To prove TLS is still being used in practice, the smoke workflow asserts that the DB's Ssl_accepts global status counter is > 0 after install — a silent regression to all-plaintext fails the smoke. Upstream follow-up: have DatabaseTLSResolver fall back to getenv() (or set variables_order = "EGPCS" in php-cli.ini) so the install wizard's CLI bootstrap reaches the resolver.
Note
Side-by-side HTTP + HTTPS stacks from the same checkout is a planned future feature. Today, two up invocations from the same directory collide on container/volume names regardless of port mapping. Pick one mode per checkout. (Port 4443 was chosen with the future side-by-side mode in mind.)
Note
Gorgone DB-TLS on Debian images (centreon-web-trixie) is currently impacted by a DBD::mysql 4.053 + libmariadb 3.x API mismatch — the old MYSQL_OPT_SSL_ENFORCE option was removed without a DBD::mysql-compatible replacement. Web (PHP via PR #9237), Broker, and DB-side TLS are unaffected on this image; only the gorgone Perl→DB path is impacted. On trixie the 16-tls-gorgone.sh hook is therefore a no-op and gorgone connects to the DB in plaintext (the DB does not enforce TLS). Follow-up: gorgone support for DBD::MariaDB, which has been validated as a working alternative.
Note
DB image compatibility — HTTPS mode has been validated against the following combinations, all passing end-to-end (web container (healthy), API returns 200, all hardening headers present):
Two operational notes that matter for the MySQL family in particular:
ulimits: nofile: 32000is set on thedbservice in the base compose. Without it, Centreon's install on bitnami MySQL images runs out of file descriptors mid-install (the PHP install scripts + dump loading open many concurrent connections + tables) and leaves the install half-complete withUnknown database 'centreon'errors. MariaDB images don't hit this limit.- MySQL 8.4 servers log a
[Warning] [MY-015011] Failed to validate certificateat startup because the docker-compose stack does not pass--ssl-cato mysqld (deliberately omitted — it was previously included but caused MySQL to embed the Root CA in its presented chain, which strict OpenSSL clients on alma9 rejected withself-signed certificate in certificate chain). The warning is informational; TLS continues to work normally.
The certgen image is built locally from .github/docker/certgen/ (alpine + openssl, same shape as centreon-images/.../gen_cert.sh minus the Apache / platform concerns). Override with CERTGEN_IMAGE=… to pin a published image.
By default, MariaDB 11.8 is used to store Centreon data (configuration & monitoring).
This can be overridden with the MYSQL_IMAGE environment variable using one of the following ways:
- Preferred: Export environment variable directly in your terminal (ex:
export MYSQL_IMAGE=bitnami/mysql:8.1) - Alternative: Add a new line to environment file
.github/docker/.envwith MYSQL_IMAGE value (ex:MYSQL_IMAGE=bitnami/mysql:8.1)
Warning
export command is not available on windows, You may need to use a tool like cross-env or directly configure windows environment variables
By default, the Centreon web image targets the develop branch and is installed on almalinux 9.
This can be overridden with the WEB_IMAGE environment variable using one of the following ways:
- Preferred: Export the environment variable directly in your terminal (ex:
export WEB_IMAGE=docker.centreon.com/centreon/centreon-web-alma9:MON-XXX) - Alternative: Add a new line to the environment file
.github/docker/.envwith WEB_IMAGE value (ex:docker.centreon.com/centreon/centreon-web-alma9:MON-XXX)
Note
To get an image of centreon-web on other operating system, web workflow needs to be run on a pull request which has label system
Then, following image can be used: export WEB_IMAGE=docker.centreon.com/centreon/centreon-web-bookworm:MON-XXX
centreon-web image accepts the following environment variables:
CENTREON_DATASET:0: centreon configuration is empty1(default value): inject minimal dataset (commands, hosts, services)
CENTREON_LANG: set language to admin useren_US(default value)fr_FRde_DEes_ESpt_BRpt_PT
Usage:
CENTREON_DATASET=0 CENTREON_LANG=fr_FR docker compose -f .github/docker/docker-compose.yml up -d --waitDocker compose has a useful feature which is called profile.
It allows to run additional services (containers) by specifying profiles which are declared in docker-compose.yml.
Currently, the following profiles are available:
poller: register automatically a poller to centreon web image (:danger: EXPERIMENTAL)poller-container: create a poller via the API and install it with the realcentreon/install-pollerDocker flow, fully automated (see Poller container setup)remote-server: run a Remote Server alongside the Central, each with its own database — registers automatically (see Remote Server setup)glpi: must be used withcentreon-open-ticketsimage to link glpi automatically in open-tickets providersvault: run a hashicorp vault (dev mode) and migrate credentials automatically (see Vault setup)openid: run a docker image of keycloak- Add the following entry to your /etc/hosts :
127.0.0.1 sso-proxy ⚠️ On Windows: C:\Windows\System32\drivers\etc\hosts- centreon configuration is done automatically with auto import enabled
- login user: oidc / Centreon!2021
⚠️ ACLs must be configured manually⚠️ if you use WSL, your browser must run from WSL. Otherwise, you will not have access to openid container ip address.
- Add the following entry to your /etc/hosts :
saml: run a docker image of keycloak- centreon configuration is done automatically with auto import enabled
- login user: saml / Centreon!2021
⚠️ ACLs must be configured manually
ldap: run a docker image of ldap- centreon configuration is done automatically with auto import enabled
- login user: centreon-ldap / centreon-ldap (admin bind:
cn=admin,dc=centreon,dc=com/ centreon) ⚠️ ACLs must be configured manually
squid-simple: run a docker image of squid without authentication (centreon configuration must be done manually)squid-basic-auth: run a docker image of squid with authentication (centreon configuration must be done manually)mediawiki: run a docker image of mediawiki (centreon configuration must be done manually)graphite: run a Graphite (graphite-statsd) receiver and auto-configure a Centreon Broker Graphite output pointing to it — for testing the Broker output cache- the Broker output is configured automatically on startup, with macro-enriched naming
centreon.metric.$INSTANCE$.$HOST$.$SERVICE$.$SERV_TAG_CAT_NAME$.$METRIC$ - Verify ingestion (from the web container, using the service hostname):
docker compose exec web curl -s "http://graphite/render?target=centreon.metric.**&format=json"— after a force check, the cache-resolved host/service names must appear in the received metric paths
- the Broker output is configured automatically on startup, with macro-enriched naming
influxdb: run an InfluxDB 1.8 receiver and auto-configure a Centreon Broker InfluxDB output pointing to it (same purpose asgraphite)- Verify ingestion:
docker compose exec web curl -s -G "http://influxdb:8086/query" --data-urlencode "db=centreon" --data-urlencode "q=SHOW MEASUREMENTS" - the two profiles are independent — enable
graphite,influxdb, or both
- Verify ingestion:
Note
docker image for poller service (centreon-poller-alma9) is built on centreon-collect repository
Multiple profiles can be specified in a single command:
docker compose --profile poller --profile vault -f .github/docker/docker-compose.yml up -d --wait4 containers will be instantiated:
- centreon-web: central server with apache, php-fpm, gorgoned, centreon-engine, centreon-broker
- database: MariaDB by default
- centreon-poller: poller with gorgoned, centreon-engine (with cbmod)
- hashicorp vault
Note
Running containers can be listed with the following command: docker ps
Container terminal can be launched with the following command: docker exec -ti <container_id> bash
Container logs can be displayed with the following command: docker logs <container_id>
Use the remote-server profile to run a Central server alongside a Remote Server, each with its own database.
Run the following command from the repository root directory:
docker compose --profile remote-server -f .github/docker/docker-compose.yml up -d --waitOnce up, both interfaces are accessible:
- Central:
http://localhost:4000/centreon - Remote Server:
http://localhost:4001/centreon - Credentials: admin / Centreon!2021
The Remote Server is fully configured automatically in the background after the containers become healthy. The following steps run without manual intervention:
- Convert the Remote Server node type and register its topology to the Central (
registerServerTopology.sh) - Link the Remote Server to the Central via the wizard API (
linkCentreonRemoteServer), which creates the monitoring server entry and configures Broker - Export the initial configuration from the Central to the Remote Server
- Retrieve the Central's Gorgone public key thumbprint
- Generate the Gorgone ZMQ configuration on the Remote Server (
/etc/centreon-gorgone/config.d/40-gorgoned.yaml) - Restart Gorgone on the Remote Server to establish the ZMQ connection with the Central
- Generate and reload the monitoring configuration for the Remote Server from the Central
- Restart
cbdandcentengineon the Remote Server to apply the generated configuration - Generate and reload the monitoring configuration for the Central to apply the Broker changes introduced by the wizard
The Remote Server should appear as running in Configuration > Pollers on the Central within a minute of --wait returning.
To follow the registration progress:
docker logs $(docker ps -qf "name=remote-server") 2>&1 | grep -i "step\|register\|link\|thumbprint\|gorgone\|generat\|running\|error\|failed"The following environment variables are available to customize the setup:
WEB_IMAGE: centreon-web image to use for both Central and Remote Server (default:docker.centreon.com/centreon/centreon-web-alma9:develop)CENTREON_WEB_OS: OS variant used to resolve entrypoint-script bind-mount paths; must matchWEB_IMAGE's OS (alma9,alma10,trixie— default:alma9)REMOTE_SERVER_NAME: name displayed for the Remote Server in the Central UI (default:remote-server)CENTRAL_API_USERNAME: API account used for registration (default:admin)CENTRAL_API_PASSWORD: password for the API account (default:Centreon!2021)
Use the poller-container profile to test a Docker poller installed via centreon/install-poller's real --type docker flow, without any manual UI click-through or config editing.
Run the following command from the repository root directory:
docker compose --profile poller-container -f .github/docker/docker-compose.yml up -d --waitThis runs a one-shot orchestrator container that:
- Logs in to the Central API and creates a poller-type API token
- Creates the poller via
POST /configuration/pollerswithcentral_address: web, so the generated install command already targets thewebservice by name — nohost.docker.internal/localhostjuggling needed - Runs the real
install.sh --type dockerwith--no-start, attaches the generated poller stack to a sharedcentreon-poller-testDocker network, then starts it - Waits (up to 15 minutes) for the poller's first successful ping, checked via Gorgone's own local API on the Central (
http://web:8085/api/internal/constatus, already enabled by default — polling.data["<poller id>"].ping_ok) rather than the poller's logs or raw TCP state: the poller's own Gorgone only loads theengine+pullwssmodules (notproxy), so it cannot report its own connection status — only the Central can. Then callsconfiguration/monitoring-servers/{id}/generate-and-reloadto export the poller's monitoring configuration - Restarts
centengineon the poller withdocker compose exec gorgone sudo systemctl restart centengine—generate-and-reloadonly exports the configuration, it does not restart the engine; on this split-container poller, centengine and gorgone are separate containers, so the restart goes through gorgone's systemctl shim, which relays it to the centengine container over gRPC (Gorgone doesn't run as root, hencesudo)
Follow the sequence in the logs:
docker compose -f .github/docker/docker-compose.yml logs poller-containerNote
The generated install command is never logged — it embeds --poller_token, --appsecret and --salt, so printing it would leak those secrets into Docker logs.
The poller should appear as running in Configuration > Pollers on the Central once the orchestrator logs "Done" (Gorgone also auto-restarts in the background as soon as it detects the new poller — no manual gorgoned restart needed).
The following environment variables are available to customize the setup:
POLLER_NAME: name of the created poller (default:poller-container) — use a different value to create several pollers side by side, or after a previous one was torn downCENTRAL_API_USERNAME/CENTRAL_API_PASSWORD: API account used for registration (default:admin/Centreon!2021)
To tear down, two separate Compose projects are involved and must both be torn down:
- The poller stack itself (
centengine/gorgone), generated and started by the orchestrator via the mounted Docker socket — this is its own Compose project, named afterPOLLER_NAME(poller-containerby default), entirely separate from this repo'sdocker-compose.yml. Tear it down by project name (works even without the generated file on hand, purely from the containers'/volumes' Compose labels):(replacedocker compose -p poller-container down -v
poller-containerwith whateverPOLLER_NAMEyou used) - Then the orchestrator's own project:
docker compose --profile poller-container -f .github/docker/docker-compose.yml down -v
Doing only step 2 leaves the poller's centengine/gorgone containers running and still attached to centreon-poller-test, which then fails to be removed with a Resource is still in use warning — always run step 1 first (or anytime after) to fully clean up.
Note
This profile mounts the host's Docker socket (/var/run/docker.sock) into the orchestrator container so it can start the poller's own centengine/gorgone containers as siblings — local dev/test only, never enabled by default or in CI.
The vault profile runs a HashiCorp Vault (dev mode) and migrates Centreon credentials into it automatically. All the VAULT_* values referenced below are test credentials already set in the committed .env, so there is nothing to fill in.
- The
webandvaultservices must be started together, otherwise the auto-configuration does not trigger. - Vault UI available at
https://127.0.0.1:8200/ui(self-signed HTTPS, accept the browser warning). - Log in with method Token, using the root token from
VAULT_DEV_ROOT_TOKEN_IDin.env. - Centreon authenticates via AppRole (policy
central, secrets stored undercentreon/) withVAULT_ROLE_ID/VAULT_SECRET_IDfrom.env. The UI has no AppRole login, so to sign in as this identity, exchange them for a token and paste it in the Token field:
# load VAULT_ROLE_ID / VAULT_SECRET_ID from the committed .env into the shell
set -a; . .github/docker/.env; set +a
# exchange them for a Vault token (-k trusts the self-signed cert), print only the token
curl -sk -X POST --data "{\"role_id\":\"$VAULT_ROLE_ID\",\"secret_id\":\"$VAULT_SECRET_ID\"}" \
https://127.0.0.1:8200/v1/auth/approle/login | jq -r .auth.client_tokenServices can be stopped with the following command:
docker compose -f .github/docker/docker-compose.yml downDo not forget to specify profiles if you used them. Otherwise, additional services will not be stopped:
docker compose --profile poller --profile vault -f .github/docker/docker-compose.yml down
docker compose --profile remote-server -f .github/docker/docker-compose.yml down
docker compose -p poller-container down -v # tear down the poller stack first — see "Poller container setup"
docker compose --profile poller-container -f .github/docker/docker-compose.yml down -v