diff --git a/machines/web02/_configuration.nix b/machines/web02/_configuration.nix index 7efe6d4..bb44155 100644 --- a/machines/web02/_configuration.nix +++ b/machines/web02/_configuration.nix @@ -10,6 +10,7 @@ lib.extra.mkConfig { enabledServices = [ # List of services to enable "cas-eleves" + "kadenios" ]; extraConfig = { diff --git a/machines/web02/kadenios/01-authens-cas-url.patch b/machines/web02/kadenios/01-authens-cas-url.patch new file mode 100644 index 0000000..4917c63 --- /dev/null +++ b/machines/web02/kadenios/01-authens-cas-url.patch @@ -0,0 +1,11 @@ +diff --git a/src/authens/utils.py b/src/authens/utils.py +index 7306506..36063b6 100644 +--- a/src/authens/utils.py ++++ b/src/authens/utils.py +@@ -16,7 +16,7 @@ def get_cas_client(request): + service_url=urlunparse( + (request.scheme, request.get_host(), request.path, "", "", "") + ), +- server_url="https://cas.eleves.ens.fr/", ++ server_url="https://cas-eleves.dgnum.eu/", + ) diff --git a/machines/web02/kadenios/default.nix b/machines/web02/kadenios/default.nix new file mode 100644 index 0000000..3a544ef --- /dev/null +++ b/machines/web02/kadenios/default.nix @@ -0,0 +1,173 @@ +{ + 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-browser-reload + 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-browser-reload + ps.django-bulma-forms + ps.django-debug-toolbar + ps.django-translated-fields + ps.loadcredential + ]); + + 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 + +{ + 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"; + WorkingDirectory = sources.kadenios; + }; + + inherit environment; + + path = [ pythonEnv ]; + + script = '' + python3 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; + }; + }; + }; +} diff --git a/machines/web02/secrets/kadenios-email_password_file b/machines/web02/secrets/kadenios-email_password_file new file mode 100644 index 0000000..5e63d50 --- /dev/null +++ b/machines/web02/secrets/kadenios-email_password_file @@ -0,0 +1,29 @@ +age-encryption.org/v1 +-> ssh-ed25519 jIXfPA IBkwP7FCPqSwXIxfjmjJ/hE8GsWOuT4TUpKdLyPtyBE +J+huohRV0yy5oGYuugwh+2VKZmFdgKmIdU6HgQL0SWo +-> ssh-ed25519 QlRB9Q 9/fSh/FQa/8fZEytnmzUpxM4QQjigJCU4wXz01ly8iM +o3n0RED/4Wbq2ZaUYoj6IskO0mvESwlrw4u5qvfVyuA +-> ssh-ed25519 r+nK/Q VZ78YXTLV02fLztOFhwjtOOEJUePHRRISu+25KqDSU4 +0CTClX5iW8r4K7sYJ1KUAoWl2dMdSYXLWPg7qqCXqmY +-> ssh-rsa krWCLQ +f8bii+hhUGjahUDhiu4ia6GduIlZJDzYkF07+8/Yr3lmFB4CBNIYbNQB4lFP+ySt +LiDKGujSXRTW+gYsfLxxeorvUW1SChAEfhEo0OIxe232OHMuhdkMjsjP4dzA7LB/ +X+U1ucudEZSJkQ4yVcaVUPvF+aWNgo4atUBkQefgyPwxinIeSics5geNkld49nDR +CCZWnrKh3LnwNvALAQwLpFTNAydxd2tkGsAATOVt3BF1lYPmOMgm3ctmuCtbY8Ut +A9hlHhLuU4z/OdtFJRGAdqJY/RsK8DariHfKFeuBA68ewIhJAs25MAE1NpzMqv7Y +ZbIUUxfgUyrZerUdbWib3A +-> ssh-ed25519 /vwQcQ vnnat/wzxZ1oUeVlofB0g4itTk1PLWHvcnEk74jsWmY +9rRPEa08SyhE79YHeKpQRlpFOf90iNfiKkzlNWTIU90 +-> ssh-ed25519 0R97PA 07WwgxATASIpKY4noqT2KsfpU1uOUrsGPYHxcZLhYVk +D0Y1fVqhkY2x1IFQuCxSzgd4wGe+JpP9n3EOr0t/wag +-> ssh-ed25519 JGx7Ng uH6ol8O8I0XdfqIuQABEw3EkAcnBJzyWhoXBGaDnCWE +efUQavCLOU1Sf+3WrVBYkT/APBEha1LUblAzf20MypM +-> ssh-ed25519 5SY7Kg A7m5fAqCklsQXSraxPuTqCmn9sOeWRNZfuZPiPod0Ss +eswjSLtSwCrTKtjj9kMhcB3ENEv5BIqLqNvtOEKCU50 +-> ssh-ed25519 p/Mg4Q eGZZx/6eYqaOBTxzDjpI0q6nPR2rJhigP6ZDaX4B2Ws +i5ayqCNOppjOnZ+VOHJIXyvh7lxvVllN7LQ39jcUpjo +-> ssh-ed25519 IY5FSQ yVdfqr4gvmuooat0dpDE8qgg+u4B7wk22ZL9GfNEAyY +6UnaFiA8O4xSYv3oWfnZPTjEoWZmLPvETRaRDJ+OoEI +--- gm8frnlY8gZyBUHFZ2Y0a32eN/g/4jJ2SEROasXDsM8 +"Ǝ5; G5:U]ݫl2AŵXt +j;MHM \ No newline at end of file diff --git a/machines/web02/secrets/kadenios-secret_key_file b/machines/web02/secrets/kadenios-secret_key_file new file mode 100644 index 0000000..47b8a88 --- /dev/null +++ b/machines/web02/secrets/kadenios-secret_key_file @@ -0,0 +1,28 @@ +age-encryption.org/v1 +-> ssh-ed25519 jIXfPA lGxXHSOTd6/4opG9rD4dGIfwLkh80QwnQH3k/Bdw40U +iSxMULumde/wjuItTSzLUCPae54DLSsDr9EnfOZpBB0 +-> ssh-ed25519 QlRB9Q s3MHkCltaqzq4z3dvgofJ6TA/e3AEE6G1m/IHV8+J00 +38Ijpio00MzJuaHIpMhB/7q7UJqTR2Rd5M73iSp68PI +-> ssh-ed25519 r+nK/Q DhhmGmaiVu3mvWmeagrXmJW2aGfobWlubjiZc8MMbGA +GoHhGtaKc9L+0G4jV/lLatx2XfSY76H7f4f4c2s1YWc +-> ssh-rsa krWCLQ +yASlTiaPLO65jdL0zTDE98HMcci2TABJ5tyqTJ+xYFGK3SJop5Wy6EYi7cqTeI1m +eBzDmtTbcVguzjBRMnKUfs5WRk56opisogKmMUg3AeafzbU1p2tCLWuXDVi0yomV +W8W1NIMlryir2zV9H8Dz3JalKHrO5Lmds0exKQbHO2TV9lY3NOWrXANoVhCkNUPL +ALhWO1ir5GkPbYRbA4hpjUcGKB1RZCpUxJrySOY3/81JB3Cm58HbEVPInXQWA6RT +EFF24drIzrboiCMlA3mC4kGVh/VvTuKHad6tkD7f2QTnH1aa349dsAkDnXhT8g0x +/ZskJ1XYTdPcE750ukTMuQ +-> ssh-ed25519 /vwQcQ oONa9ea5Ku+T8j1yByMF/Dl70bQ2iQtLdEQo+N33pHs +sbDyjoo/JUmkHU55po1nUWcETCM9gLLCKUCzl/v0SOk +-> ssh-ed25519 0R97PA KjIt1uCiN1wAb9rfrb6Umn+Mq70InZ4QgYtg5jPnRhg +Yczl5z03SC0OEnmXlnqi6y8n29EBdos02OmvxDlkjZE +-> ssh-ed25519 JGx7Ng ZyeU+UDr2koLQqkNq73CCpritek2Qas35VsXq4bihSw +dt6VPfmeSjK+LZYePwuSWNN0t8DW/Qf/RHSvnpytVto +-> ssh-ed25519 5SY7Kg i65Y3HwkDpe+fqStT5hxzIdUD8pRmGCP7mDLankEAlI +nhhRDXK1pc8w9PHAlph25yOrHl3P7CpYQuR38v5T8s4 +-> ssh-ed25519 p/Mg4Q nJXPmPpBiGL7YH9EaYVyEcu5CAGRsEY63IMXB2h9HRs +AeaHkCdEu4z8XnsQFH7s1vtxLWBu1UJD+/otGORN9uQ +-> ssh-ed25519 IY5FSQ Z+PcELNysNxewbdV5wnXwoMqQXelKvaEzZg5eKHub0w +Q+kWcxmJvVgPbWjL/V+h7oQyhnj99QksIJDCidRxQfU +--- ZslNbCL9EymV6e2hseB75Nm5BgEVgYbNFHWExgdEw0A +t$'B'2ʹF͓}ޚ^B}.qŕ|e Z