Compare commits

...

20 Commits

Author SHA1 Message Date
7153e2d3e3 Merge branch 'main' of orion:kiri/nixos-config 2025-12-04 18:48:31 +01:00
24b1438410 Sort todoman using priority 2025-12-04 18:45:31 +01:00
3d62cc10d3 Add host for work github 2025-12-04 18:45:24 +01:00
f92f4e8362 Add second key to gpg-agent 2025-12-04 18:45:11 +01:00
60fe1fd579 Remove home-manager syncthing 2025-12-04 18:44:56 +01:00
575d797b5c Add rustc for nixCats 2025-12-04 18:44:39 +01:00
b492aeb371 Move lazydev config and load blink.cmp on start 2025-12-04 18:44:15 +01:00
023007dc79 Fix syncthing perms 2025-12-04 18:42:28 +01:00
962aadd77b Add trash-cli 2025-12-04 18:42:22 +01:00
cb2388c3c6 Add harper and enable underline diagnostics 2025-12-04 18:42:17 +01:00
dca64dd6c2 Enable wake-on-lan for polaris 2025-12-04 18:41:59 +01:00
2a63a01ce3 Add float rule for imv 2025-12-02 13:29:21 +01:00
f794cdb44c Add polaris to syncthing devices 2025-12-02 13:20:03 +01:00
2b7c944ba5 Remove reference to syncthing home-manager module 2025-12-02 13:18:38 +01:00
b473b2dc16 Replace rclone with syncthing 2025-12-02 02:37:02 +01:00
1854c56c63 Add a homepage module 2025-12-02 01:31:33 +01:00
91cafd8108 Disable google drive sync 2025-12-02 01:11:59 +01:00
bdb9d72c1e Add nice fonts 2025-12-01 23:32:28 +01:00
9607277667 Improve filebrowser and rclone 2025-12-01 23:32:24 +01:00
830c3ebe5a Improve typst experience in neovim 2025-12-01 23:30:29 +01:00
19 changed files with 545 additions and 182 deletions

View File

@@ -10,9 +10,9 @@
../../modules/nixos/caddy.nix ../../modules/nixos/caddy.nix
../../modules/nixos/bitwarden.nix ../../modules/nixos/bitwarden.nix
../../modules/nixos/firewall.nix ../../modules/nixos/firewall.nix
../../modules/nixos/syncthing.nix
../../modules/nixos/filebrowser.nix ../../modules/nixos/filebrowser.nix
../../modules/nixos/home-assistant.nix ../../modules/nixos/home-assistant.nix
../../modules/nixos/glance.nix
../../modules/nixos/radicale.nix ../../modules/nixos/radicale.nix
../../modules/nixos/actual-budget.nix ../../modules/nixos/actual-budget.nix
../../modules/nixos/gitea.nix ../../modules/nixos/gitea.nix

View File

@@ -3,10 +3,22 @@
imports = [ imports = [
../../modules/nixos/desktop.nix ../../modules/nixos/desktop.nix
../../modules/nixos/ssh.nix
./hardware-configuration.nix ./hardware-configuration.nix
./variables.nix ./variables.nix
]; ];
networking = {
interfaces = {
enp5s0 = {
wakeOnLan.enable = true;
};
};
firewall = {
allowedUDPPorts = [ 9 ];
};
};
home-manager.users."${config.var.username}" = import ./home.nix; home-manager.users."${config.var.username}" = import ./home.nix;
system.stateVersion = "24.05"; system.stateVersion = "24.05";

View File

@@ -23,7 +23,6 @@
./kitty.nix ./kitty.nix
./lazygit.nix ./lazygit.nix
./nh.nix ./nh.nix
./rclone.nix
./spicetify.nix ./spicetify.nix
./ssh.nix ./ssh.nix
./thunar.nix ./thunar.nix
@@ -90,6 +89,8 @@
cmatrix cmatrix
libreoffice-qt6-fresh libreoffice-qt6-fresh
trash-cli
]; ];
}; };
} }

View File

@@ -2,7 +2,8 @@
config, config,
pkgs, pkgs,
... ...
}: { }:
{
programs.gpg = { programs.gpg = {
enable = true; enable = true;
homedir = "${config.xdg.dataHome}/gnupg"; homedir = "${config.xdg.dataHome}/gnupg";
@@ -15,6 +16,9 @@
pinentry = { pinentry = {
package = pkgs.pinentry-gnome3; package = pkgs.pinentry-gnome3;
}; };
sshKeys = ["CD848796822630B280FC6DFA55F24A20040F22B5"]; sshKeys = [
"CD848796822630B280FC6DFA55F24A20040F22B5"
"B8FBDFBD7F42C444C17E086E0EE2E34FB43A7187"
];
}; };
} }

