{ config, lib, pkgs, sources, ... }: let inherit (lib) mapAttrsToList; python = let python3 = pkgs.python312; nix-pkgs = import sources.nix-pkgs { inherit pkgs python3; }; in python3.override { packageOverrides = _: _: { inherit (nix-pkgs) django-allauth django-allauth-cas django-browser-reload django-bulma-forms django-sass-processor django-sass-processor-dart-sass django-unfold pykanidm python-cas loadcredential ; }; }; pythonEnv = python.withPackages (ps: [ ps.django ps.gunicorn ps.psycopg ps.django-compressor # Local packages ps.django-allauth ps.django-allauth-cas ps.django-bulma-forms ps.django-sass-processor ps.django-sass-processor-dart-sass ps.django-unfold ps.loadcredential ps.pykanidm ps.python-cas ]); staticDrv = pkgs.stdenv.mkDerivation { name = "dgsi-static"; src = sources.dgsi; sourceRoot = "source/src"; nativeBuildInputs = [ pkgs.dart-sass pythonEnv ]; configurePhase = '' export DGSI_STATIC_ROOT=$out/static export CREDENTIALS_DIRECTORY=$(pwd)/../.credentials export DGSI_KANIDM_CLIENT="dgsi_test"; export DGSI_KANIDM_AUTH_TOKEN="fake.token"; ''; doBuild = false; installPhase = '' mkdir -p $out/static python3 manage.py compilescss python3 manage.py collectstatic ''; }; in { users = { users.nginx.extraGroups = [ "django-apps" ]; groups.django-apps = { }; }; systemd = { services = { dj-dgsi = { description = "DGSI web app"; requires = [ "dj-dgsi.socket" ]; wantedBy = [ "multi-user.target" ]; after = [ "network.target" "postgresql.service" ]; serviceConfig = { DynamicUser = true; LoadCredential = mapAttrsToList (name: value: "${name}:${value}") { SECRET_KEY = config.age.secrets."dgsi-secret_key_file".path; KANIDM_AUTH_TOKEN = config.age.secrets."dgsi-kanidm_auth_token_file".path; KANIDM_SECRET = config.age.secrets."dgsi-kanidm_secret_file".path; }; RuntimeDirectory = "django-apps/dgsi"; StateDirectory = "django-dgsi"; UMask = "0027"; User = "dj-dgsi"; WorkingDirectory = "${sources.dgsi}/src"; }; environment = { DGSI_ALLOWED_HOSTS = builtins.toJSON [ "profil.dgnum.eu" "dgsi.dgnum.eu" ]; DGSI_STATIC_ROOT = staticDrv; DGSI_MEDIA_ROOT = "/var/lib/django-apps/dgsi/media"; }; path = [ pythonEnv ]; script = '' python3 manage.py migrate gunicorn --pythonpath ${sources.dgsi}/src --bind unix:/run/django-apps/dgsi.sock --workers=4 app.wsgi ''; }; }; sockets."dj-dgsi" = { description = "Socket for the DGSI Django Application"; wantedBy = [ "sockets.target" ]; socketConfig = { ListenStream = "/run/django-apps/dgsi.sock"; SocketMode = "600"; SocketUser = config.services.nginx.user; }; }; mounts = [ { where = "/run/django-apps/dgsi/media"; what = "/var/lib/django-apps/dgsi/media"; options = "bind"; after = [ "dj-dgsi.service" ]; partOf = [ "dj-dgsi.service" ]; upheldBy = [ "dj-dgsi.service" ]; } ]; }; dgn-redirections.redirections."dgsi.dgnum.eu" = "profil.dgnum.eu"; services = { postgresql = { ensureDatabases = [ "dgsi" ]; ensureUsers = [ { name = "dgsi"; ensureDBOwnership = true; } ]; }; nginx.virtualHosts."profil.dgnum.eu" = { enableACME = true; forceSSL = true; serverAliases = [ "dgsi.dgnum.eu" ]; locations = { "/".proxyPass = "http://unix:/run/django-apps/dgsi.sock"; "/static/".root = staticDrv; "/media/".root = "/run/django-apps/dgsi"; }; }; }; }