diff --git a/.sops.yaml b/.sops.yaml index a0685dd..bd2189d 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -71,3 +71,12 @@ creation_rules: - *admin_evlli_pgp - *admin_jcgruenhage_pgp - *admin_transcaffeine_pgp + + - path_regex: secrets/services/tandoor.yaml + key_groups: + - age: + - *admin_xanderio_age + - *host_recipes_age + pgp: + - *admin_jcgruenhage_pgp + - *admin_transcaffeine_pgp diff --git a/hosts/recipes/default.nix b/hosts/recipes/default.nix index 1391bae..b961846 100644 --- a/hosts/recipes/default.nix +++ b/hosts/recipes/default.nix @@ -4,6 +4,7 @@ ./disko.nix inputs.disko.nixosModules.disko ../../profiles/entropia-cluster-vm + ./tandoor.nix ]; networking.hostName = "recipes"; diff --git a/hosts/recipes/tandoor.nix b/hosts/recipes/tandoor.nix new file mode 100644 index 0000000..15bfbfc --- /dev/null +++ b/hosts/recipes/tandoor.nix @@ -0,0 +1,140 @@ +{ config, lib, pkgs, ... }: { + config = { + x.sops.secrets = { + "services/tandoor/oidc_secret" = { }; + "services/tandoor/email_password" = { }; + }; + + sops.templates."tandoor-socialaccount-providers" = { + content = builtins.toJSON { + openid_connect = { + OAUTH_PKCE_ENABLED = "True"; + APPS = [ + { + provider_id = "keycloak"; + name = "Entropia SSO"; + client_id = "recipes.entropia.de"; + secret = config.sops.placeholder."services/tandoor/oidc_secret"; + settings.server_url = "https://sso.entropia.de/realms/entropia/.well-known/openid-configuration"; + } + ]; + }; + }; + }; + + services.postgresql = { + enable = true; + ensureUsers = [{ + name = "tandoor_recipes"; + ensureDBOwnership = true; + }]; + ensureDatabases = [ + "tandoor_recipes" + ]; + }; + + systemd.services.nginx.serviceConfig.SupplimentaryGroups = [ "tandoor_recipes" ]; + + services.nginx = { + enable = true; + virtualHosts."recipes.entropia.de" = { + enableACME = true; + forceSSL = true; + kTLS = true; + locations."/" = { + proxyPass = "http://${config.services.tandoor-recipes.address}:${toString config.services.tandoor-recipes.port}"; + recommendedProxySettings = true; + }; + locations."/media/".alias = "/var/lib/tandoor-recipes/"; + locations."= /metrics" = { + return = "404"; + }; + }; + }; + + services.vmagent.prometheusConfig.scrape_configs = [ + { + job_name = "tandoor"; + metrics_path = "/metrics"; + static_configs = [ + { + targets = [ "${config.services.tandoor-recipes.address}:${toString config.services.tandoor-recipes.port}" ]; + } + ]; + } + ]; + + services.tandoor-recipes = { + enable = true; + extraConfig = { + SOCIAL_PROVIDERS = "allauth.socialaccount.providers.openid_connect"; + SOCIALACCOUNT_ONLY = true; + + PRIVACY_URL = "https://entropia.de/Entropia:Datenschutz"; + IMPRINT_URL = "https://entropia.de/Impressum"; + + DB_ENGINE = "django.db.backends.postgresql"; + POSTGRES_DB = "tandoor_recipes"; + + ENABLE_METRICS = true; + + SORT_TREE_BY_NAME = true; + + # Space with ID 1 is public (entropia space) + SOCIAL_DEFAULT_ACCESS = 1; + SOCIAL_DEFAULT_GROUP = "user"; + + EMAIL_HOST = "mail.entropia.de"; + EMAIL_PORT = 587; + EMAIL_HOST_USER = "recipes@entropia.de"; + EMAIL_USE_TLS = true; + DEFAULT_FROM_EMAIL = "recipes@entropia.de"; + }; + }; + + users.users.tandoor_recipes = { + isSystemUser = true; + group = "tandoor_recipes"; + }; + users.groups.tandoor_recipes = { }; + + systemd.services.tandoor-recipes = { + serviceConfig = { + ExecStart = + let + secretKeyFile = "/var/lib/tandoor-recipes/nixos-secret-key"; + + startScript = pkgs.writeShellScript "start" '' + export EMAIL_HOST_PASSWORD=$(< ''${CREDENTIALS_DIRECTORY}/email_password) + export SOCIALACCOUNT_PROVIDERS=$(< ''${CREDENTIALS_DIRECTORY}/socialaccount-providers) + + if [[ ! -f '${secretKeyFile}' ]]; then + ( + umask 0377 + tr -dc A-Za-z0-9 < /dev/urandom | head -c64 | ${pkgs.moreutils}/bin/sponge '${secretKeyFile}' + ) + fi + export SECRET_KEY=$(< '${secretKeyFile}') + if [[ ! $SECRET_KEY ]]; then + echo "SECRET_KEY is empty, refusing to start." + exit 1 + fi + + ${config.services.tandoor-recipes.package.python.pkgs.gunicorn}/bin/gunicorn recipes.wsgi + ''; + in + lib.mkForce startScript; + LoadCredential = [ + "socialaccount-providers:${config.sops.templates.tandoor-socialaccount-providers.path}" + "email_password:${config.sops.secrets."services/tandoor/email_password".path}" + ]; + BindReadOnlyPaths = [ + config.sops.templates.tandoor-socialaccount-providers.path + config.sops.secrets."services/tandoor/email_password".path + ]; + # With DynamicUser enabled nginx is unable to access the StateDirectory where the images are stored. + DynamicUser = lib.mkForce false; + }; + }; + }; +} diff --git a/secrets/hosts/recipes.yaml b/secrets/hosts/recipes.yaml index a41d1d8..ecfe0c9 100644 --- a/secrets/hosts/recipes.yaml +++ b/secrets/hosts/recipes.yaml @@ -1,6 +1,6 @@ hosts: recipes: - backup_zweitwohnsitz_password: ENC[AES256_GCM,data:RtFm,iv:8lxqqGywhPvh05Pzkd9HBvc7rX7m+HqRXXBzS5W1L04=,tag:uIu2R4SBglN/gtw+hGDxtg==,type:str] + backup_zweitwohnsitz_password: ENC[AES256_GCM,data:ilwz99RcnNLXC8TiePTR7Uqn22qZgJbUru4m9cnNi2593VkYUE4XhIl4m9yyjy3QTewzLlsPMSROUtZkwTBuvSemMzGvyHgekXYB3S+mOaplFAXVP5Ml9HT8Rr1f5Z5OKftueogM/4E58K2yE8JeoyX3GkJ5572xy4lZNE9vBtE=,iv:G3V8zOiMNWexK7GVrXf4WDQSZoFZ4Cy/djTxKxYzVsU=,tag:c9WyTGpk+vjfzXX1tmG1Pw==,type:str] sops: kms: [] gcp_kms: [] @@ -25,8 +25,8 @@ sops: WlhBMGl4bE1XaGE1RSs0THhzTkQrekEKqkZIm6L61KrnCqpzXrfEKD5COx/wyNht jCFcPxRgDu2Fbat2hbOhJXLTwJx2/SQyNtcCT6map7CcVIckUA2QAA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-05-19T16:34:22Z" - mac: ENC[AES256_GCM,data:m0TqLCAIXZjg6TSo+0ATeK5JO304nHun4UM4a0chZ65WWdg1GV0TyMITtu/x+mfzIVLFiHU/Bbhi8foP2RcVjsxNoo9p8SpfTarDbIplRaJqn11uaS714tEwIuoCmehPZx1fC2zAUcUiNYf1nRz5/4MZ2m2jio01bWOx92TOEGo=,iv:Ozjl2q7ey7Ey4OdWXYlleVXVhXSf7VlJ6Sn3EmLCrK8=,tag:B2k3i73zMZJ+mSPTmjQzCg==,type:str] + lastmodified: "2024-05-26T13:19:02Z" + mac: ENC[AES256_GCM,data:YPC+tQes0wYvb0XX4l8p+30gsuZ/Iq1ieDp1qXIV/G7R90BVlM/DD6tPkLN8OMkQXLpQ/1c5QuujKVzy061GXbeqC7DsVG/+QBGvck0wsAtxI+GOfrUDRsuPvOJk/IvQlYjyWDl41clwMOfmDklwYps3IuPRrraxiCA6IxoVGyo=,iv:zWesK+8WL+HHPQloYOl2kKs5tFOBOav0M+vWiY/3u9A=,tag:gu/bCKFVlZoRTyNJqcYaQQ==,type:str] pgp: - created_at: "2024-05-21T16:34:00Z" enc: |- diff --git a/secrets/services/tandoor.yaml b/secrets/services/tandoor.yaml new file mode 100644 index 0000000..5de7071 --- /dev/null +++ b/secrets/services/tandoor.yaml @@ -0,0 +1,64 @@ +services: + tandoor: + oidc_secret: ENC[AES256_GCM,data:ZlZMO2yL1fCkQRcCvKwmzo3rVFxm01Ic9eVW404TzwE=,iv:2tXWLyOf4HgrpJD5tfFNWl/JMgl1Snou1GZN25FtV1Q=,tag:cp4g84CPHQ8vWB/onmMZ8g==,type:str] + email_password: ENC[AES256_GCM,data:WHMlZwzuy9pjhkE=,iv:IlhdC5npH1i0XcFt1IHxmxBb4CFvD7Xf6R6ziXpZpgA=,tag:yU+R5UrNBNhQSuZ3r2BlCQ==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1e9yparaev0gxwmherrjpxmfzgqga5eqdw53lrnv05s3ppjgzyceqftnwpx + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2dTN5OEowZDRoNlY3L2ly + UXpuNEx0REI1eUdhZXYzRVV3OFFqYWZzSlRVCitJMXRwTDkvVmdQb05oUitSLytI + b1dnMit0KzhsVG9COGJBSWNTem50ZEUKLS0tIHhkVlFWUm8zRUJyMnppN2ZLTGJk + V3l6MmEycDhPd05FazZDbWgzOUt6UGsKwltRXlNAg6eT9hzhebr4kL3vBCRzxGK6 + /o/gANqKCqJ/xMUeAgJHaVEdnf8s5yo9X6tFk8BdLbyNbDUjsqeMSg== + -----END AGE ENCRYPTED FILE----- + - recipient: age1zngzchzzy46gyn99awcw2fgn97wuv35afyqrat9442sakgv0ugls606zlr + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLVmRRd3dxWE8zeFVoT1lJ + UFViUC9LVXVnbGxNekxFc05Kd3NFRTdQWmtFCmpyRmk4NzZEQytmR0U1ZHF0RWts + ald6TytIOXA0SWVCb09IenMzR2lrcHcKLS0tIHZpTks4dWZaQ2RUN1JVb1NNK1Ra + ZldiVkdNTkk4OUhadXZGczJGdWhzMG8KaFJWAVOPOeZqlrohlH1EY6Y79MCF1WLd + cbpPDxt08u5gCvlzKes1UIL3/Da0evaOv3WfycQPLxaPwZzkuQnwiw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-05-26T13:45:06Z" + mac: ENC[AES256_GCM,data:x9qZQtIrNvNmwVj2b7Zvr8IWVopYEakzfVu890Bw1okejMnn369WsmWZU6eC9QvDtvF+tvDr8dV0hqhw/MZxW5snCOtWNowpF9hzFYbfOI447tcNlU8DqaSCSG3O3b9KpRUSM7dv5lyo9gH2d6YBFWB5RGK6hZR8dzxw1RrAojA=,iv:2C82F00XgQ9rpJT4961P+KRwc7M26ZhRBUaZ1ELUyp8=,tag:qcrxrBFCfD/291fqI6FnuA==,type:str] + pgp: + - created_at: "2024-05-21T19:07:39Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DQJGoFMUUQaUSAQdAe5AxV6rKOXuC1IhZlmA0p1/88Dyo/nMDtsWNgimhfRkw + C3DGddkB4AtfkqLtuFJyHYwNypNNF2xcJfRWr0f1hv4FgpGb8x6CFb7d3lqe6RSv + 0l4BXGadNK865LbUFAZllPRQckMe3NEp2bqqdbulJ/hCbBnUzhUNXtT8myfmO0lc + 1o5nHgDlnYrBg0NFgBHA7Cz8YBRqyFcQD+SPbpdiwmUHSCSdE/Lx2V8GukYpkGxc + =SzFT + -----END PGP MESSAGE----- + fp: 09E8418B46B53B0F825DE4BE018ACF465280F466 + - created_at: "2024-05-21T19:07:39Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAxEs7W/4x4lxAQ/9Gy4kBEvrSlTYFUlcGiQvzkyhupWgcAVOgcMPRfXZcL1O + ueZs3h7iugWZVO+jkvHGeCM0TO4IWsxoiJ9LAaa50AE6h7umKqi7h3UwFe9Fw2A0 + 1B1CApqFZ8z6/xxrUMVl/jX6dp3YwjBGGvuD4lrpf9nlUXVw3QGBeFVfJxat48Vt + zXW/5/EXvqSk8cHQtsWMD5BSR1kHYh5hUXvrc9Jhtz3QGuNdSRRQvRmGaN8teTWC + RNrFcPOThcs6wOd4RijXWVZ5o9OmuGx6O5pSaYnVGdE0IHPn49+k9Jd1Vce5xy5y + LlxJ88bXp3bN42U7pddBJ9I9r8vW6xhcYuX46sICwvPhQF6sa3hiTxnemnWI+B6m + ivQh/IamoFs1KTXGG8NVtLT29k91pB3ighZqkeR6tG1Kh5w3inVfzU909G/VtmQ9 + qiPQyCG7R4GaETWLLoGFi96N4WT06L66T1CyPnnm0ee/TBegr6yqDQj5fh72qF9L + tt4FUY96DgKoQ2s3M2oYiWKp96nTNiH4PUFWrL+Srp+NCurdRSkuWkGepbz2pjxo + x0B9t9TVut8lCiqJncPb0+NdLWm4zG/ILR3vdyXfNqt6MCZ1oW7QCOvlI5ahWJOG + uN6kLFVMiip+3C75tLSfW/j7XV9VN3uxZw2ULvkGr76mcMQVH90EhGlq04ZNZ2fS + XgFzt0EEdm2iCs94M2Ck0BJ6Lpbd0uvY1daM4r7+A/4V+AcrY8UP19QLGSnWHH7P + /5G7BhwM0fS8/z9bV5wcpSzZOiQhk9Tz9gXBzCyJhZb1NTpl9zHWlzE0N4tfc28= + =P2w7 + -----END PGP MESSAGE----- + fp: 5E0A9CB3980657CB9AB94AE6790EAEC8F99AB41F + unencrypted_suffix: _unencrypted + version: 3.8.1