diff --git a/flake.lock b/flake.lock index 314c2d6..1691673 100644 --- a/flake.lock +++ b/flake.lock @@ -505,6 +505,28 @@ "type": "github" } }, + "jovian": { + "inputs": { + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1728974938, + "narHash": "sha256-pTPEx6WlM+nJVGrRUGx7Di4ljZMwE9HfvlZ6f3NzNfo=", + "owner": "Jovian-Experiments", + "repo": "Jovian-NixOS", + "rev": "23170582b0658e6afd913149a58863af3a57b376", + "type": "github" + }, + "original": { + "owner": "Jovian-Experiments", + "ref": "development", + "repo": "Jovian-NixOS", + "type": "github" + } + }, "libpng": { "flake": false, "locked": { @@ -522,6 +544,44 @@ "type": "github" } }, + "mobile-nixos": { + "flake": false, + "locked": { + "lastModified": 1728423157, + "narHash": "sha256-pJaC+Aef6oixhV6HdWPS2Pq/TgHxEN+MPLYUjighWYI=", + "owner": "lytedev", + "repo": "mobile-nixos", + "rev": "b2c496bbcebc85a28d1d939b56bd331536bd1ac4", + "type": "github" + }, + "original": { + "owner": "lytedev", + "repo": "mobile-nixos", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "jovian", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1690328911, + "narHash": "sha256-fxtExYk+aGf2YbjeWQ8JY9/n9dwuEt+ma1eUFzF8Jeo=", + "owner": "zhaofengli", + "repo": "nix-github-actions", + "rev": "96df4a39c52f53cb7098b923224d8ce941b64747", + "type": "github" + }, + "original": { + "owner": "zhaofengli", + "ref": "matrix-name", + "repo": "nix-github-actions", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1709479366, @@ -627,6 +687,8 @@ "home-manager": "home-manager", "home-manager-unstable": "home-manager-unstable", "hyprland": "hyprland", + "jovian": "jovian", + "mobile-nixos": "mobile-nixos", "nixpkgs": "nixpkgs_3", "nixpkgs-unstable": "nixpkgs-unstable", "slippi": "slippi", diff --git a/flake.nix b/flake.nix index 225aad4..d58908d 100644 --- a/flake.nix +++ b/flake.nix @@ -31,7 +31,15 @@ slippi.inputs.nixpkgs.follows = "nixpkgs-unstable"; slippi.inputs.home-manager.follows = "home-manager-unstable"; + jovian.url = "github:Jovian-Experiments/Jovian-NixOS/development"; + jovian.inputs.nixpkgs.follows = "nixpkgs-unstable"; + # nnf.url = "github:thelegy/nixos-nftables-firewall?rev=71fc2b79358d0dbacde83c806a0f008ece567b7b"; + + mobile-nixos = { + url = "github:lytedev/mobile-nixos"; + flake = false; + }; }; nixConfig = { @@ -66,6 +74,8 @@ home-manager-unstable, helix, hardware, + jovian, + mobile-nixos, # nnf, # hyprland, slippi, @@ -385,6 +395,37 @@ ]; }; + steamdeck1 = nixpkgs-unstable.lib.nixosSystem { + system = "x86_64-linux"; + modules = with nixosModules; [ + home-manager-unstable-defaults + + outputs.diskoConfigurations.standard + hardware.nixosModules.common-pc-ssd + common + gaming + graphical-workstation + plasma6 + + jovian.outputs.nixosModules.jovian + + { + networking.hostName = "steamdeck1"; + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + hardware.bluetooth.enable = true; + networking.networkmanager.enable = true; + + home-manager.users.daniel = { + imports = with homeManagerModules; [ + firefox-no-tabs + linux-desktop-environment-config + ]; + }; + } + ]; + }; + foxtrot = nixpkgs-unstable.lib.nixosSystem { system = "x86_64-linux"; modules = with nixosModules; [ @@ -401,6 +442,7 @@ virtual-machines-gui laptop gaming + cross-compiler ./nixos/foxtrot.nix @@ -432,7 +474,7 @@ # otherwise, they will likely have no effect anyways text = '' command -v powerprofilesctl &>/dev/null && bash -x -c 'powerprofilesctl set performance' - command -v swaymsg &>/dev/null && bash -x -c 'swaymsg output eDP-1 mode 2880x1920@60Hz' + command -v swaymsg &>/dev/null && bash -x -c 'swaymsg output eDP-1 mode 2880x1920@120Hz' ''; }) (writeShellApplication @@ -627,8 +669,95 @@ ./nixos/router.nix ]; }; + + # pinephone-image = + # (import "${mobile-nixos}/lib/eval-with-configuration.nix" { + # configuration = with nixosModules; [ + # linux + # home-manager-defaults + + # # outputs.diskoConfigurations.unencrypted # can I even disko with an image-based installation? + # common + # wifi + + # # TODO: how do I get a minimally useful mobile environment? + # # for me, this means an on-screen keyboard and suspend support I think? + # # I can live in a tty if needed and graphical stuff can all evolve later + # # not worried about modem + # # maybe/hopefully I can pull in or define my own sxmo via nix? + # ]; + # device = "pine64-pinephone"; + # pkgs = pkgsFor "aarch64-linux"; + # }) + # .outputs + # .disk-image; + + pinephone = let + inherit (nixpkgs-unstable) lib; + in + lib.nixosSystem { + system = "aarch64-linux"; + # lib.nixosSystem { + + modules = with nixosModules; [ + { + imports = [ + (import "${mobile-nixos}/lib/configuration.nix" { + device = "pine64-pinephone"; + }) + ]; + + # nixpkgs.hostPlatform.system = "aarch64-linux"; + nixpkgs.buildPlatform = "x86_64-linux"; + + # TODO: quirk: since the pinephone kernel doesn't seem to have "rpfilter" support, firewall ain't working + networking.firewall.enable = lib.mkForce false; + + # TODO: quirk: since git send-email requires perl support, which we don't seem to have on the pinephone, we're just disabling git for now + # TODO: would likely be easier/better to somehow ignore the assertion? probably a way to do that... + programs.git.enable = lib.mkForce false; + + # this option is conflicted, presumably due to some assumption in my defaults/common config + # the sd-image module we're importing above has this set to true, so we better go with that? + # that said, I think the mobile-nixos bootloader module has this set to false, so... + # TODO: what does this mean? + boot.loader.generic-extlinux-compatible.enable = lib.mkForce true; + + # another conflicting option since I think I default to NetworkManager and this conflicts with networking.wireless.enable + networking.networkmanager.enable = lib.mkForce false; + networking.wireless.enable = lib.mkForce true; + } + + # TODO: how do I build this as a .img to flash to an SD card? + + # for testing, this seems to work `nixos-rebuild build --impure --flake .#pinephone` + + # TODO: would like to use the mobile-nixos installer? + "${nixpkgs-unstable}/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix" + + linux + home-manager-unstable-defaults + + # outputs.diskoConfigurations.unencrypted # can I even disko with an image-based installation? + common + wifi + + { + system.stateVersion = "24.11"; + } + + { + # nixpkgs.buildPlatform = "x86_64-linux"; + # nixpkgs.hostPlatform = lib.systems.examples.aarch64-multiplatform; + # nixpkgs.localSystem.system = lib.systems.examples.x86_64-linux; + # nixpkgs.crossSystem = lib.mkForce null; + } + ]; + }; }; + images.pinephone = outputs.nixosConfigurations.pinephone.config.system.build.sdImage; + homeConfigurations = { "deck" = let system = "x86_64-linux"; @@ -657,7 +786,7 @@ }; /* - TODO: nix-on-droid for phone terminal usage? + TODO: nix-on-droid for phone terminal usage? mobile-nixos? TODO: nix-darwin for work? TODO: nixos ISO? */ diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index f11c23a..c94f24e 100644 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -327,7 +327,7 @@ settings = { PasswordAuthentication = false; KbdInteractiveAuthentication = false; - PermitRootLogin = "prohibit-password"; + PermitRootLogin = lib.mkForce "prohibit-password"; }; openFirewall = lib.mkDefault true; @@ -370,6 +370,10 @@ }; }; + cross-compiler = {config, ...}: { + boot.binfmt.emulatedSystems = ["aarch64-linux" "i686-linux"]; + }; + default-nix-configuration-and-overlays = { lib, config, @@ -392,6 +396,8 @@ trusted-users = ["root" "daniel"]; experimental-features = lib.mkDefault ["nix-command" "flakes"]; + extra-platforms = ["i686-linux" "aarch64-linux"]; + substituters = [ # TODO: dedupe with flake's config? is that even necessary? "https://cache.nixos.org/" @@ -1174,43 +1180,43 @@ boot.tmp.cleanOnBoot = true; services.irqbalance.enable = true; - services.kanidm = { - enableClient = true; - enablePam = true; - package = pkgs.kanidm; + # this is not ready for primetime yet + # services.kanidm = { + # enableClient = true; + # enablePam = true; + # package = pkgs.kanidm; - clientSettings.uri = "https://idm.h.lyte.dev"; - unixSettings = { - # hsm_pin_path = "/somewhere/else"; - pam_allowed_login_groups = []; - }; - }; - - systemd.tmpfiles.rules = [ - "d /etc/kanidm 1755 nobody users -" - ]; + # clientSettings.uri = "https://idm.h.lyte.dev"; + # unixSettings = { + # # hsm_pin_path = "/somewhere/else"; + # pam_allowed_login_groups = []; + # }; + # }; + # systemd.tmpfiles.rules = [ + # "d /etc/kanidm 1755 nobody users -" + # ]; # module has the incorrect file permissions out of the box - environment.etc = { - /* - "kanidm" = { - enable = true; - user = "nobody"; - group = "users"; - mode = "0755"; - }; - */ - "kanidm/unixd" = { - user = "kanidm-unixd"; - group = "kanidm-unixd"; - mode = "0700"; - }; - "kanidm/config" = { - user = "nobody"; - group = "users"; - mode = "0755"; - }; + # environment.etc = { + /* + "kanidm" = { + enable = true; + user = "nobody"; + group = "users"; + mode = "0755"; }; + */ + # "kanidm/unixd" = { + # user = "kanidm-unixd"; + # group = "kanidm-unixd"; + # mode = "0700"; + # }; + # "kanidm/config" = { + # user = "nobody"; + # group = "users"; + # mode = "0755"; + # }; + # }; programs.gnupg.agent = { enable = true; @@ -1269,7 +1275,6 @@ }; }; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; system.stateVersion = lib.mkDefault "24.05"; }; diff --git a/nixos/beefcake.nix b/nixos/beefcake.nix index b83ba33..97f9328 100644 --- a/nixos/beefcake.nix +++ b/nixos/beefcake.nix @@ -220,8 +220,6 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00 networking.firewall.allowedUDPPorts = lib.mkIf config.services.headscale.enable [3478]; } { - # TODO: I think I need to setup my account? wondering if this can be done in nix as well - services.restic.commonPaths = ["/var/lib/soju" "/var/lib/private/soju"]; services.soju = { enable = true; @@ -1112,26 +1110,27 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00 port = 26969; dir = "/storage/flanilla"; user = "flanilla"; - uid = config.users.users.flanilla.uid; - gid = config.users.groups.flanilla.gid; + # uid = config.users.users.flanilla.uid; + # gid = config.users.groups.flanilla.gid; in { # flanilla family minecraft server users.groups.${user} = {}; users.users.${user} = { isSystemUser = true; createHome = false; + home = dir; group = user; }; virtualisation.oci-containers.containers.minecraft-flanilla = { - autoStart = true; + autoStart = false; image = "docker.io/itzg/minecraft-server"; - user = "${toString uid}:${toString gid}"; + # user = "${toString uid}:${toString gid}"; extraOptions = ["--tty" "--interactive"]; environment = { EULA = "true"; MOTD = "Flanilla Survival! Happy hunting!"; - UID = toString uid; - GID = toString gid; + # UID = toString uid; + # GID = toString gid; STOP_SERVER_ANNOUNCE_DELAY = "20"; TZ = "America/Chicago"; VERSION = "1.21"; @@ -1152,6 +1151,10 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00 "${dir}/worlds:/worlds" ]; }; + systemd.services.podman-minecraft-flanilla.serviceConfig = { + User = user; + Group = user; + }; systemd.tmpfiles.settings = { "10-${user}-survival" = { "${dir}/data" = { @@ -1179,26 +1182,27 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00 port = 26968; dir = "/storage/flanilla-creative"; user = "flanilla"; - uid = config.users.users.flanilla.uid; - gid = config.users.groups.flanilla.gid; + # uid = config.users.users.flanilla.uid; + # gid = config.users.groups.flanilla.gid; in { # flanilla family minecraft server users.groups.${user} = {}; users.users.${user} = { isSystemUser = true; createHome = false; + home = lib.mkForce dir; group = user; }; virtualisation.oci-containers.containers.minecraft-flanilla-creative = { autoStart = true; image = "docker.io/itzg/minecraft-server"; - user = "${toString uid}:${toString gid}"; + # user = "${toString uid}:${toString gid}"; extraOptions = ["--tty" "--interactive"]; environment = { EULA = "true"; MOTD = "Flanilla Creative! Have fun building!"; - UID = toString uid; - GID = toString gid; + # UID = toString uid; + # GID = toString gid; STOP_SERVER_ANNOUNCE_DELAY = "20"; TZ = "America/Chicago"; VERSION = "1.21"; @@ -1219,6 +1223,10 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00 "${dir}/worlds:/worlds" ]; }; + # systemd.services.podman-minecraft-flanilla-creative.serviceConfig = { + # User = user; + # Group = user; + # }; systemd.tmpfiles.settings = { "10-${user}-creative" = { "${dir}/data" = { @@ -1783,7 +1791,7 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00 virtualisation.oci-containers = { containers.actual = { - image = "ghcr.io/actualbudget/actual-server:24.10.0"; + image = "ghcr.io/actualbudget/actual-server:24.10.1"; autoStart = true; ports = ["5006:5006"]; volumes = ["/storage/actual:/data"]; @@ -1794,6 +1802,29 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00 extraConfig = ''reverse_proxy :5006''; }; } + { + services.factorio = { + enable = true; + package = pkgs.factorio-headless.override { + versionsJson = ./factorio-versions.json; + }; + admins = ["lytedev"]; + autosave-interval = 5; + game-name = "Flanwheel Online"; + description = "Space Age 2.0"; + openFirewall = true; + lan = true; + # public = true; # NOTE: cannot be true if requireUserVerification is false + port = 34197; + requireUserVerification = false; # critical for DRM-free users + + # contains the game password and account password for "public" servers + extraSettingsFile = config.sops.secrets.factorio-server-settings.path; + }; + sops.secrets = { + factorio-server-settings = {mode = "0777";}; + }; + } ]; /* diff --git a/nixos/factorio-versions.json b/nixos/factorio-versions.json new file mode 100644 index 0000000..e772fd0 --- /dev/null +++ b/nixos/factorio-versions.json @@ -0,0 +1,58 @@ +{ + "x86_64-linux": { + "alpha": { + "experimental": { + "name": "factorio_alpha_x64-1.1.110.tar.xz", + "needsAuth": true, + "sha256": "0ndhb94lh47n09a7wshm2inv52fd6rjfa7fk7nk9b7zzh84i7f4x", + "tarDirectory": "x64", + "url": "https://factorio.com/get-download/1.1.110/alpha/linux64", + "version": "1.1.110" + }, + "stable": { + "name": "factorio_alpha_x64-1.1.110.tar.xz", + "needsAuth": true, + "sha256": "0ndhb94lh47n09a7wshm2inv52fd6rjfa7fk7nk9b7zzh84i7f4x", + "tarDirectory": "x64", + "url": "https://factorio.com/get-download/1.1.110/alpha/linux64", + "version": "1.1.110" + } + }, + "demo": { + "experimental": { + "name": "factorio_demo_x64-1.1.110.tar.xz", + "needsAuth": false, + "sha256": "0dasxgrybl00vrabgrlarsvg0hdg5rvn3y4hsljhqc4zpbf93nxx", + "tarDirectory": "x64", + "url": "https://factorio.com/get-download/1.1.110/demo/linux64", + "version": "1.1.110" + }, + "stable": { + "name": "factorio_demo_x64-1.1.110.tar.xz", + "needsAuth": false, + "sha256": "0dasxgrybl00vrabgrlarsvg0hdg5rvn3y4hsljhqc4zpbf93nxx", + "tarDirectory": "x64", + "url": "https://factorio.com/get-download/1.1.110/demo/linux64", + "version": "1.1.110" + } + }, + "headless": { + "experimental": { + "name": "factorio_headless_x64-1.1.110.tar.xz", + "needsAuth": false, + "sha256": "0sk4g9y051xjhiwdhj1yz808308zwsbpq3nps1ywvpp56vdycps8", + "tarDirectory": "x64", + "url": "https://factorio.com/get-download/1.1.110/headless/linux64", + "version": "1.1.110" + }, + "stable": { + "name": "factorio_headless_x64-1.1.110.tar.xz", + "needsAuth": false, + "sha256": "0sk4g9y051xjhiwdhj1yz808308zwsbpq3nps1ywvpp56vdycps8", + "tarDirectory": "x64", + "url": "https://factorio.com/get-download/1.1.110/headless/linux64", + "version": "1.1.110" + } + } + } +} \ No newline at end of file diff --git a/nixos/router.nix b/nixos/router.nix index ff8d685..751b99b 100644 --- a/nixos/router.nix +++ b/nixos/router.nix @@ -214,6 +214,7 @@ in { udp dport { 80, 443 } accept comment "Allow QUIC to server (see nat prerouting)" tcp dport { 22 } accept comment "Allow SSH to server (see nat prerouting)" tcp dport { 25565 } accept comment "Allow Minecraft server connections (see nat prerouting)" + udp dport { 34197 } accept comment "Allow Factorio server connections (see nat prerouting)" iifname "${lan}" accept comment "Allow local network to access the router" iifname "tailscale0" accept comment "Allow local network to access the router" @@ -256,6 +257,7 @@ in { iifname ${wan} tcp dport {26966} dnat to ${hosts.beefcake.ip} iifname ${wan} tcp dport {25565} dnat to ${hosts.bald.ip} iifname ${wan} udp dport {25565} dnat to ${hosts.bald.ip} + iifname ${wan} udp dport {34197} dnat to ${hosts.beefcake.ip} } chain postrouting { diff --git a/secrets/beefcake/secrets.yml b/secrets/beefcake/secrets.yml index dd41417..0b11c0f 100644 --- a/secrets/beefcake/secrets.yml +++ b/secrets/beefcake/secrets.yml @@ -27,6 +27,7 @@ restic-rascal-passphrase: ENC[AES256_GCM,data:yonKbBh4riGwxc/qcj8F/qrgAtA1sWhYej restic-rascal-ssh-private-key: ENC[AES256_GCM,data:ddsOs0XsayyQI9qc6LzwQpdDnfwNpbj8PbBJ5fyuqtlVNYndeLxaYcbZI2ULSUhgR1tN0FS+ggGTHQhVvjwksNvpskUGHNKkSLKH3D/mn5N9tsoeAblN4gZsloZdqXBVzEehumcQMdhh6iy6NkNbuinKrVKDhLV25PrFKuSBEYw9VHU7HAMW5Tfop3RzBXjZWETCDAR2OQa7d1dXsJ0Kw6b9RFmRe5MGQ0J7YhjdTg26JGMMVSeHvr5UbiUJkGA5RvOLEDM2Dfai7Lf8yRPZVxUl+rdRsNvNYEoYGu5rGLUFcuqIbQ+s40dP2uXwWauwkIvHUjEahkbP0httj4Kg3qIJBRPg7OuS+MOwAnLEAs3hl5zeBV396yA9qjWW8nhnbml58/uFFbfXbJWTM3r8cMpFbHKD+Ojo/99fm5Vy3pAMzNzEsHOaT+iyDYyNkV5OH1GyKK9n7kIRLdqmWe7GmaKXlwVvNUPi3RvLX9VXq83a4BuupFyTmaNfPGMs/17830aleV674+QVgKh3VyFtuJy6KBpMXDv16wFo,iv:S2I3h6pmKLxEc29E0zn2b8lscqA//5/ZMTV9q+/tdvs=,tag:ALeCT+nrVPDfS21xC555sA==,type:str] restic-ssh-priv-key-benland: ENC[AES256_GCM,data:G+uiYZTvqXhpJb66j6Q6S+otlXeRX0CdYeMHzSMjIbvbI0AVm0yCU7COO5/O8i47NpvrKKS1kVxVEK8ixLRUowkl3hgRXhxsBIPFnpkMD0ENmJttm4HOpi0qIWMwzPYTjkz/slY4HcTFnCfYy1ZpURQdWwZsr1EdAA05bUMTtM22R3uOMzjO8uf72PCWX7yffo8MxsLmWvNVAOhVlrb2H5KQNR/IquFK3TFoZitq5nVDG9tcEFkX+lgA3zsmCHU/2DvvodgeRoltaAFvgjVznNGf4e5p8owHUtSzX52HwGZRiUlMuhpre2gm1r73n8AyZe41II+LX/85fMfZDdyayIGv3AAMBib8H0/AoChexRcdLQEmzOgRrXsgucDJrWSWP6WMBVyamUm79m5ep0fvL1lJftuJqN0uuq9dBrispdso4x+6jk/pDf5pEM/FE6s1rY832BEb7q0PnjyvVogOez+cIihmMpDdnS0A/8TFzg29i3C+93x5vrt3k7atNzR/jN+/GqX2FKLzxWrrIw2d,iv:IP+N8JQu+XRvwTtBnxu54ujzU5UliltXG3mk9HfJaN8=,tag:4oinE9QMaSh8IfUd/ttM3Q==,type:str] paperless-superuser-password: ENC[AES256_GCM,data:lypWK73mOYI2hyQAW/4T3cDiVtsts3kKb7LZb9ES3n97Kn5l,iv:jBHUBFbb4GqQ3gnK0h5VCaGj3/kd3/eGa1QFiE7+B9I=,tag:UoQar+x1xVnCV2k+9hYjWA==,type:str] +factorio-server-settings: ENC[AES256_GCM,data:ItK+/eONdAqNAiQxCrCipUmTdIKt274qwVyNnSdOdxxd67XGozs/xr/cCYwwDiUyKQ7mD8oBLL6EVaHbXpObLwGe0Nsnz5jE9GtI0k5184/jsQ==,iv:Qre+BKhdqNDNuOz0PGZJJpTmQxJdNoTbd5FxRy0lrVs=,tag:G4dFdVclUdagyA84Yh653w==,type:str] sops: kms: [] gcp_kms: [] @@ -51,8 +52,8 @@ sops: bGpacHFRSkJYUUMwOEh4cVBXZ1NESmsKa5EhZ7148ojCqZldukLcPLr93HqnpNgq rMI0Nyz4Z4lkTVMRpA94zyNTkNwJ02/CYcKi8EJi6jGZnNPUTcnTwg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-09-13T05:09:18Z" - mac: ENC[AES256_GCM,data:rS12xfQ6FQwVa19rdfk6i1DThUOfsrw+IdKGYOMrX8a7sOKPkNxyxyZASfaKopg3BaM8qmoOFUW4B9VWwTh4d+MhruH3DhJO3UuZpOtDv7H8JFmzqg8rlYx0nm+8/+dB0zjgK7m2FP8wn0jfXraaaQ7/HobgLgGtl+NAsXQkrwQ=,iv:+JO3Yq6Kp2CHu20dSRDOJf0ivq5ASHYrKvlCgg1vGxQ=,tag:y6nIISSZFQwRoFNvqaQWbg==,type:str] + lastmodified: "2024-10-14T14:58:39Z" + mac: ENC[AES256_GCM,data:cNVTWA2S9SMEqoDz7jHuN/9hO20kDyoR03vKw8D72VJiqDEVvAkYeRu6KmGI7DWcfV/2OIrwVjyt+zry92ksYPmF1Xx8s4hu6Z0ooi7mvNrtSMnOLJ68mfpERbdBBcnvX5YivS50mbPhif/kvb5IgUxIQvo2NGFC9Sj7ZnXLa+U=,iv:kKkHVNJ0JE4CRvQdLAfFHKeL4h3o7Z6HJ57HzsqKTJY=,tag:k9K7NS2TZ0uk9u0yd9IAOg==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.9.0