{ config, lib, pkgs, sources, ... }: let inherit (lib) mapAttrsToList; port = 9889; python3 = pkgs.python312; pythonEnv = python3.withPackages (ps: [ ps.django ps.ldap3 ps.gunicorn ps.psycopg # Local packages (ps.callPackage ./packages/django-browser-reload { }) (ps.callPackage ./packages/django-bulma-forms { }) (ps.callPackage ./packages/django-cas-server { }) (ps.callPackage ./packages/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 ''; buildPhase = '' mkdir -p $out/static ''; installPhase = '' 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.dgnum.eu" = { enableACME = true; forceSSL = true; locations = { "/".proxyPass = "http://127.0.0.1:${builtins.toString port}"; "/static/".root = staticDrv; "= /robots.txt".root = "${staticDrv}/static"; }; }; }; }