View File

@@ -144,9 +144,10 @@ in
windowrule = [ windowrule = [
"match:title hyprpanel-settings, float on" "match:title hyprpanel-settings, float on"
"match:class xdg-desktop-portal-gtk, float on, center on, size monitor_w/2 monitor_h/2" "match:class xdg-desktop-portal-gtk, float on, center on, size (monitor_w * 0.5) (monitor_h * 0.5)"
# Match on bitwarden chrome extension id # Match on bitwarden chrome extension id
"match:class .*nngceckbapebfimnlniiiahkandclblb.*, float on, center on, size monitor_w/2 monitor_h/2" "match:class .*nngceckbapebfimnlniiiahkandclblb.*, float on, center on, size (monitor_w * 0.5) (monitor_h * 0.5)"
"match:class imv, float on, center on, max_size (monitor_w * 0.8) (monitor_h * 0.8)"
]; ];
layerrule = [ layerrule = [

View File

@@ -45,6 +45,7 @@ let
typescript typescript
typescript-language-server typescript-language-server
rustc
rust-analyzer rust-analyzer
rustfmt rustfmt
@@ -55,6 +56,13 @@ let
isort isort
astro-language-server astro-language-server
tinymist
typstyle
ltex-ls-plus
harper
]; ];
}; };
@@ -103,6 +111,8 @@ let
lualine-nvim lualine-nvim
bufferline-nvim bufferline-nvim
zen-mode-nvim
]; ];
}; };

View File

