- port registry: atrocore = 3058 - oci-container atrocore: Gitea-registry image, 127.0.0.1:3058:80, web network, static ip 10.89.0.16, db alias to host pg, env-file from agenix, named volume for instance data, registry login via token secret - agenix secrets: atrocore-env (ATRO_DB_*) + atrocore-registry-token, age-encrypted to AZ-PRM-1 + user, non-interactive creation - host postgres 17: idempotent atrocore-db-init oneshot (psql peer, secret only at runtime), pg_hba 10.89.0.0/24 scram-sha-256, atrocore in 03:10 backup list - traefik: pim.l.az-gruppe.com -> localhost:3058 (ionos, websecure)
88 lines
3.5 KiB
Nix
88 lines
3.5 KiB
Nix
{config, ...}: let
|
|
serviceName = "atrocore";
|
|
servicePort = config.m3ta.ports.get serviceName;
|
|
instanceDir = "/var/www/pim.l.az-gruppe.com";
|
|
in {
|
|
virtualisation.oci-containers.containers."${serviceName}" = {
|
|
# Secret-free image from the AZ-NIX-ava.1 pipeline (Gitea registry).
|
|
image = "git.az-gruppe.com/az-intec-gmbh/atrocore-web:latest";
|
|
# DB host is the alias for the host PostgreSQL on the podman web network;
|
|
# ATRO_DB_NAME/ATRO_DB_USER/ATRO_DB_PASSWORD come from the agenix secret
|
|
# (podman env-file) and are written to data/config.php by the entrypoint.
|
|
environment = {
|
|
ATRO_DB_HOST = "db";
|
|
ATRO_INSTANCE_DIR = "pim.l.az-gruppe.com";
|
|
};
|
|
environmentFiles = [config.age.secrets.atrocore-env.path];
|
|
# Registry pull credentials for the Gitea package registry (token from
|
|
# agenix secret, so nothing lands in the Nix store).
|
|
login = {
|
|
registry = "git.az-gruppe.com";
|
|
username = "sascha.koenig";
|
|
passwordFile = config.age.secrets.atrocore-registry-token.path;
|
|
};
|
|
ports = ["127.0.0.1:${toString servicePort}:80"];
|
|
volumes = [
|
|
"atrocore_data:${instanceDir}/data"
|
|
];
|
|
extraOptions = ["--network=web" "--ip=10.89.0.16" "--add-host=db:10.89.0.1"];
|
|
};
|
|
|
|
# Idempotent provisioning of the atrocore role/database on the host
|
|
# PostgreSQL 17. initialScript cannot be used here (cluster is already
|
|
# initialized and the password must never land in the Nix store), so the
|
|
# secret is read at runtime and applied via psql peer auth.
|
|
systemd.services.atrocore-db-init = {
|
|
description = "Provision atrocore role/database from agenix secret";
|
|
after = ["postgresql.service"];
|
|
before = ["podman-${serviceName}.service"];
|
|
wants = ["postgresql.service"];
|
|
wantedBy = ["multi-user.target"];
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
User = "postgres";
|
|
Group = "postgres";
|
|
RemainAfterExit = true;
|
|
};
|
|
path = [config.services.postgresql.package];
|
|
# Env-file format: plain KEY=value lines (no quotes), same file the
|
|
# container consumes.
|
|
script = ''
|
|
set -euo pipefail
|
|
ENV_FILE="${config.age.secrets.atrocore-env.path}"
|
|
get_val() {
|
|
grep -m1 "^$1=" "$ENV_FILE" | head -n1 | cut -d= -f2- | tr -d '\r'
|
|
}
|
|
db_name="$(get_val ATRO_DB_NAME)"
|
|
db_user="$(get_val ATRO_DB_USER)"
|
|
db_pass="$(get_val ATRO_DB_PASSWORD)"
|
|
if [ -z "$db_name" ] || [ -z "$db_user" ] || [ -z "$db_pass" ]; then
|
|
echo "atrocore-db-init: ATRO_DB_NAME/ATRO_DB_USER/ATRO_DB_PASSWORD missing in $ENV_FILE" >&2
|
|
exit 1
|
|
fi
|
|
psql -v ON_ERROR_STOP=1 -d postgres \
|
|
-v db_name="$db_name" -v db_user="$db_user" -v db_pass="$db_pass" <<'SQL'
|
|
SELECT format('CREATE ROLE %I LOGIN', :'db_user')
|
|
WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = :'db_user') \gexec
|
|
ALTER ROLE :"db_user" WITH LOGIN PASSWORD :'db_pass';
|
|
SELECT format('CREATE DATABASE %I OWNER %I', :'db_name', :'db_user')
|
|
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = :'db_name') \gexec
|
|
ALTER DATABASE :"db_name" OWNER TO :"db_user";
|
|
SQL
|
|
echo "atrocore-db-init: role/database '$db_name' ready"
|
|
'';
|
|
};
|
|
|
|
# Traefik configuration specific to atrocore (AtroPIM)
|
|
services.traefik.dynamicConfigOptions.http = {
|
|
services.${serviceName}.loadBalancer.servers = [{url = "http://localhost:${toString servicePort}/";}];
|
|
|
|
routers.${serviceName} = {
|
|
rule = "Host(`pim.l.az-gruppe.com`)";
|
|
tls = {certResolver = "ionos";};
|
|
service = serviceName;
|
|
entrypoints = "websecure";
|
|
};
|
|
};
|
|
}
|