{ config, lib, pkgs, sources, ... }: let inherit (lib) mapAttrsToList; port = 9889; python3 = let nix-pkgs = import sources.nix-pkgs { inherit pkgs; python3 = pkgs.python312; }; in pkgs.python312.override { packageOverrides = _: _: { inherit (nix-pkgs) django-browser-reload django-bulma-forms loadcredential; django-cas-server = nix-pkgs.django-cas-server.overridePythonAttrs (_: { patches = [ ./01-pytest-cas.patch ]; }); }; }; pythonEnv = python3.withPackages (ps: [ ps.django ps.ldap3 ps.gunicorn ps.psycopg # Local packages ps.django-browser-reload ps.django-bulma-forms ps.django-cas-server ps.loadcredential ]); staticDrv = pkgs.stdenv.mkDerivation { name = "cas_eleves-static"; src = sources.cas-eleves; nativeBuildInputs = [ pythonEnv ]; configurePhase = '' export CE_STATIC_ROOT=$out/static export CE_DEBUG=true export CREDENTIALS_DIRECTORY=$(pwd)/.credentials ''; doBuild = false; installPhase = '' mkdir -p $out/static python3 manage.py collectstatic ''; }; in { systemd.services = { django-cas-eleves = { description = "ENS CAS server"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" "postgresql.service" ]; serviceConfig = { DynamicUser = true; LoadCredential = mapAttrsToList (name: value: "${name}:${value}") { SECRET_KEY = config.age.secrets."cas_eleves-secret_key_file".path; }; StateDirectory = "django-cas-eleves"; User = "cas_server"; WorkingDirectory = sources.cas-eleves; }; environment = { CE_ALLOWED_HOSTS = builtins.toJSON [ "cas-eleves.dgnum.eu" "cas.eleves.ens.fr" ]; CE_STATIC_ROOT = staticDrv; }; path = [ pythonEnv ]; script = '' python3 manage.py loaddata patterns python3 manage.py migrate gunicorn app.wsgi --pythonpath ${sources.cas-eleves} -b 127.0.0.1:${builtins.toString port} --workers=2 --threads=4 ''; }; cas-eleves-cleanup = { description = "Periodic cleanup of cas_server database"; startAt = "daily"; serviceConfig = { Type = "oneshot"; LoadCredential = mapAttrsToList (name: value: "${name}:${value}") { SECRET_KEY = config.age.secrets."cas_eleves-secret_key_file".path; }; StateDirectory = "django-cas-eleves"; User = "cas_server"; WorkingDirectory = sources.cas-eleves; }; path = [ pythonEnv ]; script = '' python3 manage.py clearsessions python3 manage.py cas_clean_sessions python3 manage.py cas_clean_tickets ''; }; }; services = { postgresql = { ensureDatabases = [ "cas_server" ]; ensureUsers = [ { name = "cas_server"; ensureDBOwnership = true; } ]; }; nginx.virtualHosts."cas.eleves.ens.fr" = { enableACME = true; forceSSL = true; serverAliases = [ "cas-eleves.dgnum.eu" ]; locations = { "/".proxyPass = "http://127.0.0.1:${builtins.toString port}"; "/static/".root = staticDrv; "= /robots.txt".root = "${staticDrv}/static"; }; }; }; }