@@ -171,13 +171,25 @@ require("lz.n").load({
require("luasnip.loaders.from_vscode").lazy_load() require("luasnip.loaders.from_vscode").lazy_load()
end, end,
}, },
{
-- lazydev makes your lsp way better in your config without needing extra lsp configuration.
"lazydev.nvim",
cmd = "LazyDev",
ft = "lua",
after = function()
require("lazydev").setup({
library = {
{ words = { "nixCats" }, path = (nixCats.nixCatsPath or "") .. "/lua" },
},
})
end,
},
{ {
"blink.cmp", "blink.cmp",
before = function() before = function()
-- Trigger lazydev so it's ready for blink source -- Trigger lazydev so it's ready for blink source
require("lz.n").trigger_load({ "lazydev.nvim", "luasnip" }) require("lz.n").trigger_load({ "lazydev.nvim", "luasnip" })
end, end,
event = "VimEnter",
after = function() after = function()
require("blink.cmp").setup({ require("blink.cmp").setup({
keymap = { keymap = {

View File

@@ -1,18 +1,4 @@
require("lz.n").load({ require("lz.n").load({
{
{
-- lazydev makes your lsp way better in your config without needing extra lsp configuration.
"lazydev.nvim",
cmd = "LazyDev",
ft = "lua",
after = function()
require("lazydev").setup({
library = {
{ words = { "nixCats" }, path = (nixCats.nixCatsPath or "") .. "/lua" },
},
})
end,
},
{ {
"nvim-lspconfig", "nvim-lspconfig",
event = { "BufReadPre", "BufNewFile" }, event = { "BufReadPre", "BufNewFile" },
@@ -78,7 +64,7 @@ require("lz.n").load({
-- 1. Setup Diagnostics (Visuals) -- 1. Setup Diagnostics (Visuals)
vim.diagnostic.config({ vim.diagnostic.config({
severity_sort = true, severity_sort = true,
underline = { severity = vim.diagnostic.severity.ERROR }, -- underline = { severity = vim.diagnostic.severity.ERROR },
signs = { signs = {
text = { text = {
[vim.diagnostic.severity.ERROR] = "", [vim.diagnostic.severity.ERROR] = "",
@@ -161,7 +147,26 @@ require("lz.n").load({
vim.lsp.enable("basedpyright") vim.lsp.enable("basedpyright")
vim.lsp.enable("astro") vim.lsp.enable("astro")
end,
vim.lsp.config("tinymist", {
settings = {
tinymist = {
formatterMode = "typstyle",
}, },
}, },
}) })
vim.lsp.enable("tinymist")
vim.lsp.config("ltex_plus", {
settings = {
ltex = {
language = "nl",
},
},
})
vim.lsp.enable("ltex_plus")
vim.lsp.enable("harper_ls")
end,
},
})

View File

@@ -195,4 +195,16 @@ require("lz.n").load({
}) })
end, end,
}, },
{
"zen-mode.nvim",
after = function()
require("zen-mode").setup({
window = {
options = {
linebreak = true,
},
},
})
end,
},
}) })

View File

@@ -1,32 +1,70 @@
{ config, ... }: {
config,
pkgs,
...
}:
{ {
programs.rclone = { programs.rclone = {
enable = true; enable = true;
remotes = {
gdrive = {
config = {
type = "drive";
scope = "drive";
root_folder_id = ""; # Give rclone access to the ssh agent
package = pkgs.writeShellScriptBin "rclone" ''
export GNUPGHOME="${config.xdg.dataHome}/gnupg"
export SSH_AUTH_SOCK=$(${pkgs.gnupg}/bin/gpgconf --list-dirs agent-ssh-socket)
exec ${pkgs.rclone}/bin/rclone "$@"
'';
remotes = {
# gdrive = {
# config = {
# type = "drive";
# scope = "drive";
#
# root_folder_id = "";
# };
#
# secrets = {
# token = "${config.xdg.configHome}/rclone/gdrive_token";
#
# client_id = "${config.xdg.configHome}/rclone/gdrive_client_id";
# client_secret = "${config.xdg.configHome}/rclone/gdrive_client_secret"; # TODO: sops?
# };
#
# mounts = {
# "/" = {
# enable = true;
# mountPoint = "${config.home.homeDirectory}/gdrive";
#
# options = {
# dir-cache-time = "5m";
# poll-interval = "10s";
# };
# };
# };
# };
orion = {
config = {
type = "sftp";
user = config.var.username;
}; };
secrets = { secrets = {
token = "${config.xdg.configHome}/rclone/gdrive_token"; host = config.sops.secrets.orion_ip.path;
client_id = "${config.xdg.configHome}/rclone/gdrive_client_id";
client_secret = "${config.xdg.configHome}/rclone/gdrive_client_secret"; # TODO: sops?
}; };
mounts = { mounts = {
"/" = { "/var/lib/filebrowser/files" = {
enable = true; enable = true;
mountPoint = "${config.home.homeDirectory}/gdrive";
mountPoint = "${config.home.homeDirectory}/orion";
options = { options = {
dir-cache-time = "5000h"; dir-cache-time = "5m";
poll-interval = "10s"; poll-interval = "10s";
vfs-cache-mode = "full"; # Network optimizations
"buffer-size" = "32M";
"vfs-read-chunk-size" = "32M";
}; };
}; };
}; };

View File

@@ -4,6 +4,15 @@
enable = true; enable = true;
enableDefaultConfig = false; enableDefaultConfig = false;
matchBlocks = {
"github-work" = {
hostname = "github.com";
user = "git";
identityFile = "/home/kiri/.ssh/github-work.pub";
identitiesOnly = true;
};
};
includes = [ includes = [
config.sops.secrets.ssh_config_orion.path config.sops.secrets.ssh_config_orion.path
]; ];

View File

@@ -7,7 +7,7 @@
time_format = "%H:%M" time_format = "%H:%M"
default_list = "personal" default_list = "personal"
default_due = 0 default_due = 0
default_command = "list --sort due" default_command = "list --sort priority,due"
humanize = True humanize = True
''; '';
}; };

View File

@@ -9,5 +9,6 @@
./hyprland.nix ./hyprland.nix
./printing.nix ./printing.nix
./systemd-boot.nix ./systemd-boot.nix
./syncthing.nix
]; ];
} }

View File

@@ -8,11 +8,6 @@ let
storageRoot = "/var/lib/filebrowser/files"; storageRoot = "/var/lib/filebrowser/files";
publishDirName = "_publish"; publishDirName = "_publish";
fontPackages = with pkgs; [
libertinus
gyre-fonts
];
processorScript = pkgs.writeShellScriptBin "process-docs" '' processorScript = pkgs.writeShellScriptBin "process-docs" ''
SRC_ROOT="${storageRoot}" SRC_ROOT="${storageRoot}"
OUT_ROOT="${storageRoot}/${publishDirName}" OUT_ROOT="${storageRoot}/${publishDirName}"
@@ -73,6 +68,11 @@ let
in in
{ {
imports = [
./fonts.nix
];
services.filebrowser = { services.filebrowser = {
enable = true; enable = true;
@@ -87,12 +87,12 @@ in
reverse_proxy :${toString config.services.filebrowser.settings.port} reverse_proxy :${toString config.services.filebrowser.settings.port}
''; '';
# Auto compile pdfs
systemd.services.pdf-watcher = { systemd.services.pdf-watcher = {
description = "Auto-compile MD and Typst to PDF"; description = "Auto-compile MD and Typst to PDF";
after = [ "filebrowser.service" ]; after = [ "filebrowser.service" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
# Important: Run as the same user as Filebrowser to avoid permission issues
serviceConfig = { serviceConfig = {
User = "filebrowser"; User = "filebrowser";
Group = "filebrowser"; Group = "filebrowser";
@@ -102,7 +102,7 @@ in
Environment = [ Environment = [
"HOME=/var/lib/filebrowser" "HOME=/var/lib/filebrowser"
"XDG_CACHE_HOME=/var/lib/filebrowser/.cache" "XDG_CACHE_HOME=/var/lib/filebrowser/.cache"
"TYPST_FONT_PATHS=${lib.makeSearchPath "share/fonts" fontPackages}" # 3"TYPST_FONT_PATHS=${lib.makeSearchPath "share/fonts" fontPackages}"
]; ];
Restart = "always"; Restart = "always";
@@ -113,4 +113,16 @@ in
pandoc pandoc
]; ];
}; };
# Allow my user to access the filebrowser directory
users.users."${config.var.username}".extraGroups = [ "filebrowser" ];
systemd.services.filebrowser.serviceConfig = {
UMask = lib.mkForce "0007";
};
systemd.tmpfiles.rules = [
"Z /var/lib/filebrowser 0750 filebrowser filebrowser -" # Explicitly secure the data dir root
"Z /var/lib/filebrowser/files 2770 filebrowser filebrowser -" # Sticky group on files
];
} }

View File

@@ -20,6 +20,12 @@
nerd-fonts.meslo-lg nerd-fonts.meslo-lg
openmoji-color openmoji-color
twemoji-color-font twemoji-color-font
fira-sans
merriweather
lexend
literata
]; ];
enableDefaultPackages = false; enableDefaultPackages = false;

165
modules/nixos/homepage.nix Normal file
View File

@@ -0,0 +1,165 @@
{ config, pkgs, ... }:
let
# Define standard colors/icons for consistency
domain = "jelles.net";
in
{
# Enable the Homepage Dashboard service
services.homepage-dashboard = {
enable = true;
listenPort = 8082; # Different from Glance (8101)
allowedHosts = "dashboard.${domain}";
# 1. Service Discovery & API Secrets
# For live stats (widgets), Homepage needs API keys.
# You can reference sops secrets here if you map them to a file readable by the homepage user.
# For now, I have set them to placeholders or disabled the API widgets where secrets are required.
services = [
{
"Personal" = [
{
"Home Assistant" = {
href = "https://home.${domain}";
description = "Smart Home Control";
icon = "home-assistant.png";
# To enable live stats (lights on, etc), un-comment and add a Long Lived Access Token:
# widget = {
# type = "homeassistant";
# url = "http://127.0.0.1:8123";
# key = "YOUR_LONG_LIVED_TOKEN";
# };
};
}
{
"Actual Budget" = {
href = "https://finance.${domain}";
description = "Finance Tracking";
icon = "actual-budget.png";
};
}
{
"Vaultwarden" = {
href = "https://vault.${domain}";
description = "Password Manager";
icon = "bitwarden.png";
# Widget to show status
widget = {
type = "vaultwarden";
url = "https://vault.${domain}";
};
};
}
{
"Radicale" = {
href = "https://radicale.${domain}";
description = "Calendar & Contacts";
icon = "radicale.png";
};
}
];
}
{
"Code & Files" = [
{
"Gitea" = {
href = "https://git.${domain}";
description = "Git Server";
icon = "gitea.png";
};
}
{
"FileBrowser" = {
href = "https://files.${domain}";
description = "Web File Manager";
icon = "filebrowser.png";
};
}
];
}
{
"Websites" = [
{
"Community" = {
href = "https://community.${domain}";
icon = "globe.png";
description = "Community Site";
};
}
{
"Zentire" = {
href = "https://zentire.${domain}";
icon = "globe.png";
description = "Zentire Site";
};
}
];
}
];
# 2. Widgets (Calendar, Search, Resources)
widgets = [
{
search = {
provider = "google";
target = "_blank";
};
}
{
# Shows system stats. Requires 'glances' or similar installed,
# but Homepage can also just show simple resources if running locally.
resources = {
cpu = true;
memory = true;
disk = "/";
};
}
{
# Calendar Widget linked to Radicale
# You need the "Private Export URL" for your calendar from Radicale.
calendar = {
showTime = true;
maxEvents = 10;
integrations = [
{
type = "ical";
url = "https://radicale.${domain}/kiri/personal.ics"; # Verify this path in your Radicale
name = "Personal";
color = "blue";
# If your Radicale is private, you might need to pass auth in the URL
# e.g. https://user:pass@radicale.jelles.net/...
}
];
};
}
];
settings = {
title = "Orion Dashboard";
background = {
# Using the wallpaper from your config if accessible, or a hex color
image = "https://raw.githubusercontent.com/anotherhadi/awesome-wallpapers/refs/heads/main/app/static/wallpapers/leef_dark_purple_minimalist.png";
opacity = 50;
};
layout = {
"Personal" = {
style = "row";
columns = 4;
};
"Code & Files" = {
style = "row";
columns = 2;
};
"Websites" = {
style = "row";
columns = 2;
};
};
};
};
# Expose Homepage via Caddy
services.caddy.virtualHosts."dashboard.${domain}".extraConfig = ''
reverse_proxy :8082
'';
}

View File

@@ -0,0 +1,73 @@
{
config,
lib,
...
}:
let
devices = {
"altair" = {
id = "HDHWROJ-ZLNQKCL-PN6WGHA-IGJHIRI-3UHDYUU-LUJHYK4-UMKWLAZ-VFISJQF";
};
"orion" = {
id = "7ESQ3BX-FEW7656-ZPT3CKF-FLXON26-HXRNTDW-THSJBNF-LFWCHFB-ASP4WAG";
};
"polaris" = {
id = "6YBO3OK-3QVMKWL-ZOS4ZTF-G53CY6K-WYZJNFG-DTYCUA4-WJF2LRC-PJT3NAL";
};
};
username = config.var.username;
hostname = config.var.hostname;
isOrion = hostname == "orion";
# On desktops, sync to home directory. On server, sync to filebrowser storage.
syncPath = if isOrion then "/var/lib/filebrowser/files" else "/home/${username}/sync";
group = if isOrion then "filebrowser" else "users";
in
{
# 1. Firewall rules for synchronization
networking.firewall = {
allowedTCPPorts = [ 22000 ];
allowedUDPPorts = [
22000
21027
];
};
# 3. Syncthing Service Configuration
services.syncthing = {
enable = true;
user = username;
group = group;
overrideDevices = true; # Overrides any devices added via Web UI
overrideFolders = true; # Overrides any folders added via Web UI
settings = {
devices = devices;
folders = {
"sync" = {
path = syncPath;
devices = builtins.attrNames devices; # Share with all defined devices
# Ensure new files are readable by the group (chmod 770 approx)
ignorePerms = true;
};
};
gui = {
# access the GUI on localhost:8384
theme = "black";
};
};
};
# 4. Permission Hardening for Orion
# Force syncthing to write files with group-write permissions (007 umask = 770 perms)
systemd.services.syncthing.serviceConfig.UMask = lib.mkIf isOrion "0007";
systemd.tmpfiles.rules = [
"d /var/lib/syncthing 0700 ${username} ${group} -"
];
}

View File

@@ -13,6 +13,7 @@
secrets = { secrets = {
radicale_pass = { }; radicale_pass = { };
university_calendar_url = { }; university_calendar_url = { };
orion_ip = { };
ssh_config_orion = { ssh_config_orion = {
mode = "0600"; mode = "0600";
}; };

View File

@@ -1,6 +1,7 @@
radicale_pass: ENC[AES256_GCM,data:zdUxtJKNPC8SzajhFKo=,iv:H55GWMiQLJvZx6rAufkk807lZflg0sepxoq6z0XJ/q4=,tag:MoDOuF37PeF7QEpUxBntEg==,type:str] radicale_pass: ENC[AES256_GCM,data:zdUxtJKNPC8SzajhFKo=,iv:H55GWMiQLJvZx6rAufkk807lZflg0sepxoq6z0XJ/q4=,tag:MoDOuF37PeF7QEpUxBntEg==,type:str]
university_calendar_url: ENC[AES256_GCM,data:y5UtZVC0KJPUz//6S0QsrNeFGQshc88zieQgmlur75VFw9y5CJpnZRpdhLnYva00z5HBkxYQelLqS/I5GrXexWtC7Y7d1dCcQ+IZ0K7GGJ5NrYtjNXfMhzNSlhqjvl5lBGb+S565kel3VsCTyo/YRxdbBN6FA/oQNsx8/AvTgtsPeFkQRDGlGkybFRfWHWuTIDLL,iv:rZK9utRrm/KAkVRUjC3VR09MvDZjpoLx7BgaidzQo3o=,tag:tGWGoQCsS3zZh818OKixPw==,type:str] university_calendar_url: ENC[AES256_GCM,data:y5UtZVC0KJPUz//6S0QsrNeFGQshc88zieQgmlur75VFw9y5CJpnZRpdhLnYva00z5HBkxYQelLqS/I5GrXexWtC7Y7d1dCcQ+IZ0K7GGJ5NrYtjNXfMhzNSlhqjvl5lBGb+S565kel3VsCTyo/YRxdbBN6FA/oQNsx8/AvTgtsPeFkQRDGlGkybFRfWHWuTIDLL,iv:rZK9utRrm/KAkVRUjC3VR09MvDZjpoLx7BgaidzQo3o=,tag:tGWGoQCsS3zZh818OKixPw==,type:str]
ssh_config_orion: ENC[AES256_GCM,data:P2jH5BDIzeHSIwTBcZwTOXKes727xK0Xoj9W64GmEszEPZw8vA==,iv:hSY9mFdC82pBbOjMFuzoR2eufhjY2MGERJ4ODmcogbA=,tag:ejF535LrQwwH66nQG3qLGw==,type:str] ssh_config_orion: ENC[AES256_GCM,data:P2jH5BDIzeHSIwTBcZwTOXKes727xK0Xoj9W64GmEszEPZw8vA==,iv:hSY9mFdC82pBbOjMFuzoR2eufhjY2MGERJ4ODmcogbA=,tag:ejF535LrQwwH66nQG3qLGw==,type:str]
orion_ip: ENC[AES256_GCM,data:RCK6EKOEDaTu1uR2d/8=,iv:5JhIkVQEELB6MoPh49xq+0CrbPjI/6+qfqUHRqCza5s=,tag:+00T4+pWOWRj7R1ft39HAw==,type:str]
sops: sops:
age: age:
- recipient: age122w85pqj508ukv0rd388mahecgfckmpgnsgz0zcyec37ljae2epsdnvxpl - recipient: age122w85pqj508ukv0rd388mahecgfckmpgnsgz0zcyec37ljae2epsdnvxpl
@@ -21,7 +22,7 @@ sops:
ODdTa0VlYjg0ajJuUWhiRVUrR1VSTHMK6NVeKyMTomvZoqAtJN1SshIZdd2fHFBy ODdTa0VlYjg0ajJuUWhiRVUrR1VSTHMK6NVeKyMTomvZoqAtJN1SshIZdd2fHFBy
Waghxmi6x/93lf54E1ZiXZQ+LDCjqqmMY8jgoF00XCo0WeURlHXpaw== Waghxmi6x/93lf54E1ZiXZQ+LDCjqqmMY8jgoF00XCo0WeURlHXpaw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-11-29T18:05:48Z" lastmodified: "2025-12-01T16:01:07Z"
mac: ENC[AES256_GCM,data:j0pHRA3c5lRdyLjqxlP2MTzIYb3WYAy7p+FttOjTQpXcyT5dFykXuu8rv+MQTmWdvHLQKC4iuZ7HTSO9qx8SbAuxHBWpoycpy3cZpmFp5T5crCl65AVQ/yRZKD9gRxkhnVW7aAK1kC3Mq07PamznvX/b7eEJ8h3tvmymuw6z/vY=,iv:W430t2YAXVcJztbO+fNdlOyjjy6+cH5r5YwuM2QdIdc=,tag:dDRJSslL9/Hac465A/TstA==,type:str] mac: ENC[AES256_GCM,data:LAXl/FJafDOEOYrukqfzGMIXZzihX2zHMIQaR735MHWsTr3DSkCUqZ5IPEn9EmUSDkO8SaS0QdhRk0h7IhzS4MOsAAMdEtAEec4k0f9sMCLRWbV/G4tYxESPeuQNwdwS0iPsBsMQgvH93u7ttR59zyzQE1izal5nMwK3yQmNV5s=,iv:R3bnPXQY38Zf9BJuEP+inbRIVvAmLvEyGrlWzl3N9YI=,tag:eetYNetPvKXiJnR7AA3dwA==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.11.0 version: 3.11.0