add postgresql module with tests
This commit is contained in:
parent
66a3af7f0d
commit
cc57b1ced7
6 changed files with 278 additions and 23 deletions
|
@ -117,7 +117,7 @@ First, some common configuration:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
imports = [
|
imports = [
|
||||||
selfhostblocks.nixosModules.default
|
selfhostblocks.nixosModules.x86_64-linux.default
|
||||||
sops-nix.nixosModules.default
|
sops-nix.nixosModules.default
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
50
flake.lock
50
flake.lock
|
@ -1,5 +1,38 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1694529238,
|
||||||
|
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nix-flake-tests": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1677844186,
|
||||||
|
"narHash": "sha256-ErJZ/Gs1rxh561CJeWP5bohA2IcTq1rDneu1WT6CVII=",
|
||||||
|
"owner": "antifuchs",
|
||||||
|
"repo": "nix-flake-tests",
|
||||||
|
"rev": "bbd9216bd0f6495bb961a8eb8392b7ef55c67afb",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "antifuchs",
|
||||||
|
"repo": "nix-flake-tests",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687412861,
|
"lastModified": 1687412861,
|
||||||
|
@ -50,6 +83,8 @@
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nix-flake-tests": "nix-flake-tests",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"sops-nix": "sops-nix"
|
"sops-nix": "sops-nix"
|
||||||
}
|
}
|
||||||
|
@ -72,6 +107,21 @@
|
||||||
"repo": "sops-nix",
|
"repo": "sops-nix",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|
60
flake.nix
60
flake.nix
|
@ -4,29 +4,45 @@
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
sops-nix.url = "github:Mic92/sops-nix";
|
sops-nix.url = "github:Mic92/sops-nix";
|
||||||
|
nix-flake-tests.url = "github:antifuchs/nix-flake-tests";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs@{ self, nixpkgs, sops-nix, ... }: {
|
outputs = inputs@{ self, nixpkgs, sops-nix, nix-flake-tests, flake-utils, ... }: flake-utils.lib.eachDefaultSystem (system:
|
||||||
nixosModules.default = { config, ... }: {
|
let
|
||||||
imports = [
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
modules/arr.nix
|
in
|
||||||
modules/authelia.nix
|
{
|
||||||
modules/backup.nix
|
nixosModules.default = { config, ... }: {
|
||||||
modules/deluge.nix
|
imports = [
|
||||||
modules/davfs.nix
|
modules/arr.nix
|
||||||
modules/hledger.nix
|
modules/authelia.nix
|
||||||
modules/home-assistant.nix
|
modules/backup.nix
|
||||||
modules/jellyfin.nix
|
modules/deluge.nix
|
||||||
modules/ldap.nix
|
modules/davfs.nix
|
||||||
modules/monitoring.nix
|
modules/hledger.nix
|
||||||
modules/nextcloud-server.nix
|
modules/home-assistant.nix
|
||||||
modules/nginx.nix
|
modules/jellyfin.nix
|
||||||
modules/ssl.nix
|
modules/ldap.nix
|
||||||
modules/tinyproxy.nix
|
modules/monitoring.nix
|
||||||
modules/vpn.nix
|
modules/nextcloud-server.nix
|
||||||
];
|
modules/nginx.nix
|
||||||
};
|
modules/postgresql.nix
|
||||||
|
modules/ssl.nix
|
||||||
|
modules/tinyproxy.nix
|
||||||
|
modules/vpn.nix
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
# templates.default = {}; Would be nice to have a template
|
checks = {
|
||||||
};
|
tests = nix-flake-tests.lib.check {
|
||||||
|
inherit pkgs;
|
||||||
|
tests = import ./test/default.nix {
|
||||||
|
inherit (pkgs) lib;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# templates.default = {}; Would be nice to have a template
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
88
modules/postgresql.nix
Normal file
88
modules/postgresql.nix
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.shb.postgresql;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.shb.postgresql = {
|
||||||
|
tcpIPPort = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.port;
|
||||||
|
description = "Enable TCP/IP connection on given port.";
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
passwords = lib.mkOption {
|
||||||
|
type = lib.types.listOf (lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
username = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Postgres user name.";
|
||||||
|
};
|
||||||
|
|
||||||
|
database = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Postgres database.";
|
||||||
|
};
|
||||||
|
|
||||||
|
passwordFile = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "Password file for the postgres user.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config =
|
||||||
|
let
|
||||||
|
tcpConfig = port: {
|
||||||
|
services.postgresql.enableTCPIP = true;
|
||||||
|
services.postgresql.port = port;
|
||||||
|
services.postgresql.authentication = lib.mkOverride 10 ''
|
||||||
|
#type database DBuser origin-address auth-method
|
||||||
|
# ipv4
|
||||||
|
host all all 127.0.0.1/32 trust
|
||||||
|
# ipv6
|
||||||
|
host all all ::1/128 trust
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
dbConfig = passwordCfgs: {
|
||||||
|
services.postgresql.enable = (builtins.length passwordCfgs) > 0;
|
||||||
|
services.postgresql.ensureDatabases = map ({ database, ... }: database) passwordCfgs;
|
||||||
|
services.postgresql.Users = map ({ username, database, ... }: {
|
||||||
|
name = username;
|
||||||
|
ensurePermissions = {
|
||||||
|
"DATABASE ${database}" = "ALL PRIVILEGES";
|
||||||
|
};
|
||||||
|
ensureClauses = {
|
||||||
|
"login" = true;
|
||||||
|
};
|
||||||
|
}) passwordCfgs;
|
||||||
|
};
|
||||||
|
|
||||||
|
pwdConfig = passwordCfgs: {
|
||||||
|
systemd.services.postgresql.postStart =
|
||||||
|
let
|
||||||
|
script = { username, passwordFile, ... }: ''
|
||||||
|
$PSQL -tA <<'EOF'
|
||||||
|
DO $$
|
||||||
|
DECLARE password TEXT;
|
||||||
|
BEGIN
|
||||||
|
password := trim(both from replace(pg_read_file('${passwordFile}'), E'\n', '''));
|
||||||
|
EXECUTE format('ALTER ROLE ${username} WITH PASSWORD '''%s''';', password);
|
||||||
|
END $$;
|
||||||
|
EOF
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
lib.concatStringsSep "\n" (map script passwordCfgs);
|
||||||
|
};
|
||||||
|
in
|
||||||
|
lib.mkMerge (
|
||||||
|
[
|
||||||
|
(dbConfig cfg.passwords)
|
||||||
|
(pwdConfig cfg.passwords)
|
||||||
|
(lib.mkIf (!(isNull cfg.tcpIPPort)) (tcpConfig cfg.tcpIPPort))
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
2
test/default.nix
Normal file
2
test/default.nix
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
{ lib }:
|
||||||
|
import ./modules/postgresql.nix { inherit lib; }
|
99
test/modules/postgresql.nix
Normal file
99
test/modules/postgresql.nix
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
{ lib }:
|
||||||
|
let
|
||||||
|
anyOpt = default: lib.mkOption {
|
||||||
|
type = lib.types.anything;
|
||||||
|
inherit default;
|
||||||
|
};
|
||||||
|
|
||||||
|
testConfig = m:
|
||||||
|
let
|
||||||
|
cfg = (lib.evalModules {
|
||||||
|
modules = [
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services = anyOpt {};
|
||||||
|
systemd = anyOpt {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
../../modules/postgresql.nix
|
||||||
|
m
|
||||||
|
];
|
||||||
|
}).config;
|
||||||
|
in {
|
||||||
|
inherit (cfg) systemd services;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
testPostgresNoOptions = {
|
||||||
|
expected = {
|
||||||
|
services.postgresql = {
|
||||||
|
enable = false;
|
||||||
|
Users = [];
|
||||||
|
ensureDatabases = [];
|
||||||
|
};
|
||||||
|
systemd.services.postgresql.postStart = "";
|
||||||
|
};
|
||||||
|
expr = testConfig {};
|
||||||
|
};
|
||||||
|
|
||||||
|
testPostgresOnePassword = {
|
||||||
|
expected = {
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
Users = [{
|
||||||
|
name = "myuser";
|
||||||
|
ensurePermissions = {
|
||||||
|
"DATABASE mydatabase" = "ALL PRIVILEGES";
|
||||||
|
};
|
||||||
|
ensureClauses = {
|
||||||
|
"login" = true;
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
ensureDatabases = ["mydatabase"];
|
||||||
|
};
|
||||||
|
systemd.services.postgresql.postStart = ''
|
||||||
|
$PSQL -tA <<'EOF'
|
||||||
|
DO $$
|
||||||
|
DECLARE password TEXT;
|
||||||
|
BEGIN
|
||||||
|
password := trim(both from replace(pg_read_file('/my/file'), E'\n', '''));
|
||||||
|
EXECUTE format('ALTER ROLE myuser WITH PASSWORD '''%s''';', password);
|
||||||
|
END $$;
|
||||||
|
EOF
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
expr = testConfig {
|
||||||
|
shb.postgresql.passwords = [
|
||||||
|
{
|
||||||
|
username = "myuser";
|
||||||
|
database = "mydatabase";
|
||||||
|
passwordFile = "/my/file";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testPostgresTCPIP = {
|
||||||
|
expected = {
|
||||||
|
services.postgresql = {
|
||||||
|
enable = false;
|
||||||
|
Users = [];
|
||||||
|
ensureDatabases = [];
|
||||||
|
|
||||||
|
enableTCPIP = true;
|
||||||
|
port = 1234;
|
||||||
|
authentication = ''
|
||||||
|
#type database DBuser origin-address auth-method
|
||||||
|
# ipv4
|
||||||
|
host all all 127.0.0.1/32 trust
|
||||||
|
# ipv6
|
||||||
|
host all all ::1/128 trust
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
systemd.services.postgresql.postStart = "";
|
||||||
|
};
|
||||||
|
expr = testConfig {
|
||||||
|
shb.postgresql.tcpIPPort = 1234;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue