{ config, lib, pkgs, sources, ... }: let inherit (lib) mapAttrsToList; port = 9888; python3 = let nix-pkgs = import sources.nix-pkgs { inherit pkgs; }; in pkgs.python3.override { packageOverrides = _: _: { inherit (nix-pkgs) django-background-tasks django-bulma-forms django-translated-fields loadcredential ; authens = nix-pkgs.authens.overridePythonAttrs (_: { patches = [ ./01-authens-cas-url.patch ]; }); }; }; pythonEnv = python3.withPackages (ps: [ ps.django ps.gunicorn ps.markdown ps.numpy ps.networkx ps.psycopg ps.authens ps.django-background-tasks ps.django-bulma-forms ps.django-translated-fields ps.loadcredential ]); manage = pkgs.writeShellApplication { name = "kadenios-manage"; runtimeInputs = [ pythonEnv ]; text = '' MainPID=0 eval "$(${lib.getExe' config.systemd.package "systemctl"} show -pMainPID django-kadenios.service)" ${lib.getExe' pkgs.util-linux "nsenter"} -e -a -t "$MainPID" -G follow -S follow python ${sources.kadenios}/manage.py "$@" ''; }; staticDrv = pkgs.stdenv.mkDerivation { name = "kadenios-static"; src = sources.kadenios; nativeBuildInputs = [ pythonEnv ]; configurePhase = '' export KADENIOS_STATIC_ROOT=$out/static export KADENIOS_DEBUG=true export CREDENTIALS_DIRECTORY=$(pwd)/.credentials ''; doBuild = false; installPhase = '' mkdir -p $out/static python3 manage.py collectstatic ''; }; environment = builtins.mapAttrs (_: builtins.toJSON) { KADENIOS_ALLOWED_HOSTS = [ "vote.dgnum.eu" ]; KADENIOS_STATIC_ROOT = staticDrv; KADENIOS_DATABASES = { default = { ENGINE = "django.db.backends.postgresql"; NAME = "kadenios"; }; }; KADENIOS_EMAIL_HOST_USER = "web-services@infra.dgnum.eu"; KADENIOS_EMAIL_USE_SSL = true; KADENIOS_FROM_EMAIL = "Kadenios "; KADENIOS_SERVER_EMAIL = "kadenios@infra.dgnum.eu"; }; in { environment.systemPackages = [ manage ]; systemd.services = { django-kadenios = { description = "ENS simple voting server"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" "postgresql.service" ]; serviceConfig = { DynamicUser = true; LoadCredential = mapAttrsToList (name: value: "${name}:${value}") { SECRET_KEY = config.age.secrets."kadenios-secret_key_file".path; EMAIL_HOST_PASSWORD = config.age.secrets."kadenios-email_password_file".path; }; StateDirectory = "django-kadenios"; User = "kadenios"; }; inherit environment; path = [ pythonEnv ]; script = '' python3 ${sources.kadenios}/manage.py migrate gunicorn app.wsgi --pythonpath ${sources.kadenios} -b 127.0.0.1:${builtins.toString port} --workers=2 --threads=4 ''; }; django-kadenios-tasks = { description = "Background tasks worker for Kadenios"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" "postgresql.service" "django-kadenios.service" ]; serviceConfig = { DynamicUser = true; LoadCredential = mapAttrsToList (name: value: "${name}:${value}") { SECRET_KEY = config.age.secrets."kadenios-secret_key_file".path; EMAIL_HOST_PASSWORD = config.age.secrets."kadenios-email_password_file".path; }; StateDirectory = "django-kadenios"; User = "kadenios"; WorkingDirectory = sources.kadenios; }; inherit environment; path = [ pythonEnv ]; script = '' python3 manage.py process_tasks ''; }; }; services = { postgresql = { ensureDatabases = [ "kadenios" ]; ensureUsers = [ { name = "kadenios"; ensureDBOwnership = true; } ]; }; nginx.virtualHosts."vote.dgnum.eu" = { enableACME = true; forceSSL = true; locations = { "/".proxyPass = "http://127.0.0.1:${builtins.toString port}"; "/static/".root = staticDrv; }; }; }; }