{ config, inputs, lib, pkgs, this, ... }: let cfg = config.nixfiles.modules.postgresql; in { options.nixfiles.modules.postgresql = { enable = lib.mkEnableOption "PostgreSQL"; package = lib.mkOption { type = lib.types.package; default = pkgs.postgresql_15; description = "PostgreSQL package to use."; }; extraPostStart = lib.mkOption { type = with lib.types; listOf str; default = [ ]; description = '' Additional post-startup commands. This could be used to provide a crude interface to grant permissions and such. ''; }; }; config = lib.mkIf cfg.enable { assertions = [ { assertion = lib.any (x: x == "en_GB.UTF-8/UTF-8") config.i18n.supportedLocales; message = "The locale must be available"; } ]; ark.directories = [ config.services.postgresql.dataDir ]; services = { postgresql = { enable = true; inherit (cfg) package; # In hindsight, it was a poor choice to use ICU as a locale provider. # Now each time ICU version is bumped, I need to carefully upgrade each # database to match the version. initdbArgs = [ "--encoding=UTF8" "--locale-provider=icu" "--icu-locale=en_GB@collation=posix" "--locale=en_GB.UTF-8" "--lc-collate=C" "--lc-ctype=C" ]; # This crutch is here because some services cannot work via a UNIX # socket connection and I can't be bothered to configure proper # authentication. authentication = '' local all all trust ''; }; prometheus.exporters.postgres = { enable = true; listenAddress = "127.0.0.1"; port = 9187; }; }; systemd.services = { postgresql.postStart = lib.optionalString (cfg.extraPostStart != [ ]) cfg.extraPostStart |> lib.concatLines; alloy.reloadTriggers = [ config.environment.etc."alloy/postgres.alloy".source ]; }; environment = { etc."alloy/postgres.alloy".text = with config.services.prometheus.exporters.postgres; '' prometheus.scrape "postgres" { targets = [ { __address__ = "${listenAddress}:${toString port}", instance = "${config.networking.hostName}", }, ] forward_to = [prometheus.relabel.default.receiver] } ''; variables.PSQLRC = toString ( pkgs.writeText "psqlrc" '' \set QUIET 1 \timing \x auto \pset null '[NULL]' \set PROMPT1 '%[%033[1m%]%M %n@%/%R%[%033[0m%]% λ ' \set PROMPT2 ' … > ' \set VERBOSITY verbose \set HISTCONTROL ignoredups \set HISTFILE /dev/null \unset QUIET '' ); }; topology = { nodes.${this.hostname}.services.postgresql = { name = "PostgreSQL"; icon = "${inputs.homelab-svg-assets}/assets/postgresql.svg"; details.listen.text = "127.0.0.1:5432"; }; }; }; }