From ade4923a9d4d9b8597481b7fc4a2af2506e27189 Mon Sep 17 00:00:00 2001 From: self Date: Sun, 2 Jul 2023 17:43:59 -0700 Subject: [PATCH] configure lemmy staging and dev instances --- hosts/these/configuration.nix | 29 ++- lemmy/dev/default.nix | 65 +++++++ lemmy/dev/module.nix | 266 ++++++++++++++++++++++++++++ lemmy/{ => prod}/default.nix | 6 +- lemmy/{prod.nix => prod/module.nix} | 0 lemmy/staging/default.nix | 65 +++++++ lemmy/staging/module.nix | 266 ++++++++++++++++++++++++++++ secrets/secrets.yaml | 16 +- 8 files changed, 704 insertions(+), 9 deletions(-) create mode 100644 lemmy/dev/default.nix create mode 100644 lemmy/dev/module.nix rename lemmy/{ => prod}/default.nix (91%) rename lemmy/{prod.nix => prod/module.nix} (100%) create mode 100644 lemmy/staging/default.nix create mode 100644 lemmy/staging/module.nix diff --git a/hosts/these/configuration.nix b/hosts/these/configuration.nix index 86e11e0..bf527a2 100644 --- a/hosts/these/configuration.nix +++ b/hosts/these/configuration.nix @@ -5,15 +5,36 @@ ../../hardware/hetzner-cloud/cx21.nix ../../secrets ../../pass - #../../lemmy + ../../lemmy/staging + ../../lemmy/dev ../../maint-mode ../../git ]; networking.hostName = "these"; - awful.systems.maint-mode = { - enable = true; - virtualHost = "awful.systems"; + services.nginx = { + recommendedProxySettings = true; + recommendedTlsSettings = true; + + virtualHosts = { + "breaking.awful.systems" = { + addSSL = true; + enableACME = true; + }; + + "making.awful.systems" = { + addSSL = true; + enableACME = true; + }; + + }; }; + + security.acme = { + acceptTerms = true; + defaults.email = "self@awful.systems"; + }; + + networking.firewall.allowedTCPPorts = [ 443 ]; } diff --git a/lemmy/dev/default.nix b/lemmy/dev/default.nix new file mode 100644 index 0000000..7bf0d31 --- /dev/null +++ b/lemmy/dev/default.nix @@ -0,0 +1,65 @@ +{ config, lib, pkgs, pkgs-unstable, ... }: + +{ + imports = [ ./module.nix ]; + + services.lemmy-dev = { + enable = true; + server.package = pkgs.callPackage ../server.nix { Security = null; }; + ui.package = pkgs.callPackage ../ui.nix { }; + nginx.enable = true; + database.createLocally = true; + + settings = { + hostname = "making.awful.systems"; + setup = { + admin_username = "self"; + admin_email = "self@awful.systems"; + site_name = "a.s dev"; + }; + database = { + user = "lemmy_dev"; + database = "lemmy_dev"; + }; + }; + }; + + sops.secrets."lemmy-dev/initial_admin_password" = { }; + sops.secrets."lemmy-dev/smtp_server" = { }; + sops.secrets."lemmy-dev/smtp_login" = { }; + sops.secrets."lemmy-dev/smtp_password" = { }; + sops.secrets."lemmy-dev/smtp_from_address" = { }; + + sops.templates.lemmy-dev.content = builtins.toJSON + (config.services.lemmy-dev.settings // { + setup = config.services.lemmy-dev.settings.setup // { + admin_password = config.sops.placeholder."lemmy-dev/initial_admin_password"; + }; + + # email = { + # smtp_server = config.sops.placeholder."lemmy-dev/smtp_server"; + # smtp_login = config.sops.placeholder."lemmy-dev/smtp_login"; + # smtp_password = config.sops.placeholder."lemmy-dev/smtp_password"; + # smtp_from_address = config.sops.placeholder."lemmy-dev/smtp_from_address"; + # tls_type = "tls"; + # }; + }); + + systemd.services.lemmy-dev = { + serviceConfig = { + User = "lemmy_dev"; + Group = "lemmy_dev"; + LoadCredential = + "lemmy-dev:${config.sops.templates.lemmy-dev.path}"; + }; + + environment = { + LEMMY_CONFIG_LOCATION = lib.mkForce "%d/lemmy-dev"; + RUST_BACKTRACE = "full"; + LEMMY_DATABASE_URL = pkgs.lib.mkForce + "postgres:///lemmy_dev?host=/run/postgresql&user=lemmy_dev"; + }; + }; + + networking.firewall.allowedTCPPorts = [ 80 ]; +} diff --git a/lemmy/dev/module.nix b/lemmy/dev/module.nix new file mode 100644 index 0000000..8ae458d --- /dev/null +++ b/lemmy/dev/module.nix @@ -0,0 +1,266 @@ +{ lib, pkgs, config, ... }: +with lib; +let + cfg = config.services.lemmy-dev; + settingsFormat = pkgs.formats.json { }; +in { + imports = [ + (mkRemovedOptionModule [ "services" "lemmy-dev" "jwtSecretPath" ] + "As of v0.13.0, Lemmy auto-generates the JWT secret.") + ]; + + options.services.lemmy-dev = { + + enable = mkEnableOption + (lib.mdDoc "lemmy a federated alternative to reddit in rust"); + + server = { package = mkPackageOptionMD pkgs "lemmy-server" { }; }; + + ui = { + package = mkPackageOptionMD pkgs "lemmy-ui" { }; + + port = mkOption { + type = types.port; + default = 1236; + description = + lib.mdDoc "Port where lemmy-ui should listen for incoming requests."; + }; + }; + + caddy.enable = + mkEnableOption (lib.mdDoc "exposing lemmy with the caddy reverse proxy"); + nginx.enable = + mkEnableOption (lib.mdDoc "exposing lemmy with the nginx reverse proxy"); + + database = { + createLocally = + mkEnableOption (lib.mdDoc "creation of database on the instance"); + + uri = mkOption { + type = with types; nullOr str; + default = null; + description = lib.mdDoc + "The connection URI to use. Takes priority over the configuration file if set."; + }; + }; + + settings = mkOption { + default = { }; + description = lib.mdDoc "Lemmy configuration"; + + type = types.submodule { + freeformType = settingsFormat.type; + + options.hostname = mkOption { + type = types.str; + default = null; + description = + lib.mdDoc "The domain name of your instance (eg 'lemmy.ml')."; + }; + + options.port = mkOption { + type = types.port; + default = 8538; + description = + lib.mdDoc "Port where lemmy should listen for incoming requests."; + }; + + options.captcha = { + enabled = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc "Enable Captcha."; + }; + difficulty = mkOption { + type = types.enum [ "easy" "medium" "hard" ]; + default = "medium"; + description = lib.mdDoc "The difficultly of the captcha to solve."; + }; + }; + }; + }; + + }; + + config = lib.mkIf cfg.enable { + services.lemmy-dev.settings = (mapAttrs (name: mkDefault) { + bind = "127.0.0.1"; + tls_enabled = true; + pictrs_url = with config.services.pict-rs; + "http://${address}:${toString port}"; + actor_name_max_length = 20; + + rate_limit.message = 180; + rate_limit.message_per_second = 60; + rate_limit.post = 6; + rate_limit.post_per_second = 600; + rate_limit.register = 3; + rate_limit.register_per_second = 3600; + rate_limit.image = 6; + rate_limit.image_per_second = 3600; + } // { + database = mapAttrs (name: mkDefault) { + user = "lemmy"; + host = "/run/postgresql"; + port = 5432; + database = "lemmy"; + pool_size = 5; + }; + }); + + services.postgresql = mkIf cfg.database.createLocally { + enable = true; + ensureDatabases = [ cfg.settings.database.database ]; + ensureUsers = [{ + name = cfg.settings.database.user; + ensurePermissions."DATABASE ${cfg.settings.database.database}" = + "ALL PRIVILEGES"; + }]; + }; + + services.pict-rs.enable = true; + + services.caddy = mkIf cfg.caddy.enable { + enable = mkDefault true; + virtualHosts."${cfg.settings.hostname}" = { + extraConfig = '' + handle_path /static/* { + root * ${cfg.ui.package}/dist + file_server + } + @for_backend { + path /api/* /pictrs/* /feeds/* /nodeinfo/* + } + handle @for_backend { + reverse_proxy 127.0.0.1:${toString cfg.settings.port} + } + @post { + method POST + } + handle @post { + reverse_proxy 127.0.0.1:${toString cfg.settings.port} + } + @jsonld { + header Accept "application/activity+json" + header Accept "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"" + } + handle @jsonld { + reverse_proxy 127.0.0.1:${toString cfg.settings.port} + } + handle { + reverse_proxy 127.0.0.1:${toString cfg.ui.port} + } + ''; + }; + }; + + services.nginx = mkIf cfg.nginx.enable { + enable = mkDefault true; + virtualHosts."${cfg.settings.hostname}".locations = let + ui = "http://127.0.0.1:${toString cfg.ui.port}"; + backend = "http://127.0.0.1:${toString cfg.settings.port}"; + in { + "~ ^/(api|pictrs|feeds|nodeinfo|.well-known)" = { + # backend requests + proxyPass = backend; + proxyWebsockets = true; + recommendedProxySettings = true; + }; + "/" = { + # mixed frontend and backend requests, based on the request headers + proxyPass = "$proxpass"; + recommendedProxySettings = true; + extraConfig = '' + set $proxpass "${ui}"; + if ($http_accept = "application/activity+json") { + set $proxpass "${backend}"; + } + if ($http_accept = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") { + set $proxpass "${backend}"; + } + if ($request_method = POST) { + set $proxpass "${backend}"; + } + + # Cuts off the trailing slash on URLs to make them valid + rewrite ^(.+)/+$ $1 permanent; + ''; + }; + }; + }; + + assertions = [ + { + assertion = cfg.database.createLocally -> cfg.settings.database.host + == "localhost" || cfg.settings.database.host == "/run/postgresql"; + message = + "if you want to create the database locally, you need to use a local database"; + } + { + assertion = (!(hasAttrByPath [ "federation" ] cfg.settings)) + && (!(hasAttrByPath [ "federation" "enabled" ] cfg.settings)); + message = + "`services.lemmy.settings.federation` was removed in 0.17.0 and no longer has any effect"; + } + ]; + + systemd.services.lemmy-dev = { + description = "Lemmy server (dev)"; + + environment = { + LEMMY_CONFIG_LOCATION = + "${settingsFormat.generate "config.hjson" cfg.settings}"; + LEMMY_DATABASE_URL = mkIf (cfg.database.uri != null) cfg.database.uri; + }; + + documentation = [ + "https://join-lemmy.org/docs/en/admins/from_scratch.html" + "https://join-lemmy.org/docs/en/" + ]; + + wantedBy = [ "multi-user.target" ]; + + after = [ "pict-rs.service" ] + ++ lib.optionals cfg.database.createLocally [ "postgresql.service" ]; + + requires = + lib.optionals cfg.database.createLocally [ "postgresql.service" ]; + + serviceConfig = { + DynamicUser = true; + RuntimeDirectory = "lemmy"; + ExecStart = "${cfg.server.package}/bin/lemmy_server"; + }; + }; + + systemd.services.lemmy-ui-dev = { + description = "Lemmy UI (dev)"; + + environment = { + LEMMY_UI_HOST = "127.0.0.1:${toString cfg.ui.port}"; + LEMMY_UI_LEMMY_INTERNAL_HOST = "127.0.0.1:${toString cfg.settings.port}"; + LEMMY_UI_LEMMY_EXTERNAL_HOST = cfg.settings.hostname; + LEMMY_UI_HTTPS = "false"; + }; + + documentation = [ + "https://join-lemmy.org/docs/en/admins/from_scratch.html" + "https://join-lemmy.org/docs/en/" + ]; + + wantedBy = [ "multi-user.target" ]; + + after = [ "lemmy-dev.service" ]; + + requires = [ "lemmy-dev.service" ]; + + serviceConfig = { + DynamicUser = true; + WorkingDirectory = "${cfg.ui.package}"; + ExecStart = + "${pkgs.nodejs}/bin/node ${cfg.ui.package}/dist/js/server.js"; + }; + }; + }; + +} diff --git a/lemmy/default.nix b/lemmy/prod/default.nix similarity index 91% rename from lemmy/default.nix rename to lemmy/prod/default.nix index 85ae4ca..c615c02 100644 --- a/lemmy/default.nix +++ b/lemmy/prod/default.nix @@ -1,12 +1,12 @@ { config, lib, pkgs, pkgs-unstable, ... }: { - imports = [ ./prod.nix ]; + imports = [ ./module.nix ]; services.lemmy-prod = { enable = true; - server.package = pkgs.callPackage ./server.nix { Security = null; }; - ui.package = pkgs.callPackage ./ui.nix { }; + server.package = pkgs.callPackage ../server.nix { Security = null; }; + ui.package = pkgs.callPackage ../ui.nix { }; nginx.enable = true; database.createLocally = true; diff --git a/lemmy/prod.nix b/lemmy/prod/module.nix similarity index 100% rename from lemmy/prod.nix rename to lemmy/prod/module.nix diff --git a/lemmy/staging/default.nix b/lemmy/staging/default.nix new file mode 100644 index 0000000..58f3a82 --- /dev/null +++ b/lemmy/staging/default.nix @@ -0,0 +1,65 @@ +{ config, lib, pkgs, pkgs-unstable, ... }: + +{ + imports = [ ./module.nix ]; + + services.lemmy-staging = { + enable = true; + server.package = pkgs.callPackage ../server.nix { Security = null; }; + ui.package = pkgs.callPackage ../ui.nix { }; + nginx.enable = true; + database.createLocally = true; + + settings = { + hostname = "breaking.awful.systems"; + setup = { + admin_username = "self"; + admin_email = "self@awful.systems"; + site_name = "a.s staging"; + }; + database = { + user = "lemmy_staging"; + database = "lemmy_staging"; + }; + }; + }; + + sops.secrets."lemmy-staging/initial_admin_password" = { }; + sops.secrets."lemmy-staging/smtp_server" = { }; + sops.secrets."lemmy-staging/smtp_login" = { }; + sops.secrets."lemmy-staging/smtp_password" = { }; + sops.secrets."lemmy-staging/smtp_from_address" = { }; + + sops.templates.lemmy-staging.content = builtins.toJSON + (config.services.lemmy-staging.settings // { + setup = config.services.lemmy-staging.settings.setup // { + admin_password = config.sops.placeholder."lemmy-staging/initial_admin_password"; + }; + + # email = { + # smtp_server = config.sops.placeholder."lemmy-staging/smtp_server"; + # smtp_login = config.sops.placeholder."lemmy-staging/smtp_login"; + # smtp_password = config.sops.placeholder."lemmy-staging/smtp_password"; + # smtp_from_address = config.sops.placeholder."lemmy-staging/smtp_from_address"; + # tls_type = "tls"; + # }; + }); + + systemd.services.lemmy-staging = { + serviceConfig = { + User = "lemmy_staging"; + Group = "lemmy_staging"; + LoadCredential = + "lemmy-staging:${config.sops.templates.lemmy-staging.path}"; + }; + + environment = { + LEMMY_CONFIG_LOCATION = lib.mkForce "%d/lemmy-staging"; + RUST_BACKTRACE = "full"; + LEMMY_DATABASE_URL = pkgs.lib.mkForce + "postgres:///lemmy_staging?host=/run/postgresql&user=lemmy_staging"; + }; + }; + + networking.firewall.allowedTCPPorts = [ 80 ]; +} diff --git a/lemmy/staging/module.nix b/lemmy/staging/module.nix new file mode 100644 index 0000000..87a9063 --- /dev/null +++ b/lemmy/staging/module.nix @@ -0,0 +1,266 @@ +{ lib, pkgs, config, ... }: +with lib; +let + cfg = config.services.lemmy-staging; + settingsFormat = pkgs.formats.json { }; +in { + imports = [ + (mkRemovedOptionModule [ "services" "lemmy-staging" "jwtSecretPath" ] + "As of v0.13.0, Lemmy auto-generates the JWT secret.") + ]; + + options.services.lemmy-staging = { + + enable = mkEnableOption + (lib.mdDoc "lemmy a federated alternative to reddit in rust"); + + server = { package = mkPackageOptionMD pkgs "lemmy-server" { }; }; + + ui = { + package = mkPackageOptionMD pkgs "lemmy-ui" { }; + + port = mkOption { + type = types.port; + default = 1235; + description = + lib.mdDoc "Port where lemmy-ui should listen for incoming requests."; + }; + }; + + caddy.enable = + mkEnableOption (lib.mdDoc "exposing lemmy with the caddy reverse proxy"); + nginx.enable = + mkEnableOption (lib.mdDoc "exposing lemmy with the nginx reverse proxy"); + + database = { + createLocally = + mkEnableOption (lib.mdDoc "creation of database on the instance"); + + uri = mkOption { + type = with types; nullOr str; + default = null; + description = lib.mdDoc + "The connection URI to use. Takes priority over the configuration file if set."; + }; + }; + + settings = mkOption { + default = { }; + description = lib.mdDoc "Lemmy configuration"; + + type = types.submodule { + freeformType = settingsFormat.type; + + options.hostname = mkOption { + type = types.str; + default = null; + description = + lib.mdDoc "The domain name of your instance (eg 'lemmy.ml')."; + }; + + options.port = mkOption { + type = types.port; + default = 8537; + description = + lib.mdDoc "Port where lemmy should listen for incoming requests."; + }; + + options.captcha = { + enabled = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc "Enable Captcha."; + }; + difficulty = mkOption { + type = types.enum [ "easy" "medium" "hard" ]; + default = "medium"; + description = lib.mdDoc "The difficultly of the captcha to solve."; + }; + }; + }; + }; + + }; + + config = lib.mkIf cfg.enable { + services.lemmy-staging.settings = (mapAttrs (name: mkDefault) { + bind = "127.0.0.1"; + tls_enabled = true; + pictrs_url = with config.services.pict-rs; + "http://${address}:${toString port}"; + actor_name_max_length = 20; + + rate_limit.message = 180; + rate_limit.message_per_second = 60; + rate_limit.post = 6; + rate_limit.post_per_second = 600; + rate_limit.register = 3; + rate_limit.register_per_second = 3600; + rate_limit.image = 6; + rate_limit.image_per_second = 3600; + } // { + database = mapAttrs (name: mkDefault) { + user = "lemmy"; + host = "/run/postgresql"; + port = 5432; + database = "lemmy"; + pool_size = 5; + }; + }); + + services.postgresql = mkIf cfg.database.createLocally { + enable = true; + ensureDatabases = [ cfg.settings.database.database ]; + ensureUsers = [{ + name = cfg.settings.database.user; + ensurePermissions."DATABASE ${cfg.settings.database.database}" = + "ALL PRIVILEGES"; + }]; + }; + + services.pict-rs.enable = true; + + services.caddy = mkIf cfg.caddy.enable { + enable = mkDefault true; + virtualHosts."${cfg.settings.hostname}" = { + extraConfig = '' + handle_path /static/* { + root * ${cfg.ui.package}/dist + file_server + } + @for_backend { + path /api/* /pictrs/* /feeds/* /nodeinfo/* + } + handle @for_backend { + reverse_proxy 127.0.0.1:${toString cfg.settings.port} + } + @post { + method POST + } + handle @post { + reverse_proxy 127.0.0.1:${toString cfg.settings.port} + } + @jsonld { + header Accept "application/activity+json" + header Accept "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"" + } + handle @jsonld { + reverse_proxy 127.0.0.1:${toString cfg.settings.port} + } + handle { + reverse_proxy 127.0.0.1:${toString cfg.ui.port} + } + ''; + }; + }; + + services.nginx = mkIf cfg.nginx.enable { + enable = mkDefault true; + virtualHosts."${cfg.settings.hostname}".locations = let + ui = "http://127.0.0.1:${toString cfg.ui.port}"; + backend = "http://127.0.0.1:${toString cfg.settings.port}"; + in { + "~ ^/(api|pictrs|feeds|nodeinfo|.well-known)" = { + # backend requests + proxyPass = backend; + proxyWebsockets = true; + recommendedProxySettings = true; + }; + "/" = { + # mixed frontend and backend requests, based on the request headers + proxyPass = "$proxpass"; + recommendedProxySettings = true; + extraConfig = '' + set $proxpass "${ui}"; + if ($http_accept = "application/activity+json") { + set $proxpass "${backend}"; + } + if ($http_accept = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") { + set $proxpass "${backend}"; + } + if ($request_method = POST) { + set $proxpass "${backend}"; + } + + # Cuts off the trailing slash on URLs to make them valid + rewrite ^(.+)/+$ $1 permanent; + ''; + }; + }; + }; + + assertions = [ + { + assertion = cfg.database.createLocally -> cfg.settings.database.host + == "localhost" || cfg.settings.database.host == "/run/postgresql"; + message = + "if you want to create the database locally, you need to use a local database"; + } + { + assertion = (!(hasAttrByPath [ "federation" ] cfg.settings)) + && (!(hasAttrByPath [ "federation" "enabled" ] cfg.settings)); + message = + "`services.lemmy.settings.federation` was removed in 0.17.0 and no longer has any effect"; + } + ]; + + systemd.services.lemmy-staging = { + description = "Lemmy server (staging)"; + + environment = { + LEMMY_CONFIG_LOCATION = + "${settingsFormat.generate "config.hjson" cfg.settings}"; + LEMMY_DATABASE_URL = mkIf (cfg.database.uri != null) cfg.database.uri; + }; + + documentation = [ + "https://join-lemmy.org/docs/en/admins/from_scratch.html" + "https://join-lemmy.org/docs/en/" + ]; + + wantedBy = [ "multi-user.target" ]; + + after = [ "pict-rs.service" ] + ++ lib.optionals cfg.database.createLocally [ "postgresql.service" ]; + + requires = + lib.optionals cfg.database.createLocally [ "postgresql.service" ]; + + serviceConfig = { + DynamicUser = true; + RuntimeDirectory = "lemmy"; + ExecStart = "${cfg.server.package}/bin/lemmy_server"; + }; + }; + + systemd.services.lemmy-ui-staging = { + description = "Lemmy UI (staging)"; + + environment = { + LEMMY_UI_HOST = "127.0.0.1:${toString cfg.ui.port}"; + LEMMY_UI_LEMMY_INTERNAL_HOST = "127.0.0.1:${toString cfg.settings.port}"; + LEMMY_UI_LEMMY_EXTERNAL_HOST = cfg.settings.hostname; + LEMMY_UI_HTTPS = "false"; + }; + + documentation = [ + "https://join-lemmy.org/docs/en/admins/from_scratch.html" + "https://join-lemmy.org/docs/en/" + ]; + + wantedBy = [ "multi-user.target" ]; + + after = [ "lemmy-staging.service" ]; + + requires = [ "lemmy-staging.service" ]; + + serviceConfig = { + DynamicUser = true; + WorkingDirectory = "${cfg.ui.package}"; + ExecStart = + "${pkgs.nodejs}/bin/node ${cfg.ui.package}/dist/js/server.js"; + }; + }; + }; + +} diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml index 4e2432e..530e9e2 100644 --- a/secrets/secrets.yaml +++ b/secrets/secrets.yaml @@ -4,6 +4,18 @@ lemmy: smtp_login: ENC[AES256_GCM,data:ud57LkAv,iv:leOnFXK8Lm5W33UcrgAEMyb+baMcVMu687s7ih1Zp/g=,tag:7llUqPlMHEQuzsa+kNqaoA==,type:str] smtp_password: ENC[AES256_GCM,data:vrqLNdNO0v3gSGF9A/I8rJ7JhgRpQXHulnJlFj0OTNDBWt+Mi7g1r8n2XDvf8YFPh6N15i98QvzHZ0lWo3PCRoYqbOz9,iv:3+/S6OzsdsNivGNEpsm74rmq5pp4n1RcwC0dNuhALcM=,tag:Oao44DUS4I8TjeQuyKzDmw==,type:str] smtp_from_address: ENC[AES256_GCM,data:kpzULJxgqLbO5W6aDOao9OI=,iv:uCKQHZKFmStYmY4M4h1PnBwT1lHXiZeXXEYHPrbxEl8=,tag:ioMYOYuUYfxvX/K21KlzLw==,type:str] +lemmy-staging: + initial_admin_password: ENC[AES256_GCM,data:lAI52w5iEj+200bM+WNLdw==,iv:t4vMoyAzrUt5KnL5uT3loEz5zNcx+608A8/09DAFgTk=,tag:ZSLMdPRTUeX4xnYpwXpGvQ==,type:str] + smtp_server: ENC[AES256_GCM,data:CJZz4rxPgnwRyXVXY+aBP/c16Hag,iv:2D05+ZmLlbrhxaCFAZSwkR2itZOpPzfaPdvUJeQClZg=,tag:WHfZIf+1B8b15mtlTxgXgg==,type:str] + smtp_login: ENC[AES256_GCM,data:c05hsXpk,iv:S6m/BmUedMZvExTFdvkK41MhKcdOpXIFFsy8JRzDBpA=,tag:ISzUbU9V7iKC8rRrQjaqkQ==,type:str] + smtp_password: ENC[AES256_GCM,data:7uLqIkz9Hs/qFl20Mu6nvRgYNfzwN1fVf5jrgKCNVc2tCkek0LoMuFMoqSDohPRaLd459PNIoA+VrEwoVr9t23zpFJfe,iv:+OKiouo6YSsSRhN5GNrRhkJ48pw2fcHxUVhCtXj+vBw=,tag:sWiLDDfNfEOVNmMlRyeAvQ==,type:str] + smtp_from_address: ENC[AES256_GCM,data:DczTYEKW5PMhax/lp7Zmj6o=,iv:prcUFdyCst7DnCNqbM9cE+g3pap0KEHdyMrS/2CsxE0=,tag:X2e7IjkXbiQUxUEw/Cty8w==,type:str] +lemmy-dev: + initial_admin_password: ENC[AES256_GCM,data:7cQbzsfOn9l/6RI/2o6sWA==,iv:hdOWBMmt7WxD9vIUZ/V9PbEkGXCmj0NDVBwWIqjTmd4=,tag:iAgEJQO+mXSHN6MB8iwc0Q==,type:str] + smtp_server: ENC[AES256_GCM,data:Ldk72toeDAZGkyZhyr2PlNg3HM/e,iv:e+mCtSWi0qI5XGaI1RABQWeJMGmUucWqHDZdsK42O90=,tag:6ChHbPw2bNehtlXSmEnMkA==,type:str] + smtp_login: ENC[AES256_GCM,data:qwwuoUn2,iv:i+UQJZ30e7tLsV7755TYlAeGmB453t3F4rL4FgJaoio=,tag:54ZO7qMpbjuNT45HF7vaIQ==,type:str] + smtp_password: ENC[AES256_GCM,data:gx9P8gv3RuH7RkdapuqZ8z+y4nkwKOXJ9dYRRn+TEh/jQ2Zl3yWWJ1HKxrNJlzdidPtTEph7Z7YrQn5PzlNEfdBsMsXy,iv:4Aaa/2/X6NWPkX9UvN5FhyynbF4ADWG3+FTHXJCRlkY=,tag:RbVXS2lQNIiIseE7TTcmtg==,type:str] + smtp_from_address: ENC[AES256_GCM,data:55Ljo/B0JJBOBuUvFoFXino=,iv:WXQz60z/nROYtrYX8qXKK8o1Q/LISb2Ewj9ac8+Btzw=,tag:KZBPNJVtI8SRX84aQDeWgg==,type:str] sops: kms: [] gcp_kms: [] @@ -37,8 +49,8 @@ sops: RW13UEl1NEtza2NnTXY4YnFOY1d1QmsKxs+hTpa+s1jaG8T1tPo7FUtkEQA0WZpj qjgrYGhFpg6dicovfkY6Ksyx4WXgw52GTMQZjyEo6FJObUvSF6TmGg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2023-06-29T10:57:55Z" - mac: ENC[AES256_GCM,data:cV3/ptlgCPM0G62bfxVJCW5xgx0rBsiaClifdFhPdqLbaJ2MpMCbujgw8RbX7RSKpq7tNMIrPaCvAmp5RQETd08FWnQbMjaKy2dDoQefYFspaDrv0atXU5ObXM37EEc2NMUgg/7U/JJPoeqUIBAOTyPA/Uf77HrY02LTxpW2Pwk=,iv:2C3RpLOo1ghkpygw9bWWX3JuSMJy2YHJZbLYJ1yLrmw=,tag:ZoLdrFEmM/ZFXLH1lV9vJA==,type:str] + lastmodified: "2023-07-02T22:27:37Z" + mac: ENC[AES256_GCM,data:QwRu83wzt8N0cIrxeA/7mtAbIDSXWwTKD6j794hT6yCkaWmTFDhX3S1+TAIQzJXVQTvJRlPZ1sW8XD/lQy3wTgW/nKVFtNovFCABGAKWen/o8j5gjLvxKMLNjSTm93JdhvLO+vDaJSszs/50O8z3pCIYZxxFlXhz2CMtK0DRPJ4=,iv:nq3hika6ACbl+QI96i7Z5G47iWs5laPUCLztga5aPbA=,tag:YNUDgHcXV4yaEJ2VqxvVPg==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.7.3 -- 2.44.1