diff --git a/hosts/fw/modules/ddclient.nix b/hosts/fw/modules/ddclient.nix index 8217224..4df533c 100644 --- a/hosts/fw/modules/ddclient.nix +++ b/hosts/fw/modules/ddclient.nix @@ -2,20 +2,26 @@ { services.ddclient = { enable = true; - usev4 = "if, if=wan"; + usev4 = "ifv4, ifv4=wan"; + usev6 = "disabled"; protocol = "hetzner"; # server = "https://dns.hetzner.com/api/v1/"; username = "dominik.polakovics@cloonar.com"; passwordFile = config.sops.secrets.ddclient.path; zone = "cloonar.com"; domains = [ - "fw.cloonar.com" - "vpn.cloonar.com" - "git.cloonar.com" - "palworld.cloonar.com" - "matrix.cloonar.com" + "audiobooks.cloonar.com" "element.cloonar.com" - "tinder.cloonar.com" + "foundry-vtt.cloonar.com" + "foundry-ha.cloonar.com" + "fw.cloonar.com" + "git.cloonar.com" + "jellyfin.cloonar.com" + "matrix.cloonar.com" + "palworld.cloonar.com" + "support.cloonar.com" + "sync.cloonar.com" + "vpn.cloonar.com" ]; }; diff --git a/hosts/fw/modules/dnsmasq.nix b/hosts/fw/modules/dnsmasq.nix index d2884e3..12ce8e1 100644 --- a/hosts/fw/modules/dnsmasq.nix +++ b/hosts/fw/modules/dnsmasq.nix @@ -137,6 +137,7 @@ # multimedia "/dl.cloonar.com/${config.networkPrefix}.97.5" "/jellyfin.cloonar.com/${config.networkPrefix}.97.5" + "/audiobooks.cloonar.com/${config.networkPrefix}.97.5" "/deconz.cloonar.multimedia/${config.networkPrefix}.97.22" diff --git a/hosts/fw/modules/home-assistant/locks.nix b/hosts/fw/modules/home-assistant/locks.nix index aa14f1d..a2160b4 100644 --- a/hosts/fw/modules/home-assistant/locks.nix +++ b/hosts/fw/modules/home-assistant/locks.nix @@ -2,6 +2,7 @@ let devices = [ "device_tracker.dominiks_iphone" "device_tracker.dominiks_mp01" + "device_tracker.dominiks_fairphone_6" ]; in { services.home-assistant.extraComponents = [ diff --git a/hosts/fw/modules/web/proxies.nix b/hosts/fw/modules/web/proxies.nix index 5e62a11..5b33e43 100644 --- a/hosts/fw/modules/web/proxies.nix +++ b/hosts/fw/modules/web/proxies.nix @@ -57,15 +57,6 @@ enableACME = true; acmeRoot = null; - # Restrict to internal LAN only - extraConfig = '' - allow ${config.networkPrefix}.96.0/24; - allow ${config.networkPrefix}.97.0/24; - allow ${config.networkPrefix}.98.0/24; - allow ${config.networkPrefix}.99.0/24; - deny all; - ''; - locations."/" = { proxyPass = "http://${config.networkPrefix}.97.11:8096"; proxyWebsockets = true; @@ -82,4 +73,25 @@ ''; }; }; + + services.nginx.virtualHosts."audiobooks.cloonar.com" = { + forceSSL = true; + enableACME = true; + acmeRoot = null; + + locations."/" = { + proxyPass = "http://${config.networkPrefix}.97.11:13378"; + proxyWebsockets = true; + + extraConfig = '' + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $http_host; + + # Disable buffering for better streaming performance + proxy_buffering off; + ''; + }; + }; } diff --git a/hosts/fw/modules/wireguard.nix b/hosts/fw/modules/wireguard.nix index 239e36f..b8bd074 100644 --- a/hosts/fw/modules/wireguard.nix +++ b/hosts/fw/modules/wireguard.nix @@ -29,6 +29,10 @@ publicKey = "yv0AWQl4LFebVa7SvwdxpEmB3PPglwjoKy6A3og93WI="; allowedIPs = [ "${config.networkPrefix}.98.204/32" ]; } + { # FairPhone + publicKey = "tLsvuXo6Cp8tzjJau1yJZ9apeQvYa+cGrnAXBBifO3Y="; + allowedIPs = [ "${config.networkPrefix}.98.205/32" ]; + } ]; }; wg_epicenter = { diff --git a/hosts/nas/configuration.nix b/hosts/nas/configuration.nix index 18da703..6a6add6 100644 --- a/hosts/nas/configuration.nix +++ b/hosts/nas/configuration.nix @@ -17,6 +17,7 @@ in { ./modules/cyberghost.nix ./modules/pyload.nix ./modules/jellyfin.nix + ./modules/audiobookshelf.nix ./modules/power-management.nix ./modules/disk-monitoring.nix ./modules/ugreen-leds.nix @@ -64,6 +65,7 @@ in { directories = [ "/var/lib/pyload" "/var/lib/jellyfin" + "/var/lib/audiobookshelf" "/var/log" "/var/lib/nixos" "/var/bento" diff --git a/hosts/nas/modules/audiobookshelf.nix b/hosts/nas/modules/audiobookshelf.nix new file mode 100644 index 0000000..7bc2fa6 --- /dev/null +++ b/hosts/nas/modules/audiobookshelf.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: { + # Audiobookshelf user with jellyfin and pyload groups for multimedia access + users.users.audiobookshelf = { + isSystemUser = true; + group = "audiobookshelf"; + extraGroups = [ "jellyfin" "pyload" ]; + }; + users.groups.audiobookshelf = {}; + + services.audiobookshelf = { + enable = true; + openFirewall = true; # Opens default port 13378 + host = "0.0.0.0"; # Listen on all interfaces + port = 13378; + }; +} diff --git a/hosts/nas/modules/disk-monitoring.nix b/hosts/nas/modules/disk-monitoring.nix index a4cb579..af23ce0 100644 --- a/hosts/nas/modules/disk-monitoring.nix +++ b/hosts/nas/modules/disk-monitoring.nix @@ -7,8 +7,6 @@ let # Disk identifiers from hardware-configuration.nix disks = [ - "/dev/disk/by-id/ata-ST18000NM000J-2TV103_ZR52TBSB" - "/dev/disk/by-id/ata-ST18000NM000J-2TV103_ZR52V9QX" "/dev/disk/by-id/ata-TOSHIBA_MG10ACA20TE_8582A01SF4MJ" "/dev/disk/by-id/ata-TOSHIBA_MG10ACA20TE_75V2A0H3F4MJ" "/dev/disk/by-id/nvme-KIOXIA-EXCERIA_PLUS_G3_SSD_7FJKS1MAZ0E7" diff --git a/hosts/nas/modules/pyload.nix b/hosts/nas/modules/pyload.nix index 90b5c08..6788f79 100644 --- a/hosts/nas/modules/pyload.nix +++ b/hosts/nas/modules/pyload.nix @@ -52,6 +52,7 @@ in home = "/var/lib/pyload"; createHome = true; extraGroups = [ "jellyfin" ]; + shell = pkgs.bashInteractive; # Required for filebot-process script }; users.groups.pyload = {}; diff --git a/hosts/nb/modules/development/nvim/config/terminal.lua b/hosts/nb/modules/development/nvim/config/terminal.lua index d377b34..43b96c2 100644 --- a/hosts/nb/modules/development/nvim/config/terminal.lua +++ b/hosts/nb/modules/development/nvim/config/terminal.lua @@ -42,7 +42,7 @@ local config = { { vim.o.shell, "", "Float Terminal 1", "float", nil }, { vim.o.shell, "", "Float Terminal 2", "float", nil }, { "claude", "", "Claude Terminal", "float", nil }, - { vim.o.shell, "", "Float Terminal 4", "float", nil }, + { "codex", "", "Codex Terminal", "float", nil }, { vim.o.shell, "", "Float Terminal 5", "float", nil }, }, } diff --git a/hosts/nb/users/dominik.nix b/hosts/nb/users/dominik.nix index 42f58d8..b9fc281 100644 --- a/hosts/nb/users/dominik.nix +++ b/hosts/nb/users/dominik.nix @@ -20,7 +20,7 @@ let "calendar.ui.version" = 3; "calendar.timezone.local" = "Europe/Vienna"; "calendar.week.start" = 1; - "layout.css.devPixelsPerPx" = "1.25"; + "layout.css.devPixelsPerPx" = "-1.0"; }; # Base calendar settings (without identity) @@ -89,7 +89,7 @@ let "signon.rememberSignons" = false; "identity.sync.tokenserver.uri" = "https://sync.cloonar.com/1.0/sync/1.5"; # "toolkit.legacyUserProfileCustomizations.stylesheets" = true; - "layout.css.devPixelsPerPx" = "1.25"; + "layout.css.devPixelsPerPx" = "-1.0"; # auto-detect from Wayland compositor "media.ffmpeg.vaapi.enabled" = true; "media.ffmpeg.vaapi-drm-display.enabled" = true; "gfx.webrender.all" = true; diff --git a/hosts/web-arm/modules/authelia.nix b/hosts/web-arm/modules/authelia.nix index 6216b67..4f0d5d9 100644 --- a/hosts/web-arm/modules/authelia.nix +++ b/hosts/web-arm/modules/authelia.nix @@ -5,6 +5,21 @@ let system = pkgs.system; }; in { + # Redis for Authelia session persistence + services.redis.servers.authelia = { + enable = true; + user = "authelia-main"; + unixSocket = "/run/redis-authelia/redis.sock"; + unixSocketPerm = 660; + settings = { + appendonly = "yes"; # Enable AOF persistence + appendfsync = "everysec"; # Sync every second + }; + }; + + # Add authelia user to redis group for socket access + users.users.authelia-main.extraGroups = [ "redis-authelia" ]; + sops.secrets.authelia-jwt-secret = { owner = "authelia-main"; }; @@ -106,6 +121,9 @@ in { inactivity = "45m"; remember_me_duration = "1M"; domain = "cloonar.com"; + redis = { + host = "/run/redis-authelia/redis.sock"; + }; # todo: enable with 4.38 # cookies = [ # { diff --git a/hosts/web-arm/modules/grafana/alerting/storage/raid_alerts.nix b/hosts/web-arm/modules/grafana/alerting/storage/raid_alerts.nix index 82ad73e..0fbe8dd 100644 --- a/hosts/web-arm/modules/grafana/alerting/storage/raid_alerts.nix +++ b/hosts/web-arm/modules/grafana/alerting/storage/raid_alerts.nix @@ -12,7 +12,7 @@ datasourceUid = "vm-datasource-uid"; relativeTimeRange = { from = 300; to = 0; }; model = { - expr = ''mdadm_array_state == 0''; + expr = ''mdadm_array_state < 1''; instant = false; }; } @@ -35,7 +35,7 @@ } ]; for = "0s"; - noDataState = "NoData"; + noDataState = "OK"; execErrState = "Error"; annotations = { summary = "RAID array {{ $labels.array }} is degraded"; @@ -84,7 +84,7 @@ } ]; for = "0s"; - noDataState = "NoData"; + noDataState = "OK"; execErrState = "Error"; annotations = { summary = "RAID array {{ $labels.array }} has missing devices"; diff --git a/hosts/web-arm/modules/grafana/alerting/storage/smart_alerts.nix b/hosts/web-arm/modules/grafana/alerting/storage/smart_alerts.nix index dd36462..42e9fd6 100644 --- a/hosts/web-arm/modules/grafana/alerting/storage/smart_alerts.nix +++ b/hosts/web-arm/modules/grafana/alerting/storage/smart_alerts.nix @@ -12,7 +12,7 @@ datasourceUid = "vm-datasource-uid"; relativeTimeRange = { from = 300; to = 0; }; model = { - expr = ''smart_health_passed == 0''; + expr = ''smart_health_passed < 1''; instant = false; }; } @@ -35,7 +35,7 @@ } ]; for = "0s"; - noDataState = "NoData"; + noDataState = "OK"; execErrState = "Error"; annotations = { summary = "S.M.A.R.T. health check FAILED on {{ $labels.device }}"; @@ -84,7 +84,7 @@ } ]; for = "0s"; - noDataState = "NoData"; + noDataState = "OK"; execErrState = "Error"; annotations = { summary = "Reallocated sectors detected on {{ $labels.device }}"; @@ -133,7 +133,7 @@ } ]; for = "0s"; - noDataState = "NoData"; + noDataState = "OK"; execErrState = "Error"; annotations = { summary = "Pending sectors detected on {{ $labels.device }}"; @@ -182,7 +182,7 @@ } ]; for = "0s"; - noDataState = "NoData"; + noDataState = "OK"; execErrState = "Error"; annotations = { summary = "Offline uncorrectable errors on {{ $labels.device }}"; @@ -231,7 +231,7 @@ } ]; for = "10m"; - noDataState = "NoData"; + noDataState = "OK"; execErrState = "Error"; annotations = { summary = "High temperature on {{ $labels.device }}"; @@ -280,7 +280,7 @@ } ]; for = "0s"; - noDataState = "NoData"; + noDataState = "OK"; execErrState = "Error"; annotations = { summary = "UDMA CRC errors on {{ $labels.device }}"; diff --git a/hosts/web-arm/modules/grafana/default.nix b/hosts/web-arm/modules/grafana/default.nix index f4e0ce2..68576bb 100644 --- a/hosts/web-arm/modules/grafana/default.nix +++ b/hosts/web-arm/modules/grafana/default.nix @@ -115,7 +115,6 @@ in settings = { apiToken = "\${PUSHOVER_API_TOKEN}"; userKey = "\${PUSHOVER_USER_KEY}"; - device = "iphone"; priority = 2; retry = "30s"; expire = "2m"; @@ -134,7 +133,6 @@ in settings = { apiToken = "\${PUSHOVER_API_TOKEN}"; userKey = "\${PUSHOVER_USER_KEY}"; - device = "iphone"; priority = 1; sound = "siren"; okSound = "magic"; diff --git a/utils/pkgs/claude-code/default.nix b/utils/pkgs/claude-code/default.nix index f40ded4..c51270e 100644 --- a/utils/pkgs/claude-code/default.nix +++ b/utils/pkgs/claude-code/default.nix @@ -1,11 +1,11 @@ { lib, pkgs, runCommand, claude-code }: let - version = "2.0.76"; + version = "2.1.12"; src = pkgs.fetchzip { url = "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-${version}.tgz"; - hash = "sha256-46IqiGJZrZM4vVcanZj/vY4uxFH3/4LxNA+Qb6iIHDk="; + hash = "sha256-JX72YEM2fXY7qKVkuk+UFeef0OhBffljpFBjIECHMXw="; }; # Create a modified source with our package-lock.json @@ -22,7 +22,7 @@ in npmDeps = pkgs.fetchNpmDeps { src = srcWithLock; - hash = "sha256-xSNyYImDpsW6AltA7d0ayMsfVaBcnyPIQOg/Ea2cGNk="; + hash = "sha256-iJwtwAYb/+1Une6Tjxek5ccf4ui3tYWy4kNlHES9He4="; }; # Remove the old postPatch since srcWithLock already includes package-lock.json diff --git a/utils/pkgs/claude-code/package-lock.json b/utils/pkgs/claude-code/package-lock.json index 125d1b9..92b687f 100644 --- a/utils/pkgs/claude-code/package-lock.json +++ b/utils/pkgs/claude-code/package-lock.json @@ -5,13 +5,13 @@ "packages": { "": { "dependencies": { - "@anthropic-ai/claude-code": "^2.0.76" + "@anthropic-ai/claude-code": "^2.1.12" } }, "node_modules/@anthropic-ai/claude-code": { - "version": "2.0.76", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.0.76.tgz", - "integrity": "sha512-BVwPez7Pst729gxHZNb7iUdjrn4UAzO49zC+Bxlyf0fMe3SsutxEhKTT16VMs2qInE9xhEBCxajCCa888mFPBg==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.1.12.tgz", + "integrity": "sha512-oJlbUJc6iyuTA6X1z+Wsli4cYWqSHT9Ttc/jBXArrrBQcILPLb5lBOKfbVJJgcH3bNLxsXwnAkZjtmmM5SqtsQ==", "license": "SEE LICENSE IN README.md", "bin": { "claude": "cli.js"