nixos/windmill: Fix database setup config + target unit (#442367)

This commit is contained in:
Yt
2025-09-16 11:27:01 +00:00
committed by GitHub

View File

@@ -91,6 +91,16 @@ in
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = cfg.database.createLocally -> cfg.database.name == cfg.database.user;
message = ''
Automatically provisioning the windmill database requires both database name and database user to be equal. '${cfg.database.name}' != '${cfg.database.user}'
To fix this problem, assign the same value to both options services.windmill.database.{name,user}.
'';
}
];
services.postgresql = lib.optionalAttrs (cfg.database.createLocally) {
enable = lib.mkDefault true;
@@ -101,7 +111,18 @@ in
ensureDBOwnership = true;
}
];
};
systemd.targets.windmill = {
description = "Windmill";
wantedBy = [ "multi-user.target" ];
requires =
[ ]
++ (lib.optionals config.systemd.services.windmill-server.enable [ "windmill-server.service" ])
++ (lib.optionals config.systemd.services.windmill-worker.enable [ "windmill-worker.service" ])
++ (lib.optionals config.systemd.services.windmill-worker-native.enable [
"windmill-worker-native.service"
]);
};
systemd.services =
@@ -112,7 +133,6 @@ in
# using the same user to simplify db connection
User = cfg.database.user;
ExecStart = "${pkgs.windmill}/bin/windmill";
Restart = "always";
}
// lib.optionalAttrs useUrlPath {
@@ -129,42 +149,72 @@ in
};
in
{
windmill-initdb = lib.mkIf cfg.database.createLocally {
description = "Windmill database setup";
requires = [ "postgresql.target" ];
after = [ "postgresql.target" ];
requiredBy =
[ ]
++ (lib.optionals config.systemd.services.windmill-server.enable [ "windmill-server.service" ])
++ (lib.optionals config.systemd.services.windmill-worker.enable [ "windmill-worker.service" ])
++ (lib.optionals config.systemd.services.windmill-worker-native.enable [
"windmill-worker-native.service"
]);
before =
[ ]
++ (lib.optionals config.systemd.services.windmill-server.enable [ "windmill-server.service" ])
++ (lib.optionals config.systemd.services.windmill-worker.enable [ "windmill-worker.service" ])
++ (lib.optionals config.systemd.services.windmill-worker-native.enable [
"windmill-worker-native.service"
]);
# coming from https://github.com/windmill-labs/windmill/blob/main/init-db-as-superuser.sql
# modified to not grant privileges on all tables
# create role windmill_user and windmill_admin only if they don't exist
postgresql.postStart = lib.mkIf cfg.database.createLocally ''
psql -tA <<"EOF"
DO $$
BEGIN
IF NOT EXISTS (
SELECT FROM pg_catalog.pg_roles
WHERE rolname = 'windmill_user'
) THEN
CREATE ROLE windmill_user;
GRANT ALL PRIVILEGES ON DATABASE ${cfg.database.name} TO windmill_user;
ELSE
RAISE NOTICE 'Role "windmill_user" already exists. Skipping.';
END IF;
IF NOT EXISTS (
SELECT FROM pg_catalog.pg_roles
WHERE rolname = 'windmill_admin'
) THEN
CREATE ROLE windmill_admin WITH BYPASSRLS;
GRANT windmill_user TO windmill_admin;
ELSE
RAISE NOTICE 'Role "windmill_admin" already exists. Skipping.';
END IF;
GRANT windmill_admin TO windmill;
END
$$;
EOF
'';
path = [ config.services.postgresql.package ];
# coming from https://github.com/windmill-labs/windmill/blob/main/init-db-as-superuser.sql
# modified to not grant privileges on all tables
# create role windmill_user and windmill_admin only if they don't exist
script = ''
psql -tA <<"EOF"
DO $$
BEGIN
IF NOT EXISTS (
SELECT FROM pg_catalog.pg_roles
WHERE rolname = 'windmill_user'
) THEN
CREATE ROLE windmill_user;
GRANT ALL PRIVILEGES ON DATABASE ${cfg.database.name} TO windmill_user;
ELSE
RAISE NOTICE 'Role "windmill_user" already exists. Skipping.';
END IF;
IF NOT EXISTS (
SELECT FROM pg_catalog.pg_roles
WHERE rolname = 'windmill_admin'
) THEN
CREATE ROLE windmill_admin WITH BYPASSRLS;
GRANT windmill_user TO windmill_admin;
ELSE
RAISE NOTICE 'Role "windmill_admin" already exists. Skipping.';
END IF;
GRANT windmill_admin TO ${cfg.database.user};
END
$$;
EOF
'';
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
# Superuser because of required permission CREATE ROLE
User = "postgres";
ProtectSystem = "strict";
ProtectHome = "read-only";
};
};
windmill-server = {
description = "Windmill server";
after = [ "network.target" ] ++ lib.optional cfg.database.createLocally "postgresql.target";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
partOf = [ "windmill.target" ];
serviceConfig = serviceConfig // {
StateDirectory = "windmill";
@@ -181,8 +231,8 @@ in
windmill-worker = {
description = "Windmill worker";
after = [ "network.target" ] ++ lib.optional cfg.database.createLocally "postgresql.target";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
partOf = [ "windmill.target" ];
serviceConfig = serviceConfig // {
StateDirectory = "windmill-worker";
@@ -200,8 +250,8 @@ in
windmill-worker-native = {
description = "Windmill worker native";
after = [ "network.target" ] ++ lib.optional cfg.database.createLocally "postgresql.target";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
partOf = [ "windmill.target" ];
serviceConfig = serviceConfig // {
StateDirectory = "windmill-worker-native";