Add postgres role
parent
1b75419d21
commit
4137675a1c
|
@ -1,7 +1,7 @@
|
|||
traefik:
|
||||
acmeEmail: email@example.com
|
||||
CLOUDFLARE_EMAIL: email@example.com
|
||||
CLOUDFLARE_DNS_API_TOKEN: AVeryLongAPIKeyHere
|
||||
acmeEmail: email@example.com
|
||||
CLOUDFLARE_EMAIL: email@example.com
|
||||
CLOUDFLARE_DNS_API_TOKEN: AVeryLongAPIKeyHere
|
||||
authentik:
|
||||
db_pass: AVeryLongSecurePassword
|
||||
secret_key: AVeryLongSecretKey
|
||||
|
@ -11,3 +11,6 @@ authentik:
|
|||
email_from: mail@example.com
|
||||
email_username: mail@example.com
|
||||
email_password: ADifferentVeryLongSecurePassword
|
||||
postgres:
|
||||
# Every database used should have an entry with the password here
|
||||
authentik: AVeryLongSecurePassword
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
hosts
|
||||
;
|
||||
};
|
||||
nodeSpecialArgs = builtins.mapAttrs (_: cfg: { host = cfg; }) hosts;
|
||||
};
|
||||
}
|
||||
// (nixpkgs.lib.mapAttrs (
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
ip = "192.168.10.99";
|
||||
|
||||
roles = with roles; [
|
||||
postgres
|
||||
podman
|
||||
|
||||
traefik
|
||||
sonarr
|
||||
podman
|
||||
authentik
|
||||
];
|
||||
config = {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
host,
|
||||
...
|
||||
}:
|
||||
let
|
||||
|
@ -55,10 +56,6 @@
|
|||
# TODO: Persist some/all of this into ceph cluster
|
||||
environment.persistence."/persistent" = {
|
||||
directories = [
|
||||
{
|
||||
directory = "/appdata/authentik/postgres";
|
||||
mode = "0700";
|
||||
}
|
||||
{
|
||||
directory = "/appdata/authentik/redis";
|
||||
mode = "0700";
|
||||
|
@ -101,7 +98,6 @@
|
|||
owner = "authentik";
|
||||
content = ''
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD=${config.sops.placeholder."authentik/db_pass"}
|
||||
POSTGRES_PASSWORD=${config.sops.placeholder."authentik/db_pass"}
|
||||
AUTHENTIK_SECRET_KEY="${config.sops.placeholder."authentik/secret_key"}"
|
||||
AUTHENTIK_EMAIL__HOST="${config.sops.placeholder."authentik/email_host"}"
|
||||
AUTHENTIK_EMAIL__PORT="${config.sops.placeholder."authentik/email_port"}"
|
||||
|
@ -111,23 +107,11 @@
|
|||
'';
|
||||
};
|
||||
|
||||
# Create the database
|
||||
postgres.databases = [ "authentik" ];
|
||||
|
||||
podman.containers = {
|
||||
# TODO: Use system postgres here instead of a separate container
|
||||
"authentik-postgres" = {
|
||||
image = "docker.io/library/postgres:16-alpine";
|
||||
autoStart = true;
|
||||
volumes = [
|
||||
"/appdata/authentik/postgres:/var/lib/postgresql/data"
|
||||
];
|
||||
environment = {
|
||||
POSTGRES_USER = "authentik";
|
||||
POSTGRES_DB = "authentik";
|
||||
};
|
||||
environmentFiles = [
|
||||
config.sops.templates."authentik-secret.env".path
|
||||
publicEnv
|
||||
];
|
||||
};
|
||||
# TODO: Does using system redis make sense here?
|
||||
"authentik-redis" = {
|
||||
image = "docker.io/library/redis:7.4.2-alpine";
|
||||
autoStart = true;
|
||||
|
@ -137,12 +121,11 @@
|
|||
};
|
||||
"authentik-server" = {
|
||||
image = "ghcr.io/goauthentik/server:${AUTHENTIK_VERSION}";
|
||||
user = "authentik";
|
||||
autoStart = true;
|
||||
cmd = [ "server" ];
|
||||
environment = {
|
||||
AUTHENTIK_REDIS__HOST = "authentik-redis";
|
||||
AUTHENTIK_POSTGRESQL__HOST = "authentik-postgres";
|
||||
AUTHENTIK_POSTGRESQL__HOST = "host.containers.internal";
|
||||
AUTHENTIK_POSTGRESQL__USER = "authentik";
|
||||
AUTHENTIK_POSTGRESQL__NAME = "authentik";
|
||||
};
|
||||
|
@ -159,12 +142,12 @@
|
|||
};
|
||||
"authentik-worker" = {
|
||||
image = "ghcr.io/goauthentik/server:${AUTHENTIK_VERSION}";
|
||||
user = "authentik";
|
||||
user = "root";
|
||||
autoStart = true;
|
||||
cmd = [ "worker" ];
|
||||
environment = {
|
||||
AUTHENTIK_REDIS__HOST = "authentik-redis";
|
||||
AUTHENTIK_POSTGRESQL__HOST = "authentik-postgres";
|
||||
AUTHENTIK_POSTGRESQL__HOST = "host.containers.internal";
|
||||
AUTHENTIK_POSTGRESQL__USER = "authentik";
|
||||
AUTHENTIK_POSTGRESQL__NAME = "authentik";
|
||||
};
|
||||
|
|
|
@ -3,8 +3,12 @@
|
|||
...
|
||||
}:
|
||||
{
|
||||
# Utility
|
||||
postgres = utils.mkRole (import ./postgres.nix);
|
||||
podman = utils.mkRole (import ./podman.nix);
|
||||
|
||||
# Services
|
||||
sonarr = utils.mkRole (import ./sonarr.nix);
|
||||
traefik = utils.mkRole (import ./traefik.nix);
|
||||
podman = utils.mkRole (import ./podman.nix);
|
||||
authentik = utils.mkRole (import ./authentik.nix);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
virtualisation.podman.defaultNetwork.settings.dns_enabled = true;
|
||||
virtualisation.oci-containers.backend = "podman";
|
||||
|
||||
# TODO: Maybe we want to pre-fetch the images during build?
|
||||
# This would ensure the config always reproduces the exact same system
|
||||
virtualisation.oci-containers.containers = cfg.containers;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
{
|
||||
name = "PostgreSQL";
|
||||
description = ''
|
||||
Runs a PostgreSQL database server on this host.
|
||||
Other roles can use this role to create the required databases on this host through the
|
||||
`postgres` attribute.
|
||||
'';
|
||||
|
||||
nixosModule =
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
{
|
||||
options.postgres = {
|
||||
databases = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
config =
|
||||
let
|
||||
cfg = config.postgres;
|
||||
in
|
||||
{
|
||||
# Create the postgresql service
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
enableTCPIP = true;
|
||||
ensureDatabases = map (db: db) cfg.databases;
|
||||
ensureUsers = map (db: {
|
||||
name = db;
|
||||
ensureDBOwnership = true;
|
||||
ensureClauses.login = true;
|
||||
}) cfg.databases;
|
||||
identMap = ''
|
||||
# ArbitraryMapName systemUser DBUser
|
||||
superuser_map root postgres
|
||||
superuser_map postgres postgres
|
||||
'';
|
||||
|
||||
authentication = pkgs.lib.mkOverride 10 ''
|
||||
# Allow local users to log into the database user with the same name
|
||||
local sameuser postgres peer map=superuser_map
|
||||
# Allow "md5" (password) authentication
|
||||
local all all md5
|
||||
host all all 0.0.0.0/0 md5
|
||||
host all all 127.0.0.1/32 md5
|
||||
host all all ::1/128 md5
|
||||
'';
|
||||
|
||||
# FIXME: For debug
|
||||
settings = {
|
||||
log_connections = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
5432
|
||||
];
|
||||
|
||||
# Persist the database contents across reboots
|
||||
# TODO: This should be automatically backed up daily into the CEPH
|
||||
# cluster storage. It can't be on the cluster all the time, since
|
||||
# CEPH doesn't perform great with databases (according to people
|
||||
# online).
|
||||
environment.persistence."/persistent" = {
|
||||
directories = [
|
||||
{
|
||||
directory = "/var/lib/postgresql";
|
||||
user = "postgres";
|
||||
mode = "0700";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# Create the required secret files
|
||||
sops.secrets = listToAttrs (
|
||||
map (db: {
|
||||
name = "postgres/${db}";
|
||||
value = {
|
||||
owner = "postgres";
|
||||
};
|
||||
}) cfg.databases
|
||||
);
|
||||
|
||||
# Use the secret files from sops to set database user passwords
|
||||
systemd.services.postgresql.postStart = concatMapStrings (db: ''
|
||||
$PSQL -tA <<'EOF'
|
||||
DO $$
|
||||
DECLARE username TEXT;
|
||||
DECLARE password TEXT;
|
||||
BEGIN
|
||||
username := trim(both from replace('${db}', E'\n', '''));
|
||||
password := trim(both from replace(pg_read_file('${
|
||||
(attrsets.getAttrFromPath [ "postgres/${db}" ] config.sops.secrets).path
|
||||
}'), E'\n', '''));
|
||||
EXECUTE format('ALTER ROLE %s WITH PASSWORD '''%s''';', username, password);
|
||||
END $$;
|
||||
EOF
|
||||
'') cfg.databases;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -10,6 +10,8 @@ authentik:
|
|||
email_from: ENC[AES256_GCM,data:X6NP2i3uAZQFK7JdeviIMFhNPw==,iv:dwZFyzzzzFNTVfe1nhWebXrTolCa991p+vJUAOxFJf8=,tag:gClo9mZfaVFP35yZath0Nw==,type:str]
|
||||
email_username: ENC[AES256_GCM,data:c1lu5Tw6N6w96uUujSj1wHh7fQ==,iv:XX2iYXOzz8EhcZ75NlmLsasnZnCrihE9K17qS2nhAyI=,tag:qfhh3bB530IIsJwmjG20Lw==,type:str]
|
||||
email_password: ENC[AES256_GCM,data:2f/LN5q/5RRIzAc8ol9RByf+RrQ=,iv:gy/UvcKzpvC0r4nQFbTYta8alzTjPWhFWCjGIw/PnuU=,tag:LLOk7NMuQ3VZ2zA779A5dw==,type:str]
|
||||
postgres:
|
||||
authentik: ENC[AES256_GCM,data:45DJfPHXeGyT8KDty5Po68whOVSTbT+iAfBpJ/6dKy0EeaKLKq/w1A==,iv:CtmwN+9tKmsCcU46OvBME/urkAvjEtVBqfqgs8dkkCU=,tag:j+yZfVv62IhkgF7HRT6zLQ==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
|
@ -43,8 +45,8 @@ sops:
|
|||
OHkvUTViMVZSUGFSeDN1ZDcxN3NtNzQK48qiEMcKbsrh8ZhnMD7lkhsy0JRMYiOU
|
||||
EtXwHxEzIXukStQ9kXazfHJJouuqv7mhx12tgv+QKvrfWxCJ5WvE2A==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2025-02-10T22:59:35Z"
|
||||
mac: ENC[AES256_GCM,data:uTzFEW5na0YCBLGb9k/yICjNGKWCefGgiSH8M0QZgrvRf3ioXz1W/rGUJqTmIh3QdQ45evHoj6cKSIys2gU28dR98qGX2sCBmnWYMB2oT57YLXeACsaqXKtXFsOx/YnOy8baQpckUYOwHJpM+dhKf/s348X1jfx1k8TOoNE3aj0=,iv:Jr1HvXKsxKfMBUu2r6ezodySMWduVdlPw+EIckpi5i0=,tag:fDjBfC7nKwkO3mm91iB/HQ==,type:str]
|
||||
lastmodified: "2025-02-11T16:20:59Z"
|
||||
mac: ENC[AES256_GCM,data:e1uqTmgVc60EHKEwsrcdh+qA2pA+Acy89DHEMCTN2eTR9hb9ya2FkEa6+X2ckgMQsngWGg/N+wAxR+wOyqLNuX1Rcb0ee3YxzaHxQZamTp09XL5IPooTNqfQdEiexPHBoJr+OtftkvsvhxmBUvh9+/VZpvnEVHwBcJAPF9KRrCI=,iv:66Uq37oID3XrRY+xcza2VNZCqhSKkAz6SJeJ3scfTmE=,tag:r6hua8+RfF99DtJsTALRpQ==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.9.2
|
||||
|
|
Loading…
Reference in New Issue