80 lines
3.9 KiB
Nix
80 lines
3.9 KiB
Nix
final: prev: {
|
|
postgresql = {
|
|
config,
|
|
lib,
|
|
...
|
|
}: let
|
|
cfg = config.services.postgresql;
|
|
|
|
postStartScript = prev.writeScript "postgresql-post-start" ''
|
|
#!${prev.bash}/bin/bash
|
|
set -e
|
|
|
|
# Wait for PostgreSQL to be ready
|
|
until ${cfg.package}/bin/pg_isready -h localhost -p ${toString cfg.port} -U ${cfg.superUser}; do
|
|
sleep 1
|
|
done
|
|
|
|
# Create databases if they don't exist
|
|
${prev.lib.concatMapStringsSep "\n" (db: ''
|
|
if ! ${cfg.package}/bin/psql -h localhost -p ${toString cfg.port} -U ${cfg.superUser} -lqt | cut -d'|' -f1 | grep -qw ${prev.lib.escapeShellArg db}; then
|
|
echo "Creating database: ${prev.lib.escapeShellArg db}"
|
|
${cfg.package}/bin/createdb -h localhost -p ${toString cfg.port} -U ${cfg.superUser} ${prev.lib.escapeShellArg db}
|
|
fi
|
|
'')
|
|
cfg.ensureDatabases}
|
|
|
|
# Create users and set permissions
|
|
${prev.lib.concatMapStringsSep "\n" (user: ''
|
|
# Create user if it doesn't exist
|
|
if ! ${cfg.package}/bin/psql -h localhost -p ${toString cfg.port} -U ${cfg.superUser} -tAc "SELECT 1 FROM pg_roles WHERE rolname='${prev.lib.escapeShellArg user.name}'" | grep -q 1; then
|
|
echo "Creating user: ${prev.lib.escapeShellArg user.name}"
|
|
${cfg.package}/bin/psql -h localhost -p ${toString cfg.port} -U ${cfg.superUser} -c "CREATE USER \"${prev.lib.escapeShellArg user.name}\""
|
|
fi
|
|
|
|
# Set user privileges
|
|
${prev.lib.optionalString (user ? ensureDBOwnership && user.ensureDBOwnership) ''
|
|
echo "Setting database ownership for ${prev.lib.escapeShellArg user.name}"
|
|
${cfg.package}/bin/psql -h localhost -p ${toString cfg.port} -U ${cfg.superUser} -c "ALTER USER \"${prev.lib.escapeShellArg user.name}\" CREATEDB CREATEROLE"
|
|
''}
|
|
|
|
${prev.lib.optionalString (user ? ensureClauses) ''
|
|
${prev.lib.optionalString (user.ensureClauses ? superuser && user.ensureClauses.superuser) ''
|
|
echo "Granting superuser to ${prev.lib.escapeShellArg user.name}"
|
|
${cfg.package}/bin/psql -h localhost -p ${toString cfg.port} -U ${cfg.superUser} -c "ALTER USER \"${prev.lib.escapeShellArg user.name}\" SUPERUSER"
|
|
''}
|
|
${prev.lib.optionalString (user.ensureClauses ? createdb && user.ensureClauses.createdb) ''
|
|
echo "Granting createdb to ${prev.lib.escapeShellArg user.name}"
|
|
${cfg.package}/bin/psql -h localhost -p ${toString cfg.port} -U ${cfg.superUser} -c "ALTER USER \"${prev.lib.escapeShellArg user.name}\" CREATEDB"
|
|
''}
|
|
''}
|
|
|
|
# Grant permissions (legacy support)
|
|
${prev.lib.concatMapStringsSep "\n" (perm: ''
|
|
echo "Granting ${prev.lib.escapeShellArg perm} to ${prev.lib.escapeShellArg user.name}"
|
|
${cfg.package}/bin/psql -h localhost -p ${toString cfg.port} -U ${cfg.superUser} -c "GRANT ${prev.lib.escapeShellArg perm} TO \"${prev.lib.escapeShellArg user.name}\""
|
|
'') (prev.lib.optionals (user ? ensurePermissions) (prev.lib.mapAttrsToList (target: perm: "${perm} ON ${target}") user.ensurePermissions))}
|
|
'')
|
|
cfg.ensureUsers}
|
|
|
|
# Run initial script if provided
|
|
${prev.lib.optionalString (cfg.initialScript != null) ''
|
|
echo "Running initial script"
|
|
${cfg.package}/bin/psql -h localhost -p ${toString cfg.port} -U ${cfg.superUser} -f ${cfg.initialScript}
|
|
''}
|
|
'';
|
|
in {
|
|
config = prev.lib.mkIf cfg.enable {
|
|
launchd.user.agents.postgresql = prev.lib.mkIf (cfg.ensureDatabases != [] || cfg.ensureUsers != [] || cfg.initialScript != null) {
|
|
script = prev.lib.mkAfter ''
|
|
# Run post-start script in background after PostgreSQL starts
|
|
(
|
|
sleep 5 # Give PostgreSQL a moment to fully start
|
|
${prev.bash}/bin/bash ${postStartScript}
|
|
) &
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
}
|