fragdenrat/module.nix
2025-08-21 11:04:07 +02:00

111 lines
2.9 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.fragdenrat;
dataDir = "/var/lib/fragdenrat";
manageCmd = "${pkgs.fragdenrat}/bin/fragdenrat-manage";
pythonPath = "${pkgs.fragdenrat}/share:${pkgs.fragdenrat.pythonPath}";
envVars = [
"PYTHONPATH=${pythonPath}"
"DJANGO_SETTINGS_MODULE=fragdenrat.settings"
"FRAGDENRAT_DATA_DIR=${dataDir}"
];
in
{
options = {
services.fragdenrat = {
enable = lib.mkEnableOption "FragDenRat web app";
};
};
config = lib.mkIf cfg.enable {
# Ensure data dir exists with proper perms
systemd.tmpfiles.rules = [
"d ${dataDir} 0750 fragdenrat fragdenrat -"
"d ${dataDir}/staticfiles 0750 fragdenrat fragdenrat -"
];
# One-shot setup: migrate DB and collect static into dataDir
systemd.services.fragdenrat-setup = {
description = "Initialize FragDenRat database and static files";
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
User = "fragdenrat";
Group = "fragdenrat";
WorkingDirectory = dataDir;
Environment = envVars;
};
script = ''
set -euo pipefail
${manageCmd} migrate --noinput
${manageCmd} collectstatic --noinput
'';
};
# uWSGI app
services.uwsgi = {
enable = true;
plugins = [ "python3" ];
postActivation = ''
# Ensure setup runs before uwsgi serves
${config.systemd.package}/bin/systemctl start fragdenrat-setup.service
'';
instance = {
type = "emperor";
vassals = {
fragdenrat = {
type = "normal";
# Use data dir as working directory
chdir = dataDir;
# Absolute WSGI entrypoint in Nix store
wsgi-file = "${pkgs.fragdenrat}/share/fragdenrat/wsgi.py";
callable = "application";
socket = "${config.services.uwsgi.runDir}/fragdenrat.sock";
"chmod-socket" = "660";
umask = "0077";
vacuum = true;
master = true;
processes = 2;
threads = 2;
harakiri = 60;
"buffer-size" = 65535;
need-app = true;
"no-orphans" = true;
env = envVars;
settings = {
# Serve collected static files from dataDir
"static-map" = "/static=${dataDir}/staticfiles";
# Python import path for the app and its deps
pythonpath = "${pkgs.fragdenrat}/share";
};
};
};
};
};
# Ensure fragdenrat user and group exist
users.users.fragdenrat = {
isSystemUser = true;
group = "fragdenrat";
description = "FragDenRat web application user";
};
users.groups.fragdenrat = { };
};
meta = {
maintainers = with lib.maintainers; [ onny ];
};
}