Compare commits

...

13 commits

Author SHA1 Message Date
Chris Kruining
8d46d0d60b
Update service configs and secrets handling
Some checks failed
Test action / kaas (push) Failing after 1s
- Add restartUnits and ownership to Matrix and Servarr secrets
- Use sops secret for qbittorrent password hash
- Refactor Cardigann indexer config in Servarr
- Update Caddy plugin version and hash
- Add debug output to machine update justfile
2026-03-05 11:40:40 +01:00
Chris Kruining
a5de9aea37
feat: add poor mans version of clan vars 2026-03-05 11:39:41 +01:00
13ca5cadd4 chore(secrets): set secret "qbittorrent/password_hash" for machine "ulmo" 2026-03-05 10:38:20 +00:00
2c7890152b chore(secrets): set secret "qbittorrent/password" for machine "ulmo" 2026-03-05 10:38:18 +00:00
d0b3a0f27c chore(secrets): removed secret "qbittorrent" from machine "ulmo" 2026-03-05 10:34:54 +00:00
939cab4383 chore(secrets): set secret "qbittorrent/password_hash" for machine "ulmo" 2026-03-05 10:32:25 +00:00
fb8ead924a chore(secrets): set secret "qbittorrent/password_hash" for machine "ulmo" 2026-03-05 08:25:19 +00:00
9b2bc8e604 chore(secrets): set secret "qbittorrent/password" for machine "ulmo" 2026-03-05 08:24:46 +00:00
3ae310f2e1 chore(secrets): set secret "sabnzbd/nzbkey" for machine "ulmo" 2026-03-04 09:45:12 +00:00
Chris Kruining
95ae5b8b83
Refactor sabnzbd config to use settings and secretFiles
Switch sabnzbd configuration to use the settings and secretFiles options
instead of a static config file. Add support for nzbkey secret. Update
sops template to include nzb_key and remove duplicated server and misc
settings.
2026-03-04 10:44:11 +01:00
Chris Kruining
a97c244c4f
Update Caddy plugin source and clear hash in config 2026-03-04 10:43:57 +01:00
Chris Kruining
e69a7a8669
Update machine docstring 2026-03-04 09:55:43 +01:00
Chris Kruining
4e9ef9dc4f
Refactor Caddy config into networking.caddy module
Move Caddy configuration from individual services to a shared
networking.caddy module. Update service modules and system config to use
the new interface. Remove redundant user definitions and old Caddy
config blocks.
2026-03-04 09:55:19 +01:00
17 changed files with 504 additions and 348 deletions

View file

@ -4,9 +4,11 @@
@list: @list:
ls -1 ../systems/x86_64-linux/ ls -1 ../systems/x86_64-linux/
[doc('Update the target machine')] [doc('Update target machine')]
[no-exit-message] [no-exit-message]
@update machine: @update machine:
echo "Checking vars"
cd .. && just vars _check {{ machine }} cd .. && just vars _check {{ machine }}
echo ""
just assert '-d "../systems/x86_64-linux/{{ machine }}"' "Machine {{ machine }} does not exist, must be one of: $(ls ../systems/x86_64-linux/ | sed ':a;N;$!ba;s/\n/, /g')" just assert '-d "../systems/x86_64-linux/{{ machine }}"' "Machine {{ machine }} does not exist, must be one of: $(ls ../systems/x86_64-linux/ | sed ':a;N;$!ba;s/\n/, /g')"
nixos-rebuild switch -L --sudo --target-host {{ machine }} --build-host {{ machine }} --flake ..#{{ machine }} --log-format internal-json -v |& nom --json nixos-rebuild switch -L --sudo --target-host {{ machine }} --build-host {{ machine }} --flake ..#{{ machine }} --log-format internal-json -v |& nom --json

View file

