From a7c8b86b1f6fbc094ee0a6db1a606ec1aae8b496 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 6 Jul 2024 20:53:26 +0100 Subject: [PATCH] Postgres docker configuration --- hosts/common/optional/docker/postgres.nix | 116 ++++++++++++++-------- 1 file changed, 75 insertions(+), 41 deletions(-) diff --git a/hosts/common/optional/docker/postgres.nix b/hosts/common/optional/docker/postgres.nix index c5d7c3e..f698c4d 100644 --- a/hosts/common/optional/docker/postgres.nix +++ b/hosts/common/optional/docker/postgres.nix @@ -1,6 +1,72 @@ { pkgs, lib, inputs, config, ... }: let admin_dbPasswordFile = lib.optionalString (lib.hasAttr "sops-nix" inputs) config.sops.secrets."software/postgres/admin_db/password".path; + initScript = pkgs.writeText "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 + ''; + + pg_hbaConfig = pkgs.writeText "pg_hba.conf" '' + none + ''; + + pgsqlConfig = pkgs.writeText "postgresql.conf" '' + listen_addresses = '*' + port = 5432 + max_connections = 100 + shared_buffers = 24GB + work_mem = 1GB + maintenance_work_mem = 10GB + autovacuum_work_mem = 2GB + dynamic_shared_memory_type = posix + wal_level = minimal + checkpoint_timeout = 60min + checkpoint_completion_target = 0.9 + max_wal_size = 10GB + min_wal_size = 80MB + max_wal_senders = 0 + random_page_cost = 1.0 + effective_cache_size = 25GB + jit = off + log_line_prefix = '%m [%p] %q%u@%d ' + log_timezone = 'Etc/UTC' + cluster_name = 'postgres-docker' + datestyle = 'iso, dmy' + timezone = 'Etc/UTC' + default_text_search_config = 'pg_catalog.english' + ''; in { sops.secrets = { @@ -12,7 +78,7 @@ in "db".settings.services."db".service = { restart = "unless-stopped"; build.context = "/nix/store"; - build.dockerfile = builtins.baseNameOf "${pkgs.writeScript "pgDockerfile" '' + build.dockerfile = builtins.baseNameOf "${pkgs.writeText "pgDockerfile" '' FROM postgres:16 # install packages RUN apt-get update \ @@ -21,6 +87,7 @@ in jq \ && rm -rf /var/lib/apt/lists/* ''}"; + command = [ "postgres" "-c" "config_file=/etc/postgresql/postgresql.conf" ]; environment = { POSTGRES_PASSWORD_FILE = admin_dbPasswordFile; POSTGRES_USER = "admin"; @@ -48,59 +115,26 @@ in "user": "dbt", "extensions": [] } - "test": { - "user": "test", - "extensions": [hstore] - } } ] ''; }; ports = [ "5432:5432" ]; volumes = [ + + # Mount pgdata to external zfs volume "/mnt/postgres:/var/lib/postgresql/data" + # Mount config files + # "${pg_hbaConfig}:/var/lib/postgres/data/pgdata/pg_hba.conf" + "${pgsqlConfig}:/etc/postgresql/postgresql.conf" + # 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" + "${initScript}:/docker-entrypoint-initdb.d/init.sh" ]; }; };