{ pkgs, lib, inputs, config, ... }: let admin_dbPasswordFile = lib.optionalString (lib.hasAttr "sops-nix" inputs) config.sops.secrets."software/postgres/admin_db/password".path; in { sops.secrets = { "software/postgres/admin_db/password" = { }; }; virtualisation.arion = { backend = "docker"; projects = { "db".settings.services."db".service = { restart = "unless-stopped"; build.context = "/nix/store"; build.dockerfile = builtins.baseNameOf "${pkgs.writeScript "pgDockerfile" '' FROM postgres:16 # install packages RUN apt-get update \ && apt-get install -y --no-install-recommends \ postgresql-16-postgis \ jq \ && rm -rf /var/lib/apt/lists/* ''}"; environment = { POSTGRES_PASSWORD_FILE = admin_dbPasswordFile; POSTGRES_USER = "admin"; POSTGRES_DB = "admin_db"; PGDATA = "/var/lib/postgresql/data/pgdata"; POSTGRES_MULTIPLE_DATABASES = '' [ { "osm": { "user": "gis", "extensions": [ "hstore", "postgis" ] }, "bitcoin": { "user": "satoshi", "extensions": [] }, "btc_models": { "user": "dbt", "extensions": [] }, "dev_btc_models": { "user": "dbt", "extensions": [] } "test": { "user": "test", "extensions": [hstore] } } ] ''; }; ports = [ "5432:5432" ]; volumes = [ "/mnt/postgres:/var/lib/postgresql/data" # Need to mount secret file "${admin_dbPasswordFile}:${admin_dbPasswordFile}" # PG init script to parse json specified in POSTGRES_MULTIPLE_DATABASES # creates databases, users and installs extensions for each database. "${pkgs.writeScript "init.sh" '' #!/bin/bash function create_user_and_database() { local database=$1 local user=$2 local extensions=$3 echo "### admin user: $POSTGRES_USER ###" echo " Creating database '$database'" echo " Creating user '$user'" psql -v --username "$POSTGRES_USER" -d "$POSTGRES_DB" <<-EOSQL CREATE USER $user; CREATE DATABASE $database; GRANT ALL PRIVILEGES ON DATABASE $database TO $user; EOSQL # Loop through extensions and create them for ext in $(echo "$extensions" | tr ',' ' '); do echo " - Installing extention $ext" psql -v --username "$POSTGRES_USER" -d "$database" -c "CREATE EXTENSION $ext;" done } if [ -n "$POSTGRES_MULTIPLE_DATABASES" ]; then # Parse the JSON string database_names=$(echo "$POSTGRES_MULTIPLE_DATABASES" | jq -r '.[0] | keys[]') echo "Multiple database creation requested: $(echo "$database_names" | tr "\n" " ")" # Loop through each database and create it for db_name in $database_names; do user=$(echo "$POSTGRES_MULTIPLE_DATABASES" | jq -r ".[0] | .''${db_name} | .user") extensions=$(echo "$POSTGRES_MULTIPLE_DATABASES" | jq -r ".[0] | .''${db_name} | .extensions | join(\",\")") create_user_and_database "$db_name" "$user" "$extensions" done fi ''}:/docker-entrypoint-initdb.d/init.sh" ]; }; }; }; }