@ -1,7 +1,7 @@
set unstable := true set unstable := true
set quiet := true set quiet := true
base_path := invocation_directory() / "systems/x86_64-linux" base_path := justfile_directory() + "/systems/x86_64-linux"
_default: _default:
just --list vars just --list vars
@ -25,7 +25,7 @@ edit machine:
[doc('Get var by {key} from {machine}')] [doc('Get var by {key} from {machine}')]
get machine key: get machine key:
sops decrypt {{ base_path }}/{{ machine }}/secrets.yml | yq ".$(echo "{{ key }}" | sed -E 's/\//./g')" sops decrypt {{ base_path }}/{{ machine }}/secrets.yml | yq ".$(echo "{{ key }}" | sed -E 's/\//./g') // \"\""
[doc('Remove var by {key} for {machine}')] [doc('Remove var by {key} for {machine}')]
remove machine key: remove machine key:
@ -36,6 +36,20 @@ remove machine key:
echo "Done" echo "Done"
[doc('Remove var by {key} for {machine}')]
[script]
generate machine:
for key in $(nix eval --apply 'builtins.attrNames' --json ..#nixosConfigurations.{{ machine }}.config.sops.secrets | jq -r '.[]'); do
# Skip if there's no script
[ -f "{{ justfile_directory() }}/script/$key" ] || continue
# Skip if we already have a value
[ $(just vars get {{ machine }} "$key" | jq -r) ] && continue
echo "Executing script for $key"
just vars set {{ machine }} "$key" "$(cd -- "$(dirname "{{ justfile_directory() }}/script/$key")" && source "./$(basename $key)")"
done
[script] [script]
check: check:
cd .. cd ..

View file

@ -1,16 +1,36 @@
{ config, lib, pkgs, namespace, ... }: {
let config,
lib,
pkgs,
namespace,
...
}: let
inherit (lib) mkIf mkEnableOption; inherit (lib) mkIf mkEnableOption;
user = "authelia-testing"; user = "authelia-testing";
cfg = config.${namespace}.services.authentication.authelia; cfg = config.${namespace}.services.authentication.authelia;
in in {
{
options.${namespace}.services.authentication.authelia = { options.${namespace}.services.authentication.authelia = {
enable = mkEnableOption "Authelia"; enable = mkEnableOption "Authelia";
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
${namespace}.services.networking.caddy = {
hosts = {
"auth.kruining.eu".extraConfig = ''
reverse_proxy http://127.0.0.1:9091
'';
};
extraConfig = ''
(auth) {
forward_auth http://127.0.0.1:9091 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
}
'';
};
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
authelia authelia
]; ];
@ -112,8 +132,8 @@ in
authorization_policy = "one_factor"; authorization_policy = "one_factor";
userinfo_signed_response_alg = "none"; userinfo_signed_response_alg = "none";
consent_mode = "implicit"; consent_mode = "implicit";
scopes = [ "openid" "profile" "groups" ]; scopes = ["openid" "profile" "groups"];
redirect_uris = [ "https://jellyfin.kruining.eu/sso/OID/redirect/authelia" ]; redirect_uris = ["https://jellyfin.kruining.eu/sso/OID/redirect/authelia"];
} }
{ {
client_id = "streamarr"; client_id = "streamarr";
@ -127,8 +147,8 @@ in
authorization_policy = "one_factor"; authorization_policy = "one_factor";
userinfo_signed_response_alg = "none"; userinfo_signed_response_alg = "none";
consent_mode = "implicit"; consent_mode = "implicit";
scopes = [ "offline_access" "openid" "email" "picture" "profile" "groups" ]; scopes = ["offline_access" "openid" "email" "picture" "profile" "groups"];
redirect_uris = [ "http://localhost:3000/api/auth/oauth2/callback/authelia" ]; redirect_uris = ["http://localhost:3000/api/auth/oauth2/callback/authelia"];
} }
{ {
client_id = "forgejo"; client_id = "forgejo";
@ -142,10 +162,10 @@ in
authorization_policy = "one_factor"; authorization_policy = "one_factor";
userinfo_signed_response_alg = "none"; userinfo_signed_response_alg = "none";
consent_mode = "implicit"; consent_mode = "implicit";
scopes = [ "offline_access" "openid" "email" "picture" "profile" "groups" ]; scopes = ["offline_access" "openid" "email" "picture" "profile" "groups"];
response_types = [ "code" ]; response_types = ["code"];
grant_types = [ "authorization_code" ]; grant_types = ["authorization_code"];
redirect_uris = [ "http://localhost:5002/user/oauth2/authelia/callback" ]; redirect_uris = ["http://localhost:5002/user/oauth2/authelia/callback"];
} }
]; ];
}; };
@ -195,48 +215,8 @@ in
- jellyfin-users - jellyfin-users
- admin - admin
- dev - dev
jacqueline:
disabled: false
displayname: Jacqueline Bevers
password: $argon2id$v=19$m=65536,t=3,p=4$XgN8yEJV+syAE5yeos3HsA$SlN+j/lJfxJ5VxLu2CdrwowlCiWQNNGhIrSyDpohq18
groups:
- jellyfin-users
martijn:
disabled: false
displayname: Martijn Kruining
password: $argon2id$v=19$m=65536,t=3,p=4$XgN8yEJV+syAE5yeos3HsA$SlN+j/lJfxJ5VxLu2CdrwowlCiWQNNGhIrSyDpohq18
groups:
- jellyfin-users
andrea:
disabled: false
displayname: Andrea Kruining
password: $argon2id$v=19$m=65536,t=3,p=4$XgN8yEJV+syAE5yeos3HsA$SlN+j/lJfxJ5VxLu2CdrwowlCiWQNNGhIrSyDpohq18
groups:
- jellyfin-users
''; '';
}; };
}; };
services.caddy = {
enable = true;
virtualHosts = {
"auth.kruining.eu".extraConfig = ''
reverse_proxy http://127.0.0.1:9091
'';
};
extraConfig = ''
(auth) {
forward_auth http://127.0.0.1:9091 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
}
'';
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
}; };
} }

View file

@ -537,7 +537,25 @@ in
}; };
in in
mkIf cfg.enable { mkIf cfg.enable {
${namespace}.services.persistance.postgresql.enable = true; ${namespace}.services = {
persistance.postgresql.enable = true;
networking.caddy = {
hosts = {
"auth.kruining.eu" = ''
reverse_proxy h2c://::1:9092
'';
};
extraConfig = ''
(auth) {
forward_auth h2c://::1:9092 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
}
'';
};
};
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
zitadel zitadel
@ -678,23 +696,6 @@ in
} }
]; ];
}; };
caddy = {
enable = true;
virtualHosts = {
"auth.kruining.eu".extraConfig = ''
reverse_proxy h2c://::1:9092
'';
};
extraConfig = ''
(auth) {
forward_auth h2c://::1:9092 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
}
'';
};
}; };
networking.firewall.allowedTCPPorts = [ 80 443 ]; networking.firewall.allowedTCPPorts = [ 80 443 ];

View file

