diff --git a/.github/workflows/container-image.yml b/.github/workflows/container-image.yml new file mode 100644 index 00000000000..18985d65b8d --- /dev/null +++ b/.github/workflows/container-image.yml @@ -0,0 +1,32 @@ +name: Container Image + +on: + push: + branches: + - master + pull_request: {} + release: + types: + - published + +concurrency: + group: container-image-${{ github.event_name == 'push' && github.sha || github.ref }} + cancel-in-progress: true + +jobs: + container-image: + # Required by the base Container Image Action [^1]. + # [^1]: https://github.com/Icinga/github-actions/blob/main/.github/workflows/container-image.yml#L54-L58 + permissions: + contents: read + packages: write + attestations: write + id-token: write + + name: Container Image + uses: icinga/github-actions/.github/workflows/container-image.yml@main + with: + documentation_url: https://icinga.com/docs/icinga2 + secrets: + dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} + dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index 575db1c68e2..00000000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Docker image - -on: - pull_request: {} - push: - branches: - - master - release: - types: - - published - -concurrency: - group: docker-${{ github.event_name == 'push' && github.sha || github.ref }} - cancel-in-progress: true - -jobs: - docker-release: - if: github.event_name == 'release' - concurrency: docker-release - runs-on: ubuntu-latest - - steps: - - name: Docker image - uses: Icinga/docker-icinga2@master - with: - dockerhub-token: '${{ secrets.DOCKER_HUB_PERSONAL_TOKEN }}' - - docker: - if: github.event_name != 'release' - runs-on: ubuntu-latest - - steps: - - name: Docker image - uses: Icinga/docker-icinga2@master - with: - dockerhub-token: '${{ secrets.DOCKER_HUB_PERSONAL_TOKEN }}' diff --git a/Containerfile b/Containerfile new file mode 100644 index 00000000000..54a427c698b --- /dev/null +++ b/Containerfile @@ -0,0 +1,227 @@ +# Icinga 2 Docker image | (c) 2025 Icinga GmbH | GPLv2+ + +FROM debian:trixie-slim AS build-base + +# Install all the necessary build dependencies for building Icinga 2 and the plugins. +# +# This stage includes the build dependencies for the plugins as well, so that they can share the same base +# image, since Docker builds common stages only once [^1] even if they are used in multiple build stages. +# This eliminates the need to have a separate base image for the plugins, that basically has kind of the +# same dependencies as the Icinga 2 build stage (ok, not exactly the same, but some of them are shared). +# +# [^1]: https://docs.docker.com/build/building/best-practices/#create-reusable-stages +RUN apt-get update && \ + apt-get upgrade -y && \ + apt-get install -y --no-install-recommends --no-install-suggests \ + autoconf \ + automake \ + bison \ + ccache \ + cmake \ + flex \ + g++ \ + git \ + libboost1.83-dev \ + libboost-context1.83-dev \ + libboost-coroutine1.83-dev \ + libboost-date-time1.83-dev \ + libboost-filesystem1.83-dev \ + libboost-iostreams1.83-dev \ + libboost-program-options1.83-dev \ + libboost-regex1.83-dev \ + libboost-system1.83-dev \ + libboost-thread1.83-dev \ + libboost-test1.83-dev \ + libedit-dev \ + libmariadb-dev \ + libpq-dev \ + libssl-dev \ + libsystemd-dev \ + make && \ + rm -rf /var/lib/apt/lists/* + +# Set the default working directory for subsequent commands of the next stages. +WORKDIR /icinga2-build + +FROM build-base AS build-plugins + +# Install all the plugins that are not included in the monitoring-plugins package. +ADD https://github.com/lausser/check_mssql_health.git#747af4c3c261790341da164b58d84db9c7fa5480 /check_mssql_health +ADD https://github.com/lausser/check_nwc_health.git#a5295475c9bbd6df9fe7432347f7c5aba16b49df /check_nwc_health +ADD https://github.com/bucardo/check_postgres.git#58de936fdfe4073413340cbd9061aa69099f1680 /check_postgres +ADD https://github.com/matteocorti/check_ssl_cert.git#341b5813108fb2367ada81e866da989ea4fb29e7 /check_ssl_cert + +WORKDIR /check_mssql_health +RUN mkdir bin && \ + autoconf && \ + autoreconf && \ + ./configure "--build=$(uname -m)-unknown-linux-gnu" --libexecdir=/usr/lib/nagios/plugins && \ + make && \ + make install DESTDIR="$(pwd)/bin" + +WORKDIR /check_nwc_health +RUN mkdir bin && \ + autoreconf && \ + ./configure "--build=$(uname -m)-unknown-linux-gnu" --libexecdir=/usr/lib/nagios/plugins && \ + make && \ + make install DESTDIR="$(pwd)/bin" + +WORKDIR /check_postgres +RUN mkdir bin && \ + perl Makefile.PL INSTALLSITESCRIPT=/usr/lib/nagios/plugins && \ + make && \ + make install DESTDIR="$(pwd)/bin" && \ + # This is necessary because of this build error: cannot copy to non-directory: /var/lib/docker/.../merged/usr/local/man + rm -rf bin/usr/local/man + +FROM build-base AS build-icinga2 + +# To access the automated build arguments in the Dockerfile originated from the Docker BuildKit [^1], +# we need to declare them here as build arguments. This is necessary because we want to use unique IDs +# for the mount cache below for each platform to avoid conflicts between multi arch builds. Otherwise, +# the build targets will invalidate the cache one another, leading to strange build errors. +# +# [^1]: https://docs.docker.com/reference/dockerfile/#automatic-platform-args-in-the-global-scope +ARG TARGETPLATFORM + +# Icinga 2 build arguments. +# +# These arguments are used to configure the build of Icinga 2 and can be overridden +# by the user when building the image. All of them have a default value suitable for our official image. +ARG CMAKE_BUILD_TYPE=ReleaseWithDebInfo +ARG ICINGA2_UNITY_BUILD=ON +ARG ICINGA2_BUILD_TESTING=ON + +# The number of jobs to run in parallel when building Icinga 2. +# By default, it is set to the number of available CPU cores on the build machine. +ARG MAKE_JOBS=auto + +# Create the directory where the final Icinga 2 files will be installed. +# +# This directory will be used as the destination for the `make install` command below and will be +# copied to the final image. Other than that, this directory will not be used for anything else. +RUN mkdir /icinga2-install + +# Mount the source code as a bind mount instead of copying it, so that we can use the cache effectively. +# Additionally, add the ccache and CMake build directories as cache mounts to speed up rebuilds. +RUN --mount=type=bind,source=.,target=/icinga2,readonly \ + --mount=type=cache,id=ccache-${TARGETPLATFORM},target=/root/.ccache \ + --mount=type=cache,id=icinga2-build-${TARGETPLATFORM},target=/icinga2-build \ + PATH="/usr/lib/ccache:$PATH" \ + cmake -S /icinga2 -B /icinga2-build \ + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \ + # Podman supports forwarding notifications from containers to systemd, so build Icinga 2 with systemd support. + -DUSE_SYSTEMD=ON \ + -DBUILD_TESTING=${ICINGA2_BUILD_TESTING} \ + -DICINGA2_UNITY_BUILD=${ICINGA2_UNITY_BUILD} \ + # The command group name below is required for the prepare-dirs script to work, as it expects + # the command group name, which by default is `icingacmd` to exist on the system. Since we + # don't create the `icingacmd` command group in this image, we need to override it with icinga. + -DICINGA2_COMMAND_GROUP=icinga \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_SYSCONFDIR=/data/etc \ + -DCMAKE_INSTALL_LOCALSTATEDIR=/data/var \ + -DICINGA2_SYSCONFIGFILE=/etc/sysconfig/icinga2 \ + -DICINGA2_RUNDIR=/run \ + -DICINGA2_WITH_COMPAT=OFF \ + -DICINGA2_WITH_LIVESTATUS=OFF && \ + make -j$([ "$MAKE_JOBS" = auto ] && nproc || echo "$MAKE_JOBS") && \ + CTEST_OUTPUT_ON_FAILURE=1 make test && \ + make install DESTDIR=/icinga2-install + +RUN rm -rf /icinga2-install/etc/icinga2/features-enabled/mainlog.conf \ + /icinga2-install/usr/share/doc/icinga2/markdown && \ + strip -g /icinga2-install/usr/lib/*/icinga2/sbin/icinga2 && \ + strip -g /icinga2-install/usr/lib/nagios/plugins/check_nscp_api + +# Prepare the final image with the necessary configuration files and runtime dependencies. +FROM debian:trixie-slim AS icinga2 + +# The real UID of the Icinga user to be used in the final image. +ARG ICINGA_USER_ID=5665 + +# Install the necessary runtime dependencies for the Icinga 2 binary and the monitoring-plugins. +RUN apt-get update && \ + apt-get upgrade -y && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests \ + bc \ + ca-certificates \ + curl \ + dumb-init \ + file \ + libboost1.83-dev \ + libboost-context1.83-dev \ + libboost-coroutine1.83-dev \ + libboost-date-time1.83-dev \ + libboost-filesystem1.83-dev \ + libboost-iostreams1.83-dev \ + libboost-program-options1.83-dev \ + libboost-regex1.83-dev \ + libboost-system1.83-dev \ + libboost-thread1.83-dev \ + libboost-test1.83-dev \ + libcap2-bin \ + libedit2 \ + libldap-common \ + libmariadb3 \ + libmoosex-role-timer-perl \ + libpq5 \ + libssl3 \ + libsystemd0 \ + mailutils \ + monitoring-plugins \ + msmtp \ + msmtp-mta \ + openssh-client \ + openssl && \ + # Official Debian images automatically run `apt-get clean` after every install, so we don't need to do it here. + rm -rf /var/lib/apt/lists/* + +# Create the icinga user and group with a specific UID as recommended by Docker best practices. +# The user has a home directory at /var/lib/icinga2, and if configured, that directory will also +# be used to store the ".msmtprc" file created by the entrypoint script. +RUN adduser \ + --system \ + --group \ + --home /var/lib/icinga2 \ + --disabled-login \ + --no-create-home \ + --uid ${ICINGA_USER_ID} icinga + +COPY --from=build-plugins /check_mssql_health/bin/ / +COPY --from=build-plugins /check_nwc_health/bin/ / +COPY --from=build-plugins /check_postgres/bin/ / +COPY --from=build-plugins /check_ssl_cert/check_ssl_cert /usr/lib/nagios/plugins/check_ssl_cert + +COPY --from=build-icinga2 /icinga2-install/ / + +# Create a corresponding symlink in the root filesystem for all Icinga 2 directories in /data. +# This is necessary because we want to maintain the compatibility with containers built with the +# legacy Dockerfile, which expects the Icinga 2 directories to be in the root directory. +RUN for dir in /etc/icinga2 /var/cache/icinga2 /var/lib/icinga2 /var/log/icinga2 /var/spool/icinga2; do \ + ln -vs "/data$dir" "$dir"; \ +done + +# The below prepare-dirs script will not fix any permissions issues for the actuall /var/lib/icinga2 or +# /etc/icinga2 directories, so we need to set the correct ownership for the /data directory recursively. +RUN chown -R icinga:icinga /data + +# Run the prepare-dirs script to create non-existing directories and set the correct permissions for them. +# It's invoked in the same way as in the systemd unit file in a Debian package, so this will ensure that +# all the necessary directories are created with the correct permissions and ownership. +RUN /usr/lib/icinga2/prepare-dirs /etc/sysconfig/icinga2 + +# Well, since the /data directory is intended to be used as a volume, we should also declare it as such. +# This will allow users to mount their own directories or even specific files to the /data directory +# without any issues. We've already filled the /data directory with the necessary configuration files, +# so users can simply mount their own files or directories if they want to override the default ones and +# they will be able to do so without any issues. +VOLUME ["/data"] + +COPY --chmod=0755 tools/container/entrypoint.sh /usr/local/bin/entrypoint.sh +ENTRYPOINT ["/usr/bin/dumb-init", "-c", "--", "/usr/local/bin/entrypoint.sh"] + +EXPOSE 5665 +USER icinga + +CMD ["icinga2", "daemon"] diff --git a/doc/02-installation.md.d/For-Container.md b/doc/02-installation.md.d/For-Container.md new file mode 100644 index 00000000000..028d4a6ee04 --- /dev/null +++ b/doc/02-installation.md.d/For-Container.md @@ -0,0 +1,184 @@ +# Installing Icinga 2 in Containers + +To be able to run Icinga 2 in a containerized environment, you'll need to set up a few things. +This guide will help you get started with running Icinga 2 in a container using our official images. + +## Prerequisites + +- A container runtime such as [Docker](https://www.docker.com) or [Podman](https://podman.io) installed on your system. +- Basic knowledge of how to use Docker or Podman commands. +- A basic understanding of Icinga 2 and its configuration. + +## Getting Started + +First, create a dedicated docker network for Icinga 2 to ensure that all containers can communicate with each other: + +``` +docker network create icinga +``` + +Next, start an Icinga 2 master container using the official Icinga 2 image. By default, all Icinga 2 containers will +listen on port `5665` from within the docker network, but you can expose this port on a different port on your host +system if needed. The following command will start an Icinga 2 master container with the necessary configurations: + +``` +docker run --detach \ + --network icinga \ + --name icinga-master \ + --hostname icinga-master \ + --publish 5665:5665 \ + --volume icinga-master:/data \ + --env ICINGA_MASTER=1 \ + icinga/icinga2 +``` + +This command will run the Icinga 2 master container in detached mode, exposing port 5665 for communication and mounting +the `/data` directory to a persistent volume named `icinga-master`. You can adjust the volume name and other parameters +as needed. You can also set additional environment variables to configure the Icinga 2 instance, +see [Environment Variables](#environment-variables) for a list of available options. + +Alternatively, if you're used to using the `icinga2 node wizard` command to set up Icinga 2 nodes, you can still run +the `icinga2 node wizard` command to set up the containers interactively. + +``` +docker run --rm -it \ + --network icinga \ + --hostname icinga-master \ + --volume icinga-master:/data \ + icinga/icinga2 icinga2 node wizard +``` + +This command will run the Icinga 2 master container in interactive mode, allowing you to answer the prompts from the +`icinga2 node wizard` command. + +Another option is to mount all the necessary configuration files from your host system into the container. +This way, you can use your existing Icinga 2 configuration files without needing any additional setup steps. +By default, the container will be populated with the default Icinga 2 configuration files, but you can override +them by creating bind mounts from your host system to the respective directories in the container. For example, to +replace the default `api-users.conf` file with your own one, you can start the Icinga 2 master container with the +following command: + +``` +docker run --detach \ + --network icinga \ + --name icinga-master \ + --hostname icinga-master \ + --publish 5665:5665 \ + --volume icinga-master:/data \ + --mount=type=bind,source=/absolute/path/to/your/api-users.conf,target=/data/etc/icinga2/conf.d/api-users.conf \ + --env ICINGA_MASTER=1 \ + icinga/icinga2 +``` + +> **Note** +> +> If you [mount an empty](https://docs.docker.com/engine/storage/bind-mounts/#mount-into-a-non-empty-directory-on-the-container) +> directory from your host into the container's `/data` directory using `--volume /path/to/empty-directory:/data`, +> all files in `/data` inside the container will be obscured. The container may not start correctly because its +> important files are no longer visible. This happens because Docker replaces the container's `/data` directory with +> your empty host directory. To avoid this, either use `--mount` to bind only specific files or subdirectories, or +> use `--volume` with a named volume (like `icinga-master:/data`) so the container's default files are preserved and +> only your specified files are replaced. + +## Adding Icinga 2 Agents + +To add Icinga 2 agents to your setup, you can run additional containers for each agent. In order your agents be able +to successfully connect to the master, they need to have a copy of the master's `ca.crt` file created during the master +setup. You can first copy this file from the master container to your host system using the following command: + +``` +docker cp icinga-master:/var/lib/icinga2/certs/ca.crt icinga-ca.crt +``` + +If you didn't use `icinga-master` as the name of your master container, replace it with the actual name you used. +For easier setup, you may want to also obtain a `ticket` from the master container, which will allow the agent to +authenticate itself without needing you to manually sign a certificate signing request (CSR). + +You can create a ticket for the agent by running the following command on your host system: + +``` +docker exec icinga-master icinga2 pki ticket --cn icinga-agent > icinga-agent.ticket +``` + +Again, replace `icinga-master` with the actual name of your master container if necessary. Additionally, you may want +to adjust the `--cn` parameter to match the hostname of your agent containers. For non-ticket based setups, the required +steps are described in the [On-Demand CSR Signing](https://icinga.com/docs/icinga-2/latest/doc/06-distributed-monitoring/#on-demand-csr-signing) +section of the Icinga 2 documentation. So, we won't cover that here. + +Now, you can start an Icinga 2 agent container using the following command: + +``` +docker run --detach \ + --network icinga \ + --name icinga-agent \ + --hostname icinga-agent \ + --volume icinga-agent:/data \ + --env ICINGA_ZONE=icinga-agent \ + --env ICINGA_ENDPOINT=icinga-master,icinga-master,5665 \ + --env ICINGA_CACERT="$(< icinga-ca.crt)" \ + --env ICINGA_TICKET="$(< icinga-agent.ticket)" \ + icinga/icinga2 +``` + +This command will run the Icinga 2 agent container in detached mode, mounting the `/data` directory to a persistent +volume named `icinga-agent`. As with the master container, you can adjust the volume name and other parameters as +needed. The environment variables will be processed by the container's entrypoint script and perform a `icinga2 node setup` +on your behalf, configuring the agent to connect to the master. + +You can repeat this step for each additional agent you want to add, ensuring that each agent has a unique hostname and +zone name. + +## Icinga 2 API + +By default, if the `icinga2 node setup` command is run when starting the container, the Icinga 2 API will be enabled, +and it will use a default API user named `root` with a randomly generated password. If you want to use your own API +users and passwords, you can bind mount your api-users file from your host system into the +`/data/etc/icinga2/conf.d/api-users.conf` in the container as described in the [Getting Started](#getting-started) +section. + +## Notifications + +By default, Icinga 2 does not send notifications when running in a containerized environment. However, it is possible +to enable mail notifications by configuring [msmtp](https://wiki.archlinux.org/title/Msmtp) client in the container. +The binary is already included in the official Icinga 2 container image, so it just needs to be configured. In order +to do this, you can either mount the `/etc/msmtprc` file from your host system into the container or provide the +necessary configuration for the `~icinga/.msmtprc` file via the `MSMTPRC` environment variable. + +## Environment Variables + +Most of the environment variables are used as parameters for the `icinga2 node setup` command. If you set any of these +variables, and the `node setup` has not been run yet, the entrypoint script will automatically run the command for you. + +The following environment variables are available: + +| Variable | Node setup CLI | +|----------------------------------------------------------|---------------------------------------------------------------| +| `ICINGA_ACCEPT_COMMANDS=1` | `--accept-commands` | +| `ICINGA_ACCEPT_CONFIG=1` | `--accept-config` | +| `ICINGA_DISABLE_CONFD=1` | `--disable-confd` | +| `ICINGA_MASTER=1` | `--master` | +| `ICINGA_CN=icinga-master` | `--cn icinga-master` | +| `ICINGA_ENDPOINT=icinga-master,2001:db8::192.0.2.9,5665` | `--endpoint icinga-master,2001:db8::192.0.2.9,5665` | +| `ICINGA_GLOBAL_ZONES=global-config,global-commands` | `--global_zones global-config --global_zones global-commands` | +| `ICINGA_LISTEN=::,5665` | `--listen ::,5665` | +| `ICINGA_PARENT_HOST=2001:db8::192.0.2.9,5665` | `--parent_host 2001:db8::192.0.2.9,5665` | +| `ICINGA_PARENT_ZONE=master` | `--parent_zone master` | +| `ICINGA_TICKET=0123456789abcdef0123456789abcdef01234567` | `--ticket 0123456789abcdef0123456789abcdef01234567` | +| `ICINGA_ZONE=master` | `--zone master` | + +Special variables: + +* `ICINGA_TRUSTEDCERT`'s value is written to a temporary file in the container, which is then used + as the `--trustedcert` parameter for the `icinga2 node setup` command. +* `ICINGA_CACERT`'s value is directly written to the `/var/lib/icinga2/certs/ca.crt` file in the container. + +## Build Your Own Image + +If you want to build your own Icinga 2 container image, you can clone the Icinga 2 repository and build the image +using the provided `Containerfile`. + +``` +git clone https://github.com/Icinga/icinga2.git +cd icinga2 +docker build --tag icinga/icinga2:test --file Containerfile . +``` diff --git a/tools/container/entrypoint.sh b/tools/container/entrypoint.sh new file mode 100755 index 00000000000..0ab2ddcd316 --- /dev/null +++ b/tools/container/entrypoint.sh @@ -0,0 +1,142 @@ +#!/bin/bash + +set -eo pipefail + +# Function to display messages with different severity levels +# Usage: icinga2_log +icinga2_log() { + local severity="$1" + local message="$2" + + local color="" + local reset="" + + # Check if we are running in a terminal that supports colors, + # otherwise fallback to plain text output. + if [ -t 2 ]; then + reset="\033[0m" + # Set color codes based on severity + case "$severity" in + "information") + color="\033[32m" # Green + ;; + "warning") + color="\033[1;33m" # Yellow bold + ;; + "critical") + color="\033[1;31m" # Red bold + ;; + esac + fi + + # Print the message with the appropriate color and reset code to stderr + echo -e "[$(date +'%Y-%m-%d %H:%M:%S %z')] ${color}${severity}${reset}/DockerEntrypoint: ${message}" >&2 +} + +# The entrypoint script expects at least one command to run. +if [ $# -eq 0 ]; then + icinga2_log "critical" "Icinga 2 Docker entrypoint script requires at least one command to run." + exit 1 +fi + +icinga2_log "information" "Icinga 2 Docker entrypoint script started." + +ca="/var/lib/icinga2/certs/ca.crt" +if [ ! -e "$ca" ]; then + nodeSetup=("node" "setup") + runNodeSetup=false + + # The following loop looks for environment variables that start with ICINGA_ and applies some transformations + # to the keys before processing them in one way or another. Their values are never modified or printed in + # unintended ways. The key transformations have the following rules and are applied in the order they are listed: + # + # - Since it only processes environment variables that start with ICINGA_, it'll first strip that prefix. + # It then passes the key through awk to convert it to lowercase e.g. ICINGA_CN becomes cn. + # - For each key, that hits one of the cases below, it will be processed a bit differently. In the first match, + # the environment variable is expected to be a boolean (1 or 0) and it only becomes part of the node setup + # command if and only if its value is 1. In that case, underscores in the key are replaced with dashes and + # passed as-is to the node setup command (e.g., ICINGA_ACCEPT_COMMANDS=1 becomes --accept-commands). + # - The second case matches exclusively on the "global_zones" key. The value of this environment variable + # is expected to be one or comma-separated list of zones. If the value is not empty, it will be split by + # commas and each zone will be passed as a separate argument to the node setup command + # (e.g., ICINGA_GLOBAL_ZONES=icinga,example becomes --global_zones icinga --global_zones example). + # - For the third match, the key is expected to be a key-value pair that should be passed to the node setup + # command. In this case, key and value pairs are passed as-is to the node setup command (e.g., + # ICINGA_CN=icinga.example.com becomes --cn icinga.example.com). + # - For the fourth match, the trusted certificate is expected to be a PEM-encoded certificate that should be + # written to a temporary file and passed to the node setup command. + # - Lastly, the CA certificate is likewise expected to be a PEM-encoded certificate that should be written to + # the expected location at /var/lib/icinga2/certs/ca.crt. + # + # When encountering an environment variable prefixed with ICINGA_ that we don't know how to handle, we log it + # as an informational message and continue processing the next environment variable but it doesn't cause the + # script to fail. + for k in "${!ICINGA_@}"; do + # Strip the ICINGA_ prefix and convert the key to lowercase. + key=$(echo "${k#ICINGA_}" | awk '{print tolower($0)}') + # Get the value of the environment variable. + value="${!k}" + + case "$key" in + "accept_commands" | "accept_config" | "disable_confd" | "master") + runNodeSetup=true + if [ "$value" = "1" ]; then + nodeSetup+=("--${key//_/-}") + fi + ;; + "global_zones") + runNodeSetup=true + # Split the value by commas and pass each part as a separate argument. + IFS=',' read -ra zones <<< "$value" + for zone in "${zones[@]}"; do + nodeSetup+=("--global_zones" "$zone") + done + ;; + "cn" | "endpoint" | "listen" | "parent_host" | "parent_zone" | "zone" | "ticket") + runNodeSetup=true + nodeSetup+=("--$key" "$value") + ;; + "trustedcert") + icinga2_log "information" "Writing trusted certificate to temporary file." + runNodeSetup=true + trustedCertFile=$(mktemp /tmp/trusted.cert.XXXXXXXX) + printf "%s" "$value" > "$trustedCertFile" + nodeSetup+=("--$key" "$trustedCertFile") + chmod 0644 "$trustedCertFile" + ;; + "cacert") + icinga2_log "information" "Writing CA certificate to $ca." + runNodeSetup=true + printf "%s" "$value" > "$ca" + chmod 0644 "$ca" + ;; + *) + # We don't know how to handle this environment variable, so log it and move on. + icinga2_log "warning" "Ignoring unknown environment variable $k" + ;; + esac + done + + if [ "$runNodeSetup" = true ]; then + icinga2_log "information" "Running Icinga 2 node setup command..." + + icinga2 "${nodeSetup[@]}" + # If the node setup command wasn't successful, we shouldn't reach this point due to set -e. + icinga2_log "information" "Node setup completed successfully." + else + icinga2_log "information" "No node setup required based on environment variables." + fi +fi + +msmtprc_path="/var/lib/icinga2/.msmtprc" +# This script should initialize the container's msmtp configuration but never overwrite an existing configuration file. +# If the file already exists, it should not be modified, even if the MSMTPRC environment variable is set. +if [ ! -e "$msmtprc_path" ] && [ -n "${MSMTPRC}" ]; then + icinga2_log "information" "Configuring msmtp with the provided MSMTPRC environment variable." + printf "%s" "$MSMTPRC" > "$msmtprc_path" + chmod 0644 "$msmtprc_path" +fi + +icinga2_log "information" "Starting Icinga 2 daemon." + +exec "$@"