Commit 8a716c2

HPCesia <me@hpcesia.com>
2026-04-29 13:41:57
feat: forgejo-runner service
As Forgejo v15 launched, Forgejo Runner is quitely different from Gitea Action Runner, so a seperate service entry is needed.
1 parent 298522a
modules/hosts/kevin/services/default.nix
@@ -4,13 +4,18 @@ in {
   den.aspects.kevin.includes = [
     <services/forgejo-runner>
     (<services/forgejo-runner/instance> {
-      instance = "codeberg";
-      name = "runner@codeberg.kevin.hpcesia.com";
-      url = "https://codeberg.org/";
-      tokenFileAged = ./forgejo-runner-codeberg-token.age;
-      labels = [
-        "nixos-latest-lazy:docker://repo.hpcesia.com/hpcesia/nix-act-image:latest-x86_64"
-      ];
+      instance = "default";
+      name = "runner@kevin.hpcesia.com";
+      servers = {
+        codeberg = {
+          url = "https://codeberg.org/";
+          uuid = "7e6e56d5-b49f-4277-8c78-f3e9b8bf52e9";
+          tokenFileAged = ./forgejo-runner-codeberg-token.age;
+          labels = [
+            "nixos-latest-lazy:docker://repo.hpcesia.com/hpcesia/nix-act-image:latest-x86_64"
+          ];
+        };
+      };
     })
 
     <services/mihomo>
modules/hosts/kevin/services/forgejo-runner-codeberg-token.age
@@ -1,10 +1,8 @@
 age-encryption.org/v1
--> X25519 mAYEnhk7zOeorrULGpiwyOVLgLEno1QbKHhirWdscx4
-aS+UI9VhSC6YrJXHc7KAaMDk5YNYTOp5AMQpk4pnruM
--> \Tu=-grease 9 H ZW'
-w8dshIkhDaqoy1MYp7E9P0cHHJCcP6dJGEBU4hUFV4VYKU5XUL/Gmn8X8B7gsmWx
-GGEMQfocKxLvHsYE3WvPMjrFci/bdAs11rHb90U/kI5xN7Emypu96LueN3UVcscN
-
---- vWANJS4q8I7800Z57NJDpYeSD8Ks2LsdP6hdIpudozM
-���v3��x@�/��lv\78�ix�
-�]�^���B#5��Շ^���G1�����:cɪ�K�$WÌ��D�c:~�s1;T����*
\ No newline at end of file
+-> X25519 93lFeEeKaeX4nOgls11E7ex5yAaKEX95wxbRWoeb0TA
+mxL/jADWraIb2O4lS7CPJ5UlUf/OBS9UWZkbgoaOtFE
+-> `W>-grease
+81cwzrxojyGra7oiRVyU9Xm9Us+nKpBkmSHb/d1XiJc
+--- OU77NJb1uX5LgNbk5cAESEz90e3odMW2gprMBOxcv7U
+1۲&��b6E$Jtu�p�
+���fo��Q*��.z��3�ب����&0N:N�^�Q\��Lіs/�_�u���;�
\ No newline at end of file
modules/hosts/pardofelis/services/default.nix
@@ -8,23 +8,27 @@ in {
 
     <services/forgejo-runner>
     (<services/forgejo-runner/instance> {
-      instance = "local";
-      name = "runner@local.pardofelis.hpcesia.com";
-      url = "https://repo.hpcesia.com/";
-      tokenFileAged = ./forgejo-runner-local-token.age;
-      labels = [
-        "ubuntu-latest:docker://ghcr.io/catthehacker/ubuntu:act-latest"
-        "nixos-latest:docker://repo.hpcesia.com/hpcesia/nix-act-image:latest-x86_64"
-      ];
-    })
-    (<services/forgejo-runner/instance> {
-      instance = "codeberg";
-      name = "runner@codeberg.pardofelis.hpcesia.com";
-      url = "https://codeberg.org/";
-      tokenFileAged = ./forgejo-runner-codeberg-token.age;
-      labels = [
-        "nixos-latest:docker://repo.hpcesia.com/hpcesia/nix-act-image:latest-x86_64"
-      ];
+      instance = "default";
+      name = "runner@pardofelis.hpcesia.com";
+      servers = {
+        myforgejo = {
+          url = "https://repo.hpcesia.com/";
+          uuid = "8782a5ff-71d5-40cf-8d43-465be266ec7b";
+          tokenFileAged = ./forgejo-runner-myforgejo-token.age;
+          labels = [
+            "ubuntu-latest:docker://ghcr.io/catthehacker/ubuntu:act-latest"
+            "nixos-latest:docker://repo.hpcesia.com/hpcesia/nix-act-image:latest-x86_64"
+          ];
+        };
+        codeberg = {
+          url = "https://codeberg.org/";
+          uuid = "38eb4ed0-ac44-4363-8164-5c870f654e04";
+          tokenFileAged = ./forgejo-runner-codeberg-token.age;
+          labels = [
+            "nixos-latest:docker://repo.hpcesia.com/hpcesia/nix-act-image:latest-x86_64"
+          ];
+        };
+      };
     })
 
     <services/goatcounter>
modules/hosts/pardofelis/services/forgejo-runner-codeberg-token.age
@@ -1,10 +1,8 @@
 age-encryption.org/v1
--> X25519 mAYEnhk7zOeorrULGpiwyOVLgLEno1QbKHhirWdscx4
-aS+UI9VhSC6YrJXHc7KAaMDk5YNYTOp5AMQpk4pnruM
--> \Tu=-grease 9 H ZW'
-w8dshIkhDaqoy1MYp7E9P0cHHJCcP6dJGEBU4hUFV4VYKU5XUL/Gmn8X8B7gsmWx
-GGEMQfocKxLvHsYE3WvPMjrFci/bdAs11rHb90U/kI5xN7Emypu96LueN3UVcscN
-
---- vWANJS4q8I7800Z57NJDpYeSD8Ks2LsdP6hdIpudozM
-���v3��x@�/��lv\78�ix�
-�]�^���B#5��Շ^���G1�����:cɪ�K�$WÌ��D�c:~�s1;T����*
\ No newline at end of file
+-> X25519 KKio5IMoeN3gBkiBLxH3OyuihNkBjcBAx+mhDhUwvgA
+hgW08sM/sg6Dd9nddIHCTqlOdh51ixFEck2aE9iTanA
+-> WI{C(_f-grease PF y1<6hJkb {k
+KgP4+kYa7z4qd+pGsJHsEKSHIwj/dvHENYn6yA
+--- RI2KFmDxxRabii0lWEiVMA1BYKcJ2A8JyZxwHVDxrPA
+`�,y����%U��]ڠI�̙����U�D��_�i�u�������9}�����
+��xs���z1Gp��m)��
\ No newline at end of file
modules/hosts/pardofelis/services/forgejo-runner-local-token.age
@@ -1,7 +0,0 @@
-age-encryption.org/v1
--> X25519 oqyjfZ4+i4zeHtzvsbbcDHNe3G4/Ma3OI8zfU2+wO1M
-yGOEbBIGx6wAsPjCfv4gFtvvCglDuAgTrqaM4/HoddQ
--> $f)-grease nF~D
-U1h152PEXQ0MNal+xJ1oU22VOpeT6wXJfwpQe8ab+pBL
---- 3KSb1iICSlVFyy+unhZaZ+LvXNGHMXpJKEnHwiYdFzU
-�r*��2���l��Rp[ۿ2Y����0/�A*h��Vqk�T���]�+������]ټm>A�;�v"�`�)��J(n�3X=
\ No newline at end of file
modules/hosts/pardofelis/services/forgejo-runner-myforgejo-token.age
Binary file
modules/services/forgejo-runner/default.nix
@@ -0,0 +1,81 @@
+{lib, ...}: {
+  den.aspects.services.provides.forgejo-runner.nixos = {config, ...}: {
+    # If you would like to use docker runners in combination with cache actions,
+    # be sure to add docker bridge interfaces “br-*” to the firewalls’ trusted interfaces.
+    # See https://forgejo.org/docs/next/admin/actions/runner-installation/#nixos
+    networking.firewall.trustedInterfaces =
+      if (config.networking.nftables.enable)
+      then ["br-*"]
+      else ["br-+"];
+  };
+
+  den.aspects.services.provides.forgejo-runner.provides.instance = {
+    instance,
+    name ? instance,
+    servers ? {},
+    labels ? [],
+    settings ? {},
+  }: {
+    nixos = {config, ...}: {
+      assertions = [
+        {
+          assertion = lib.all (s: lib.hasAttr "tokenFileAged" s) (lib.attrValues servers);
+          message = "All forgejo runner server should has tokenFileAged.";
+        }
+      ];
+
+      services.forgejo-runner.instances.${instance} = {
+        enable = true;
+        inherit name labels;
+        servers =
+          lib.mapAttrs (server: v: {
+            inherit (v) url uuid;
+            tokenFile = config.vaultix.secrets."forgejo-runner-${instance}-${server}-token".path;
+            labels = v.labels or [];
+          })
+          servers;
+        settings = lib.mkMerge [
+          {
+            cache = {
+              host = "172.17.0.1";
+            };
+            container = {
+              network = "";
+              enable_ipv6 = true;
+              privileged = true; # For docker-in-docker
+              options = "-v /var/run/docker.sock:/var/run/docker.sock";
+            };
+          }
+          settings
+        ];
+      };
+
+      users.users."forgejo-runner-${instance}" = {
+        isSystemUser = true;
+        useDefaultShell = true;
+        group = "forgejo-runner-${instance}";
+      };
+      users.groups."forgejo-runner-${instance}" = {};
+
+      systemd.services."forgejo-runner-${instance}".serviceConfig = {
+        DynamicUser = lib.mkForce false;
+        User = "forgejo-runner-${instance}";
+        Group = "forgejo-runner-${instance}";
+      };
+
+      vaultix.secrets =
+        lib.mapAttrs' (
+          server: v:
+            lib.nameValuePair
+            "forgejo-runner-${instance}-${server}-token"
+            {
+              file = v.tokenFileAged;
+              owner = "forgejo-runner-${instance}";
+              group = "forgejo-runner-${instance}";
+              mode = "0440";
+            }
+        )
+        servers;
+    };
+  };
+}
modules/services/forgejo-runner/options.nix
@@ -0,0 +1,278 @@
+{inputs, ...}: {
+  den.aspects.services.provides.forgejo-runner.nixos = {
+    pkgs,
+    lib,
+    config,
+    ...
+  }: let
+    cfg = config.services.forgejo-runner;
+    settingsFormat = pkgs.formats.yaml {};
+
+    # Check whether any runner instance label requires a container runtime
+    # Empty label strings result in the upstream defined defaultLabels, which require docker
+    # https://gitea.com/gitea/act_runner/src/tag/v0.1.5/internal/app/cmd/register.go#L93-L98
+    _hasDockerScheme = x: x.labels == [] || lib.any (label: lib.hasInfix ":docker:" label) x.labels;
+    hasDockerScheme = instance: _hasDockerScheme instance || lib.any _hasDockerScheme (lib.attrValues instance.servers);
+    wantsContainerRuntime = lib.any hasDockerScheme (lib.attrValues cfg.instances);
+
+    _hasHostScheme = x: lib.any (label: lib.hasSuffix ":host" label) x.labels;
+    hasHostScheme = instance: _hasHostScheme instance || lib.any _hasHostScheme (lib.attrValues instance.servers);
+
+    # provide shorthands for whether container runtimes are enabled
+    hasDocker = config.virtualisation.docker.enable;
+    hasPodman = config.virtualisation.podman.enable;
+
+    _tokenXorTokenFile = server:
+      (server.token == null && server.tokenFile != null)
+      || (server.token != null && server.tokenFile == null);
+    tokenXorTokenFile = instance: lib.any _tokenXorTokenFile (lib.attrValues instance.servers);
+
+    utils = pkgs.callPackage "${inputs.nixpkgs}/nixos/lib/utils.nix" {};
+  in {
+    options.services.forgejo-runner = {
+      package = lib.mkPackageOption pkgs "forgejo-runner" {};
+
+      instances = lib.mkOption {
+        default = {};
+        description = ''
+          Forgejo Runner instances
+        '';
+        type = lib.types.attrsOf (lib.types.submodule ({
+          name,
+          config,
+          ...
+        }: {
+          options = {
+            enable = lib.mkEnableOption "Forgejo Runner instance";
+
+            name = lib.mkOption {
+              type = lib.types.str;
+              example = lib.literalExpression "config.networking.hostName";
+              default = name;
+              description = ''
+                The name identifying the runner instance towards the Gitea/Forgejo instance.
+              '';
+            };
+
+            servers = lib.mkOption {
+              type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
+                options = {
+                  name = lib.mkOption {
+                    type = lib.types.str;
+                    example = "codeberg";
+                    default = name;
+                    description = ''
+                      The name identifying the runner instance towards the Gitea/Forgejo instance.
+                    '';
+                  };
+
+                  url = lib.mkOption {
+                    type = lib.types.str;
+                    example = "https://forge.example.com";
+                    description = ''
+                      Base URL of your Gitea/Forgejo instance.
+                    '';
+                  };
+
+                  uuid = lib.mkOption {
+                    type = lib.types.str;
+                    example = "c9e50be9-a7c3-4aee-ba35-624c4ff8c519";
+                    description = ''
+                      Base URL of your Gitea/Forgejo instance.
+                    '';
+                  };
+
+                  token = lib.mkOption {
+                    type = lib.types.nullOr lib.types.str;
+                    default = null;
+                    description = ''
+                      Plain token to register at the configured Gitea/Forgejo instance.
+                    '';
+                  };
+
+                  tokenFile = lib.mkOption {
+                    type = lib.types.nullOr (lib.types.either lib.types.str lib.types.path);
+                    default = null;
+                    description = ''
+                      Path to a file contains token to register at the configured Gitea/Forgejo instance.
+                    '';
+                  };
+
+                  labels = lib.mkOption {
+                    type = lib.types.listOf lib.types.str;
+                    example = lib.literalExpression ''
+                      [
+                        # provide a debian base with nodejs for actions
+                        "debian-latest:docker://node:18-bullseye"
+                        # fake the ubuntu name, because node provides no ubuntu builds
+                        "ubuntu-latest:docker://node:18-bullseye"
+                        # provide native execution on the host
+                        #"native:host"
+                      ]
+                    '';
+                    description = ''
+                      Labels used to map jobs to their runtime environment for specific instance.
+
+                      Many common actions require bash, git and nodejs, as well as a filesystem
+                      that follows the filesystem hierarchy standard.
+                    '';
+                  };
+                };
+              }));
+            };
+
+            labels = lib.mkOption {
+              type = lib.types.listOf lib.types.str;
+              example = lib.literalExpression ''
+                [
+                  # provide a debian base with nodejs for actions
+                  "debian-latest:docker://node:18-bullseye"
+                  # fake the ubuntu name, because node provides no ubuntu builds
+                  "ubuntu-latest:docker://node:18-bullseye"
+                  # provide native execution on the host
+                  #"native:host"
+                ]
+              '';
+              description = ''
+                Labels used to map jobs to their runtime environment.
+
+                Many common actions require bash, git and nodejs, as well as a filesystem
+                that follows the filesystem hierarchy standard.
+              '';
+            };
+
+            settings = lib.mkOption {
+              description = ''
+                Configuration for `act_runner daemon`.
+                See <https://gitea.com/gitea/act_runner/src/branch/main/internal/pkg/config/config.example.yaml> for an example configuration
+              '';
+
+              type = lib.types.submodule {
+                freeformType = settingsFormat.type;
+                options = {
+                  runner.labels = lib.mkOption {
+                    type = lib.types.listOf lib.types.str;
+                    default = config.labels;
+                  };
+                  server.connections = lib.mkOption {
+                    type = lib.types.attrsOf (lib.types.submodule {
+                      freeformType = settingsFormat.type;
+                    });
+                    default =
+                      lib.mapAttrs (n: v: {
+                        inherit (v) url uuid labels;
+                        token = lib.mkIf (v.token != null) v.token;
+                        token_url = lib.mkIf (v.tokenFile != null) "file://${v.tokenFile}";
+                      })
+                      config.servers;
+                  };
+                };
+              };
+            };
+
+            hostPackages = lib.mkOption {
+              type = lib.types.listOf lib.types.package;
+              default = with pkgs; [
+                bash
+                coreutils
+                curl
+                gawk
+                gitMinimal
+                gnused
+                nodejs
+                wget
+              ];
+              defaultText = lib.literalExpression ''
+                with pkgs; [
+                  bash
+                  coreutils
+                  curl
+                  gawk
+                  gitMinimal
+                  gnused
+                  nodejs
+                  wget
+                ]
+              '';
+              description = ''
+                List of packages, that are available to actions, when the runner is configured
+                with a host execution label.
+              '';
+            };
+          };
+        }));
+      };
+    };
+
+    config = lib.mkIf (cfg.instances != {}) {
+      assertions = [
+        {
+          assertion = lib.any tokenXorTokenFile (lib.attrValues cfg.instances);
+          message = "Servers of instances of forgejo-runner can have `token` or `tokenFile`, not both.";
+        }
+        {
+          assertion = wantsContainerRuntime -> hasDocker || hasPodman;
+          message = "Label configuration on forgejo-runner instance requires either docker or podman.";
+        }
+      ];
+
+      systemd.services = let
+        mkRunnerService = name: instance: let
+          wantsContainerRuntime = hasDockerScheme instance;
+          wantsHost = hasHostScheme instance;
+          wantsDocker = wantsContainerRuntime && config.virtualisation.docker.enable;
+          wantsPodman = wantsContainerRuntime && config.virtualisation.podman.enable;
+          configFile = settingsFormat.generate "config.yaml" instance.settings;
+        in
+          lib.nameValuePair "forgejo-runner-${utils.escapeSystemdPath name}" {
+            inherit (instance) enable;
+            description = "Forgejo Runner";
+            wants = ["network-online.target"];
+            after =
+              [
+                "network-online.target"
+              ]
+              ++ lib.optionals wantsDocker [
+                "docker.service"
+              ]
+              ++ lib.optionals wantsPodman [
+                "podman.service"
+              ];
+            wantedBy = [
+              "multi-user.target"
+            ];
+            environment =
+              lib.optionalAttrs wantsPodman {
+                DOCKER_HOST = "unix:///run/podman/podman.sock";
+              }
+              // {
+                HOME = "/var/lib/forgejo-runner/${name}";
+              };
+            path = with pkgs;
+              [
+                coreutils
+              ]
+              ++ lib.optionals wantsHost instance.hostPackages;
+            serviceConfig = {
+              DynamicUser = true;
+              StateDirectory = "forgejo-runner";
+              WorkingDirectory = "-/var/lib/forgejo-runner/${name}";
+
+              Restart = "on-failure";
+              RestartSec = 2;
+
+              ExecStart = "${cfg.package}/bin/act_runner daemon --config ${configFile}";
+              SupplementaryGroups =
+                lib.optionals wantsDocker [
+                  "docker"
+                ]
+                ++ lib.optionals wantsPodman [
+                  "podman"
+                ];
+            };
+          };
+      in
+        lib.mapAttrs' mkRunnerService cfg.instances;
+    };
+  };
+}
modules/services/forgejo-runner.nix
@@ -1,73 +0,0 @@
-{lib, ...}: {
-  den.aspects.services.provides.forgejo-runner = {
-    nixos = {
-      pkgs,
-      config,
-      ...
-    }: {
-      services.gitea-actions-runner = {
-        package = lib.mkDefault pkgs.forgejo-runner;
-      };
-      # If you would like to use docker runners in combination with cache actions,
-      # be sure to add docker bridge interfaces “br-*” to the firewalls’ trusted interfaces.
-      # See https://forgejo.org/docs/next/admin/actions/runner-installation/#nixos
-      networking.firewall.trustedInterfaces =
-        if (config.networking.nftables.enable)
-        then ["br-*"]
-        else ["br-+"];
-    };
-  };
-
-  den.aspects.services.provides.forgejo-runner.provides.instance = {
-    instance,
-    name ? "runner-${instance}",
-    url,
-    tokenFileAged,
-    labels ? [],
-    settings ? {},
-  }: {
-    nixos = {config, ...}: {
-      services.gitea-actions-runner = {
-        instances.${instance} = {
-          enable = true;
-          inherit name url labels;
-          tokenFile = config.vaultix.secrets."forgejo-runner-${instance}-token".path;
-          settings = lib.mkMerge [
-            {
-              cache = {
-                host = "172.17.0.1";
-              };
-              container = {
-                network = "";
-                enable_ipv6 = true;
-                privileged = true; # For docker-in-docker
-                options = "-v /var/run/docker.sock:/var/run/docker.sock";
-              };
-            }
-            settings
-          ];
-        };
-      };
-
-      users.users."forgejo-runner-${instance}" = {
-        isSystemUser = true;
-        useDefaultShell = true;
-        group = "forgejo-runner-${instance}";
-      };
-      users.groups."forgejo-runner-${instance}" = {};
-
-      systemd.services."forgejo-runner-${instance}".serviceConfig = {
-        DynamicUser = lib.mkForce false;
-        User = "forgejo-runner-${instance}";
-        Group = "forgejo-runner-${instance}";
-      };
-
-      vaultix.secrets."forgejo-runner-${instance}-token" = {
-        file = tokenFileAged;
-        owner = "forgejo-runner-${instance}";
-        group = "forgejo-runner-${instance}";
-        mode = "0440";
-      };
-    };
-  };
-}
secrets/cache/kevin/157244bd697b504d7455b9d258e6106bdd5b5fb232a45075c183a073e45fbe8e
Binary file
secrets/cache/kevin/caffa847ad05df1b1b52ad127cd9e10e2e04f64ce705ab857095a9130f3b2344
@@ -1,7 +0,0 @@
-age-encryption.org/v1
--> ssh-ed25519 WM7kiQ WZxrUB9dhRMhahzuloSjCYBsiSpASN7WKQoc1Gl8DgM
-UtIooQmIEY8IjRHdz9hVPIOPMhNtWipO/oltA+gurdc
--> )J<,g-grease y!VH4 WN
-/7wZ2vlx4mxozlkPD7Gj10y28cTuryJlU7E0aKgA1foaGklr
---- H6VUeSApfZxwR2t3lVg0uEQNzPrjddCV7Bx8GQvPn2g
-c	3��>J�U��,T~�a}����Dñ<�|Q?�¡���!���RK��l�<dX�B�H�Α��"2�����tօ��� �æF
\ No newline at end of file
secrets/cache/pardofelis/20035d64d3f56c4311ce7c9bb7d7bba397c220cd6cd5c276a66ed9b483cf683d
@@ -1,7 +0,0 @@
-age-encryption.org/v1
--> ssh-ed25519 B1HLiw NuG90Ey/xUqbBjLuejPyF0i3EqdFFqdLd5hy1xEoPQo
-JP5xEZGQSUqDFnKfPZpU6hD9T8JC2c49I90sI4FbbsY
--> N%EYL-grease
-xmAFlWb1tBeMudcwTaY7kcweML/fQNkn6BVJGqjxkzPcydCmm7BePC4
---- Qeeb050TT3i67cEUi1b2NA4iUaUZ3wJfRScYKWugkDg
-�G��㔡ʟ������9T����~��IWX�L��H�	�iA%k>"JA�J!�%z����ۨ^(4�w9�R�!�rn�
\ No newline at end of file
secrets/cache/pardofelis/8a06b2342150695d690a21f2d345cc4326c9b8e0c41dd37f622dd2ff1766f889
@@ -1,8 +0,0 @@
-age-encryption.org/v1
--> ssh-ed25519 B1HLiw 7ryR98ZISUc1tSJoPxcb29ZX1TEtH3yFRAb/f0701y8
-fXm0v3b/Uf3J7G/zQ56LSYZoiz64nZgFgEk3fxbqAdQ
--> RI\-grease ] =+MI6 $$#c C
-g9H3eguOBqtWc9BlwH5Qy6COQNWNZ1g6jCi8VH+w1h86+1WMOa0Tlg
---- BYlafOLZlsgMHPDpLSQhSfxtasJGPq0/k+1uoGlyWaM
-cwh��̥6�Q����#6KT7s[����fH�Hލ#��sR��F��������D���W�2g+���
-6�ӷ�����5
\ No newline at end of file
secrets/cache/pardofelis/9cb6e3f94d91b827eb7abaa8a3b921a6454369c2909a0a3936522b11d3522759
@@ -0,0 +1,9 @@
+age-encryption.org/v1
+-> ssh-ed25519 B1HLiw ZWsGl0VhbKJ6xTVfzmFbktctBZEK4xNbGl0kV0+c4lE
+ICLFmrmEYr7ZN1CdyRzoY2mxCBgStVGNJLp+/Ib8kx8
+-> NY4/S.-grease Wux(=z E3Gjiq 7\t |
+1KNt3LMbP8sufkPUBmIUnxsvObZWsddimGicO4f6csXF1VHK91zMoT7VXZCdHgKt
+6E7etN7JNaimUZSpKBtEJXLIsQ
+--- th6MZBZZmNuGeoSJ2qLLYNsQ0MuCWpxRSAiwy8ZlFO8
+3�jf���+p��*c�#ղX{�T�۟��)��x�Z������f��
+�t���<%<�Cw��!��)���
\ No newline at end of file
secrets/cache/pardofelis/ad544da9ba61eeb6fc0c448e567b5051671758f4bf6e4480edf886a1d97a7bfa
Binary file