@ -25,6 +25,75 @@ in {
${namespace}.services = { ${namespace}.services = {
persistance.postgresql.enable = true; persistance.postgresql.enable = true;
# virtualisation.podman.enable = true; # virtualisation.podman.enable = true;
networking.caddy = {
# globalConfig = ''
# layer4 {
# 127.0.0.1:4004
# route {
# proxy {
# upstream synapse:4004
# }
# }
# }
# 127.0.0.1:4005
# route {
# proxy {
# upstream synapse:4005
# }
# }
# }
# }
# '';
hosts = let
server = {
"m.server" = "${fqn}:443";
};
client = {
"m.homeserver".base_url = "https://${fqn}";
"m.identity_server".base_url = "https://auth.${domain}";
"org.matrix.msc3575.proxy".url = "https://${domain}";
"org.matrix.msc4143.rtc_foci" = [
{
type = "livekit";
livekit_service_url = "https://${domain}/livekit/jwt";
}
];
};
in {
"${domain}, darkch.at" = ''
# Route for lk-jwt-service
handle /livekit/jwt* {
uri strip_prefix /livekit/jwt
reverse_proxy http://[::1]:${toString config.services.lk-jwt-service.port} {
header_up Host {host}
header_up X-Forwarded-Server {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}
}
handle_path /livekit/sfu* {
reverse_proxy http://[::1]:${toString config.services.livekit.settings.port} {
header_up Host {host}
header_up X-Forwarded-Server {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}
}
header /.well-known/matrix/* Content-Type application/json
header /.well-known/matrix/* Access-Control-Allow-Origin *
respond /.well-known/matrix/server `${toJSON server}`
respond /.well-known/matrix/client `${toJSON client}`
'';
"${fqn}" = ''
reverse_proxy /_matrix/* http://::1:${toString port}
reverse_proxy /_synapse/client/* http://::1:${toString port}
'';
};
};
}; };
services = { services = {
@ -197,75 +266,6 @@ in {
]; ];
}; };
caddy = {
enable = true;
# globalConfig = ''
# layer4 {
# 127.0.0.1:4004
# route {
# proxy {
# upstream synapse:4004
# }
# }
# }
# 127.0.0.1:4005
# route {
# proxy {
# upstream synapse:4005
# }
# }
# }
# }
# '';
virtualHosts = let
server = {
"m.server" = "${fqn}:443";
};
client = {
"m.homeserver".base_url = "https://${fqn}";
"m.identity_server".base_url = "https://auth.${domain}";
"org.matrix.msc3575.proxy".url = "https://${domain}";
"org.matrix.msc4143.rtc_foci" = [
{
type = "livekit";
livekit_service_url = "https://${domain}/livekit/jwt";
}
];
};
in {
"${domain}, darkch.at".extraConfig = ''
# Route for lk-jwt-service
handle /livekit/jwt* {
uri strip_prefix /livekit/jwt
reverse_proxy http://[::1]:${toString config.services.lk-jwt-service.port} {
header_up Host {host}
header_up X-Forwarded-Server {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}
}
handle_path /livekit/sfu* {
reverse_proxy http://[::1]:${toString config.services.livekit.settings.port} {
header_up Host {host}
header_up X-Forwarded-Server {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}
}
header /.well-known/matrix/* Content-Type application/json
header /.well-known/matrix/* Access-Control-Allow-Origin *
respond /.well-known/matrix/server `${toJSON server}`
respond /.well-known/matrix/client `${toJSON client}`
'';
"${fqn}".extraConfig = ''
reverse_proxy /_matrix/* http://::1:${toString port}
reverse_proxy /_synapse/client/* http://::1:${toString port}
'';
};
};
livekit = { livekit = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
@ -370,9 +370,17 @@ in {
sops = { sops = {
secrets = { secrets = {
"synapse/oidc_id" = {}; "synapse/oidc_id" = {
"synapse/oidc_secret" = {}; restartUnits = ["synapse-matrix.service"];
"coturn/secret" = {}; };
"synapse/oidc_secret" = {
restartUnits = ["synapse-matrix.service"];
};
"coturn/secret" = {
owner = config.systemd.services.coturn.serviceConfig.User;
group = config.systemd.services.coturn.serviceConfig.Group;
restartUnits = ["coturn.service"];
};
}; };
templates = { templates = {

View file

@ -28,6 +28,20 @@ in {
${namespace}.services = { ${namespace}.services = {
persistance.postgresql.enable = true; persistance.postgresql.enable = true;
virtualisation.podman.enable = true; virtualisation.podman.enable = true;
networking.caddy = {
hosts = {
"${domain}" = ''
# import auth
# stupid dumb way to prevent the login page and go to zitadel instead
# be aware that this does not disable local login at all!
# rewrite /user/login /user/oauth2/Zitadel
reverse_proxy http://127.0.0.1:${toString cfg.port}
'';
};
};
}; };
environment.systemPackages = with pkgs; [forgejo]; environment.systemPackages = with pkgs; [forgejo];
@ -168,21 +182,6 @@ in {
}; };
}; };
}; };
caddy = {
enable = true;
virtualHosts = {
"${domain}".extraConfig = ''
# import auth
# stupid dumb way to prevent the login page and go to zitadel instead
# be aware that this does not disable local login at all!
# rewrite /user/login /user/oauth2/Zitadel
reverse_proxy http://127.0.0.1:${toString cfg.port}
'';
};
};
}; };
users = { users = {

View file

@ -17,6 +17,14 @@ in {
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
${namespace}.services.networking.caddy = {
hosts = {
"jellyfin.kruining.eu" = ''
reverse_proxy http://[::1]:8096
'';
};
};
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
jellyfin jellyfin
jellyfin-web jellyfin-web
@ -34,15 +42,6 @@ in {
user = "media"; user = "media";
group = "media"; group = "media";
}; };
caddy = {
enable = true;
virtualHosts = {
"jellyfin.kruining.eu".extraConfig = ''
reverse_proxy http://[::1]:8096
'';
};
};
}; };
systemd.services.jellyfin.serviceConfig.killSignal = lib.mkForce "SIGKILL"; systemd.services.jellyfin.serviceConfig.killSignal = lib.mkForce "SIGKILL";

View file

@ -1,11 +1,15 @@
{ config, lib, pkgs, namespace, ... }: {
let config,
lib,
pkgs,
namespace,
...
}: let
inherit (lib) mkIf mkEnableOption mkOption; inherit (lib) mkIf mkEnableOption mkOption;
inherit (lib.types) str; inherit (lib.types) str;
cfg = config.${namespace}.services.media.nextcloud; cfg = config.${namespace}.services.media.nextcloud;
in in {
{
options.${namespace}.services.media.nextcloud = { options.${namespace}.services.media.nextcloud = {
enable = mkEnableOption "Nextcloud"; enable = mkEnableOption "Nextcloud";
@ -21,6 +25,14 @@ in
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
${namespace}.services.networking.caddy = {
hosts."cloud.kruining.eu" = ''
php_fastcgi unix//run/phpfpm/nextcloud.sock {
env front_controller_active true
}
'';
};
users = { users = {
users.${cfg.user} = { users.${cfg.user} = {
isSystemUser = true; isSystemUser = true;
@ -75,14 +87,5 @@ in
# startServices = true; # startServices = true;
# }; # };
services.caddy = {
enable = true;
virtualHosts."cloud.kruining.eu".extraConfig = ''
php_fastcgi unix//run/phpfpm/nextcloud.sock {
env front_controller_active true
}
'';
};
}; };
} }

View file

@ -86,7 +86,7 @@ in {
Prefecences.WebUI = { Prefecences.WebUI = {
Username = "admin"; Username = "admin";
Password_PBKDF2 = "@ByteArray(JpfX3wSUcMolUFD+8AD67w==:fr5kmc6sK9xsCfGW6HkPX2K1lPYHL6g2ncLLwuOVmjphmxkwBJ8pi/XQDsDWzyM/MRh5zPhUld2Xqn8o7BWv3Q==)"; Password_PBKDF2 = config.sops.secrets."qbittorrent/password_hash".path;
}; };
}; };
@ -94,12 +94,35 @@ in {
group = "media"; group = "media";
}; };
# port is harcoded in nixpkgs module
sabnzbd = { sabnzbd = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
configFile = "/var/media/sabnzbd/config.ini";
# configFile = config.sops.templates."sabnzbd/config.ini".path; allowConfigWrite = false;
configFile = lib.mkForce null;
secretFiles = [
config.sops.templates."sabnzbd/config.ini".path
];
settings = {
misc = {
port = 2009;
download_dir = "/var/media/downloads/incomplete";
complete_dir = "/var/media/downloads/done";
};
servers = {
"news.sunnyusenet.com" = {
name = "news.sunnyusenet.com";
displayname = "news.sunnyusenet.com";
host = "news.sunnyusenet.com";
port = 563;
timeout = 60;
};
};
};
user = "sabnzbd"; user = "sabnzbd";
group = "media"; group = "media";
@ -207,7 +230,6 @@ in {
host = "localhost"; host = "localhost";
username = "admin"; username = "admin";
password = lib.tfRef "var.qbittorrent_api_key"; password = lib.tfRef "var.qbittorrent_api_key";
# password = "poChieN5feeph0igeaCadeJ9Xux0ohmuy6ruH5ieThaPheib3iuzoo0ahw1aiceif1feegioh9Aimau0pai5thoh5ieH0aechohw";
url_base = "/"; url_base = "/";
port = 2008; port = 2008;
}; };
@ -250,47 +272,126 @@ in {
priority = 1; priority = 1;
name = "Nyaa"; name = "Nyaa";
implementation = "nyaa"; implementation = "Cardigann";
config_contract = "nyaa_settings"; config_contract = "CardigannSettings";
protocol = "torrent"; protocol = "torrent";
fields = [ fields = [
{ {
name = "targetType"; name = "definitionFile";
value = ""; text_value = "nyaasi";
}
{
name = "baseSettings.limitsUnit";
number_value = 0;
}
{
name = "torrentBaseSettings.preferMagnetUrl";
bool_value = false;
}
{
name = "prefer_magnet_links";
bool_value = true;
}
{
name = "sonarr_compatibility";
bool_value = false;
}
{
name = "strip_s01";
bool_value = false;
}
{
name = "radarr_compatibility";
bool_value = false;
}
{
name = "filter-id";
number_value = 0;
}
{
name = "cat-id";
number_value = 0;
}
{
name = "sort";
number_value = 0;
}
{
name = "type";
number_value = 1;
} }
]; ];
}; };
"nzbgeek" = { # "_1337x" = {
enable = true; # enable = true;
app_profile_id = 2; # app_profile_id = 1;
priority = 1; # priority = 1;
name = "NZBgeek"; # name = "1337x";
implementation = "nzbgeek"; # implementation = "Cardigann";
config_contract = "nzbgeek_settings"; # config_contract = "CardigannSettings";
protocol = "torrent"; # protocol = "torrent";
# tags = [1];
fields = [ # fields = [
]; # {
}; # name = "definitionFile";
# text_value = "1337x";
# }
# {
# name = "baseSettings.limitsUnit";
# number_value = 0;
# }
# {
# name = "torrentBaseSettings.preferMagnetUrl";
# bool_value = false;
# }
# {
# name = "disablesort";
# bool_value = false;
# }
# {
# name = "sort";
# number_value = 2;
# }
# {
# name = "type";
# number_value = 1;
# }
# ];
# };
# "nzbgeek" = { # "nzbgeek" = {
# enable = true; # enable = true;
# app_profile_id = 1; # app_profile_id = 2;
# priority = 1;
# name = "NZBgeek"; # name = "NZBgeek";
# implementation = "nzbgeek"; # implementation = "Newznab";
# config_contract = "nzbgeek_settings"; # config_contract = "NewznabSettings";
# protocol = "torrent"; # protocol = "usenet";
# fields = [ # fields = [
# # { # {
# # name = ""; # name = "baseUrl";
# # value = ""; # text_value = "https://api.nzbgeek.info";
# # } # }
# {
# name = "apiPath";
# text_value = "/api";
# }
# {
# name = "apiKey";
# text_value = "__TODO_API_KEY_SECRET__";
# }
# {
# name = "baseSettings.limitsUnit";
# number_value = 5;
# }
# ]; # ];
# }; # };
}; };
@ -401,7 +502,12 @@ in {
{ {
secrets = { secrets = {
"qbittorrent/password" = {}; "qbittorrent/password" = {};
"qbittorrent/password_hash" = {
owner = "qbittorrent";
group = "media";
};
"sabnzbd/apikey" = {}; "sabnzbd/apikey" = {};
"sabnzbd/nzbkey" = {};
"sabnzbd/sunnyweb/username" = {}; "sabnzbd/sunnyweb/username" = {};
"sabnzbd/sunnyweb/password" = {}; "sabnzbd/sunnyweb/password" = {};
}; };
@ -428,36 +534,14 @@ in {
group = "media"; group = "media";
mode = "0660"; mode = "0660";
content = '' content = ''
__version__ = 19
__encoding__ = utf-8
[misc] [misc]
download_dir = /var/media/downloads/incomplete
complete_dir = /var/media/downloads/done
api_key = ${config.sops.placeholder."sabnzbd/apikey"} api_key = ${config.sops.placeholder."sabnzbd/apikey"}
log_dir = logs nzb_key = ${config.sops.placeholder."sabnzbd/nzbkey"}
[servers] [servers]
[[news.sunnyusenet.com]] [[news.sunnyusenet.com]]
name = news.sunnyusenet.com
displayname = news.sunnyusenet.com
host = news.sunnyusenet.com
port = 563
timeout = 60
username = ${config.sops.placeholder."sabnzbd/sunnyweb/username"} username = ${config.sops.placeholder."sabnzbd/sunnyweb/username"}
password = ${config.sops.placeholder."sabnzbd/sunnyweb/password"} password = ${config.sops.placeholder."sabnzbd/sunnyweb/password"}
connections = 8
ssl = 1
ssl_verify = 3
ssl_ciphers = ""
enable = 1
required = 0
optional = 0
retention = 0
expire_date = ""
quota = ""
usage_at_start = 0
priority = 1
notes = ""
''; '';
}; };
}; };

View file

@ -0,0 +1,40 @@
{
config,
pkgs,
lib,
namespace,
...
}: let
inherit (builtins) length;
inherit (lib) mkIf mkEnableOption mkOption types attrNames mapAttrs;
cfg = config.${namespace}.services.networking.caddy;
hasHosts = (cfg.hosts |> attrNames |> length) > 0;
in {
options.${namespace}.services.networking.caddy = {
enable = mkEnableOption "enable caddy" // {default = true;};
hosts = mkOption {
type = types.attrsOf types.str;
};
extraConfig = mkOption {
type = types.str;
};
};
config = mkIf hasHosts {
services.caddy = {
enable = cfg.enable;
package = pkgs.caddy.withPlugins {
plugins = ["github.com/corazawaf/coraza-caddy/v2@v2.1.0"];
hash = "sha256-AdL/LFKXbWmCsJ/xZWZmYBnw57c7sS6s1miR3sSx1Ow=";
};
virtualHosts =
cfg.hosts
|> mapAttrs (host: extraConfig: {inherit extraConfig;});
};
};
}

View file

@ -91,6 +91,22 @@ in {
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
${namespace}.services.networking.caddy.hosts = {
"vault.kruining.eu" = ''
encode zstd gzip
handle_path /admin {
respond 401 {
close
}
}
reverse_proxy http://localhost:${toString config.services.vaultwarden.config.ROCKET_PORT} {
header_up X-Real-IP {remote_host}
}
'';
};
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d '/var/lib/vaultwarden' 0700 vaultwarden vaultwarden - -" "d '/var/lib/vaultwarden' 0700 vaultwarden vaultwarden - -"
]; ];
@ -150,25 +166,6 @@ in {
} }
]; ];
}; };
caddy = {
enable = true;
virtualHosts = {
"vault.kruining.eu".extraConfig = ''
encode zstd gzip
handle_path /admin {
respond 401 {
close
}
}
reverse_proxy http://localhost:${toString config.services.vaultwarden.config.ROCKET_PORT} {
header_up X-Real-IP {remote_host}
}
'';
};
};
}; };
sops = { sops = {

View file

@ -1,105 +1,109 @@
{ pkgs, inputs }: let {
pkgs,
inputs,
}: let
inherit (builtins) fetchurl; inherit (builtins) fetchurl;
inherit (pkgs) makeDesktopItem copyDesktopItems wineWowPackages; inherit (pkgs) makeDesktopItem copyDesktopItems wineWow64Packages;
inherit (inputs.erosanix.lib.x86_64-linux) mkWindowsAppNoCC makeDesktopIcon copyDesktopIcons; inherit (inputs.erosanix.lib.x86_64-linux) mkWindowsAppNoCC makeDesktopIcon copyDesktopIcons;
wine = wineWowPackages.base; wine = wineWow64Packages.base;
in mkWindowsAppNoCC rec { in
inherit wine; mkWindowsAppNoCC rec {
inherit wine;
pname = "studio"; pname = "studio";
version = "2.25.4"; version = "2.25.4";
src = fetchurl { src = fetchurl {
url = "https://studio.download.bricklink.info/Studio2.0+EarlyAccess/Archive/2.25.12_1/Studio+2.0+EarlyAccess.exe"; url = "https://studio.download.bricklink.info/Studio2.0+EarlyAccess/Archive/2.25.12_1/Studio+2.0+EarlyAccess.exe";
sha256 = "sha256:1xl3zvzkzr64zphk7rnpfx3whhbaykzw06m3nd5dc12r2p4sdh3v"; sha256 = "sha256:1xl3zvzkzr64zphk7rnpfx3whhbaykzw06m3nd5dc12r2p4sdh3v";
}; };
enableMonoBootPrompt = false; enableMonoBootPrompt = false;
dontUnpack = true; dontUnpack = true;
wineArch = "win64"; wineArch = "win64";
enableInstallNotification = true; enableInstallNotification = true;
fileMap = { fileMap = {
"$HOME/.config/${pname}/Stud.io" = "drive_c/users/$USER/AppData/Local/Stud.io"; "$HOME/.config/${pname}/Stud.io" = "drive_c/users/$USER/AppData/Local/Stud.io";
"$HOME/.config/${pname}/Bricklink" = "drive_c/users/$USER/AppData/LocalLow/Bricklink"; "$HOME/.config/${pname}/Bricklink" = "drive_c/users/$USER/AppData/LocalLow/Bricklink";
}; };
fileMapDuringAppInstall = false; fileMapDuringAppInstall = false;
persistRegistry = false; persistRegistry = false;
persistRuntimeLayer = true; persistRuntimeLayer = true;
inputHashMethod = "version"; inputHashMethod = "version";
# Can be used to precisely select the Direct3D implementation. # Can be used to precisely select the Direct3D implementation.
# #
# | enableVulkan | rendererOverride | Direct3D implementation | # | enableVulkan | rendererOverride | Direct3D implementation |
# |--------------|------------------|-------------------------| # |--------------|------------------|-------------------------|
# | false | null | OpenGL | # | false | null | OpenGL |
# | true | null | Vulkan (DXVK) | # | true | null | Vulkan (DXVK) |
# | * | dxvk-vulkan | Vulkan (DXVK) | # | * | dxvk-vulkan | Vulkan (DXVK) |
# | * | wine-opengl | OpenGL | # | * | wine-opengl | OpenGL |
# | * | wine-vulkan | Vulkan (VKD3D) | # | * | wine-vulkan | Vulkan (VKD3D) |
enableVulkan = false; enableVulkan = false;
rendererOverride = null; rendererOverride = null;
enableHUD = false; enableHUD = false;
enabledWineSymlinks = { }; enabledWineSymlinks = {};
graphicsDriver = "auto"; graphicsDriver = "auto";
inhibitIdle = false; inhibitIdle = false;
nativeBuildInputs = [ copyDesktopIcons copyDesktopItems ]; nativeBuildInputs = [copyDesktopIcons copyDesktopItems];
winAppInstall = '' winAppInstall = ''
wine64 ${src} wine64 ${src}
wineserver -W wineserver -W
wine64 reg add 'HKEY_CURRENT_USER\Software\Wine\X11 Driver' /t REG_SZ /v UseTakeFocus /d N /f wine64 reg add 'HKEY_CURRENT_USER\Software\Wine\X11 Driver' /t REG_SZ /v UseTakeFocus /d N /f
''; '';
winAppPreRun = '' winAppPreRun = ''
wineserver -W wineserver -W
wine64 reg add 'HKEY_CURRENT_USER\Software\Wine\X11 Driver' /t REG_SZ /v UseTakeFocus /d N /f wine64 reg add 'HKEY_CURRENT_USER\Software\Wine\X11 Driver' /t REG_SZ /v UseTakeFocus /d N /f
''; '';
winAppRun = '' winAppRun = ''
wine64 "$WINEPREFIX/drive_c/Program Files/Studio 2.0/Studio.exe" "$ARGS" wine64 "$WINEPREFIX/drive_c/Program Files/Studio 2.0/Studio.exe" "$ARGS"
''; '';
winAppPostRun = ""; winAppPostRun = "";
installPhase = '' installPhase = ''
runHook preInstall runHook preInstall
ln -s $out/bin/.launcher $out/bin/${pname} ln -s $out/bin/.launcher $out/bin/${pname}
runHook postInstall runHook postInstall
''; '';
desktopItems = [ desktopItems = [
(makeDesktopItem { (makeDesktopItem {
mimeTypes = []; mimeTypes = [];
name = pname;
exec = pname;
icon = pname;
desktopName = "Bricklink studio";
genericName = "Lego creation app";
categories = [];
})
];
desktopIcon = makeDesktopIcon {
name = pname; name = pname;
exec = pname; src = ./studio.png;
icon = pname; };
desktopName = "Bricklink studio";
genericName = "Lego creation app";
categories = [];
})
];
desktopIcon = makeDesktopIcon { meta = {
name = pname; description = "App for creating lego builds";
src = ./studio.png; homepage = "https://www.bricklink.com/v3/studio/main.page";
}; license = "";
maintainers = [];
meta = { platforms = ["x86_64-linux"];
description = "App for creating lego builds"; };
homepage = "https://www.bricklink.com/v3/studio/main.page"; }
license = "";
maintainers = [];
platforms = [ "x86_64-linux" ];
};
}

View file

@ -0,0 +1,19 @@
#!/usr/bin/bash
import base64
import hashlib
import sys
import uuid
password = sys.argv[1]
salt = uuid.uuid4()
salt_bytes = salt.bytes
password = str.encode(password)
hashed_password = hashlib.pbkdf2_hmac("sha512", password, salt_bytes, 100000, dklen=64)
b64_salt = base64.b64encode(salt_bytes).decode("utf-8")
b64_password = base64.b64encode(hashed_password).decode("utf-8")
password_string = "@ByteArray({salt}:{password})".format(
salt=b64_salt, password=b64_password
)
print(password_string)

View file

@ -0,0 +1,3 @@
#!/bin/bash
pwgen -s 128 1

View file

@ -0,0 +1,3 @@
#!/bin/bash
python ./hash.py "$(just vars get ulmo qbittorrent/password | jq -r)"

View file

@ -27,17 +27,6 @@
}; };
}; };
# Expose amarht cloud stuff like this until I have a proper solution
services.caddy.virtualHosts = {
"auth.amarth.cloud".extraConfig = ''
reverse_proxy http://192.168.1.223:9092
'';
"amarth.cloud".extraConfig = ''
reverse_proxy http://192.168.1.223:8080
'';
};
# virtualisation = { # virtualisation = {
# containers.enable = true; # containers.enable = true;
# podman = { # podman = {
@ -204,6 +193,16 @@
development.forgejo.enable = true; development.forgejo.enable = true;
networking.ssh.enable = true; networking.ssh.enable = true;
networking.caddy.hosts = {
# Expose amarht cloud stuff like this until I have a proper solution
"auth.amarth.cloud" = ''
reverse_proxy http://192.168.1.223:9092
'';
"amarth.cloud" = ''
reverse_proxy http://192.168.1.223:8080
'';
};
media.enable = true; media.enable = true;
media.glance.enable = true; media.glance.enable = true;

View file

@ -23,9 +23,6 @@ mydia:
oidc_secret: ENC[AES256_GCM,data:PgI4hmP/3wt9uj+1QvCYcT8Wav0hgCRADouzWM3V695SSfXfbwDgez8tA/tm1/1jymAU2F2sZH8G2hZ1cdHyHQ==,iv:h3o3jsTmnoNE3+mGX12J3ZU0/6PlQNjdndEvaj/czj0=,tag:p3+p4E8fBtR7a8UpM8cUsg==,type:str] oidc_secret: ENC[AES256_GCM,data:PgI4hmP/3wt9uj+1QvCYcT8Wav0hgCRADouzWM3V695SSfXfbwDgez8tA/tm1/1jymAU2F2sZH8G2hZ1cdHyHQ==,iv:h3o3jsTmnoNE3+mGX12J3ZU0/6PlQNjdndEvaj/czj0=,tag:p3+p4E8fBtR7a8UpM8cUsg==,type:str]
secret_key_base: ENC[AES256_GCM,data:yG7HJ5r74Qtxbeyf8F6dA0uHv2pQ8YAJKlKiKjS+m24JRvJWQaTThJ+c5HbuUa6R3e9XtVHchhlVPkF0Is/b+g==,iv:v65xdRr4JdKZmBtjZ08/J3LLqnphSGt9QfVPNQ2x/xg=,tag:n7tD2dhr4IJn1LWM9WW8UA==,type:str] secret_key_base: ENC[AES256_GCM,data:yG7HJ5r74Qtxbeyf8F6dA0uHv2pQ8YAJKlKiKjS+m24JRvJWQaTThJ+c5HbuUa6R3e9XtVHchhlVPkF0Is/b+g==,iv:v65xdRr4JdKZmBtjZ08/J3LLqnphSGt9QfVPNQ2x/xg=,tag:n7tD2dhr4IJn1LWM9WW8UA==,type:str]
guardian_secret: ENC[AES256_GCM,data:OjnNFSHlecL+qXwlhTm++itRM6ga5E5KrSJxbgIUpbMEkIWgu3xhRtnPdipXbedgall0XdO/s+jnWCagZX94BA==,iv:DukdKvm9vey8BWUiml20tgA/Vji1XVX4+sUPge9nTk0=,tag:q3HdvgUYqR0APiaFz0ul5Q==,type:str] guardian_secret: ENC[AES256_GCM,data:OjnNFSHlecL+qXwlhTm++itRM6ga5E5KrSJxbgIUpbMEkIWgu3xhRtnPdipXbedgall0XdO/s+jnWCagZX94BA==,iv:DukdKvm9vey8BWUiml20tgA/Vji1XVX4+sUPge9nTk0=,tag:q3HdvgUYqR0APiaFz0ul5Q==,type:str]
qbittorrent:
password_hash: ENC[AES256_GCM,data:yCfCslj01wtfwzzPOGlwA6wLLf+EUuEweYa3ZxvDtd/VGMxuV38quV+ob1Of+W0UH3+U4Qmgh4BK3I3IJZuKOvNdkZ0i81YBwW6cgvZUmnxwh8wokpNzxCKbYk5nF7y7SaGEdzQLvV7ad3fNMJsQ+s2zCsKWbm+j8Bwgq0E=,iv:IIktPS9pYXaYPzH0r4wrkp31CpunKnr70Ainu6hOeWY=,tag:bYCfhDfIwiQZ1tKAvITewQ==,type:str]
password: ENC[AES256_GCM,data:UepYY6UjJV/jo2aXTOEnKRtsjSqOSYPQlKlrAa7rf9rdnt2UXGjCkvN+A72pICuIBCAmhXZBAUMvmWTV9trk6NREHe0cY1xTC7pNv3x9TM/ZQmH498pbT/95pYAKwouHp9heJQ==,iv:FzjF+xPoaOp+gplxpz940V2dkWSTWe8dWUxexCoxxHc=,tag:TDZsboq9fEmmBrwJN/HTpQ==,type:str]
grafana: grafana:
oidc_id: ENC[AES256_GCM,data:NVdIgCQ6nz4BSUDJYCKyILtK,iv:tcljy9PzC/yyd7TSdngyJt+uh60uXi2PKu47czErbaQ=,tag:zE4q3dD4UQaHIpGeZ1L48Q==,type:str] oidc_id: ENC[AES256_GCM,data:NVdIgCQ6nz4BSUDJYCKyILtK,iv:tcljy9PzC/yyd7TSdngyJt+uh60uXi2PKu47czErbaQ=,tag:zE4q3dD4UQaHIpGeZ1L48Q==,type:str]
oidc_secret: ENC[AES256_GCM,data:b7qILK9ZHW2khtM1Hl/KdjCv3Wq6eOo2Ym/cbjcMB8/3Hn2UelpP4K4lFyiV3bn1/GF6Jl5Z7A0EwMybOx0InA==,iv:3HL/7BiyObwT8DmFxzNPI9CdmCH/4j/4oc9x7qBE1k0=,tag:dBhcq1zLKy6N+jp/v42R4A==,type:str] oidc_secret: ENC[AES256_GCM,data:b7qILK9ZHW2khtM1Hl/KdjCv3Wq6eOo2Ym/cbjcMB8/3Hn2UelpP4K4lFyiV3bn1/GF6Jl5Z7A0EwMybOx0InA==,iv:3HL/7BiyObwT8DmFxzNPI9CdmCH/4j/4oc9x7qBE1k0=,tag:dBhcq1zLKy6N+jp/v42R4A==,type:str]
@ -35,10 +32,14 @@ sabnzbd:
password: ENC[AES256_GCM,data:flw8AahqO1Mx,iv:Qhu8iVWMzzqy18y8dj3aHoBnSZatm74/tYvZ456l2sA=,tag:sCYBdw7kD0zJZFFr5EyPIQ==,type:str] password: ENC[AES256_GCM,data:flw8AahqO1Mx,iv:Qhu8iVWMzzqy18y8dj3aHoBnSZatm74/tYvZ456l2sA=,tag:sCYBdw7kD0zJZFFr5EyPIQ==,type:str]
username: ENC[AES256_GCM,data:IboJ8WDWuVNgvrk7c3V8I5S6Xg==,iv:BRohMuQFQz2S+HFasIaok6npT3C5v/SlhAhbLQXfB0s=,tag:M3/u0WBQ3AufHqe4DCtsrA==,type:str] username: ENC[AES256_GCM,data:IboJ8WDWuVNgvrk7c3V8I5S6Xg==,iv:BRohMuQFQz2S+HFasIaok6npT3C5v/SlhAhbLQXfB0s=,tag:M3/u0WBQ3AufHqe4DCtsrA==,type:str]
apikey: ENC[AES256_GCM,data:j5sPXKbBhMdNHOuoTfZ+c8nGu5JameOgK2z428iLdP01Hi6MvHVaN8Zs8YxMoSBtOjdtIEC8MS+3m1S1rU/P4pCRfZpK5ua1DBHq4l0xROUqokFWjDcAmJJv3pYXl0cQxQcGKQ==,iv:v5hu3gmO1Zn1FfXkHLPGN9f7JOcQjzoQahdqJwfM+xY=,tag:uI1LFcTgcyRgAaTJ1kzKow==,type:str] apikey: ENC[AES256_GCM,data:j5sPXKbBhMdNHOuoTfZ+c8nGu5JameOgK2z428iLdP01Hi6MvHVaN8Zs8YxMoSBtOjdtIEC8MS+3m1S1rU/P4pCRfZpK5ua1DBHq4l0xROUqokFWjDcAmJJv3pYXl0cQxQcGKQ==,iv:v5hu3gmO1Zn1FfXkHLPGN9f7JOcQjzoQahdqJwfM+xY=,tag:uI1LFcTgcyRgAaTJ1kzKow==,type:str]
nzbkey: ENC[AES256_GCM,data:tGFnZ24XNI7U8pVYq45ENSVTeVkkcWfT5/NewqSJ3sm7Bexxml/PFTMBIl+97mWzNMMFklBurX/115P06NHCj1mxEvIjIc1bF4yuYhZFdSTlqRVWaESE/Ei7gke758FCt37N43wADgaKj4i5jizDHJMIbaw8ncP3qBSCy1F4BAU=,iv:RA+3oYGhVLBG+ikHMwBG3t2iN15lGsncdmlkfF6vJhY=,tag:6FNM18KCSzzpIXYDpQfHSg==,type:str]
whisparr: whisparr:
apikey: ENC[AES256_GCM,data:kIGCsd4mszm90PoQMzlSEBKw9Ow0GvP1qdLtwXYKkAb6b65l89v8lMWJ2X1MyD2gJX+P+Bv1F/2BSjUFXErq/UYnp4dAjwKi/ezGCbhjMutDM1FvwFWEHRnR3gjd9uXPWJ8Xhg==,iv:98aPQlcZHJovpnzACDs6RtKblLnHg6wyi+Er5DAowj8=,tag:Tl8jz/pWYWAtBCfoztKdyw==,type:str] apikey: ENC[AES256_GCM,data:kIGCsd4mszm90PoQMzlSEBKw9Ow0GvP1qdLtwXYKkAb6b65l89v8lMWJ2X1MyD2gJX+P+Bv1F/2BSjUFXErq/UYnp4dAjwKi/ezGCbhjMutDM1FvwFWEHRnR3gjd9uXPWJ8Xhg==,iv:98aPQlcZHJovpnzACDs6RtKblLnHg6wyi+Er5DAowj8=,tag:Tl8jz/pWYWAtBCfoztKdyw==,type:str]
coturn: coturn:
secret: ENC[AES256_GCM,data:5RmLZ7vQIAvIzvax8oNJkImQ6vXR+MZ2eqxaBJCBlccnFC1rP16/6UtausXVf0eWysw+fpMW5yEmUtAdyxQoPiBCK8lziAZBdkekQnAvFouBaWy8WIZt6XRa71P4xDCDGudpMiGwGGNt+R9yylez+azaLrLyJM3481RPohDMoOM=,iv:2P83lgxGtHwYr+ApAdHopVfRWagxWlC+nt53API/SiQ=,tag:Qv+A03BE1QvEqJMtORiQVA==,type:str] secret: ENC[AES256_GCM,data:5RmLZ7vQIAvIzvax8oNJkImQ6vXR+MZ2eqxaBJCBlccnFC1rP16/6UtausXVf0eWysw+fpMW5yEmUtAdyxQoPiBCK8lziAZBdkekQnAvFouBaWy8WIZt6XRa71P4xDCDGudpMiGwGGNt+R9yylez+azaLrLyJM3481RPohDMoOM=,iv:2P83lgxGtHwYr+ApAdHopVfRWagxWlC+nt53API/SiQ=,tag:Qv+A03BE1QvEqJMtORiQVA==,type:str]
qbittorrent:
password: ENC[AES256_GCM,data:LIDxh0Ni0JgQGWFix/Ihw7IlUPgzMhrMlWNP5LKkAnEM6EoqA9kFwiPeizB0CZ20+vSqRiL9fikBf8qGLA17L7AKh8I4OTFDlpKpMRtRlMq9S5UBEyOqtOMcvkCSf6/qGoORd1KJSlaitZk47SYRuccOpy/2vAvbMRdLm0SYEqc=,iv:tQdN1N9kXoq7OZbR2eYyy50FltsMAAUI4Lr7U4/SpJE=,tag:3ZOLvjHXD7i7WFy1/Ggqtg==,type:str]
password_hash: ENC[AES256_GCM,data:urufJbSErLqPdU6jLLZk+27fe4k+cKLXcGRGSqroUDdGMzDnhSF+ZWuPxwDlJQR3ws2GnuiEASncwNO/SALKXFDk2V2gsKJ4hsjyiIbsqCwSEFB/XMY0nY/x0xrcIfMVE0HdrNYeQ3zT01Z5jQpSd7wo2M63LaULL/Av498=,iv:tnUVhOgrImKa6iii2hJZn5LKrySM5v47B2zDZMgmUow=,tag:g3xa/4Z+t1Q9Wnd4XzefLg==,type:str]
sops: sops:
age: age:
- recipient: age19qfpf980tadguqq44zf6xwvjvl428dyrj46ha3n6aeqddwhtnuqqml7etq - recipient: age19qfpf980tadguqq44zf6xwvjvl428dyrj46ha3n6aeqddwhtnuqqml7etq
@ -59,7 +60,7 @@ sops:
TTRWaHhpNWlkVDFmMFN4ZTNHMUxyNVkKV693pzTKRkZboQCMPr9IyMGSgxfuHXcb TTRWaHhpNWlkVDFmMFN4ZTNHMUxyNVkKV693pzTKRkZboQCMPr9IyMGSgxfuHXcb
Y6BNcp6Qg6PWtX5QI7wRkPNINAK1TEbRBba+b8h6gMmVU4DliQyFiQ== Y6BNcp6Qg6PWtX5QI7wRkPNINAK1TEbRBba+b8h6gMmVU4DliQyFiQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2026-02-25T07:35:41Z" lastmodified: "2026-03-05T10:38:19Z"
mac: ENC[AES256_GCM,data:UKAWLSj/OpyCGj1U9rhCX2rQr5E2CXodU+Z5RZddTdFis1+1opw7GLr+2s4OTRbREdZsNP3JSoXycgCssf4na88p/PTZh/VUa9ymbRr9eTacJq6ZkqRC5J8WyDK6gI+Qv4gv5CxdxZd92vUa4uXlwrZ4VsYepvrrkatCe9YTA9w=,iv:dkm+hkdyzJsIXp4uB36wYa/uzl8VA7LwhmvQT3hQlog=,tag:zHxeEze6RVfTCcduVkwuoQ==,type:str] mac: ENC[AES256_GCM,data:gS6YTRTl6UdOC7Afrj1LrkgA7MWRLF0HNWytfzhkvThLW+JJrHPEhvWiYrsPW1Bm6o2JkKqVP5HfzcuGNIHJySkEQ4HV02BbibtMNiUKqk+voATsWOpo6957bwRJaTbvDvxmzIQ38TSUoj/pt8Z8WTl0hSPAlqNlWYffXX0y8K4=,iv:53R2bKYKiHJi9DTecg7hiuGNb3Kj9rA2U/oPJ+AFO5I=,tag:5uqvmEJCaCS/yNqyt/FPZg==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.11.0 version: 3.11.0