diff --git a/config/users.nix b/config/users.nix index 0ea6f90..cf30a62 100644 --- a/config/users.nix +++ b/config/users.nix @@ -47,5 +47,6 @@ # firefly-pico = uidGid 964; avahi = uidGid 963; ente = uidGid 962; + minio = uidGid 961; }; } diff --git a/hosts/sentinel/default.nix b/hosts/sentinel/default.nix index 774f011..6e9f76f 100644 --- a/hosts/sentinel/default.nix +++ b/hosts/sentinel/default.nix @@ -54,4 +54,15 @@ # This node shall monitor the infrastructure availableMonitoringNetworks = [ "internet" ]; }; + + services.ente.web = { + enable = true; + domains = { + api = "api.photos.${globals.domains.me}"; + accounts = "accounts.photos.${globals.domains.me}"; + albums = "albums.photos.${globals.domains.me}"; + cast = "cast.photos.${globals.domains.me}"; + photos = "photos.${globals.domains.me}"; + }; + }; } diff --git a/hosts/sentinel/firezone.nix b/hosts/sentinel/firezone.nix index dceb1a8..94dbb4d 100644 --- a/hosts/sentinel/firezone.nix +++ b/hosts/sentinel/firezone.nix @@ -12,7 +12,12 @@ let # FIXME: new entry here? make new firezone gateway on ward entry too. homeDomains = [ globals.services.grafana.domain - globals.services.ente.domain + "accounts.photos.${globals.domains.me}" + "albums.photos.${globals.domains.me}" + "api.photos.${globals.domains.me}" + "cast.photos.${globals.domains.me}" + "photos.${globals.domains.me}" + "s3.photos.${globals.domains.me}" globals.services.immich.domain globals.services.influxdb.domain globals.services.loki.domain diff --git a/hosts/sentinel/secrets/local.nix.age b/hosts/sentinel/secrets/local.nix.age index e4a317b..0039011 100644 Binary files a/hosts/sentinel/secrets/local.nix.age and b/hosts/sentinel/secrets/local.nix.age differ diff --git a/hosts/sire/default.nix b/hosts/sire/default.nix index 277d7e1..6287694 100644 --- a/hosts/sire/default.nix +++ b/hosts/sire/default.nix @@ -150,7 +150,9 @@ } // mkMicrovm "ai" { } // mkMicrovm "minecraft" { } - // mkMicrovm "ente" { } + // mkMicrovm "ente" { + enableStorageDataset = true; + } #// mkMicrovm "fasten-health" {} ); } diff --git a/hosts/sire/guests/ente.nix b/hosts/sire/guests/ente.nix new file mode 100644 index 0000000..b1b3fa0 --- /dev/null +++ b/hosts/sire/guests/ente.nix @@ -0,0 +1,238 @@ +{ + config, + globals, + lib, + pkgs, + ... +}: +let + enteAccountsDomain = "accounts.photos.${globals.domains.me}"; + enteAlbumsDomain = "albums.photos.${globals.domains.me}"; + enteApiDomain = "api.photos.${globals.domains.me}"; + enteCastDomain = "cast.photos.${globals.domains.me}"; + entePhotosDomain = "photos.${globals.domains.me}"; + s3Domain = "s3.photos.${globals.domains.me}"; + + proxyConfig = remoteAddr: nginxExtraConfig: { + upstreams.ente = { + servers."${remoteAddr}:80" = { }; + extraConfig = '' + zone ente 64k; + keepalive 20; + ''; + monitoring.enable = true; + }; + + upstreams.museum = { + servers."${remoteAddr}:8080" = { }; + extraConfig = '' + zone museum 64k; + keepalive 20; + ''; + }; + + upstreams.minio = { + servers."${remoteAddr}:9000" = { }; + extraConfig = '' + zone minio 64k; + keepalive 20; + ''; + }; + + virtualHosts = + { + ${enteApiDomain} = { + forceSSL = true; + useACMEWildcardHost = true; + locations."/".proxyPass = "http://museum"; + extraConfig = '' + client_max_body_size 4M; + ${nginxExtraConfig} + ''; + }; + ${s3Domain} = { + forceSSL = true; + useACMEWildcardHost = true; + locations."/".proxyPass = "http://minio"; + extraConfig = '' + client_max_body_size 32M; + proxy_buffering off; + proxy_request_buffering off; + ${nginxExtraConfig} + ''; + }; + } + // lib.genAttrs + [ + enteAccountsDomain + enteAlbumsDomain + enteCastDomain + entePhotosDomain + ] + (_domain: { + useACMEWildcardHost = true; + extraConfig = nginxExtraConfig; + }); + }; +in +{ + wireguard.proxy-sentinel = { + client.via = "sentinel"; + firewallRuleForNode.sentinel.allowedTCPPorts = [ + 80 + 9000 + ]; + }; + + wireguard.proxy-home = { + client.via = "ward"; + firewallRuleForNode.ward-web-proxy.allowedTCPPorts = [ + 80 + 9000 + ]; + }; + + globals.services.ente.domain = entePhotosDomain; + # FIXME: also monitor from internal network + globals.monitoring.http.ente = { + url = "https://${entePhotosDomain}"; + expectedBodyRegex = "Ente Photos"; + network = "internet"; + }; + + fileSystems."/storage".neededForBoot = true; + environment.persistence."/storage".directories = [ + { + directory = "/var/lib/minio"; + user = "minio"; + group = "minio"; + mode = "0750"; + } + ]; + + environment.persistence."/persist".directories = [ + { + directory = "/var/lib/ente"; + user = "ente"; + group = "ente"; + mode = "0750"; + } + ]; + + # NOTE: don't use the root user for access. In this case it doesn't matter + # since the whole minio server is only for ente anyway, but it would be a + # good practice. + age.secrets.minio-access-key = { + generator.script = "alnum"; + mode = "440"; + group = "ente"; + }; + age.secrets.minio-secret-key = { + generator.script = "alnum"; + mode = "440"; + group = "ente"; + }; + age.secrets.minio-root-credentials = { + generator.dependencies = [ + config.age.secrets.minio-access-key + config.age.secrets.minio-secret-key + ]; + generator.script = + { + lib, + decrypt, + deps, + ... + }: + '' + echo -n "MINIO_ROOT_USER=" + ${decrypt} ${lib.escapeShellArg (builtins.elemAt deps 0).file} + echo -n "MINIO_ROOT_PASSWORD=" + ${decrypt} ${lib.escapeShellArg (builtins.elemAt deps 1).file} + ''; + mode = "440"; + group = "minio"; + }; + + # base64 (url) + age.secrets.ente-jwt = { + generator.script = + { pkgs, ... }: "${pkgs.openssl}/bin/openssl rand -base64 32 | tr -d '\n' | tr '/+' '_-'"; + mode = "440"; + group = "ente"; + }; + # base64 (standard) + age.secrets.ente-encryption-key = { + generator.script = "base64"; + mode = "440"; + group = "ente"; + }; + # base64 (standard) + age.secrets.ente-hash-key = { + generator.script = { pkgs, ... }: "${pkgs.openssl}/bin/openssl rand -base64 64 | tr -d '\n'"; + mode = "440"; + group = "ente"; + }; + + services.minio = { + enable = true; + rootCredentialsFile = config.age.secrets.minio-root-credentials.path; + }; + systemd.services.minio = { + environment.MINIO_SERVER_URL = "https://${s3Domain}"; + postStart = '' + # Wait until minio is up + ${lib.getExe pkgs.curl} --retry 5 --retry-connrefused --fail --no-progress-meter -o /dev/null "http://localhost:9000/minio/health/live" + + # Make sure bucket exists + mkdir -p ${lib.escapeShellArg config.services.minio.dataDir}/data/ente + ''; + }; + + systemd.services.ente.after = [ "minio.service" ]; + services.ente.api = { + enable = true; + enableLocalDB = true; + domain = enteApiDomain; + settings = { + apps = { + accounts = "https://${enteAccountsDomain}"; + cast = "https://${enteCastDomain}"; + public-albums = "https://${enteAlbumsDomain}"; + }; + + webauthn = { + rpid = enteAccountsDomain; + rporigins = [ "https://${enteAccountsDomain}" ]; + }; + + s3 = { + use_path_style_urls = true; + b2-eu-cen = { + endpoint = "https://${s3Domain}"; + region = "us-east-1"; + bucket = "ente"; + key._secret = config.age.secrets.minio-access-key.path; + secret._secret = config.age.secrets.minio-secret-key.path; + }; + }; + + jwt.secret._secret = config.age.secrets.ente-jwt.path; + key = { + encryption._secret = config.age.secrets.ente-encryption-key.path; + hash._secret = config.age.secrets.ente-hash-key.path; + }; + }; + }; + + # NOTE: services.ente.web is configured separately on both proxy servers! + nodes.sentinel.services.nginx = proxyConfig config.wireguard.proxy-sentinel.ipv4 ""; + nodes.ward-web-prox.services.nginxy = proxyConfig config.wireguard.proxy-home.ipv4 '' + allow ${globals.net.home-lan.vlans.home.cidrv4}; + allow ${globals.net.home-lan.vlans.home.cidrv6}; + # Firezone traffic + allow ${globals.net.home-lan.vlans.services.hosts.ward.ipv4}; + allow ${globals.net.home-lan.vlans.services.hosts.ward.ipv6}; + deny all; + ''; +} diff --git a/hosts/sire/secrets/ente/host.pub b/hosts/sire/secrets/ente/host.pub new file mode 100644 index 0000000..83f16da --- /dev/null +++ b/hosts/sire/secrets/ente/host.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILPHm23XtSiwueXpmqJqFWIxYVWU/eq+dQ0PcwMrsN+c diff --git a/hosts/ward/default.nix b/hosts/ward/default.nix index b5207b7..518ee23 100644 --- a/hosts/ward/default.nix +++ b/hosts/ward/default.nix @@ -13,7 +13,13 @@ let # FIXME: new entry here? make new firezone entry too. homeDomains = [ globals.services.grafana.domain - globals.services.ente.domain + # TODO: allow multiple domains per global service. + "accounts.photos.${globals.domains.me}" + "albums.photos.${globals.domains.me}" + "api.photos.${globals.domains.me}" + "cast.photos.${globals.domains.me}" + "photos.${globals.domains.me}" + "s3.photos.${globals.domains.me}" globals.services.immich.domain globals.services.influxdb.domain globals.services.loki.domain diff --git a/hosts/ward/guests/adguardhome.nix b/hosts/ward/guests/adguardhome.nix index f7b6bbd..626859d 100644 --- a/hosts/ward/guests/adguardhome.nix +++ b/hosts/ward/guests/adguardhome.nix @@ -112,7 +112,12 @@ in # FIXME: new entry here? make new firezone entry too. # FIXME: new entry here? make new firezone gateway on ward entry too. globals.services.grafana.domain - globals.services.ente.domain + "accounts.photos.${globals.domains.me}" + "albums.photos.${globals.domains.me}" + "api.photos.${globals.domains.me}" + "cast.photos.${globals.domains.me}" + "photos.${globals.domains.me}" + "s3.photos.${globals.domains.me}" globals.services.immich.domain globals.services.influxdb.domain globals.services.loki.domain diff --git a/hosts/ward/guests/web-proxy.nix b/hosts/ward/guests/web-proxy.nix index efb50bd..45ffe09 100644 --- a/hosts/ward/guests/web-proxy.nix +++ b/hosts/ward/guests/web-proxy.nix @@ -85,4 +85,15 @@ in users.groups.acme.members = [ "nginx" ]; services.nginx.enable = true; services.nginx.recommendedSetup = true; + + services.ente.web = { + enable = true; + domains = { + api = "api.photos.${globals.domains.me}"; + accounts = "accounts.photos.${globals.domains.me}"; + albums = "albums.photos.${globals.domains.me}"; + cast = "cast.photos.${globals.domains.me}"; + photos = "photos.${globals.domains.me}"; + }; + }; } diff --git a/modules/default.nix b/modules/default.nix index fe00f12..a1176f9 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -4,6 +4,7 @@ ./backups.nix ./deterministic-ids.nix ./distributed-config.nix + ./ente.nix ./globals.nix ./meta.nix ./nginx-upstream-monitoring.nix diff --git a/modules/ente.nix b/modules/ente.nix new file mode 100644 index 0000000..2cceb5e --- /dev/null +++ b/modules/ente.nix @@ -0,0 +1,346 @@ +{ + config, + lib, + pkgs, + utils, + ... +}: +let + inherit (lib) + getExe + mkDefault + mkEnableOption + mkIf + mkMerge + mkOption + mkPackageOption + optional + types + ; + + cfgApi = config.services.ente.api; + cfgWeb = config.services.ente.web; + + webPackage = + enteApp: + cfgWeb.package.override { + inherit enteApp; + enteMainUrl = "https://${cfgWeb.domains.photos}"; + extraBuildEnv = { + NEXT_PUBLIC_ENTE_ENDPOINT = "https://${cfgWeb.domains.api}"; + NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT = "https://${cfgWeb.domains.albums}"; + NEXT_TELEMETRY_DISABLED = "1"; + }; + }; + + defaultUser = "ente"; + defaultGroup = "ente"; + dataDir = "/var/lib/ente"; + + yamlFormat = pkgs.formats.yaml { }; +in +{ + options.services.ente = { + web = { + enable = mkEnableOption "Ente web frontend (Photos, Albums)"; + package = mkPackageOption pkgs "ente-web" { }; + + domains = { + api = mkOption { + type = types.str; + description = '' + The domain under which the api is served. This will NOT serve the api itself, + but is a required setting to host the frontends! This will automatically be set + for you if you enable both the api server and web frontends. + ''; + }; + + accounts = mkOption { + type = types.str; + description = "The domain under which the accounts frontend will be served."; + }; + + cast = mkOption { + type = types.str; + description = "The domain under which the cast frontend will be served."; + }; + + albums = mkOption { + type = types.str; + description = "The domain under which the albums frontend will be served."; + }; + + photos = mkOption { + type = types.str; + description = "The domain under which the photos frontend will be served."; + }; + }; + }; + + api = { + enable = mkEnableOption "Museum (API server for ente.io)"; + package = mkPackageOption pkgs "museum" { }; + nginx.enable = mkEnableOption "nginx proxy for the API server"; + + user = mkOption { + type = types.str; + default = defaultUser; + description = "User under which museum runs."; + }; + + group = mkOption { + type = types.str; + default = defaultGroup; + description = "Group under which museum runs."; + }; + + domain = mkOption { + type = types.str; + description = "The domain under which the api will be served."; + }; + + enableLocalDB = mkEnableOption "the automatic creation of a local postgres database for museum."; + + settings = mkOption { + description = '' + Museum yaml configuration. Refer to upstream [local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml) for more information. + You can specify secret values in this configuration by setting `somevalue._secret = "/path/to/file"` instead of setting `somevalue` directly. + ''; + default = { }; + type = types.submodule { + freeformType = yamlFormat.type; + options = { + apps = { + public-albums = mkOption { + type = types.str; + default = "https://albums.ente.io"; + description = '' + If you're running a self hosted instance and wish to serve public links, + set this to the URL where your albums web app is running. + ''; + }; + + cast = mkOption { + type = types.str; + default = "https://cast.ente.io"; + description = '' + Set this to the URL where your cast page is running. + This is for browser and chromecast casting support. + ''; + }; + + accounts = mkOption { + type = types.str; + default = "https://accounts.ente.io"; + description = '' + Set this to the URL where your accounts page is running. + This is primarily for passkey support. + ''; + }; + }; + + db = { + host = mkOption { + type = types.str; + description = "The database host"; + }; + + port = mkOption { + type = types.port; + default = 5432; + description = "The database port"; + }; + + name = mkOption { + type = types.str; + description = "The database name"; + }; + + user = mkOption { + type = types.str; + description = "The database user"; + }; + }; + }; + }; + }; + }; + }; + + config = mkMerge [ + (mkIf cfgApi.enable { + services.postgresql = mkIf cfgApi.enableLocalDB { + enable = true; + ensureUsers = [ + { + name = "ente"; + ensureDBOwnership = true; + } + ]; + ensureDatabases = [ "ente" ]; + }; + + services.ente.web.domains.api = mkIf cfgWeb.enable cfgApi.domain; + services.ente.api.settings = { + log-file = mkDefault ""; + db = mkIf cfgApi.enableLocalDB { + host = "/run/postgresql"; + port = 5432; + name = "ente"; + user = "ente"; + }; + }; + + systemd.services.ente = { + description = "Ente.io Museum API Server"; + after = [ "network.target" ] ++ optional cfgApi.enableLocalDB "postgresql.service"; + requires = optional cfgApi.enableLocalDB "postgresql.service"; + wantedBy = [ "multi-user.target" ]; + + preStart = '' + # Generate config including secret values. YAML is a superset of JSON, so we can use this here. + ${utils.genJqSecretsReplacementSnippet cfgApi.settings "/run/ente/local.yaml"} + + # Setup paths + mkdir -p ${dataDir}/configurations + ln -sTf /run/ente/local.yaml ${dataDir}/configurations/local.yaml + ''; + + serviceConfig = { + ExecStart = getExe cfgApi.package; + Type = "simple"; + Restart = "on-failure"; + + AmbientCapablities = [ ]; + CapabilityBoundingSet = [ ]; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateMounts = true; + PrivateTmp = true; + PrivateUsers = false; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_NETLINK" + "AF_UNIX" + ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = "@system-service"; + UMask = "077"; + + BindReadOnlyPaths = [ + "${cfgApi.package}/share/museum/migrations:${dataDir}/migrations" + "${cfgApi.package}/share/museum/mail-templates:${dataDir}/mail-templates" + ]; + + User = cfgApi.user; + Group = cfgApi.group; + + SyslogIdentifier = "ente"; + StateDirectory = "ente"; + WorkingDirectory = dataDir; + RuntimeDirectory = "ente"; + }; + + # Environment MUST be called local, otherwise we cannot log to stdout + environment = { + ENVIRONMENT = "local"; + GIN_MODE = "release"; + }; + }; + + users = { + users = mkIf (cfgApi.user == defaultUser) { + ${defaultUser} = { + description = "ente.io museum service user"; + inherit (cfgApi) group; + isSystemUser = true; + home = dataDir; + }; + }; + groups = mkIf (cfgApi.group == defaultGroup) { ${defaultGroup} = { }; }; + }; + + services.nginx = mkIf cfgApi.nginx.enable { + enable = true; + upstreams.museum = { + servers."localhost:8080" = { }; + extraConfig = '' + zone museum 64k; + keepalive 20; + ''; + }; + + virtualHosts.${cfgApi.domain} = { + forceSSL = mkDefault true; + locations."/".proxyPass = "http://museum"; + extraConfig = '' + client_max_body_size 4M; + ''; + }; + }; + }) + (mkIf cfgWeb.enable { + services.ente.api.settings = mkIf cfgApi.enable { + apps = { + accounts = "https://${cfgWeb.domains.accounts}"; + cast = "https://${cfgWeb.domains.cast}"; + public-albums = "https://${cfgWeb.domains.albums}"; + }; + + webauthn = { + rpid = cfgWeb.domains.accounts; + rporigins = [ "https://${cfgWeb.domains.accounts}" ]; + }; + }; + + services.nginx = + let + domainFor = app: cfgWeb.domains.${app}; + in + { + enable = true; + virtualHosts.${domainFor "accounts"} = { + forceSSL = mkDefault true; + locations."/" = { + root = webPackage "accounts"; + tryFiles = "$uri $uri.html /index.html"; + }; + }; + virtualHosts.${domainFor "cast"} = { + forceSSL = mkDefault true; + locations."/" = { + root = webPackage "cast"; + tryFiles = "$uri $uri.html /index.html"; + }; + }; + virtualHosts.${domainFor "photos"} = { + serverAliases = [ + (domainFor "albums") # the albums app is shared with the photos frontend + ]; + forceSSL = mkDefault true; + locations."/" = { + root = webPackage "photos"; + tryFiles = "$uri $uri.html /index.html"; + }; + }; + }; + }) + ]; + + meta.maintainers = with lib.maintainers; [ oddlama ]; +} diff --git a/pkgs/default.nix b/pkgs/default.nix index df2d242..ef5abf1 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -18,6 +18,8 @@ _inputs: [ # }) # ]; + ente-web = prev.callPackage ./ente-web.nix { }; + formats = prev.formats // { ron = import ./ron.nix { inherit (prev) lib pkgs; }; }; diff --git a/pkgs/ente-web.nix b/pkgs/ente-web.nix new file mode 100644 index 0000000..71453b8 --- /dev/null +++ b/pkgs/ente-web.nix @@ -0,0 +1,91 @@ +{ + lib, + stdenv, + fetchFromGitHub, + fetchYarnDeps, + nodejs, + yarnConfigHook, + yarnBuildHook, + nix-update-script, + extraBuildEnv ? { }, + # This package contains serveral sub-applications. This specifies which of them you want to build. + enteApp ? "photos", + # Accessing some apps (such as account) directly will result in a hardcoded redirect to ente.io. + # To prevent users from accidentally logging in to ente.io instead of the selfhosted instance, you + # can set this parameter to override these occurrences with your own url. Must include the schema. + # Example: https://my-ente.example.com + enteMainUrl ? null, +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "ente-web-${enteApp}"; + version = "1.0.4"; + + src = fetchFromGitHub { + owner = "ente-io"; + repo = "ente"; + sparseCheckout = [ "web" ]; + tag = "photos-v${finalAttrs.version}"; + fetchSubmodules = true; + hash = "sha256-M1kAZgqjbWNn6LqymtWRmAk/v0vWEGbyS50lVrsr85o="; + }; + sourceRoot = "${finalAttrs.src.name}/web"; + + offlineCache = fetchYarnDeps { + yarnLock = "${finalAttrs.src}/web/yarn.lock"; + hash = "sha256-EYhYwy6+7bgWckU/7SfL1PREWw9JUgKxWadSVtoZwXs="; + }; + + nativeBuildInputs = [ + yarnConfigHook + yarnBuildHook + nodejs + ]; + + # See: https://github.com/ente-io/ente/blob/main/web/apps/photos/.env + env = extraBuildEnv; + + # Replace hardcoded ente.io urls if desired + postPatch = lib.optionalString (enteMainUrl != null) '' + substituteInPlace \ + apps/payments/src/services/billing.ts \ + apps/photos/src/pages/shared-albums.tsx \ + --replace-fail "https://ente.io" ${lib.escapeShellArg enteMainUrl} + + substituteInPlace \ + apps/accounts/src/pages/index.tsx \ + --replace-fail "https://web.ente.io" ${lib.escapeShellArg enteMainUrl} + ''; + + yarnBuildScript = "build:${enteApp}"; + installPhase = + let + distName = if enteApp == "payments" then "dist" else "out"; + in + '' + runHook preInstall + + cp -r apps/${enteApp}/${distName} $out + + runHook postInstall + ''; + + passthru.updateScript = nix-update-script { + extraArgs = [ + "--version-regex" + "photos-v(.*)" + ]; + }; + + meta = { + description = "Ente application web frontends"; + homepage = "https://ente.io/"; + changelog = "https://github.com/ente-io/ente/releases"; + license = lib.licenses.agpl3Only; + maintainers = with lib.maintainers; [ + pinpox + oddlama + ]; + platforms = lib.platforms.all; + }; +}) diff --git a/secrets/generated/sentinel/loki-basic-auth-hashes.age b/secrets/generated/sentinel/loki-basic-auth-hashes.age index b5cef56..858f27a 100644 Binary files a/secrets/generated/sentinel/loki-basic-auth-hashes.age and b/secrets/generated/sentinel/loki-basic-auth-hashes.age differ diff --git a/secrets/generated/sire-ente/ente-encryption-key.age b/secrets/generated/sire-ente/ente-encryption-key.age new file mode 100644 index 0000000..6c1e565 --- /dev/null +++ b/secrets/generated/sire-ente/ente-encryption-key.age @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> X25519 zRngxioYpKJbERi6At0Wiuy9D9vVfieDcpElvJWeIUI +qYMaG1W7b42179kEL2NJsuCoREGrZBPs+U8+rNdFyOM +-> piv-p256 xqSe8Q AmC86Dj5laQaiH2OIrcZG2AiGB4T5wgzIhLMPgBzJaKn +VjFnsl5UgDDw3sap9mgd3jJR/jqlRL4KS3/jxxcuLQM +-> ,?FIg-grease iYX?nyr *z|V}ruN +i/j/P1jbT8hP6RHqUKAzg94nWWWk5E8EJXomFBc9tQ +--- S7mlAB35SMtQSlUn5dPpNjj9ekUkOJTPvLuEAPGJNXQ +8ݾ x|?-NX-vSB$eVZp\m 2ӳBBB,틖%P_ \ No newline at end of file diff --git a/secrets/generated/sire-ente/ente-hash-key.age b/secrets/generated/sire-ente/ente-hash-key.age new file mode 100644 index 0000000..47c6e0f Binary files /dev/null and b/secrets/generated/sire-ente/ente-hash-key.age differ diff --git a/secrets/generated/sire-ente/ente-jwt.age b/secrets/generated/sire-ente/ente-jwt.age new file mode 100644 index 0000000..7eb095a --- /dev/null +++ b/secrets/generated/sire-ente/ente-jwt.age @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> X25519 fSjolShGCdhJfr1tdcTeYmkpWG3iiA8QEKZjgHjIMUM +Wc0uFJRebFT6xVzxpNStdGyNkC1l+SrtbKBe0vYEX/w +-> piv-p256 xqSe8Q AhhzkRFNoGd0Sv9t08g/wxkCqiKjcMUAutwztgIs+x9U +Q8Y8SEIcGrSQbp//vTWIFAfXcy6LADNEJ6Q0GxFQOpI +-> 754F*-grease k$4zy* >% { og8qk- +r8c9fTLupld7X0fmQ6OLuuBSITL4xU/m0G0eTBcau7o +--- nQo78/W1zOcPeBsXIEEepU5WOCvlllLwB6+Fqrc9OY8 +:f;oQY9; 2Y e]vbUﳕ[p(Wet^vd8: \ No newline at end of file diff --git a/secrets/generated/sire-ente/minio-access-key.age b/secrets/generated/sire-ente/minio-access-key.age new file mode 100644 index 0000000..cc1a5ca --- /dev/null +++ b/secrets/generated/sire-ente/minio-access-key.age @@ -0,0 +1,10 @@ +age-encryption.org/v1 +-> X25519 RUswhRVBILKxzva+FcHu69TNIDotls9+FTqL3IYiZio +MwXFm8JK7Viy6cQZXjBT5U2ERhH6jAckfU0bph6BixU +-> piv-p256 xqSe8Q A6dYQvH4lZ8FSM00u8YCyYHQQvu9xy+UfzBhXepKDWdu +eBb9JP+MLrQ5sttl2MDOyrYI0V1fI7spw57DbAGriVI +-> w.wd]R-grease >g2~Z~ \ ,6 +2S+12Sh/Bjvx0wFMVU4ApN4aVMTkHOqitD9OjcxwuG6Z22Cz04H4e7FD/9VQ57uD +BcvbmzU/sN52h/7K8/wBjHj43V+3L9SVafm2+WF+VfVON6CfcznCfgCq2w +--- wFSnGM1uYgDGmVkYKoARx7uKyV0KEbyYWzeYIA3bxNg +mQjdfv~2X0YBx[ #_S`C/#Kl)QC:" \ No newline at end of file diff --git a/secrets/generated/sire-ente/minio-root-credentials.age b/secrets/generated/sire-ente/minio-root-credentials.age new file mode 100644 index 0000000..520d61f --- /dev/null +++ b/secrets/generated/sire-ente/minio-root-credentials.age @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> X25519 1g/zXfi1yIQ8Gr7s8vXVcqY2SqSY54wIm2K5jZw2FGU +20yDp5BbvL4/Dwj5wUsqICutjmcdEzQzHzhYn2wGxa4 +-> piv-p256 xqSe8Q A0hl01YjJvSgNoVVgqbXtbJebphdyC1KfXuq0KHsGLEY +/tp18Vk3vM2UUxfB+rCi6a1hKvtNi1E+o/CkfEdejBM +-> AR0.!FY-grease jw9K!j +eujGLw +--- 5iSrLf3Tc9d65fjQZvzv2XO5E2FnOKIAcG0aViBQ3T0 +GNN)o@")a
ssh-ed25519 yV7lcA tb9kSCCrR4ZsCY2rFru596/nvJ3Ls0CAIx1SbeBb3jE
+sFwhpTJtUKZLI05/Pka9UN+/AhqRr1T2qOsoXqnJm+I
+-> M{JlUebq-grease