Compare commits

..

23 Commits

Author SHA1 Message Date
5f300d9e7b feat: nb initial click and load 2025-12-10 12:49:30 +01:00
99ac2ea3b0 feat: nas move archive extraction to filebot script 2025-12-10 11:40:19 +01:00
2caa36c0ab fix: nas filebot and add extraction passwords 2025-12-10 11:29:05 +01:00
55c15c790d fix: fw lightning 2025-12-10 11:28:08 +01:00
450d9d6457 fix: claude.md update 2025-12-07 12:59:43 +01:00
e08bf42eaa fix: nas leds and disks 2025-12-07 12:59:27 +01:00
8e0e5c0d16 feat: add disks to monitoring 2025-12-05 21:57:58 +01:00
ada9db7942 feat: add disks to nas 2025-12-04 15:01:47 +01:00
5995612407 fix: amzebs add mysql port 2025-12-04 12:46:28 +01:00
5762916970 feat: add mcp server 2025-12-04 11:39:17 +01:00
dd456eab69 feat: update pyload 2025-12-04 11:39:08 +01:00
18a8fde66e feat: add uv for mcp 2025-12-04 11:38:22 +01:00
f97c9185c1 docs: update claude 2025-12-02 11:28:05 +01:00
8bf4b185a1 feat(nas): update to 25.11, add software, add storage plan 2025-12-02 11:27:52 +01:00
8424d771f6 feat(fw): update to 25.11 2025-12-02 08:34:57 +01:00
840f99a7e9 feat(amzebs-01): update to 25.11 2025-12-01 23:02:35 +01:00
1b27bafd41 feat(web-arm): update to 25.11
- Migrate logind.extraConfig to logind.settings.Login
- Update dovecot alert for service rename (dovecot2 → dovecot)
- Fix sa-core buildGoModule env attribute for CGO_ENABLED
2025-12-01 22:48:02 +01:00
4770d671c0 docs: add commit footer convention to CLAUDE.md 2025-12-01 22:25:08 +01:00
28a7bed3b9 feat(mail): update to 25.11 with TLS hardening
- Upgrade NixOS channel from 25.05 to 25.11
- Fix dovecot systemd service rename (dovecot2 -> dovecot)
- Convert postfix numeric settings to integers (25.11 requirement)
- Remove insecure 512-bit DH params, fix 2048-bit DH params
- Update postfix ciphers to modern ECDHE/DHE+AESGCM/CHACHA20
- Require TLS 1.2 minimum for OpenLDAP
- Remove weak ciphers (3DES, RC4, aNULL) from OpenLDAP
2025-12-01 22:24:57 +01:00
170becceb0 fix: nvim 2025-12-01 22:05:24 +01:00
6e8f530537 feat: amz add cron job 2025-12-01 16:17:45 +01:00
209bafd70f feat: test-configuration script get real errors 2025-12-01 16:17:28 +01:00
1d182437db feat: nb update to 25.11 2025-12-01 16:17:10 +01:00
56 changed files with 1320 additions and 397 deletions

8
.mcp.json Normal file
View File

@@ -0,0 +1,8 @@
{
"mcpServers": {
"nixos": {
"command": "uvx",
"args": ["mcp-nixos"]
}
}
}

View File

@@ -40,7 +40,7 @@ Each host in `hosts/<hostname>/` contains:
- `fleet.nix` → symlink to root `fleet.nix` (SFTP user provisioning) - `fleet.nix` → symlink to root `fleet.nix` (SFTP user provisioning)
- `utils/` → symlink to root `utils/` (shared modules) - `utils/` → symlink to root `utils/` (shared modules)
Current hosts: `fw` (firewall/router), `nb` (notebook), `web-arm`, `mail`, `amzebs-01` Current hosts: `fw` (firewall/router), `nb` (notebook), `web-arm`, `mail`, `amzebs-01`, `nas`
### Shared Components (`utils/`) ### Shared Components (`utils/`)
- `modules/` - Reusable NixOS modules (nginx, sops, borgbackup, lego, promtail, etc.) - `modules/` - Reusable NixOS modules (nginx, sops, borgbackup, lego, promtail, etc.)
@@ -80,6 +80,13 @@ utils/pkgs/<package-name>/
└── (other files like patches, lock files) └── (other files like patches, lock files)
``` ```
**IMPORTANT: When modifying a custom package** (patches, version updates, etc.), always test by building the package directly, not just running `test-configuration`. The configuration test only checks that the Nix expression evaluates, but doesn't verify the package actually builds:
```bash
# Build a custom package directly to verify it works
nix-build -E 'with import <nixpkgs> { overlays = [ (import ./utils/overlays/packages.nix) ]; config.allowUnfree = true; }; <package-name>'
```
## Workflow ## Workflow
**IMPORTANT: Always run `./scripts/test-configuration <hostname>` after making any changes** to verify the NixOS configuration builds successfully. This is required before committing. **IMPORTANT: Always run `./scripts/test-configuration <hostname>` after making any changes** to verify the NixOS configuration builds successfully. This is required before committing.
@@ -87,6 +94,7 @@ utils/pkgs/<package-name>/
## Conventions ## Conventions
- Nix files: two-space indentation, lower kebab-case naming - Nix files: two-space indentation, lower kebab-case naming
- Commits: Conventional Commits format (`fix:`, `feat:`, `chore:`), scope by host when relevant (`fix(mail):`) - Commits: Conventional Commits format (`fix:`, `feat:`, `chore:`), scope by host when relevant (`fix(mail):`). Do not add "Generated with Claude Code" or "Co-Authored-By: Claude" footers.
- Modules import via explicit paths, not wildcards - Modules import via explicit paths, not wildcards
- Comments explain non-obvious decisions (open ports, unusual service options) - Comments explain non-obvious decisions (open ports, unusual service options)
- **Never update `system.stateVersion`** - it should remain at the original installation version. To upgrade NixOS, update the `channel` file instead.

1
hosts/amzebs-01/channel Normal file
View File

@@ -0,0 +1 @@
https://channels.nixos.org/nixos-25.11

View File

@@ -3,10 +3,12 @@
./utils/bento.nix ./utils/bento.nix
./utils/modules/sops.nix ./utils/modules/sops.nix
./utils/modules/nginx.nix ./utils/modules/nginx.nix
./utils/modules/set-nix-channel.nix
./modules/mysql.nix ./modules/mysql.nix
./modules/web/stack.nix ./modules/web/stack.nix
./modules/laravel-storage.nix ./modules/laravel-storage.nix
./modules/laravel-scheduler.nix
./modules/blackbox-exporter.nix ./modules/blackbox-exporter.nix
./modules/postfix.nix ./modules/postfix.nix
./modules/rspamd.nix ./modules/rspamd.nix
@@ -67,7 +69,7 @@
networking.firewall = { networking.firewall = {
enable = true; enable = true;
allowedTCPPorts = [ 22 80 443 ]; allowedTCPPorts = [ 22 80 443 3306 ];
# Allow MariaDB access only from specific IP # Allow MariaDB access only from specific IP
extraCommands = '' extraCommands = ''
@@ -75,5 +77,5 @@
''; '';
}; };
system.stateVersion = "23.11"; system.stateVersion = "25.11";
} }

View File

@@ -0,0 +1,51 @@
{ config, lib, pkgs, ... }:
# Daily scheduled Laravel artisan jobs
# Runs artisan finish:reports at 01:00 for production and staging APIs
let
php = pkgs.php82;
sites = [
{
domain = "api.ebs.amz.at";
user = "api_ebs_amz_at";
}
{
domain = "api.stage.ebs.amz.at";
user = "api_stage_ebs_amz_at";
}
];
mkArtisanService = site: {
name = "artisan-finish-reports-${site.domain}";
value = {
description = "Laravel artisan finish:reports for ${site.domain}";
after = [ "network.target" "mysql.service" "phpfpm-${site.domain}.service" ];
serviceConfig = {
Type = "oneshot";
User = site.user;
Group = "nginx";
WorkingDirectory = "/var/www/${site.domain}";
ExecStart = "${php}/bin/php artisan finish:reports";
};
};
};
mkArtisanTimer = site: {
name = "artisan-finish-reports-${site.domain}";
value = {
description = "Daily timer for artisan finish:reports on ${site.domain}";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "*-*-* 01:00:00";
Persistent = true;
};
};
};
in
{
systemd.services = builtins.listToAttrs (map mkArtisanService sites);
systemd.timers = builtins.listToAttrs (map mkArtisanTimer sites);
}

View File

@@ -3,15 +3,16 @@
, config , config
, ... , ...
}: }:
{ let
# Header checks file for validating email headers headerChecksFile = pkgs.writeText "header_checks" ''
environment.etc."postfix/header_checks".text = ''
# Warn about missing critical headers (but don't reject from localhost) # Warn about missing critical headers (but don't reject from localhost)
# These help identify misconfigured applications # These help identify misconfigured applications
/^$/ WARN Missing headers detected /^$/ WARN Missing headers detected
''; '';
in
{
services.postfix = { services.postfix = {
mapFiles."header_checks" = headerChecksFile;
enable = true; enable = true;
hostname = "amzebs-01.amz.at"; hostname = "amzebs-01.amz.at";
domain = "amz.at"; domain = "amz.at";
@@ -34,20 +35,20 @@
compatibility_level = "2"; compatibility_level = "2";
# Only accept mail from localhost # Only accept mail from localhost
mynetworks = "127.0.0.0/8 [::1]/128"; mynetworks = [ "127.0.0.0/8" "[::1]/128" ];
# Larger message size limits for attachments # Larger message size limits for attachments
mailbox_size_limit = "202400000"; # ~200MB mailbox_size_limit = 202400000; # ~200MB
message_size_limit = "51200000"; # ~50MB message_size_limit = 51200000; # ~50MB
# Ensure proper header handling # Ensure proper header handling
# Reject mail that's missing critical headers # Reject mail that's missing critical headers
header_checks = "regexp:/etc/postfix/header_checks"; header_checks = "regexp:/var/lib/postfix/conf/header_checks";
# Rate limiting to prevent spam-like behavior # Rate limiting to prevent spam-like behavior
# Allow reasonable sending rates for applications # Allow reasonable sending rates for applications
smtpd_client_message_rate_limit = "100"; smtpd_client_message_rate_limit = 100;
smtpd_client_recipient_rate_limit = "200"; smtpd_client_recipient_rate_limit = 200;
# Milter configuration is handled automatically by rspamd.postfix.enable # Milter configuration is handled automatically by rspamd.postfix.enable
}; };

View File

@@ -1 +1 @@
https://channels.nixos.org/nixos-25.05 https://channels.nixos.org/nixos-25.11

View File

@@ -10,6 +10,7 @@
./utils/modules/victoriametrics ./utils/modules/victoriametrics
./utils/modules/promtail ./utils/modules/promtail
./utils/modules/borgbackup.nix ./utils/modules/borgbackup.nix
./utils/modules/set-nix-channel.nix
# fw # fw
./modules/network-prefix.nix ./modules/network-prefix.nix
@@ -103,7 +104,7 @@
time.timeZone = "Europe/Vienna"; time.timeZone = "Europe/Vienna";
services.logind.extraConfig = "RuntimeDirectorySize=2G"; services.logind.settings.Login.RuntimeDirectorySize = "2G";
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sops.defaultSopsFile = ./secrets.yaml; sops.defaultSopsFile = ./secrets.yaml;

View File

@@ -396,7 +396,13 @@
all = true; all = true;
entities = [ entities = [
"light.livingroom_switch" "light.livingroom_switch"
"light.living_room" "light.living_bulb_1"
"light.living_bulb_2"
"light.living_bulb_3"
"light.living_bulb_4"
"light.living_bulb_5"
"light.living_bulb_6"
# "light.living_room"
]; ];
} }
{ {
@@ -410,6 +416,7 @@
all = true; all = true;
entities = [ entities = [
"light.kitchen_switch" "light.kitchen_switch"
"light.kitchen_bulb_1"
"light.kitchen" "light.kitchen"
]; ];
} }

View File

@@ -19,21 +19,19 @@
}; };
# n8n service configuration # n8n service configuration
services.n8n = { services.n8n.enable = true;
enable = true;
settings = {
database.type = "postgresdb";
database.postgresdb.host = "/run/postgresql";
database.postgresdb.database = "n8n";
database.postgresdb.user = "n8n";
executions.pruneData = true;
executions.pruneDataMaxAge = 168; # 7 days
};
};
# Configure git integration via environment variables # Configure n8n via environment variables
systemd.services.n8n = { systemd.services.n8n = {
environment = lib.mkForce { environment = lib.mkForce {
# Database configuration (migrated from services.n8n.settings)
DB_TYPE = "postgresdb";
DB_POSTGRESDB_HOST = "/run/postgresql";
DB_POSTGRESDB_DATABASE = "n8n";
DB_POSTGRESDB_USER = "n8n";
EXECUTIONS_DATA_PRUNE = "true";
EXECUTIONS_DATA_MAX_AGE = "168"; # 7 days
# Other settings
N8N_ENCRYPTION_KEY = ""; # Will be set via environmentFile N8N_ENCRYPTION_KEY = ""; # Will be set via environmentFile
N8N_VERSION_NOTIFICATIONS_ENABLED = "false"; N8N_VERSION_NOTIFICATIONS_ENABLED = "false";
N8N_DIAGNOSTICS_ENABLED = "false"; N8N_DIAGNOSTICS_ENABLED = "false";

View File

@@ -1 +1 @@
https://channels.nixos.org/nixos-25.05 https://channels.nixos.org/nixos-25.11

View File

@@ -240,11 +240,11 @@ in
sops.secrets.dovecot-ldap-password = { }; sops.secrets.dovecot-ldap-password = { };
systemd.services.dovecot2.preStart = '' systemd.services.dovecot.preStart = ''
sed -e "s/@ldap-password@/$(cat ${config.sops.secrets.dovecot-ldap-password.path})/" ${ldapConfig} > /run/dovecot2/ldap.conf sed -e "s/@ldap-password@/$(cat ${config.sops.secrets.dovecot-ldap-password.path})/" ${ldapConfig} > /run/dovecot2/ldap.conf
''; '';
systemd.services.dovecot2 = { systemd.services.dovecot = {
wants = [ "acme-imap.${domain}.service" ]; wants = [ "acme-imap.${domain}.service" ];
after = [ "acme-imap.${domain}.service" ]; after = [ "acme-imap.${domain}.service" ];
}; };
@@ -257,7 +257,7 @@ in
"imap-test.${domain}" "imap-test.${domain}"
"imap-02.${domain}" "imap-02.${domain}"
]; ];
postRun = "systemctl --no-block restart dovecot2.service"; postRun = "systemctl --no-block restart dovecot.service";
}; };
networking.firewall.allowedTCPPorts = [ networking.firewall.allowedTCPPorts = [

View File

@@ -17,10 +17,10 @@ in {
olcTLSCACertificateFile = "/var/lib/acme/ldap.${domain}/full.pem"; olcTLSCACertificateFile = "/var/lib/acme/ldap.${domain}/full.pem";
olcTLSCertificateFile = "/var/lib/acme/ldap.${domain}/cert.pem"; olcTLSCertificateFile = "/var/lib/acme/ldap.${domain}/cert.pem";
olcTLSCertificateKeyFile = "/var/lib/acme/ldap.${domain}/key.pem"; olcTLSCertificateKeyFile = "/var/lib/acme/ldap.${domain}/key.pem";
olcTLSCipherSuite = "HIGH:MEDIUM:+3DES:+RC4:+aNULL"; olcTLSCipherSuite = "HIGH:!aNULL:!MD5:!3DES:!RC4";
olcTLSCRLCheck = "none"; olcTLSCRLCheck = "none";
olcTLSVerifyClient = "never"; olcTLSVerifyClient = "never";
olcTLSProtocolMin = "3.1"; olcTLSProtocolMin = "3.3";
olcSecurity = "tls=1"; olcSecurity = "tls=1";
}; };

View File

@@ -128,16 +128,16 @@ in
compatibility_level = "2"; compatibility_level = "2";
# bigger attachement size # bigger attachement size
mailbox_size_limit = "202400000"; mailbox_size_limit = 202400000;
message_size_limit = "51200000"; message_size_limit = 51200000;
smtpd_helo_required = "yes"; smtpd_helo_required = "yes";
smtpd_delay_reject = "yes"; smtpd_delay_reject = "yes";
strict_rfc821_envelopes = "yes"; strict_rfc821_envelopes = "yes";
# send Limit # send Limit
smtpd_error_sleep_time = "1s"; smtpd_error_sleep_time = "1s";
smtpd_soft_error_limit = "10"; smtpd_soft_error_limit = 10;
smtpd_hard_error_limit = "20"; smtpd_hard_error_limit = 20;
smtpd_use_tls = "yes"; smtpd_use_tls = "yes";
smtp_tls_note_starttls_offer = "yes"; smtp_tls_note_starttls_offer = "yes";
@@ -151,14 +151,13 @@ in
smtpd_tls_key_file = "/var/lib/acme/mail.cloonar.com/key.pem"; smtpd_tls_key_file = "/var/lib/acme/mail.cloonar.com/key.pem";
smtpd_tls_CAfile = "/var/lib/acme/mail.cloonar.com/fullchain.pem"; smtpd_tls_CAfile = "/var/lib/acme/mail.cloonar.com/fullchain.pem";
smtpd_tls_dh512_param_file = config.security.dhparams.params.postfix512.path;
smtpd_tls_dh1024_param_file = config.security.dhparams.params.postfix2048.path; smtpd_tls_dh1024_param_file = config.security.dhparams.params.postfix2048.path;
smtpd_tls_session_cache_database = ''btree:''${data_directory}/smtpd_scache''; smtpd_tls_session_cache_database = ''btree:''${data_directory}/smtpd_scache'';
smtpd_tls_mandatory_protocols = "!SSLv2,!SSLv3,!TLSv1,!TLSv1.1"; smtpd_tls_mandatory_protocols = "!SSLv2,!SSLv3,!TLSv1,!TLSv1.1";
smtpd_tls_protocols = "!SSLv2,!SSLv3,!TLSv1,!TLSv1.1"; smtpd_tls_protocols = "!SSLv2,!SSLv3,!TLSv1,!TLSv1.1";
smtpd_tls_mandatory_ciphers = "medium"; smtpd_tls_mandatory_ciphers = "medium";
tls_medium_cipherlist = "AES128+EECDH:AES128+EDH"; tls_medium_cipherlist = "ECDHE+AESGCM:DHE+AESGCM:ECDHE+CHACHA20:DHE+CHACHA20";
# authentication # authentication
smtpd_sasl_auth_enable = "yes"; smtpd_sasl_auth_enable = "yes";
@@ -225,8 +224,7 @@ in
security.dhparams = { security.dhparams = {
enable = true; enable = true;
params.postfix512.bits = 512; params.postfix2048.bits = 2048;
params.postfix2048.bits = 1024;
}; };
security.acme.certs."mail.${domain}" = { security.acme.certs."mail.${domain}" = {

View File

@@ -119,7 +119,7 @@ in
# systemd.services.rspamd.serviceConfig.SupplementaryGroups = [ "redis-rspamd" ]; # systemd.services.rspamd.serviceConfig.SupplementaryGroups = [ "redis-rspamd" ];
systemd.services.dovecot2.preStart = '' systemd.services.dovecot.preStart = ''
mkdir -p /var/lib/dovecot/sieve/ mkdir -p /var/lib/dovecot/sieve/
for i in ${sieve-spam-filter}/share/sieve-rspamd-filter/*.sieve; do for i in ${sieve-spam-filter}/share/sieve-rspamd-filter/*.sieve; do
dest="/var/lib/dovecot/sieve/$(basename $i)" dest="/var/lib/dovecot/sieve/$(basename $i)"

60
hosts/nas/STORAGE.md Normal file
View File

@@ -0,0 +1,60 @@
# NAS Storage Notes
## Current Issue: XFS Metadata Overhead
The XFS filesystem on `/var/lib/multimedia` uses ~100GB more than the actual file data due to metadata overhead.
### Root Cause
The filesystem was created with advanced features enabled:
```
rmapbt=1 # Reverse mapping btree - tracks block ownership
reflink=1 # Copy-on-write support
```
These features add metadata that scales with **filesystem size**, not file count. On a 5TB filesystem with 700GB of data, this results in ~100GB (~2%) overhead.
### Diagnostic Commands
```bash
# Compare file data vs filesystem usage
du -sh /var/lib/multimedia # Actual file data
df -h /var/lib/multimedia # Filesystem reports
# Check XFS features
xfs_info /var/lib/multimedia
# Verify block allocation
xfs_db -r -c "freesp -s" /dev/mapper/vg--data-lv--multimedia
```
## Recommendation: LVM + ext4
For media storage (write-once, read-many), ext4 with minimal reserved space offers the lowest overhead:
```bash
# Create filesystem with 0% reserved blocks
mkfs.ext4 -m 0 /dev/vg/lv
# Or adjust existing ext4
tune2fs -m 0 /dev/vg/lv
```
### Why ext4 over XFS for this use case
| Consideration | ext4 | XFS (current) |
|---------------|------|---------------|
| Reserved space | 0% with `-m 0` | N/A |
| Metadata overhead | ~0.5% | ~2% (with rmapbt) |
| Shrink support | Yes | No |
| Performance for 4K stream | Identical | Identical |
A single 4K remux stream requires ~12 MB/s. Any filesystem handles this trivially.
## Migration Path
1. Backup data from XFS volumes
2. Recreate LVs with ext4 (`mkfs.ext4 -m 0`)
3. Restore data
4. Update `/etc/fstab` or NixOS `fileSystems` config

1
hosts/nas/channel Normal file
View File

@@ -0,0 +1 @@
https://channels.nixos.org/nixos-25.11

View File

@@ -9,6 +9,7 @@ in {
"${impermanence}/nixos.nix" "${impermanence}/nixos.nix"
./utils/bento.nix ./utils/bento.nix
./utils/modules/sops.nix ./utils/modules/sops.nix
./utils/modules/set-nix-channel.nix
./utils/modules/victoriametrics ./utils/modules/victoriametrics
./utils/modules/promtail ./utils/modules/promtail
@@ -76,6 +77,12 @@ in {
]; ];
}; };
# System packages
environment.systemPackages = with pkgs; [
vim
screen
];
# Nix settings # Nix settings
nix = { nix = {
settings = { settings = {

View File

@@ -24,12 +24,14 @@
"i915.enable_fbc=1" # Frame buffer compression "i915.enable_fbc=1" # Frame buffer compression
]; ];
# RAID 1 array for data storage # RAID 1 arrays for data storage
boot.swraid = { boot.swraid = {
enable = true; enable = true;
mdadmConf = '' mdadmConf = ''
DEVICE /dev/disk/by-id/ata-ST18000NM000J-2TV103_ZR52TBSB-part1 DEVICE /dev/disk/by-id/nvme-KIOXIA-EXCERIA_PLUS_G3_SSD_7FJKS1MAZ0E7-part1
DEVICE /dev/disk/by-id/ata-ST18000NM000J-2TV103_ZR52V9QX-part1 DEVICE /dev/disk/by-id/nvme-KIOXIA-EXCERIA_PLUS_G3_SSD_7FJKS1M9Z0E7-part1
DEVICE /dev/disk/by-id/ata-TOSHIBA_MG10ACA20TE_8582A01SF4MJ-part1
DEVICE /dev/disk/by-id/ata-TOSHIBA_MG10ACA20TE_75V2A0H3F4MJ-part1
''; '';
}; };
@@ -84,14 +86,13 @@
# LVM volumes on RAID array # LVM volumes on RAID array
fileSystems."/var/lib/downloads" = { fileSystems."/var/lib/downloads" = {
device = "/dev/vg-data/lv-downloads"; device = "/dev/vg-data-fast/downloads";
fsType = "xfs"; fsType = "ext4";
options = [ "noatime" ];
}; };
fileSystems."/var/lib/multimedia" = { fileSystems."/var/lib/multimedia" = {
device = "/dev/vg-data/lv-multimedia"; device = "/dev/vg-data-slow/multimedia";
fsType = "xfs"; fsType = "ext4";
options = [ "noatime" ]; options = [ "noatime" ];
}; };

View File

@@ -9,6 +9,10 @@ let
disks = [ disks = [
"/dev/disk/by-id/ata-ST18000NM000J-2TV103_ZR52TBSB" "/dev/disk/by-id/ata-ST18000NM000J-2TV103_ZR52TBSB"
"/dev/disk/by-id/ata-ST18000NM000J-2TV103_ZR52V9QX" "/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"
"/dev/disk/by-id/nvme-KIOXIA-EXCERIA_PLUS_G3_SSD_7FJKS1M9Z0E7"
]; ];
textfileDir = "/var/lib/prometheus-node-exporter"; textfileDir = "/var/lib/prometheus-node-exporter";
@@ -40,12 +44,16 @@ let
continue continue
fi fi
# Resolve symlink to get actual device # Resolve symlink to get actual device (needed for hdparm/smartctl)
device=$(readlink -f "$disk") device=$(readlink -f "$disk")
short_name=$(basename "$device")
# Extract serial from disk ID for labels # Extract model+serial from disk-by-id path for stable labeling
serial=$(basename "$disk" | sed 's/ata-ST18000NM000J-2TV103_//') # ata-ST18000NM000J-2TV103_ZR52TBSB ST18000NM000J-2TV103-ZR52TBSB
# nvme-KIOXIA-EXCERIA_PLUS_G3_SSD_7FJKS1MAZ0E7 KIOXIA-EXCERIA_PLUS_G3_SSD-7FJKS1MAZ0E7
disk_id=$(basename "$disk")
serial=$(echo "$disk_id" | sed 's/.*_//')
model=$(echo "$disk_id" | sed 's/^[^-]*-//; s/_[^_]*$//')
short_name="$model-$serial"
# Check power state without waking disk # Check power state without waking disk
power_state=$(${pkgs.hdparm}/bin/hdparm -C "$device" 2>/dev/null | grep -oP '(standby|active/idle|active|idle)' | head -1 || echo "unknown") power_state=$(${pkgs.hdparm}/bin/hdparm -C "$device" 2>/dev/null | grep -oP '(standby|active/idle|active|idle)' | head -1 || echo "unknown")

View File

@@ -19,6 +19,7 @@ pkgs.writeShellScriptBin "filebot-process" ''
OUTPUT_DIR="/var/lib/multimedia" OUTPUT_DIR="/var/lib/multimedia"
LOG_FILE="/var/lib/pyload/filebot-amc.log" LOG_FILE="/var/lib/pyload/filebot-amc.log"
EXCLUDE_LIST="/var/lib/pyload/filebot-exclude-list.txt" EXCLUDE_LIST="/var/lib/pyload/filebot-exclude-list.txt"
PASSWORD_FILE="/var/lib/pyload/extraction-passwords.txt"
# Ensure FileBot data directory exists # Ensure FileBot data directory exists
mkdir -p /var/lib/pyload/.local/share/filebot/data mkdir -p /var/lib/pyload/.local/share/filebot/data
@@ -32,18 +33,114 @@ pkgs.writeShellScriptBin "filebot-process" ''
fi fi
echo "===========================================" >> "$LOG_FILE" echo "===========================================" >> "$LOG_FILE"
echo "$(date): PyLoad package extracted hook triggered" >> "$LOG_FILE" echo "$(date): PyLoad package hook triggered" >> "$LOG_FILE"
echo "Package ID: $PACKAGE_ID" >> "$LOG_FILE" echo "Package ID: $PACKAGE_ID" >> "$LOG_FILE"
echo "Package Name: $PACKAGE_NAME" >> "$LOG_FILE" echo "Package Name: $PACKAGE_NAME" >> "$LOG_FILE"
echo "Download Directory: $DOWNLOAD_DIR" >> "$LOG_FILE" echo "Download Directory: $DOWNLOAD_DIR" >> "$LOG_FILE"
echo "===========================================" >> "$LOG_FILE" echo "===========================================" >> "$LOG_FILE"
# Check if download directory exists and has media files # Check if download directory exists
if [ ! -d "$DOWNLOAD_DIR" ]; then if [ ! -d "$DOWNLOAD_DIR" ]; then
echo "$(date): Download directory does not exist: $DOWNLOAD_DIR" >> "$LOG_FILE" echo "$(date): Download directory does not exist: $DOWNLOAD_DIR" >> "$LOG_FILE"
exit 0 exit 0
fi fi
# --- Archive Extraction ---
# Try extraction with passwords, then without
try_extract() {
local archive="$1"
local outdir
outdir="$(dirname "$archive")"
# Try each password from file
if [ -f "$PASSWORD_FILE" ]; then
while IFS= read -r pass || [ -n "$pass" ]; do
[ -z "$pass" ] && continue
case "$archive" in
*.rar) ${pkgs.unrar}/bin/unrar x -p"$pass" -o+ "$archive" "$outdir/" >/dev/null 2>&1 && return 0 ;;
*.7z) ${pkgs.p7zip}/bin/7z x -p"$pass" -aoa -o"$outdir" "$archive" >/dev/null 2>&1 && return 0 ;;
*.zip) ${pkgs.p7zip}/bin/7z x -p"$pass" -aoa -o"$outdir" "$archive" >/dev/null 2>&1 && return 0 ;;
esac
done < "$PASSWORD_FILE"
fi
# Try without password
case "$archive" in
*.rar) ${pkgs.unrar}/bin/unrar x -o+ "$archive" "$outdir/" >/dev/null 2>&1 && return 0 ;;
*.7z) ${pkgs.p7zip}/bin/7z x -aoa -o"$outdir" "$archive" >/dev/null 2>&1 && return 0 ;;
*.zip) ${pkgs.p7zip}/bin/7z x -aoa -o"$outdir" "$archive" >/dev/null 2>&1 && return 0 ;;
esac
return 1
}
# Delete all parts of a split RAR archive
delete_rar_parts() {
local first_part="$1"
local base dir
dir="$(dirname "$first_part")"
# Extract base name: "foo.part1.rar" -> "foo", "foo.part01.rar" -> "foo"
base="$(basename "$first_part" | ${pkgs.gnused}/bin/sed -E 's/\.part[0-9]+\.rar$//')"
# Delete all parts matching the pattern
find "$dir" -maxdepth 1 -type f -iname "''${base}.part*.rar" -delete
echo "$(date): Deleted all parts: ''${base}.part*.rar" >> "$LOG_FILE"
}
# Extract archives in directory
extract_archives() {
local dir="$1"
local extracted=0
# 1. Handle split RAR archives (*.part1.rar or *.part01.rar - first part only)
while IFS= read -r -d "" archive; do
echo "$(date): Extracting split RAR: $archive" >> "$LOG_FILE"
if try_extract "$archive"; then
echo "$(date): Extraction successful" >> "$LOG_FILE"
delete_rar_parts "$archive"
extracted=1
else
echo "$(date): Extraction FAILED: $archive" >> "$LOG_FILE"
fi
done < <(find "$dir" -type f \( -iname "*.part1.rar" -o -iname "*.part01.rar" \) -print0 2>/dev/null)
# 2. Handle single RAR files (not part of split archive)
while IFS= read -r -d "" archive; do
echo "$(date): Extracting RAR: $archive" >> "$LOG_FILE"
if try_extract "$archive"; then
echo "$(date): Extraction successful, deleting: $archive" >> "$LOG_FILE"
rm -f "$archive"
extracted=1
else
echo "$(date): Extraction FAILED: $archive" >> "$LOG_FILE"
fi
done < <(find "$dir" -type f -iname "*.rar" ! -iname "*.part*.rar" -print0 2>/dev/null)
# 3. Handle 7z and zip archives
while IFS= read -r -d "" archive; do
echo "$(date): Extracting: $archive" >> "$LOG_FILE"
if try_extract "$archive"; then
echo "$(date): Extraction successful, deleting: $archive" >> "$LOG_FILE"
rm -f "$archive"
extracted=1
else
echo "$(date): Extraction FAILED: $archive" >> "$LOG_FILE"
fi
done < <(find "$dir" -type f \( -iname "*.7z" -o -iname "*.zip" \) -print0 2>/dev/null)
[ "$extracted" -eq 1 ] && return 0 || return 1
}
# Run extraction (loop to handle nested archives)
echo "$(date): Starting archive extraction..." >> "$LOG_FILE"
for i in 1 2 3; do
extract_archives "$DOWNLOAD_DIR" || break
done
echo "$(date): Archive extraction complete" >> "$LOG_FILE"
# --- Media Processing ---
# Check if there are any video/media files to process # Check if there are any video/media files to process
if ! find "$DOWNLOAD_DIR" -type f \( -iname "*.mkv" -o -iname "*.mp4" -o -iname "*.avi" -o -iname "*.m4v" -o -iname "*.mov" \) -print -quit | grep -q .; then if ! find "$DOWNLOAD_DIR" -type f \( -iname "*.mkv" -o -iname "*.mp4" -o -iname "*.avi" -o -iname "*.m4v" -o -iname "*.mov" \) -print -quit | grep -q .; then
echo "$(date): No media files found in: $DOWNLOAD_DIR" >> "$LOG_FILE" echo "$(date): No media files found in: $DOWNLOAD_DIR" >> "$LOG_FILE"

View File

@@ -15,5 +15,10 @@
ACTION=="add", KERNEL=="sd[a-z]", SUBSYSTEM=="block", \ ACTION=="add", KERNEL=="sd[a-z]", SUBSYSTEM=="block", \
ATTRS{model}=="ST18000NM000J*", \ ATTRS{model}=="ST18000NM000J*", \
RUN+="${pkgs.hdparm}/bin/hdparm -B 127 -S 180 /dev/%k" RUN+="${pkgs.hdparm}/bin/hdparm -B 127 -S 180 /dev/%k"
# Toshiba 20TB NAS drives - same settings
ACTION=="add", KERNEL=="sd[a-z]", SUBSYSTEM=="block", \
ATTRS{model}=="TOSHIBA MG10ACA2*", \
RUN+="${pkgs.hdparm}/bin/hdparm -B 127 -S 180 /dev/%k"
''; '';
} }

View File

@@ -20,12 +20,13 @@ in
"d /var/lib/multimedia/movies 0775 jellyfin jellyfin - -" "d /var/lib/multimedia/movies 0775 jellyfin jellyfin - -"
"d /var/lib/multimedia/tv-shows 0775 jellyfin jellyfin - -" "d /var/lib/multimedia/tv-shows 0775 jellyfin jellyfin - -"
"d /var/lib/multimedia/music 0755 jellyfin jellyfin - -" "d /var/lib/multimedia/music 0755 jellyfin jellyfin - -"
"d /var/lib/multimedia/audiobooks 0775 jellyfin jellyfin - -"
# PyLoad hook scripts directory # PyLoad hook scripts directory (package_finished triggers after download completes)
"d /var/lib/pyload/config 0755 pyload pyload - -" "d /var/lib/pyload/config 0755 pyload pyload - -"
"d /var/lib/pyload/config/scripts 0755 pyload pyload - -" "d /var/lib/pyload/config/scripts 0755 pyload pyload - -"
"d /var/lib/pyload/config/scripts/package_extracted 0755 pyload pyload - -" "d /var/lib/pyload/config/scripts/package_finished 0755 pyload pyload - -"
"L+ /var/lib/pyload/config/scripts/package_extracted/filebot-process.sh - - - - ${filebotScript}/bin/filebot-process" "L+ /var/lib/pyload/config/scripts/package_finished/filebot-process.sh - - - - ${filebotScript}/bin/filebot-process"
]; ];
# FileBot license secret (only if secrets.yaml exists) # FileBot license secret (only if secrets.yaml exists)
@@ -36,7 +37,7 @@ in
path = "/var/lib/pyload/filebot-license.psm"; path = "/var/lib/pyload/filebot-license.psm";
}; };
# Extraction passwords for pyload (one password per line) # Extraction passwords for filebot-process script (one password per line)
sops.secrets.pyload-extraction-passwords = { sops.secrets.pyload-extraction-passwords = {
mode = "0440"; mode = "0440";
owner = "pyload"; owner = "pyload";
@@ -77,14 +78,8 @@ in
PYLOAD__DOWNLOAD__LIMIT_SPEED = "1"; PYLOAD__DOWNLOAD__LIMIT_SPEED = "1";
PYLOAD__DOWNLOAD__MAX_SPEED = "19200"; PYLOAD__DOWNLOAD__MAX_SPEED = "19200";
# Enable ExtractArchive plugin # Disable ExtractArchive plugin (extraction handled by filebot-process script)
PYLOAD__EXTRACTARCHIVE__ENABLED = "1"; PYLOAD__EXTRACTARCHIVE__ENABLED = "0";
PYLOAD__EXTRACTARCHIVE__DELETE = "1";
PYLOAD__EXTRACTARCHIVE__DELTOTRASH = "0";
PYLOAD__EXTRACTARCHIVE__REPAIR = "1";
PYLOAD__EXTRACTARCHIVE__RECURSIVE = "1";
PYLOAD__EXTRACTARCHIVE__FULLPATH = "1";
PYLOAD__EXTRACTARCHIVE__PASSWORDFILE = "/var/lib/pyload/extraction-passwords.txt";
# Enable ExternalScripts plugin for hooks # Enable ExternalScripts plugin for hooks
PYLOAD__EXTERNALSCRIPTS__ENABLED = "1"; PYLOAD__EXTERNALSCRIPTS__ENABLED = "1";

View File

@@ -4,11 +4,11 @@
let let
# Disk mapping: ata port -> LED name # Disk mapping: ata port -> LED name
# DXP4800 has bays 1-4, currently bays 2 and 4 are populated # DXP4800 has bays 1-4, all populated
diskMapping = { diskMapping = {
# ata-2 (sdb) -> disk2 "1" = "disk1";
"2" = "disk2"; "2" = "disk2";
# ata-4 (sdc) -> disk4 "3" = "disk3";
"4" = "disk4"; "4" = "disk4";
}; };

View File

@@ -1,48 +1,48 @@
pyload-extraction-passwords: ENC[AES256_GCM,data:M4ONmZXoSg==,iv:9+NEibTSoJwZ2uLJZZzQtJHMNtR084CCyBXq7ORqxI0=,tag:QE2QMlxycK+OJWgiLWKlRA==,type:str] pyload-extraction-passwords: ENC[AES256_GCM,data:zOvPYcnvcg2OwJaCZovYQz87ZN9DdpKX1Re1/v24daw0WGBG3sGeJn1q+LDfjPIMy487CdY=,iv:loWfUcIw30kVXchmXwAts10FNUGxSsTY2UVRKs0RTJ8=,tag:WlTYugSv2ApR496Uc1KPEg==,type:str]
cyberghost-auth: ENC[AES256_GCM,data:ZX+vfTcIH/8QMOIpIFdYV71sYBS5MA==,iv:4TeDcMs+lz7N6myLwZ9pG8mwzDzjWBpyi2CpsUtcaoc=,tag:RM24rTag4RfgPWKfrX3fnw==,type:str] cyberghost-auth: ENC[AES256_GCM,data:v8PlO2qi06p2FZR1iFbHAVPr0k+X/A==,iv:oEzIIZ7KiVJ5EpMT2YMgvMZSJZwtIsnTWwkMXxl/R4w=,tag:+NOMggSKloW0SOYxopHrYA==,type:str]
cyberghost-ca: ENC[AES256_GCM,data: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,iv:inCj141jhzAAUXPHYPyfWV34XLOs3IzZDu7F86zTCyA=,tag:r5Gg4q1B8SammluvIi+nxA==,type:str] cyberghost-ca: ENC[AES256_GCM,data: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,iv:mWBG6fP3do+VzwyBlCVXsWiywRNiyMiWNaxlYFTkms0=,tag:94YPWZtVy1viq0KbclF6LA==,type:str]
cyberghost-cert: ENC[AES256_GCM,data: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,iv:TvtZ8/eeeUwMq07nl+fx7ixkifN06shxcyV7vIs5zvU=,tag:fZXmrkIvQ1ZH3aqkkfLLIQ==,type:str] cyberghost-cert: ENC[AES256_GCM,data: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,iv:kavsBNAUcK7vHOJnj9nyX4D9dHzgP3aBwCLQb9umBJo=,tag:aeTpc2vpO72R45cjBR+cFw==,type:str]
cyberghost-key: ENC[AES256_GCM,data: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,iv:moUhCD9vW2fREB1hXGyP3ha4PEzXWhbW3kI0x1KWxVA=,tag:UIW2trbJ2g6nkU7IfI06fA==,type:str] cyberghost-key: ENC[AES256_GCM,data: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,iv:DmcNUOhsi9doTYta+s65BFpuIgiK7QAjAorfVq/VGLA=,tag:c/mZS7ZnasX5XX4HIx80AA==,type:str]
filebot-license: ENC[AES256_GCM,data:oOVGag9rzJkgPb7Sic+nVg6n//3E7o0BLamF5ugXCdKYVoEw1koZWrB8kVwAmGAmzgpT98gMmWFvej5eZBlTR1CDV/ZFJHE5nr+1b7RhcVrzxVfkanpr6JOu3JJ2TDx+z6+JyuZsoHQe6zGIlyz1DO1/+tgYChEInZB+apFvbEsKzwT92yQztaJ2TivjCwcxhjZR9lnFTQWvTsZZ8Fatwi03FsbHNkz5UdlKZ+N8yFJoKc7a2+UrnV91ClfGpvOpaGfmgls7Uen69LPb2TLujhc1W+WBOwvzgWrrG4+KF+4yMtJ0apVJd5iBKq2zZwZo6EdC8Ynv8DqJOhTrjScoVCZ+xPEmcZGuOa0y1bEFYcDO31Y8iyVEUpfMfyyjFIWIm6IGkPDP3tWQWAQIIhlsYbRipKKN7aCaetg/ib33q2M0M1XFME2IBVEZMyEJ/PMt+qi0CUJqx+S2nxqEB8jNnJTXc+ANJfiJ1YdgtG67wLCdzrDTkDPT/HEIvTUumwWSLdZnXvfqvB4f5ZO20vPN8S66EgGZeWU3x/HXqV6MSQSLOOtySP3kY3gn/hSWIo9JB+63BEgdI1WvqlkA4wBB7kHuA6YqBR9ofODUt3ae7X7qbVcimGN9fRBtKny5u9A04/+gJ9BhWsaQruX2EPvIb/evxmYqFvg+suvBPu50KExmdjXPJJsRgR6dwYyxXwVOtbrFhKIK17e7s3+DyXrYWhMGOfUOpl4ew377E4YHjLBm1r5WtU46NfK4TA1rDVTSlBXOfV6Hmhs3ThUhNJ3sgHzrrQiEZcC0Of+4RBLhKNMTgOO39Tjz48BAYObBxw2F3oiLT9RBXFAz5ebwxzf6ciBwjEi4Bf76rIcE2RTdiA90J4NsDTsFNoknEIxqvHE=,iv:dbmC8UBE1dwCBSWcYg94mBvdq6Xi+nBweMWlvvnxN9k=,tag:UQZ6rlM3loJg4vxav7dg+A==,type:str] filebot-license: ENC[AES256_GCM,data:Ib+NXsb0dJfBqm5GYvXxGMOQk3zL28oeS3VXsk4pFIGV5XsakqZRZb307X1oJnafMVXva/eQppraI8CqjwBDzy3AZSnwpFgj96/zvPWZi12IWemnqhFUDFZGaMG4Scg6Ugcq8hwJqU39Mf5JehSbJ/PoULg/Ovekj8R0nG7WlmQsqxpZWXWeAdfYZHw1/4MQTX/IGZG82SdsdFc4J9jTedks0yvW5MLkS3azZSFDqY2WXAMVa5J9jXEcie58k6p0QqAUpWGltoXz1tdN/mTnVV7PA35wReS/Ejm11KS5AsjkTIZRLeJ14BL0vALUh3z6JSdr8kPG1S31MMYxarzGBqjI78LfFmFynGonAlqj/jPoxA7AXOew5xRfoEqnxf8lSUf2F2n7PF+B1SgY/hwFvwUeoaA4ep8uFugT7pCvg3N+FmfsV4TAP6tfU75WjwZ07UKQ0t63C/aDI1lZZjfKDzXDFqliD6omhFPUVxhGIo9gBkvOZj6ujdn7ErWohxAc7JSVsDJ8nBKqVGXMMgecWHyqU5LB9+3CKkE32vMy6fbGVlHhgRI4EofVCiuCn2Opg8txCz7Rh8eU297xotIjfCzhPjaY0CmD0dm/8SVLT9Tt3qQMDzlzolcWg+9o3e4bbjSOzliR+4c4fCGBPxZvBPd4kZ87eo22m6WqtS18tMTD1tq+8nVjpHFyrsyyMZtfv9/QXug0SFhJpUz6izCcl+iiNiQIb+DBi4Oifhr88Ji+Y4iQrj7mPUGzNr/T1x/uSBabv83HPsZUa5+OBrlbvp/Ya2ktIagiyv+JrHmcFMkVGYvFK4idLsREcvteduP7XeWaOXuJZJ5GOPZPDM+8DSxv3eOULH1B25J1/838vaVKZM3ukQkiybYTJWVV2co=,iv:G6bhfqx0go6vbJ2zwXkSbHLt5WdDRwu2o4BsCXw5Rlw=,tag:msCGdlefM3M8lbQWJPcOgA==,type:str]
sops: sops:
age: age:
- recipient: age14grjcxaq4h55yfnjxvnqhtswxhj9sfdcvyas4lwvpa8py27pjy2sv3g6v7 - recipient: age14grjcxaq4h55yfnjxvnqhtswxhj9sfdcvyas4lwvpa8py27pjy2sv3g6v7
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvZW5uSzROdXE0R2VLOGlG YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvemExcjFLT2tjTlhtMlFl
WXhTVW0rOGt0a1RRQzZaSlNNOWgydEN0cGxZClA0K0JnRnVmNTM3TGVRL25xT2pH UFlCQWhtUDc5YmFHU21SdDBoMXNCV2dlbXl3CnJzVmpMcXUwbWx1a1VLUVRhSnFu
aTFld0ZDRERvb2NrVkJkbldWemtUQ0kKLS0tIENmTktaK2tJZmNCWWtPTDR4Q2JG MmtmYjVESVJpdFh1UmtwSWl5WE5WZFkKLS0tIE5wZzQ0MENna2EwMzVDUU9QcDlk
MTY4dW52aXYzQmhOMjJnYnhCZXZxSzQKVaw9iZSG3MX4a8qfPqeN4VuEjHXX8L8J bitkdVVwM0l4ajJVYldWM2JqV05tUzgKsJem/g4ckwrmiTJgwtHc98zALWlwmVgH
hn9nk5yHIOYjhmB8y1+Zoe/12+w4qHHF/yudnU+9oJCEcOvafhK83A== +O0nH3kcU54SjDQYVRKUWdaCNbsXHEN9wqICS9q0Ill7pD2K0ElZLg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1exny8unxynaw03yu8ppahu5z28uermghr8ag34e7kdqnaduq9stsyettzz - recipient: age1exny8unxynaw03yu8ppahu5z28uermghr8ag34e7kdqnaduq9stsyettzz
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVZy9vTVRIdElJZ3R4ckNN YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEb1dtSlJMKzFreWtmclBE
aXhCS216Q0pjSGVERXRVVVE0Tng2cmhXZUhnCjliWEROcjh0NU1VUlpXNmtuOGxr YUgvYXBQb1FtaFhZRjlqTWk1aUZkcjhCbjBFCi9rSUMzdWFkL3I3c3E0bUxERkVN
cjNyeFFRNVRsUCs4emlHaVd0b0lzME0KLS0tIGw4ZE11M01uQjhUMUJNMnlyNXBM TDFaUCtHWE5xNEN4NzNXTlBWWnpYR2sKLS0tIDQ5dTM3S0JQdGJvaE0rTkZYWXNN
VkREd3FvRUVwOUNSa1lMMUZQdU5aK0EK/RUCQuPK/mgFfjqStVapOD/XpTVe63OY aTJQNUZuMW5kZVNJQ0lObkZRdzVyZ3MKwfD8PgUM1kHCa1aaDAp0Iv3zaSGsOWS8
9z9I3LLD54OlkQFyK1oPXxnMmjo0QezA+30E6rcxKERoe5N55ffxUA== f3W8gUMV2Qv1FC4hBccbYH2bHuq5ENVhkleIyE51GT+Ckwt5oR14vw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1v6p8dan2t3w9h94fz4flldl32082j3s9x6zqq7u5j66keth9aphsd6pvch - recipient: age1v6p8dan2t3w9h94fz4flldl32082j3s9x6zqq7u5j66keth9aphsd6pvch
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNNDJzbGRGTC9ibEYwb0VE YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0dE5zaEpBSEYvVE5QTjVF
Z1BXcU42YmsxTTMvQzZUYmpWM29PaDFTeFZBCkV0MHhKdjdLaitGZ0RGRHdnQlI2 dldFY2t3YThTalowbkMrckhUWjhGdXFVNG1BCldqV2lOS280Z0xjQXo4THlPenQ2
KysvSk0rbS9PazAzOVRoSjNQSEordEEKLS0tIFlQNnJ0a1dzbDR5NVVkM3JxMzVq WVRiWDAxSFgzQUkvSjVZUEpBNzZkR0kKLS0tIC9rOHAvSUZadCs5OXhheFpERzlx
bjBGUW5SQ3lVMW9BV3lzVklISHVrOFkKkkQTxWMLVzt6XGdu+WdphYigSzeeoIWr QmRCYldBUW9zeTF3cmtUOXVuV2pOMEEKDJC7lyekw9TQmuwfPRb9UsUgqdbAVaxy
ImJuy1oXVd69XK4KUkXOrg4XfeKXXjslAHTVVI0+PFnDaM4SBC1h3Q== tZYmhSYhUFBOUyJ7xwiIfMgOu5A4D2p/q+T2MPCmeOSLUDyycE8Zuw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1x3elhtccp4u8ha5ry32juj9fkpg0qg7qqx4gduuehgwwnnhcxp8s892hek - recipient: age1x3elhtccp4u8ha5ry32juj9fkpg0qg7qqx4gduuehgwwnnhcxp8s892hek
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZTXdqdVd6ZmxtYSsrWDA0 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzdkUramxKVFVZQVJVMU9E
WWtzZEhuVWxCNkZwbjJJcDBSU0t0cEpjRkRJCkp4TkRqeUJiVnBFS0pkdEM3eEpx a1pYck8yOEhpZWZGcktxYkR0U290dll6VmdnCnZWZU9uWXFWZ2ZrVnp0cDBteGdr
K2JlN2lSQ3NWdzd1R1NoYTVmSzByajQKLS0tIFB4ZHA1WG1DU29CbWlTSlAxdDA2 azVGVHg5Y0VuZi82UUtkWUtLeDA3UWcKLS0tIDNJZGJQNmpHdFpQUVdiMHh3djhP
Um9vMWRwQWk4VGF6eExMU2FvMjJSblUK/XiDETNk97IvN9A3yP+sfRxQMO2bXXdm WURRbGNNWWJvKzZabGxyd3NXN3lKZ2cKryVInc722ZsjoiYel0YYAQZUsgXDx0by
GDODc3E65x7Gftbvu44KS9UARFPzj32W+JhE0k/C+ihECUzz3ChyLg== Ds65yQDcI0ttbmMyFN8oYqD7pnOaD1aZYg6cxqzUVPen9iqCkclMwg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-11-30T18:50:08Z" lastmodified: "2025-12-08T12:02:01Z"
mac: ENC[AES256_GCM,data:A7cQQgB6RMe3JdGSv7SjHrD9eoEY86ElfjIUp2PtYdzDiQfrxTsJf962P/IRRWdMn7cCwQDNwxJkiZCRZ7lv/iDznvibC+0FGkGIiFvbkIK88hr7hqvpzf/CQOpNvyvXfJb1Y13R00mSfNzJw7xo98IjZYlsLAAFxpapCbUV7Bc=,iv:/Gmq6AnMGVy7QKjvruFs8c3WcbGxW61P7VjYT2u2ooc=,tag:BT9gv7ebsWEpSARCI97rqg==,type:str] mac: ENC[AES256_GCM,data:K1kelYSO6R1kU3hLQVmlPI3vn9p4uEHDQnb7eVgn5PH/HFlqJrRj9HfagD/yKT0hBIehC3R8rxv73SeXacBcCaBx+A1Ty1fj/K18oQdEpFlOWxYhIvRX23NHaaqudFdVRiVg23spOoTgP48+mSzJdE4dk3jQcm94yxiUQy9kBSw=,iv:iSL9knAzk0SLXDJ1m6xy+Vkv6RqtUP2lzcluQTdKG5g=,tag:Z8I+UY/taf/uq4sQ7qIUEg==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.11.0 version: 3.11.0

View File

@@ -1 +1 @@
https://channels.nixos.org/nixos-25.05 https://channels.nixos.org/nixos-25.11

View File

@@ -307,7 +307,7 @@ in {
''; '';
}; };
services.xserver.desktopManager.gnome.extraGSettingsOverrides = '' services.desktopManager.gnome.extraGSettingsOverrides = ''
[org.gnome.desktop.interface] [org.gnome.desktop.interface]
cursor-size=24 cursor-size=24
''; '';

View File

@@ -115,7 +115,7 @@
hardware.graphics = { hardware.graphics = {
enable = true; enable = true;
extraPackages = with pkgs; [ extraPackages = with pkgs; [
vaapiVdpau libva-vdpau-driver
libvdpau-va-gl libvdpau-va-gl
libva libva
libva-utils libva-utils

View File

@@ -26,14 +26,13 @@ in
description = "Bitwarden Desktop"; description = "Bitwarden Desktop";
after = [ "graphical-session.target" "network-online.target" ]; after = [ "graphical-session.target" "network-online.target" ];
wantedBy = [ "graphical-session.target" ]; wantedBy = [ "graphical-session.target" ];
serviceConfig.ExecStart = "${pkgs.bitwarden}/bin/bitwarden"; serviceConfig.ExecStart = "${pkgs.bitwarden-desktop}/bin/bitwarden-desktop";
serviceConfig.Restart = "on-abort"; serviceConfig.Restart = "on-abort";
}; };
#### Handy tools ############################################################# #### Handy tools #############################################################
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
goldwarden bitwarden-desktop
bitwarden
bitwarden-cli bitwarden-cli
fprintd fprintd
lxqt.lxqt-policykit lxqt.lxqt-policykit

View File

@@ -57,10 +57,10 @@ in {
netflix netflix
networkmanagerapplet networkmanagerapplet
nextcloud-client nextcloud-client
onlyoffice-bin onlyoffice-desktopeditors
obs-studio obs-studio
pavucontrol pavucontrol
pinentry pinentry-gnome3
rbw rbw
rofi-rbw rofi-rbw
swayimg swayimg
@@ -103,7 +103,7 @@ in {
fonts.packages = with pkgs; [ fonts.packages = with pkgs; [
noto-fonts noto-fonts
noto-fonts-cjk-sans noto-fonts-cjk-sans
noto-fonts-emoji noto-fonts-color-emoji
nerd-fonts._0xproto nerd-fonts._0xproto
nerd-fonts.droid-sans-mono nerd-fonts.droid-sans-mono
open-sans open-sans

View File

@@ -20,7 +20,7 @@ in {
nixpkgs.config.android_sdk.accept_license = true; nixpkgs.config.android_sdk.accept_license = true;
programs.adb.enable = true; # sets up udev + adb group programs.adb.enable = true; # sets up udev + adb group
services.udev.packages = [ pkgs.android-udev-rules ]; # android-udev-rules removed in 25.11 - superseded by built-in systemd uaccess rules
users.users.dominik.extraGroups = [ "adbusers" ]; users.users.dominik.extraGroups = [ "adbusers" ];
} }

View File

@@ -38,6 +38,7 @@ in {
rbw rbw
sops sops
unzip unzip
uv
vim vim
wget wget
wireguard-tools wireguard-tools
@@ -52,11 +53,6 @@ in {
# Socket activation - only start when needed to save battery # Socket activation - only start when needed to save battery
onBoot = "ignore"; onBoot = "ignore";
onShutdown = "shutdown"; onShutdown = "shutdown";
qemu = { # qemu.swtpm.enable = true; # enable if you need TPM emulation, etc.
ovmf = {
enable = true; # Enable OVMF firmware support
};
# swtpm.enable = true; # enable if you need TPM emulation, etc.
};
}; };
} }

View File

@@ -1,3 +1,6 @@
-- Set leader key before any other mappings
vim.g.mapleader = " "
-- vim.opt.expandtab = true -- vim.opt.expandtab = true
-- vim.opt.hidden = true -- vim.opt.hidden = true
-- vim.opt.incsearch = true -- vim.opt.incsearch = true

View File

@@ -1,54 +1,31 @@
local status, lspc = pcall(require, 'lspconfig') -- LSP Capabilities (for nvim-cmp integration)
if (not status) then return end
lspc.clangd.setup{}
local buf_map = function(bufnr, mode, lhs, rhs, opts)
vim.api.nvim_buf_set_keymap(bufnr, mode, lhs, rhs, opts or {
silent = true,
})
end
local protocol = require('vim.lsp.protocol')
local on_attach = function(client, buffnr)
if client.server.capabilities.documentFormattingProvider then
vim.api.nvim_create_autocmd("BufWritePre", {
group = vim.api.nvim_create_augroup("format", { clear = true }),
buffer = buffnr,
callback = function() vim.lsp.buf.formatting_seq_sync() end
})
end
end
local capabilities = vim.lsp.protocol.make_client_capabilities() local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem.snippetSupport = true capabilities.textDocument.completion.completionItem.snippetSupport = true
capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
local servers = { 'ts_ls', 'lua_ls', 'cssls', 'yamlls', 'intelephense', 'gopls' } -- Global LSP configuration
for _, lsp in pairs(servers) do vim.lsp.config('*', {
require('lspconfig')[lsp].setup {
-- on_attach = on_attach,
capabilities = capabilities, capabilities = capabilities,
} })
end
lspc.yamlls.setup({ -- Server-specific configurations
vim.lsp.config('clangd', {})
vim.lsp.config('yamlls', {
settings = { settings = {
yaml = { yaml = {
keyOrdering = false, keyOrdering = false,
}, },
}, },
}); })
-- autoformat json files with jq -- Enable all LSP servers
vim.lsp.enable({ 'clangd', 'ts_ls', 'lua_ls', 'cssls', 'yamlls', 'intelephense', 'gopls' })
-- JSON file formatting with jq
vim.api.nvim_create_autocmd("FileType", { vim.api.nvim_create_autocmd("FileType", {
pattern = "json", pattern = "json",
callback = function(ev) callback = function(ev)
vim.bo[ev.buf].formatprg = "jq" vim.bo[ev.buf].formatprg = "jq"
print("It's a json file")
end, end,
}) })
-- lspc.intelephense.setup()

View File

@@ -1,41 +1,13 @@
config = { local status_ok, project = pcall(require, "project")
---@usage set to false to disable project.nvim.
--- This is on by default since it's currently the expected behavior.
active = true,
on_config_done = nil,
---@usage set to true to disable setting the current-woriking directory
--- Manual mode doesn't automatically change your root directory, so you have
--- the option to manually do so using `:ProjectRoot` command.
manual_mode = false,
---@usage Methods of detecting the root directory
--- Allowed values: **"lsp"** uses the native neovim lsp
--- **"pattern"** uses vim-rooter like glob pattern matching. Here
--- order matters: if one is not detected, the other is used as fallback. You
--- can also delete or rearangne the detection methods.
-- detection_methods = { "lsp", "pattern" }, -- NOTE: lsp detection will get annoying with multiple langs in one project
detection_methods = { "pattern" },
---@usage patterns used to detect root dir, when **"pattern"** is in detection_methods
patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json", "pom.xml" },
---@ Show hidden files in telescope when searching for files in a project
show_hidden = false,
---@usage When set to false, you will get a message when project.nvim changes your directory.
-- When set to false, you will get a message when project.nvim changes your directory.
silent_chdir = true,
---@usage list of lsp client names to ignore when using **lsp** detection. eg: { "efm", ... }
ignore_lsp = {},
}
local status_ok, project = pcall(require, "project_nvim")
if not status_ok then if not status_ok then
return return
end end
project.setup(config) project.setup({
use_lsp = false, -- Use pattern matching only (equivalent to old detection_methods = { "pattern" })
manual_mode = false,
patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json", "pom.xml" },
show_hidden = false,
silent_chdir = true,
ignore_lsp = {},
})

View File

@@ -1,7 +1,7 @@
-- none-ls -- none-ls (module is still named "null-ls" for backward compatibility)
local status_ok_nls, none_ls_module = pcall(require, "none-ls") local status_ok_nls, none_ls_module = pcall(require, "null-ls")
if not status_ok_nls then if not status_ok_nls then
vim.notify("none-ls plugin not found or failed to load. Check Nix config and plugin paths.", vim.log.levels.WARN) vim.notify("null-ls plugin not found or failed to load. Check Nix config and plugin paths.", vim.log.levels.WARN)
else else
local nb = none_ls_module.builtins local nb = none_ls_module.builtins
none_ls_module.setup({ none_ls_module.setup({

View File

@@ -1,5 +1,3 @@
vim.g.mapleader = " "
local function smart_quit() local function smart_quit()
local bufnr = vim.api.nvim_get_current_buf() local bufnr = vim.api.nvim_get_current_buf()
local modified = vim.api.nvim_buf_get_option(bufnr, "modified") local modified = vim.api.nvim_buf_get_option(bufnr, "modified")
@@ -27,122 +25,77 @@ end
local wk = require("which-key") local wk = require("which-key")
wk.setup({}) wk.setup({
preset = "classic",
wk.register({ delay = 0,
["<leader>"] = { triggers = {
{ "<auto>", mode = "nxso" },
[";"] = { "<cmd>Alpha<CR>", "Dashboard" }, { " ", mode = "n" }, -- literal space character
["w"] = { "<cmd>w!<CR>", "Save" },
["q"] = { "<cmd>smart_quit()<CR>", "Quit" },
["/"] = { "<Plug>(comment_toggle_linewise_current)", "Comment toggle current line" },
["c"] = { "<cmd>BufferKill<CR>", "Close Buffer" },
["f"] = { find_project_files, "Find File" },
["h"] = { "<cmd>nohlsearch<CR>", "No Highlight" },
["t"] = { "<cmd>TodoTelescope keywords=TODO,FIX<CR>", "Find TODO,FIX" },
b = {
name = "Buffers",
j = { "<cmd>BufferLinePick<cr>", "Jump" },
f = { "<cmd>Telescope buffers<cr>", "Find" },
b = { "<cmd>BufferLineCyclePrev<cr>", "Previous" },
n = { "<cmd>BufferLineCycleNext<cr>", "Next" },
-- w = { "<cmd>BufferWipeout<cr>", "Wipeout" }, -- TODO: implement this for bufferline
e = {
"<cmd>BufferLinePickClose<cr>",
"Pick which buffer to close",
}, },
h = { "<cmd>BufferLineCloseLeft<cr>", "Close all to the left" },
l = {
"<cmd>BufferLineCloseRight<cr>",
"Close all to the right",
},
D = {
"<cmd>BufferLineSortByDirectory<cr>",
"Sort by directory",
},
L = {
"<cmd>BufferLineSortByExtension<cr>",
"Sort by language",
},
},
-- " Available Debug Adapters:
-- " https://microsoft.github.io/debug-adapter-protocol/implementors/adapters/
-- " Adapter configuration and installation instructions:
-- " https://github.com/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation
-- " Debug Adapter protocol:
-- " https://microsoft.github.io/debug-adapter-protocol/
-- " Debugging
g = {
name = "Git",
g = { Lazygit_toggle, "Lazygit" },
j = { "<cmd>lua require 'gitsigns'.next_hunk({navigation_message = false})<cr>", "Next Hunk" },
k = { "<cmd>lua require 'gitsigns'.prev_hunk({navigation_message = false})<cr>", "Prev Hunk" },
l = { "<cmd>lua require 'gitsigns'.blame_line()<cr>", "Blame" },
p = { "<cmd>lua require 'gitsigns'.preview_hunk()<cr>", "Preview Hunk" },
r = { "<cmd>lua require 'gitsigns'.reset_hunk()<cr>", "Reset Hunk" },
R = { "<cmd>lua require 'gitsigns'.reset_buffer()<cr>", "Reset Buffer" },
s = { "<cmd>lua require 'gitsigns'.stage_hunk()<cr>", "Stage Hunk" },
u = {
"<cmd>lua require 'gitsigns'.undo_stage_hunk()<cr>",
"Undo Stage Hunk",
},
o = { "<cmd>Telescope git_status<cr>", "Open changed file" },
b = { "<cmd>Telescope git_branches<cr>", "Checkout branch" },
c = { "<cmd>Telescope git_commits<cr>", "Checkout commit" },
C = {
"<cmd>Telescope git_bcommits<cr>",
"Checkout commit(for current file)",
},
d = {
"<cmd>Gitsigns diffthis HEAD<cr>",
"Git Diff",
},
},
l = {
name = "LSP",
a = { "<cmd>lua vim.lsp.buf.code_action()<cr>", "Code Action" },
d = { "<cmd>Telescope diagnostics bufnr=0 theme=get_ivy<cr>", "Buffer Diagnostics" },
w = { "<cmd>Telescope diagnostics<cr>", "Diagnostics" },
-- f = { require("lvim.lsp.utils").format, "Format" },
i = { "<cmd>LspInfo<cr>", "Info" },
I = { "<cmd>Mason<cr>", "Mason Info" },
j = {
vim.diagnostic.goto_next,
"Next Diagnostic",
},
k = {
vim.diagnostic.goto_prev,
"Prev Diagnostic",
},
l = { vim.lsp.codelens.run, "CodeLens Action" },
q = { vim.diagnostic.setloclist, "Quickfix" },
r = { vim.lsp.buf.rename, "Rename" },
s = { "<cmd>Telescope lsp_document_symbols<cr>", "Document Symbols" },
S = {
"<cmd>Telescope lsp_dynamic_workspace_symbols<cr>",
"Workspace Symbols",
},
e = { "<cmd>Telescope quickfix<cr>", "Telescope Quickfix" },
},
a = { "<cmd>lua require('telescope.builtin').lsp_code_actions()<cr>", "Code Actions" },
d = { "<cmd>lua require('telescope.builtin').lsp_document_diagnostics()<cr>", "LSP Diagnostics" },
k = { "<cmd>lua vim.lsp.buf.signature_help()<cr>", "Signature Help" },
P = { "<cmd>lua require'telescope'.extensions.projects.projects{}<cr>", "Signature Help" },
}
}) })
wk.register( wk.add({
{ -- Single key mappings
["/"] = { "<Plug>(comment_toggle_linewise_visual)", "Comment toggle linewise (visual)" }, { "<leader>;", "<cmd>Alpha<CR>", desc = "Dashboard" },
}, { "<leader>w", "<cmd>w!<CR>", desc = "Save" },
{ { "<leader>q", smart_quit, desc = "Quit" },
mode = "v", -- VISUAL mode { "<leader>/", "<Plug>(comment_toggle_linewise_current)", desc = "Comment toggle current line" },
prefix = "<leader>", { "<leader>c", "<cmd>BufferKill<CR>", desc = "Close Buffer" },
buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings { "<leader>f", find_project_files, desc = "Find File" },
silent = true, -- use `silent` when creating keymaps { "<leader>h", "<cmd>nohlsearch<CR>", desc = "No Highlight" },
noremap = true, -- use `noremap` when creating keymaps { "<leader>t", "<cmd>TodoTelescope keywords=TODO,FIX<CR>", desc = "Find TODO,FIX" },
nowait = true, -- use `nowait` when creating keymaps
} -- Buffers group
) { "<leader>b", group = "Buffers" },
{ "<leader>bj", "<cmd>BufferLinePick<cr>", desc = "Jump" },
{ "<leader>bf", "<cmd>Telescope buffers<cr>", desc = "Find" },
{ "<leader>bb", "<cmd>BufferLineCyclePrev<cr>", desc = "Previous" },
{ "<leader>bn", "<cmd>BufferLineCycleNext<cr>", desc = "Next" },
{ "<leader>be", "<cmd>BufferLinePickClose<cr>", desc = "Pick which buffer to close" },
{ "<leader>bh", "<cmd>BufferLineCloseLeft<cr>", desc = "Close all to the left" },
{ "<leader>bl", "<cmd>BufferLineCloseRight<cr>", desc = "Close all to the right" },
{ "<leader>bD", "<cmd>BufferLineSortByDirectory<cr>", desc = "Sort by directory" },
{ "<leader>bL", "<cmd>BufferLineSortByExtension<cr>", desc = "Sort by language" },
-- Git group
{ "<leader>g", group = "Git" },
{ "<leader>gg", Lazygit_toggle, desc = "Lazygit" },
{ "<leader>gj", "<cmd>lua require 'gitsigns'.next_hunk({navigation_message = false})<cr>", desc = "Next Hunk" },
{ "<leader>gk", "<cmd>lua require 'gitsigns'.prev_hunk({navigation_message = false})<cr>", desc = "Prev Hunk" },
{ "<leader>gl", "<cmd>lua require 'gitsigns'.blame_line()<cr>", desc = "Blame" },
{ "<leader>gp", "<cmd>lua require 'gitsigns'.preview_hunk()<cr>", desc = "Preview Hunk" },
{ "<leader>gr", "<cmd>lua require 'gitsigns'.reset_hunk()<cr>", desc = "Reset Hunk" },
{ "<leader>gR", "<cmd>lua require 'gitsigns'.reset_buffer()<cr>", desc = "Reset Buffer" },
{ "<leader>gs", "<cmd>lua require 'gitsigns'.stage_hunk()<cr>", desc = "Stage Hunk" },
{ "<leader>gu", "<cmd>lua require 'gitsigns'.undo_stage_hunk()<cr>", desc = "Undo Stage Hunk" },
{ "<leader>go", "<cmd>Telescope git_status<cr>", desc = "Open changed file" },
{ "<leader>gb", "<cmd>Telescope git_branches<cr>", desc = "Checkout branch" },
{ "<leader>gc", "<cmd>Telescope git_commits<cr>", desc = "Checkout commit" },
{ "<leader>gC", "<cmd>Telescope git_bcommits<cr>", desc = "Checkout commit(for current file)" },
{ "<leader>gd", "<cmd>Gitsigns diffthis HEAD<cr>", desc = "Git Diff" },
-- LSP group
{ "<leader>l", group = "LSP" },
{ "<leader>la", "<cmd>lua vim.lsp.buf.code_action()<cr>", desc = "Code Action" },
{ "<leader>ld", "<cmd>Telescope diagnostics bufnr=0 theme=get_ivy<cr>", desc = "Buffer Diagnostics" },
{ "<leader>lw", "<cmd>Telescope diagnostics<cr>", desc = "Diagnostics" },
{ "<leader>li", "<cmd>LspInfo<cr>", desc = "Info" },
{ "<leader>lI", "<cmd>Mason<cr>", desc = "Mason Info" },
{ "<leader>lj", vim.diagnostic.goto_next, desc = "Next Diagnostic" },
{ "<leader>lk", vim.diagnostic.goto_prev, desc = "Prev Diagnostic" },
{ "<leader>ll", vim.lsp.codelens.run, desc = "CodeLens Action" },
{ "<leader>lq", vim.diagnostic.setloclist, desc = "Quickfix" },
{ "<leader>lr", vim.lsp.buf.rename, desc = "Rename" },
{ "<leader>ls", "<cmd>Telescope lsp_document_symbols<cr>", desc = "Document Symbols" },
{ "<leader>lS", "<cmd>Telescope lsp_dynamic_workspace_symbols<cr>", desc = "Workspace Symbols" },
{ "<leader>le", "<cmd>Telescope quickfix<cr>", desc = "Telescope Quickfix" },
-- Direct LSP shortcuts
{ "<leader>a", "<cmd>lua require('telescope.builtin').lsp_code_actions()<cr>", desc = "Code Actions" },
{ "<leader>d", "<cmd>lua require('telescope.builtin').lsp_document_diagnostics()<cr>", desc = "LSP Diagnostics" },
{ "<leader>k", "<cmd>lua vim.lsp.buf.signature_help()<cr>", desc = "Signature Help" },
{ "<leader>P", "<cmd>lua require'telescope'.extensions.projects.projects{}<cr>", desc = "Projects" },
-- Visual mode mappings
{ "<leader>/", "<Plug>(comment_toggle_linewise_visual)", desc = "Comment toggle linewise (visual)", mode = "v" },
})

View File

@@ -13,7 +13,7 @@ in
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
nodePackages.typescript-language-server nodePackages.typescript-language-server
sumneko-lua-language-server lua-language-server
nest nest
nodePackages.intelephense nodePackages.intelephense
nodePackages.vscode-langservers-extracted nodePackages.vscode-langservers-extracted
@@ -105,9 +105,9 @@ in
"sops" "sops"
]); ]);
in '' in ''
lua << EOF lua << EOF
${luaConfig} ${luaConfig}
EOF EOF
''; '';
}; };
extraLuaPackages = luaPackages: [ luaPackages.lyaml ]; extraLuaPackages = luaPackages: [ luaPackages.lyaml ];

View File

@@ -1,46 +1,47 @@
epicenter_vpn_ca: ENC[AES256_GCM,data:DUvpuL92zpQkK0auXGdHDw+f5gzjMARMroBknmgR+eq1LV5aISdA0XOCw7d3VFpMtHY+tPM4pDEWlnGJDoHDJBSFAUdmbLkDq2DvoDR1RBbsidmlXpvu7UnL4OyCgrN9G3I65HQmCh64/453T0Y5MZKUiFZXn9SZJgOU3h0qOnAiIKTQADXmUo6imhLuUdPxjwiLkNp8zHNystbfUuZkF15J+TXV9yndy/E8E4sFs4uysK9E+VM84v0q75zTf48cheE+cBGI9xOP5QMvSND6MloyGYUTPZOiQyz8M9AmJObvQFryysKf5Q1W1GBiTz9FVuSsr1IM7meljdBYwfxQaA5MurdsXVFYfdRgL6NyL5x7WOd367pgtBBwuVyT+cygg5ITIBc6YTuT8thp/q0BsJkq1OdVQrLa4PK12Tg2IOUg2Za/tLJxxiNWqs1gAmTWEIGAeJWmNgCZAjJIISwTGcdbpdWqhjAEgaaLf9ZD0hUXQ5MmSO+KXzP7lIGgqCXoMEc7W7rn3R2VkIrvaVgCBK3psTg6+CxoPQwnYbUKgPLG7ys54eECJyRfc8YPH1957Q67pYkVD166ZP/sDJfplOGH19QyFnaaSLRLoXCAfWuO72NwO/fSljN4+pmB6Ev1cRCe4mXicz7TTqGG740VOam/JW4OJCrnHVs67cs9/MsVSNZOsI+x44TKJjaFph4onaodDh5P7e52IkfRnHnjK6FjEvYPasUr9YDqUR3ucHxhD9UqvINDwhp3L/zyFb2HRuO1KzEQLzmG96xiJpJxBVl8GOTeNrK2owOf6cCuh6o3iPaAFjFok26gI1ujX/mPbBigOxB6S0cLOLoA7oA+E6L22nsoYdIwjU4b6Y/DQvndgsZFnycLsSA4TRYHUH1Q51fGU3S/zAlB66rYchsw3JqODD51axxEdo5uu/2a6K9c8BSDo+stHBPmGvty6IorhM+17IGwSVrnxBFbSICja/Mi9eHmkUuUQWaXe5iWiNGYOIe0Xsbu4PQANhDE0f4U1LboVdI46uVhBV36zLSRJ5hUYARdmaz+aUSfNSE20xwCQiqd4U1cb2W6ZRER5WOfNFa8LCjk1YyhDY1yKCbo5tZrYZtmo4T47EuH/2uyW9vPtDlAhpZWmJJ0LEbZMhl9hIEAgGYmhnxPIVItJWHgq4O+YavYWvu1qgbdBC/FZJ8xx0uSy48oKCbuTUbIBUHQ37/6wp+IC+FAoYc2CDgCKzYvYjGrjMr+l/bhWE6KqI2DE/8yG4sOZIyrKNOYRq/aqDRkaeu96bLSYZECoLpohEKRNLTFQ+J8btjGX+xak0HRNEX9bxx8Zs3ml8mDKfh11uy05zPMVU4jaLrc5VtvmNdCg1EffbtEIRhi88aP5K2flRLxvSsYODd8iisqJ3CEqa8/C/FoHhWqgs7vk9UeRs46CJjGQ2Nx7UeQhAK8ey8FwqqSPQ6hp6jFnAv5ha583GZm3G8CsapajioHOpNcyYRhUW/ekdQ1E7DafOLRRO0hdWws8fsP/96uuWJ1Ir1ec2pepmh8s9zCZl/CKSU6+PUjX03Y9buZDnAYao5nDFsF5hgi2nLCTRbHnCh/S5C4NL/Lss2gi/9HdQUWr3KNONgoGbdRNS4MHtK/t9MtxQT8FOS54fM76XLygYZhQEQuDHUr3vaihOPKXncPNx+M4IGd+tsOoGADfpZk7W4OLd5jl8OiCulKvmRXzGCrmyofifh6XBE/EDa97j4eXt/fZPhUh+kv7i39mLKiccPUqpq9WYA/pqlMc84PAsewRerk3Z7jygFb2oX8LwYX2vDer565q+74n/y+oqz/CQ7jypoGBC8f9a16h2e2ZuvjQZ2sUdBB0xKwmLHC5mXLRkJYZ8Myt0Bzp0iVnC8P,iv:0GfL3sG36nsg/4BPw32kKMB78TmbN+mLq/mqEFp0yas=,tag:x+kxJsS+Fn7VO3MlOmqgwQ==,type:str] clicknload-proxy-config: ENC[AES256_GCM,data:lGoX0iItw21nFT6n5qZRddiz9O0KGjaktXzHamSBmpE7nZv0INhIic1etwrluOnv4n4+0pn6qGeqLcEYsN3S9zDDshdYgrxmPl1xwpVUkvCIA8MGMSg1rdLByYjMOA==,iv:F0sBov54Rk8te34n70s4pPitQXjCfrKQT1+SgQO4ZZk=,tag:x50kpNEr5hYipdIknRQ99A==,type:str]
epicenter_vpn_cert: ENC[AES256_GCM,data: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,iv:MVId1jgmyhY/iUxnjca5IpYwlzUAsa6Nwchg52AKgRc=,tag:1RASj3dFAYVNphJ4zjXxtA==,type:str] epicenter_vpn_ca: ENC[AES256_GCM,data:qWq8Y2JRQIdEzVOKki8YmSMhpxFmFougQSJtGTaSgak2uP4MRzgrwpKGqDqhkPfqXeD1GSHRJNPe4plIv6//en0IEjV4vvupUrJuSp5cwmjhvbJLWWpUSQOhhDM/sN/ODDPLy+JucUoQRIt3bgrOoWRWro3cPuorGcFJfOedOy2tc7oTrpQBYNyx32kDfh3IHzuaasSFtCAnE2y5TVEXsLcMzkzvBIpTGzHUOG+9tn/nR5Ro7EodQKXfs11pL3mvr/iMlRX4QTSGYfl3pJE4O+Jssn1+/zDd0bNrSU1kKunDsuKDlv9Nkp0hIjpCzc55v74Jrda+UATB3f0muLLgULbsFA3JfaqqufLP/rgYjkFZ14qidjby55Z2+IkoH6U6et2jL1O6BcUaxYo7dbsE8kbNPdk4XPoV+5WYSOKOQrx0xXiW33fQnWq0R1x3k6YJ1oVO1CoxMLadbaAkjhoZeAP+VFviKHoX/GqMGlkox5KgdO4dUz4UcJon6F69wG/LzXf+gb1VBacqx1MltrdN+nUFNTowFor0AofUofWMM6xpn4Xy+gLy3AFQi2+3hkBmPbtgcWEWnTuekhixuPUrO8h7CwXMRgpiBBqeJTQVVoQ1puY/1Rw+K1KXY4QdRwd5laynkU4owvJtgHk1jogUIBpfAOtIq18gOznS1HhgH8s0Af0eU7lSAAPDfRoe5awydb9Wejpjed2LypMwtYE0qEC+tR0cq+NTYnINg9bcAwDz5iRSpKtGPmy8Xj320LAlH5eDyhcxQjF4ZHCtJ9/3QcpbBJoIwWlS2+R0fk4qOLq1/q4RqnP2aDc0CLd0MKx+tJs9yBZyMU8dLJtqTnd7z28odhrZ9E7PmJ/Ky2t7WsLNZF9lOWWbJ2og2Mxsu85HCmntQxjX8Jk17Eyl6jOl5NFnFEWMTPfSsaf3J5HcwffGV3RjdM/XAleHCoNP+ydM/hPra+HsFqoyMYqT/HuZPv6ZMLY1KogBy/17OdgO6Pava7kB717v6t9/eO2FH0LGKYrPUJBha8Yq7vUJFhpABO29vTJSdG6gfrRpPafgKjZig5z8BXNU+R03DiGrL9LdraFUFnu+HSF4YVXd0EGrVfQF7mw7KrH/TsAOc1KOtlHaXFkP/SgZ+etwyC48xCy1sgQi/7t2kozPtM+RcAQJMhF0DHGFQUWwj1HesHsKaOl/HdM+eU7DcMwN01is2lD1HUp63HC5OBItET374DcdqfVUBBjiOt3srd1OWuE+FkrqKpCaxLihu2dHP8SR3DYMlSIrGwy8U09Q3iIe1hD863HVOCcn3uQZHj+g1GOXpUytouUhE9EEC0THEaPNwygNQvSu9AmG+YnFaXn6ZWVokbvf4xfttSc9KUD50qK54gd7Aa32fvzsPH9O6gMtQ18wPmeCzTzVEMBFUO33BI38UKpmKB4/r5k6F53L5YOOvVsD6R5H/0ABoIjXPF8gFW2f8RkGuAH+8dOS3VdOWFvk7ZUQxa8QjMrg09n+khjZ4kPPz42W9uaRVQeXAWLhcNOBeT7U/pT23Z0M3Qfs+NK6JRXhIOj1Os77uSkLYVKuf8yfhbI+1J1/Y7WVe7/W3BkHi7SN7Unyt30QntY+FrAfbFb59aqNptkSlmDX0TbVTWxAeD7NGi/nBnZSJyE40iJ86YzqDjv2E/oS3BWRV023tfp8iljRKKD3lLinheKwaFoZE5s+h2MY1tGkO/LeZlRhxsBznouCinQoqxdxinNxCiSpP8tTxcZ1VW5W9/JxWwoRhTR/WyDVa38vVHaVMVmhCruMDCHlckHMU5qo1+5xNkDNM2kirADqIJ5CygRI+qc5CLVWqmmve/ICG5cGff3JvMTENnptNhkWIzHDemMukJpaPCF5pmH9mP6b,iv:HiTBKc+JD2NETPL4JYOfYCHjNmagZXscpWV0o1QXyfE=,tag:SM+tAq6NfBG5xDnrfqN96A==,type:str]
epicenter_vpn_key: ENC[AES256_GCM,data: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,iv:pB/cNgmHi14ugi6kd+J6poWXX79LMHiiakNa03ibZ0Q=,tag:nLfjOesXDm5/QtwHznJROw==,type:str] epicenter_vpn_cert: ENC[AES256_GCM,data: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,iv:jUlERMQxELOGGZBu9ZZ5Z3pIaNdpiV38BnSCfvkS5wg=,tag:k7I+eceH9Kuk45yHjV9EHA==,type:str]
wg_private_key: ENC[AES256_GCM,data:A80vGf9aMxowC2xME4FIVTmKpSRLNB2tWiUQeP1v8vCRk6Gt8BKYOuXYt04=,iv:vr7qvfr78syrI5pIytjLouPwZcw4xvBTvEUzzv7ibnQ=,tag:qjALlFkd8JocLJqMKFERaw==,type:str] epicenter_vpn_key: ENC[AES256_GCM,data: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,iv:IAxV9RV1hqq1Fn6e78a1Iv353mVZ1Qb/yFpzkeFtvjQ=,tag:deb0M9hJPqzsL0shaDJ1Pg==,type:str]
wg_preshared_key: ENC[AES256_GCM,data:bhXoD95ahDRawoHd5Z35FY0G6Xv0PHwWJf300fHQ5jNsGN1TQKHsIswx8YI=,iv:fBsIWkVZUt8pahuO9daaRBIEEIWsSnFW5Velj9uP2ZY=,tag:RvbCYhnRv0OrjTxjsNFW6g==,type:str] wg_private_key: ENC[AES256_GCM,data:XJ2dZINMd+gKlqdQtI9XZw7nQ5UIx0IWbYdj+HWIa4x/zERGPZy35EWcK4c=,iv:6YWnWwuHHw69S1gq4xrS3p0DXpF6lJt1lmZZ7NJ4uGU=,tag:gpgMkD/e2p7XOy7uacv1WA==,type:str]
wg-cloonar-key: ENC[AES256_GCM,data:ZMEeIZApOD0ij3nPMZeQRwJ4MwVx0sHu08F+m/u6IMHBGid5YwMgxZ7qbLk=,iv:OfIZ9TqBLjToIQi7zRUBATrynBtu0bzXeGVI/EAUPhQ=,tag:mJICT/ak5U76JE/IxJsCKw==,type:str] wg_preshared_key: ENC[AES256_GCM,data:k7NdIMYTes35HKKCpDcPCCoGo3SdO5KlwB8C2EvSAJmRM7VFOfum6TYNae8=,iv:gbYR7OTOsIaFQtchYxblHcoj7dc9D5qz+N8F4+Ru9os=,tag:FfxMVal5j1593s/HHprlYg==,type:str]
cyberghost_user_pass: ENC[AES256_GCM,data:Eaz8iEV9vNZh/bJePmacQ06zU8FfIA==,iv:GcnU10VLVJsoeIU6t6eVjopLsBamvk12DpMbM9BsBv0=,tag:rLYoghkD8O9JepnopJfiuw==,type:str] wg-cloonar-key: ENC[AES256_GCM,data:lHJdTGPA+XexVKA3JCckUkGXQm+ev2p5VhPnHpsYfRiao+rr5+N3byoBw3I=,iv:q2djx79niGelafKNl03OBPfMAcIAyPhEqsiN0UUum3k=,tag:96CU7iCd+Dd1iAKmHWcEkw==,type:str]
cyberghost_ca: ENC[AES256_GCM,data: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,iv:8uQbG4ObsDSS0DeKx24lt1vpfeSms2v7KGRQrKoWwds=,tag:2RoiW5VWLXfMgXA4cbnKBg==,type:str] cyberghost_user_pass: ENC[AES256_GCM,data:ogaoPZDUosjpoCVmiIrvSnVEcCYSUg==,iv:QS8HQbcv4t/Utv3RwVi2xS2mSvnr44z0YwaqKGHGXPk=,tag:bwh91qZDkE4N0So2dbd8iQ==,type:str]
cyberghost_cert: ENC[AES256_GCM,data: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,iv:vYJer+NYyRo/jcpGb66askFA42T+TmSfWTm3DKOIIt4=,tag:RlvqzLfvtJN0HloJZTJb1Q==,type:str] cyberghost_ca: ENC[AES256_GCM,data:hLsCa+H7RYQio6J5O+6TqWE/Ug1URHBXrgl+WNqrBYJJDNFr1ibDE57+LAdPfSWDVISjkuadfvleIzkDIe1RSlfMVN5oFoIoSDhzm3t/CZlMUjoAOU6QsutrzM6/Obfh/B70SideuBbG3IPm//6bgQ0eiiKvYmR1vyYGGyK8tFm26t3WVLdMKUde2SGRUA/Iexmcejmy1lXm+320vA9YD1BfMeOqtRJMAnrvyNPMKkWNV2hK6E+BXxiWCQK12k1RBw1Y7Y2uLfdImAWHzM4S9XZpy/Jqdi3EcSjKIA7IRXjtQQ/aaeU7JkMlbfHCOs+NElcJWlwtvsgfloMCvvljFtzALPSPbqRkpD6VqiknDvS1bWBW/8Tzz16Z+DP0UPnlSJOiiqEbuhmC8a0v5DilH/MZroKHqIzySwtG80JvHDiAFsN+OborWITefaHCl/oaOjDwM6jT6O61GbqJbwUgiCVKRcCv0gKuDrl1n05XEejCAyTE8z6y5Oo6ULd3unBvr3tn7GO6nVzFWzGSb7WY5Hw8pY1/1uJP9xufkkhY/YdYvoi1xdE2P2x1CEF6c7jgEFB0K/T2I4BfxPGLve9Rn6O7jZQEALHxj0B+JR8EBf7frK4WweyBOLz2pXLctA0OM9kpdutzfzS5tODgsC66/FZsHVyuY8VWnv368V6vXPhJOFZDMeLawXrv2BjMRHiHxI9Q4fWPutoF/4l6LVLBV/Ci8QU+gJvVZuzAcBSYSJXL40GcKQnRG7U2WWgF5ChAUSdSDUMd/NXQU0YhqHoxOmXTwM//tHVv2fo8xy+x++zKW+91H3VxVWa8nBVdI1c7d/uifHhjf0fTUyTXdbVmEo+EM7P13Pt6vnr9RmnWA1ZPo7KBe3m0+OUslwL+TK2wrCP3TaxhRy6xcpZdNZUnLeByIn+ck6PJOVfl3bObOIcmrzx+KbX0D6IYAlMF4P90B+miYe2cw2XFDmtaLDzc2U9JyxtmsfW+TzQqSFgrQyGiIEUZ78l0DrIcCIhaZv374ItMpW4vExpYsZbjk6+Ard0ZhkKuV4bOWwh0kpa3cZ+1sKi/6fd1ChkrbjNryLCRDU+ByrxRq3RaKhffG/tiJ8d6XESkMHODy6CwFTEDsxCbVfguwKiu91cWm/2P8fc5d1PjrKcljboSGgs9CX8c7MzWsGiNzCMJSFUMqB+kdH8W3Wz8lZzmvxSQ9n/5SIbvEz8gmEBxcwCW7imLegigwySVyEKO/NVi6HwETKXSAG5rZQgLtzRkiLLJWAL6PluoDXOlH2y/TLrmYINncYe2+36z1mFxnNqNVMLLIvkPihP+fA2P2CU7BFMzZ+GP36B4QuoDvW/o9YKLHQvQqOeVWbEBXSmp3ve5iisWS2CxiCICIXTrRgeg8jjMpVppuHIdIFgar6S3/T/0Lz2BlVacA78n/NG9dy4IDtlfKFYw3MOH5J0p5xd9bOx0TcZlzrPEcIwnw3lDms3DWiFLdeX6eOrXTM7F3UTYqIDUVjKTfI/YCZPupTOXkmPcuMcPiyrsAg58IsREN6KEsbhXuUD49J5oJWhrr2UPkxLwb87jiELIvWr2XIWBvsdwTfs/J5jh1hYJ8Pis52inxcJdmyxsoBH8W16xMj6EfG24HUpGc42H4puAkCVkKsrF/k4RAZXsSwWT+zkOnoNyIgnwAURICZl6LlR9Bfw5veXqSztQLzc/GsJnQEQYap3cxNxO39oGUunYWYZYqUI9tIotNr7VLr8Y02cu77xRGk9e8EzSX6IS3KF/9p4PRao2Jr/ZPHPl/pCtb1yy6g72kV8ymLTtWlHV4pvZSl6W4AMPo/c6V3s1Rh83+04H5qjFX8mSV6ePTdrojfq/QUjaUAbrhYzKWVW9a8TfA/BakoywEnNaUzItfs+X0RWrTIqoGeHaDO7kst1DDi/0fTZSCwIEPOMGSaPI668/0mgCZ1Dp4joAM9TZPDJVeFLySaD606PXTR2NHO0FoAwN6+dNo7L8ZSuyPVfbQi4DfHNQt5rFlHsTP9Iotw40632XmrHnz2xmTH5gqFm+FeV2s0ZDVvDigz7b7OXGtJ1m85qBP1vfTaEoF2jrpA6OJbBWxa/oEET5uC7al2gSFkTHqcUlP1UMzC0WlqddH1Bm8Jsk6rIlVyrx6SQgZ86lOoS65U65oZJbaLB3LtJFsIlHEBCokqwUugvvNYcw22II85cql6A4n1U7nfdmNwy0+iAreKg7ZuPJcSLhLT5uc1VRm2pyLN2WF0RPSeg3T0kPKyGuVE6/9+EKFOLzCJ/ECI828saUJslcOInOUSBUG7PFvqpEkChcajPTtllIgtUVode7dezTXkuyhv2SdfImwV7SXI2Q5j35ApXYg6dmS1ny4u1Z667qoeWuecTH0cTSun74zCa/GrT27JB4MhPHXk6CCmZpiupTcHLyylfwtP09f8MRwpE7k67+6pBQpKCRwDFJAtgSQlP4nklqNUGSQxMqwSQUg3EzwiVqk246vGimlYELBn+riO2pzFj/I/49thuHtmAe/1mXq3rjUYEg/NFKZrcJWIlwd9rP/XYr0FbAX5V7GeYoYk3pOKQWusUiWWmtkRaE0YKYemwOyMCu0L2Omi6mFNF9bQoTrfQ3WID8PDHMyzPlWYViUnq/iB1scox9fMRZLmnu8O3318YOMR9O4/ipDYkgrClX1T0qu4m8u2ETQ7OSh2G2OeYOpUby47MG0VTHSXNYV0ey3rJVa42Crs0ixRWHdBJxHk3JxJ8mlR4voOECPl6Ydge9cXfaP9S5m9CXslSPdRt5azXihhAJGHnCYaHNVutecbVVe7EoI4+zi+blr1KxTrAHX84a9Jz9jpDL6OJJorwEgSYqzJP+EG/Vx9EU0787JSr/axF5NQVcaR+rMZqlh+S+cwt6waaYf9k5trdSrsHh0N5uTOzUjHOIDloDTGqgzwbHIx2XYw0tmHsNq+qUTRCnHmxaLhURyrTbFd7ygj7VWiFNpbDhKJOP1PJ8zxrBSdKfzE2AElc=,iv:n1d++hy58nH4kZHEyXrELMCdQ3botkc3tHUA/Czm6iw=,tag:Fcd9qGgOwqQ5uZGbbObhLg==,type:str]
cyberghost_key: ENC[AES256_GCM,data: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,iv:EgSXZvyWmcBxBkAe6asJ2B12FKaLQPy4tRAtCvkys3M=,tag:B0lyX7IRNHX1CqlvBZaSpg==,type:str] cyberghost_cert: ENC[AES256_GCM,data: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,iv:YokQRmSP1F43BhS51wOry5iiQa3f78Rvs50STxeyphY=,tag:k+ZxxVSmurIr2PiJJIoFjQ==,type:str]
openai_api_key: ENC[AES256_GCM,data:lH5Jf/xvtRRwuGYPM3g39J5DTQJowSKVqLtObgXRo+GOfpY/BKb46/R25rkWrOUv5pYK8PXmSm7obEkVBfoaYG0WufR6SzGH+R7hjrNgCzBA6g5pxmlE7CWPlPy6C6XqVgblL8aP2vD9qxJmIw8FYCLRgFHt5hK4d+Gd23BeBnkmPWIH23xyRFhCcb891CoiEEdXL5p1LNAOAW5ePmAyavc/Dlk=,iv:lWXy8/LlWeRVSect87/qsG2nOkmL5W7jpw/DVSnAbEs=,tag:n3pWUJ5uEMXtgt/kHG8J8w==,type:str] cyberghost_key: ENC[AES256_GCM,data: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,iv:LPskqYo7V7SMKD8HdEXDNwxyiLFLaLr5AdrU5x53R4Q=,tag:zhEYACY4xhl0ba+dBUBT1A==,type:str]
mcp-brave-env: ENC[AES256_GCM,data:FND006AIjGjSkJqx12RVd8NnyDIhqdUBgZxucaAOFlnt7ZRYAHj4xQqgSJuFxg==,iv:Fn/663cGELKYQWg+Ok1uCtNCeIP7zZBJgxhhcsR/Q8M=,tag:v8K6JQ15CYwcLj7vSjyN6g==,type:str] openai_api_key: ENC[AES256_GCM,data:Z5AiYIRQoFSmjErwgJ7mxkxmp5BVOgVy72xwag+PJeRiQAddgNMeeqOh1ka0nP/HLPnbbWgSBgzdXxD+Kx4m6dX3W2AtzO0QE68XDyuM+PKts2pUSDYDmFSWZ7FFlQSQrpuHgnit1xjorpQqRjgVkHXgNObYGvs1wUZwhfUg4zPd9UdTU7daXcUdJ1c9t5G6FuJLMNF3gmqr6j7hMYXPcCGrx18=,iv:SMy/19Jw1CX9OYEQ3VABisZ61fYyVVbGzgeIwlqdtRs=,tag:oakwiviNCiu5jWIwuAQP6Q==,type:str]
rustdesk-cloonar-key: ENC[AES256_GCM,data:nn1PKpOvhs3E1Lqtbx+W3oWon8+j74CrB4KuB+BqjfaHAaKdj+KMstYAv+0=,iv:UGjTZ9LauAALRMvJnqKkHYqGH6rjZMTZPQs0O7/aDd0=,tag:g6IZMCsE1dqZh3QYRuitzw==,type:str] mcp-brave-env: ENC[AES256_GCM,data:JAMYqb9rOYDLM8y8HABGQIvEGZUUKWt/iRJXwLZ/UftHd5iMPLDAHDcRva1MpQ==,iv:wFWJr74H6nX2nOaCUWHdeQkjBDYTEltxE84BTQfqy7I=,tag:cAj9Cjjo9WBVot2rklRWZQ==,type:str]
rustdesk-cloonar-key: ENC[AES256_GCM,data:genBO0paccI1pcH8//X8q+88yBeBFfgEd8jKmglEHbvnf2f9DDxfWVrHlX8=,iv:FEHkJ2wPBAKZFhoRRBbLzjkv28DRDJ4npBkTGVEK6l4=,tag:hx9FPzlyDf96BuMhrEXLEQ==,type:str]
sops: sops:
age: age:
- recipient: age14grjcxaq4h55yfnjxvnqhtswxhj9sfdcvyas4lwvpa8py27pjy2sv3g6v7 - recipient: age14grjcxaq4h55yfnjxvnqhtswxhj9sfdcvyas4lwvpa8py27pjy2sv3g6v7
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYYWRBbk1wckFYbkZxQllS YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSByeDBlZ00wSDkxaVc1K3Qr
T09LUEljM0VKbUw2cW5hLys1OUZZdFBBSXlnClRvc3YyRFpaQW9GOTVjR1dpdU1Q aGt2YXlHdXJ5UXNhM3R4dnRQT2ZiNGdvcmtNCmxmdDZYQWt6NktVdGNwQjlUOEZG
TWVsYmwyZ3Nxb29HZVdTSXhmV3F2MWMKLS0tIGNZM0cyWmRiMUNFUkhVUkJhUjRR My9mUHFBT3lWOFc0N0JNcWh2dm00a0kKLS0tIFhud215VVA1SWVFdVZDZHZjY3ZK
SHpCTVR6VW9pdzFTMDBtWkxxY2VIWmMKrReAwG9+6W/R1AoUr8JFw2QQ9WZ+e+Pn ektUZVQ0aTVKRUFnQWUyUUtzYUs5QkUKkLJ2e2+a3VYcVepB2QIrD4Dsv/Vw0WiV
wuTlcKayDrNHuM1ldW6BEYQAV+8Z4Nhbj1ygo+2tqOsXm2YL6uzlBA== ZXqudx8UqY4xbsYaWehEVrIBIaQ/cLqVP+0YKaS6CFvIWHhP+lu/2Q==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1exny8unxynaw03yu8ppahu5z28uermghr8ag34e7kdqnaduq9stsyettzz - recipient: age1exny8unxynaw03yu8ppahu5z28uermghr8ag34e7kdqnaduq9stsyettzz
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCYk9zVTZUUUl3YWJobFNu YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4R1I0RjBxUWdrelAwY1Nt
bndaSGJyTWdoOWxUZHZYVDNMTjdkQVdyaFY4ClFEUjZuaTJRdVdlcEU5UFIzbmlC Qjk2UXRqVS91MHhDY0xFaVR4THFLVXM2MGhJCmNaeHhwQ0I4bGNsMi9ySi9YMkg1
OE44MFhLOGh4ZkJmeFl1QlNCM05kYVkKLS0tIFNCWnJhMFJ3MG1hKzZVRXlpODl5 NWVrb0pKN0FaZ3QxUkJSSDd0VWQ4M2MKLS0tIHIwYnEvYVhONDhGazZ2ekJ3TnVx
R1dpWnZKNHR4RERSdm5OclI1SncvYkUKBDZKeh6xlTn3tRnZOCD6oe2uFP1NeQe9 WE44dU43QmxPTncycHVGNHNlTG83MU0KQPJWz3YF8RXwxp8SUFRuo39NN/2tSzw2
b7JuigPRPnhah0rWZ6jPjnk38Jp6z/I1Oqh5UJ94H4KNi/h3HKqMSw== bMuv5JWSI8i3TNiWmOELF/Lt34Z4p5yZZ7OA8mfx1bbTsZOJ35I0LA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1v6p8dan2t3w9h94fz4flldl32082j3s9x6zqq7u5j66keth9aphsd6pvch - recipient: age1v6p8dan2t3w9h94fz4flldl32082j3s9x6zqq7u5j66keth9aphsd6pvch
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPTkdSM3hoTWdlcE9McDFt YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJcUFXVi8yOTBWWVhLbjZ4
engvOU5hZUtKaVZjUEFnT0huNWpMWnBjUFZnClZxZ1JrMThrT2kyejFkUnlUVUhU VU9YazRzWW8zTmNzalArcVNtQXpLdVJ0U2kwCnY0ci9nSE5qZTZpSk93MlNpR2pp
bVhTNUovM0ZRZVRRemRsNml2RXcrNk0KLS0tIDZWYWJUTHlXWUFMcE82YlZBby9E WGVENTdWbHUrdTN0K1ZHaTZEUkdpemcKLS0tIFhseFdlL3BpZHFQbE0rNlo3c1dO
clM4RXI2V1pIRVZNeWdaM24xZlFJSjQKY1+Nw3X0FynI6BhhLE5caUpDENqa6S6d SmtzUnk3V0pCakpXcmhvZWVTWURKK3MKuB/3RDvEZh1o7WHmJHFh5njBdjICO34G
HMRhiL7SIZQrmkdIeCSikjRCkvqBFIgn7sff3S+7neYxgGkFp1nzGg== o8KdfkLcAwTnSbOy0mEVLhQjLayhRq/ifMWwJfN4/MUZo1cSBwO+iQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-06-05T16:28:03Z" lastmodified: "2025-12-07T23:35:10Z"
mac: ENC[AES256_GCM,data:NNYwveO78Q4cWOPPt3Pyqh6AtbfRj/ax6D4t2KlVXWSLzKTUZKKaULXGY5PBp/jI2pyhPp5yEMhEyjRPWC8Xhvxjv+NLb6KltgaMfzIBS/jfSNk3dcYx6i8Y2oSG1efLJrRMc2Q/uACeztyivtjV9A7JCrEtb84Wb9HzkI4nZVs=,iv:Q8cTw+/RMJ3WHrkB9lyaAyI2K3O1ZhDnAMUYMJ4JMRk=,tag:JvrLiaKKYXiOmud4oZZZ1w==,type:str] mac: ENC[AES256_GCM,data:5tRkzTUeiKf3WQBFJZBBCa3vnPGVLspbCF/bf+rQEGuQ0ehA5uZXLlc3nBlC3fBqQh3JQUyVw1xcqYJc8Ziu1a5pcG28Mdls6IWr8JOzh+h2fAgqWbn9UGqEU9fNJE0aSzHSptpKA5fqgJYqmb3voz8tFn3jMNrPsGenHFn20C0=,iv:s6lOchFabWnyW2gkoYaXBhOkJyhhXyh2ZbnFTwj83bs=,tag:HosULSsgllcEzoBifQLYSA==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.10.2 version: 3.11.0

View File

@@ -1,6 +1,6 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
let let
home-manager = builtins.fetchTarball "https://github.com/nix-community/home-manager/archive/release-24.11.tar.gz"; home-manager = builtins.fetchTarball "https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz";
in in

View File

@@ -7,6 +7,8 @@ let
config = { allowUnfree = true; }; config = { allowUnfree = true; };
}; };
clicknload-proxy = pkgs.callPackage ../utils/pkgs/clicknload-proxy {};
thunderbirdSettings = { thunderbirdSettings = {
"extensions.activeThemeID" = "thunderbird-compact-dark@mozilla.org"; "extensions.activeThemeID" = "thunderbird-compact-dark@mozilla.org";
"browser.theme.content-theme" = 0; "browser.theme.content-theme" = 0;
@@ -135,11 +137,11 @@ let
{ name = "q"; value = "{searchTerms}"; } { name = "q"; value = "{searchTerms}"; }
]; ];
}]; }];
iconUpdateURL = "https://perplexity.ai/favicon.ico"; icon = "https://perplexity.ai/favicon.ico";
definedAliases = [ "@perplexity" ]; definedAliases = [ "@perplexity" ];
}; };
"Google".metaData.hidden = true; "google".metaData.hidden = true;
"Bing".metaData.hidden = true; "bing".metaData.hidden = true;
}; };
}; };
@@ -160,6 +162,9 @@ in
sops.secrets.openai_api_key = { sops.secrets.openai_api_key = {
owner = "dominik"; owner = "dominik";
}; };
sops.secrets.clicknload-proxy-config = {
owner = "dominik";
};
programs.fuse.userAllowOther = true; programs.fuse.userAllowOther = true;
programs.zsh = { programs.zsh = {
@@ -228,9 +233,9 @@ in
Restart = "always"; Restart = "always";
}; };
}; };
pyload-tunnel = { clicknload-proxy = {
Unit = { Unit = {
Description = "SSH tunnel for pyLoad Click'n'Load"; Description = "Click'n'Load proxy for pyLoad";
After = [ "graphical-session-pre.target" ]; After = [ "graphical-session-pre.target" ];
PartOf = [ "graphical-session.target" ]; PartOf = [ "graphical-session.target" ];
}; };
@@ -238,7 +243,7 @@ in
WantedBy = [ "graphical-session.target" ]; WantedBy = [ "graphical-session.target" ];
}; };
Service = { Service = {
ExecStart = "${pkgs.openssh}/bin/ssh -N -L 9666:10.42.97.11:9666 -o ServerAliveInterval=60 -o ServerAliveCountMax=3 root@fw.cloonar.com"; ExecStart = "${clicknload-proxy}/bin/clicknload-proxy --config ${config.sops.secrets.clicknload-proxy-config.path}";
Restart = "always"; Restart = "always";
RestartSec = "10s"; RestartSec = "10s";
}; };
@@ -301,26 +306,23 @@ in
programs.git = { programs.git = {
enable = true; enable = true;
lfs.enable = true; lfs.enable = true;
package = pkgs.gitAndTools.gitFull; package = pkgs.gitFull;
userName = "Dominik Polakovics";
userEmail = "dominik.polakovics@cloonar.com";
# signing = { # signing = {
# key = "dominik.polakovics@cloonar.com"; # key = "dominik.polakovics@cloonar.com";
# signByDefault = false; # signByDefault = false;
# }; # };
iniContent = { settings = {
user.name = "Dominik Polakovics";
user.email = "dominik.polakovics@cloonar.com";
# Branch with most recent change comes first # Branch with most recent change comes first
branch.sort = "-committerdate"; branch.sort = "-committerdate";
# Remember and auto-resolve merge conflicts # Remember and auto-resolve merge conflicts
# https://git-scm.com/book/en/v2/Git-Tools-Rerere # https://git-scm.com/book/en/v2/Git-Tools-Rerere
rerere.enabled = true; rerere.enabled = true;
}; "url \"gitea@git.cloonar.com:\"" = {
extraConfig = {
"url.gitea@git.cloonar.com:" = {
insteadOf = "https://git.cloonar.com/"; insteadOf = "https://git.cloonar.com/";
}; };
}; };
}; };
programs.thunderbird = { programs.thunderbird = {
@@ -525,7 +527,7 @@ in
settings = firefoxSettings; settings = firefoxSettings;
# userChrome = firefoxUserChrome; # userChrome = firefoxUserChrome;
search = firefoxSearchSettings; search = firefoxSearchSettings;
extensions = firefoxExtensions; extensions.packages = firefoxExtensions;
}; };
social = { social = {
id = 1; id = 1;
@@ -560,7 +562,7 @@ in
id = 3; id = 3;
}; };
}; };
extensions = firefoxExtensions; extensions.packages = firefoxExtensions;
}; };
}; };
}; };

View File

@@ -1 +1 @@
https://channels.nixos.org/nixos-25.05 https://channels.nixos.org/nixos-25.11

View File

@@ -63,7 +63,7 @@
time.timeZone = "Europe/Vienna"; time.timeZone = "Europe/Vienna";
services.logind.extraConfig = "RuntimeDirectorySize=2G"; services.logind.settings.Login.RuntimeDirectorySize = "2G";
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sops.defaultSopsFile = ./secrets.yaml; sops.defaultSopsFile = ./secrets.yaml;

View File

@@ -15,7 +15,7 @@
datasourceUid = "vm-datasource-uid"; datasourceUid = "vm-datasource-uid";
model = { model = {
editorMode = "code"; editorMode = "code";
expr = "node_systemd_unit_state{state=\"active\", name=\"dovecot2.service\"} OR on() vector(0)"; expr = "node_systemd_unit_state{state=\"active\", name=\"dovecot.service\"} OR on() vector(0)";
hide = false; hide = false;
intervalMs = 1000; intervalMs = 1000;
legendFormat = "__auto"; legendFormat = "__auto";

View File

@@ -0,0 +1,17 @@
{ lib, pkgs, ... }:
let
smartDashboard = import ./smart-dashboard.nix { inherit lib pkgs; };
dashboardDir = pkgs.linkFarm "grafana-dashboards" [
{ name = "smart.json"; path = smartDashboard; }
];
in
{
services.grafana.provision.dashboards.settings = {
apiVersion = 1;
providers = [{
name = "nix-dashboards";
type = "file";
options.path = dashboardDir;
}];
};
}

View File

@@ -0,0 +1,463 @@
{ lib, pkgs }:
let
datasourceUid = "vm-datasource-uid";
# Helper to create a panel with common defaults
mkPanel = { id, title, type, gridPos, targets, options ? { }, fieldConfig ? { }, ... }@args:
{
inherit id title type gridPos targets;
datasource = { uid = datasourceUid; type = "prometheus"; };
options = options;
fieldConfig = {
defaults = fieldConfig.defaults or { };
overrides = fieldConfig.overrides or [ ];
};
} // (builtins.removeAttrs args [ "id" "title" "type" "gridPos" "targets" "options" "fieldConfig" ]);
# Dashboard definition
dashboard = {
uid = "smart-disk-health";
title = "S.M.A.R.T Disk Health";
description = "S.M.A.R.T metrics and RAID array status";
tags = [ "disk" "smart" "storage" "nas" ];
timezone = "browser";
editable = false;
refresh = "5m";
schemaVersion = 39;
version = 1;
# Variables
templating.list = [
{
name = "host";
label = "Host";
type = "query";
datasource = { uid = datasourceUid; type = "prometheus"; };
query = "label_values(smart_health_passed, instance)";
regex = "";
sort = 1;
refresh = 1;
includeAll = true;
multi = false;
current = { selected = true; text = "All"; value = "$__all"; };
}
];
# Panels
panels = [
# === OVERVIEW ROW ===
{
id = 1;
type = "row";
title = "Overview";
collapsed = false;
gridPos = { x = 0; y = 0; w = 24; h = 1; };
panels = [ ];
}
# Alert Status - Shows firing disk alerts
{
id = 5;
title = "Alert Status";
type = "alertlist";
gridPos = { x = 0; y = 1; w = 6; h = 5; };
options = {
alertInstanceLabelFilter = "";
alertName = "Disk";
dashboardAlerts = false;
groupBy = [ ];
groupMode = "default";
maxItems = 20;
sortOrder = 1;
stateFilter = {
"error" = true;
firing = true;
noData = false;
normal = false;
pending = false;
};
viewMode = "list";
};
}
# Health Status - Stat panel
(mkPanel {
id = 2;
title = "Disk Health Status";
type = "stat";
gridPos = { x = 6; y = 1; w = 6; h = 5; };
targets = [{
expr = ''smart_health_passed{instance=~"$host"}'';
legendFormat = "{{device}}";
refId = "A";
}];
options = {
reduceOptions = { values = false; calcs = [ "lastNotNull" ]; fields = ""; };
orientation = "horizontal";
textMode = "auto";
colorMode = "background";
graphMode = "none";
};
fieldConfig = {
defaults = {
mappings = [
{ type = "value"; options."1" = { text = "PASSED"; color = "green"; index = 0; }; }
{ type = "value"; options."0" = { text = "FAILED"; color = "red"; index = 1; }; }
];
thresholds = {
mode = "absolute";
steps = [
{ color = "red"; value = null; }
{ color = "green"; value = 1; }
];
};
};
};
})
# Temperature Gauge
(mkPanel {
id = 3;
title = "Disk Temperatures";
type = "gauge";
gridPos = { x = 12; y = 1; w = 6; h = 8; };
targets = [{
expr = ''smart_temperature_celsius{instance=~"$host"}'';
legendFormat = "{{device}}";
refId = "A";
}];
options = {
reduceOptions = { values = false; calcs = [ "lastNotNull" ]; fields = ""; };
orientation = "auto";
showThresholdLabels = false;
showThresholdMarkers = true;
};
fieldConfig = {
defaults = {
unit = "celsius";
min = 0;
max = 70;
thresholds = {
mode = "absolute";
steps = [
{ color = "green"; value = null; }
{ color = "yellow"; value = 45; }
{ color = "red"; value = 55; }
];
};
};
};
})
# RAID Status - Stat panel
(mkPanel {
id = 4;
title = "RAID Array Status";
type = "stat";
gridPos = { x = 18; y = 1; w = 6; h = 8; };
targets = [{
expr = ''mdadm_array_state{instance=~"$host"}'';
legendFormat = "{{array}}";
refId = "A";
}];
options = {
reduceOptions = { values = false; calcs = [ "lastNotNull" ]; fields = ""; };
orientation = "horizontal";
textMode = "auto";
colorMode = "background";
graphMode = "none";
};
fieldConfig = {
defaults = {
mappings = [
{ type = "value"; options."1" = { text = "Healthy"; color = "green"; index = 0; }; }
{ type = "value"; options."0" = { text = "Degraded"; color = "red"; index = 1; }; }
];
thresholds = {
mode = "absolute";
steps = [
{ color = "red"; value = null; }
{ color = "green"; value = 1; }
];
};
};
};
})
# Sector Health Table - Promoted to overview for visibility
(mkPanel {
id = 13;
title = "Sector Health";
type = "table";
gridPos = { x = 0; y = 6; w = 12; h = 4; };
targets = [
{
expr = ''smart_reallocated_sector_ct{instance=~"$host"}'';
legendFormat = "{{device}}";
refId = "A";
format = "table";
instant = true;
}
{
expr = ''smart_current_pending_sector{instance=~"$host"}'';
legendFormat = "{{device}}";
refId = "B";
format = "table";
instant = true;
}
{
expr = ''smart_offline_uncorrectable{instance=~"$host"}'';
legendFormat = "{{device}}";
refId = "C";
format = "table";
instant = true;
}
];
options = {
showHeader = true;
cellHeight = "sm";
};
transformations = [
{ id = "merge"; options = { }; }
{
id = "organize";
options = {
excludeByName = { Time = true; __name__ = true; instance = true; job = true; serial = true; };
renameByName = {
device = "Device";
"Value #A" = "Reallocated Sectors";
"Value #B" = "Pending Sectors";
"Value #C" = "Offline Uncorrectable";
};
};
}
];
fieldConfig = {
defaults = {
thresholds = {
mode = "absolute";
steps = [
{ color = "green"; value = null; }
{ color = "yellow"; value = 1; }
{ color = "red"; value = 10; }
];
};
custom = { displayMode = "color-background-solid"; };
};
};
})
# === DETAILED METRICS ROW ===
{
id = 10;
type = "row";
title = "Detailed Metrics";
collapsed = false;
gridPos = { x = 0; y = 10; w = 24; h = 1; };
panels = [ ];
}
# Temperature Time Series
(mkPanel {
id = 11;
title = "Temperature Over Time";
type = "timeseries";
gridPos = { x = 0; y = 11; w = 12; h = 8; };
targets = [{
expr = ''smart_temperature_celsius{instance=~"$host"}'';
legendFormat = "{{device}}";
refId = "A";
}];
options = {
legend = { displayMode = "list"; placement = "bottom"; showLegend = true; };
tooltip = { mode = "multi"; sort = "desc"; };
};
fieldConfig = {
defaults = {
unit = "celsius";
custom = {
drawStyle = "line";
lineInterpolation = "smooth";
fillOpacity = 10;
pointSize = 5;
showPoints = "auto";
};
thresholds = {
mode = "absolute";
steps = [
{ color = "green"; value = null; }
{ color = "yellow"; value = 45; }
{ color = "red"; value = 55; }
];
};
};
};
})
# Power On Hours
(mkPanel {
id = 12;
title = "Power On Hours";
type = "stat";
gridPos = { x = 12; y = 11; w = 12; h = 8; };
targets = [{
expr = ''smart_power_on_hours{instance=~"$host"}'';
legendFormat = "{{device}}";
refId = "A";
}];
options = {
reduceOptions = { values = false; calcs = [ "lastNotNull" ]; fields = ""; };
orientation = "horizontal";
textMode = "value_and_name";
colorMode = "none";
graphMode = "none";
};
fieldConfig = {
defaults = {
unit = "h";
};
};
})
# === RAID DETAILS ROW ===
{
id = 20;
type = "row";
title = "RAID Details";
collapsed = false;
gridPos = { x = 0; y = 19; w = 24; h = 1; };
panels = [ ];
}
# RAID Devices
(mkPanel {
id = 21;
title = "RAID Array Devices";
type = "stat";
gridPos = { x = 0; y = 20; w = 12; h = 4; };
targets = [
{
expr = ''mdadm_array_devices_active{instance=~"$host"}'';
legendFormat = "{{array}} Active";
refId = "A";
}
{
expr = ''mdadm_array_devices_total{instance=~"$host"}'';
legendFormat = "{{array}} Total";
refId = "B";
}
];
options = {
reduceOptions = { values = false; calcs = [ "lastNotNull" ]; fields = ""; };
orientation = "horizontal";
textMode = "value_and_name";
colorMode = "value";
graphMode = "none";
};
fieldConfig = {
defaults = {
unit = "short";
};
};
})
# UDMA CRC Errors
(mkPanel {
id = 22;
title = "UDMA CRC Errors";
type = "timeseries";
gridPos = { x = 12; y = 20; w = 12; h = 4; };
targets = [{
expr = ''smart_udma_crc_error_count{instance=~"$host"}'';
legendFormat = "{{device}}";
refId = "A";
}];
options = {
legend = { displayMode = "list"; placement = "bottom"; showLegend = true; };
tooltip = { mode = "multi"; sort = "desc"; };
};
fieldConfig = {
defaults = {
unit = "short";
custom = {
drawStyle = "line";
lineInterpolation = "stepAfter";
fillOpacity = 0;
pointSize = 5;
showPoints = "auto";
};
};
};
})
# Last Update Timestamp
(mkPanel {
id = 30;
title = "Last Metrics Update";
type = "stat";
gridPos = { x = 0; y = 24; w = 6; h = 5; };
targets = [{
expr = ''time() - disk_metrics_last_update{instance=~"$host"}'';
legendFormat = "Age";
refId = "A";
}];
options = {
reduceOptions = { values = false; calcs = [ "lastNotNull" ]; fields = ""; };
orientation = "horizontal";
textMode = "value";
colorMode = "value";
graphMode = "none";
};
fieldConfig = {
defaults = {
unit = "s";
thresholds = {
mode = "absolute";
steps = [
{ color = "green"; value = null; }
{ color = "yellow"; value = 1800; }
{ color = "red"; value = 3600; }
];
};
};
};
})
# Device Activity Status
(mkPanel {
id = 31;
title = "Device Activity";
type = "stat";
gridPos = { x = 6; y = 24; w = 18; h = 5; };
targets = [{
expr = ''smart_device_active{instance=~"$host"}'';
legendFormat = "{{device}}";
refId = "A";
}];
options = {
reduceOptions = { values = false; calcs = [ "lastNotNull" ]; fields = ""; };
orientation = "horizontal";
textMode = "auto";
colorMode = "background";
graphMode = "none";
};
fieldConfig = {
defaults = {
mappings = [
{ type = "value"; options."1" = { text = "Active"; color = "green"; index = 0; }; }
{ type = "value"; options."0" = { text = "Standby"; color = "blue"; index = 1; }; }
];
thresholds = {
mode = "absolute";
steps = [
{ color = "blue"; value = null; }
{ color = "green"; value = 1; }
];
};
};
};
})
];
};
in
pkgs.writeText "smart-dashboard.json" (builtins.toJSON dashboard)

View File

@@ -36,6 +36,8 @@ in
./datasources/victoriametrics.nix ./datasources/victoriametrics.nix
./datasources/loki.nix ./datasources/loki.nix
./dashboards/default.nix
./alert-cleanup.nix ./alert-cleanup.nix
]; ];

View File

@@ -17,7 +17,7 @@ buildGoModule rec {
subPackages = [ "." ]; subPackages = [ "." ];
# Optional tuning # Optional tuning
CGO_ENABLED = 0; env.CGO_ENABLED = "0";
ldflags = [ "-s" "-w" ]; ldflags = [ "-s" "-w" ];
doCheck = false; doCheck = false;

View File

@@ -19,9 +19,9 @@ fi
HOSTNAME="$1" HOSTNAME="$1"
# Check if 'nixos-rebuild' command is available # Check if 'nix-instantiate' command is available
if ! command -v nixos-rebuild > /dev/null; then if ! command -v nix-instantiate > /dev/null; then
echo "ERROR: 'nixos-rebuild' command not found. Please ensure it is installed and in your PATH." >&2 echo "ERROR: 'nix-instantiate' command not found. Please ensure Nix is installed and in your PATH." >&2
exit 1 exit 1
fi fi
@@ -38,27 +38,42 @@ if [ ! -f "$CONFIG_PATH" ]; then
exit 1 exit 1
fi fi
# Check for host-specific channel file
CHANNEL_PATH="$SCRIPT_DIR/../hosts/$HOSTNAME/channel"
CHANNEL_OPT=""
if [ -f "$CHANNEL_PATH" ]; then
CHANNEL_URL=$(cat "$CHANNEL_PATH")
# Append /nixexprs.tar.xz to get the actual tarball URL
TARBALL_URL="${CHANNEL_URL}/nixexprs.tar.xz"
echo "INFO: Using channel '$TARBALL_URL' from '$CHANNEL_PATH'."
CHANNEL_OPT="-I nixpkgs=$TARBALL_URL"
else
echo "WARNING: No channel file found at '$CHANNEL_PATH'. Using system default." >&2
fi
echo "INFO: Attempting dry-build for host '$HOSTNAME' using configuration '$CONFIG_PATH'..." echo "INFO: Attempting dry-build for host '$HOSTNAME' using configuration '$CONFIG_PATH'..."
if [ "$VERBOSE" = true ]; then if [ "$VERBOSE" = true ]; then
echo "INFO: Verbose mode enabled, --show-trace will be used." echo "INFO: Verbose mode enabled, --show-trace will be used."
fi fi
# Execute nixos-rebuild dry-build # Execute nix-instantiate to evaluate the configuration
# Store the output and error streams, and the exit code # nix-instantiate fetches fresh tarballs and catches all evaluation errors
NIX_OUTPUT_ERR=$(nixos-rebuild dry-build $SHOW_TRACE_OPT -I nixos-config="$CONFIG_PATH" --show-trace 2>&1) # unlike nixos-rebuild which may use cached results
NIX_OUTPUT_ERR=$(nix-instantiate $SHOW_TRACE_OPT $CHANNEL_OPT -I nixos-config="$CONFIG_PATH" '<nixpkgs/nixos>' -A system 2>&1)
NIX_EXIT_STATUS=$? NIX_EXIT_STATUS=$?
# Check the exit status # Check the exit status
if [ "$NIX_EXIT_STATUS" -eq 0 ]; then if [ "$NIX_EXIT_STATUS" -eq 0 ]; then
echo "INFO: Dry-build for host '$HOSTNAME' completed successfully." echo "INFO: Dry-build for host '$HOSTNAME' completed successfully."
if [ "$VERBOSE" = true ]; then if [ "$VERBOSE" = true ]; then
echo "Output from nixos-rebuild:" echo "Output from nix-instantiate:"
echo "$NIX_OUTPUT_ERR" echo "$NIX_OUTPUT_ERR"
fi fi
exit 0 exit 0
else else
echo "ERROR: Dry-build for host '$HOSTNAME' failed. 'nixos-rebuild' exited with status $NIX_EXIT_STATUS." >&2 echo "ERROR: Dry-build for host '$HOSTNAME' failed. 'nix-instantiate' exited with status $NIX_EXIT_STATUS." >&2
echo "Output from nixos-rebuild:" >&2 echo "Output from nix-instantiate:" >&2
echo "$NIX_OUTPUT_ERR" >&2 echo "$NIX_OUTPUT_ERR" >&2
exit "$NIX_EXIT_STATUS" exit "$NIX_EXIT_STATUS"
fi fi

View File

@@ -10,6 +10,7 @@ self: super: {
# Python packages # Python packages
python3 = super.python3.override { python3 = super.python3.override {
packageOverrides = pself: psuper: { packageOverrides = pself: psuper: {
aia-chaser = pself.callPackage ../pkgs/aia-chaser { };
mini-racer = pself.callPackage ../pkgs/mini-racer.nix { }; mini-racer = pself.callPackage ../pkgs/mini-racer.nix { };
}; };
}; };

View File

@@ -0,0 +1,32 @@
{ lib
, buildPythonPackage
, fetchPypi
, cryptography
}:
buildPythonPackage rec {
pname = "aia-chaser";
version = "3.3.0";
format = "wheel";
src = fetchPypi {
pname = "aia_chaser";
inherit version format;
dist = "py3";
python = "py3";
hash = "sha256-L0aBV3kfAVI1aJH7VgiiEXzGBSP/HU2zAlahkHeT8hk=";
};
dependencies = [
cryptography
];
pythonImportsCheck = [ "aia_chaser" ];
meta = with lib; {
description = "Retrieve missing certificates to complete SSL certificate chains";
homepage = "https://github.com/dirkjanm/aia-chaser";
license = licenses.mit;
maintainers = [ ];
};
}

View File

@@ -0,0 +1,205 @@
#!/usr/bin/env python3
"""
Click'n'Load proxy - receives CNL requests and forwards to pyLoad API.
Implements the Click'n'Load protocol:
1. GET /jdcheck.js -> responds with jdownloader=true
2. POST /flash/addcrypted2 -> decrypts links and sends to pyLoad
"""
import argparse
import base64
import json
import re
import sys
import traceback
import urllib.request
import urllib.parse
from http.server import HTTPServer, BaseHTTPRequestHandler
from Crypto.Cipher import AES
def log(msg):
"""Log with immediate flush for systemd journal visibility."""
print(f"[CNL] {msg}", flush=True)
class ClickNLoadHandler(BaseHTTPRequestHandler):
pyload_url = None
pyload_user = None
pyload_pass = None
def log_message(self, format, *args):
log(f"{self.command} {self.path}")
def send_cors_headers(self):
"""Add CORS headers to allow cross-origin requests."""
self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
self.send_header("Access-Control-Allow-Headers", "Content-Type")
def do_OPTIONS(self):
"""Handle CORS preflight requests."""
self.send_response(200)
self.send_cors_headers()
self.end_headers()
def do_GET(self):
if self.path == "/jdcheck.js":
self.send_response(200)
self.send_header("Content-Type", "text/javascript")
self.send_cors_headers()
self.end_headers()
self.wfile.write(b"jdownloader=true;")
else:
self.send_response(404)
self.send_cors_headers()
self.end_headers()
def do_POST(self):
if self.path == "/flash/addcrypted2":
content_length = int(self.headers.get("Content-Length", 0))
post_data = self.rfile.read(content_length).decode("utf-8")
params = urllib.parse.parse_qs(post_data)
jk = params.get("jk", [""])[0]
crypted = params.get("crypted", [""])[0]
source = params.get("source", ["Click'n'Load"])[0]
log(f"Received addcrypted2: source={source}, jk_len={len(jk)}, crypted_len={len(crypted)}")
try:
links = self.decrypt_links(jk, crypted)
if links:
self.add_to_pyload(links, source)
self.send_response(200)
self.send_cors_headers()
self.end_headers()
self.wfile.write(b"success")
else:
log("Error: No links found after decryption")
self.send_response(500)
self.send_cors_headers()
self.end_headers()
self.wfile.write(b"No links found")
except Exception as e:
log(f"Error: {e}")
log(traceback.format_exc())
self.send_response(500)
self.send_cors_headers()
self.end_headers()
self.wfile.write(str(e).encode())
else:
self.send_response(404)
self.send_cors_headers()
self.end_headers()
def decrypt_links(self, jk, crypted):
"""Decrypt Click'n'Load encrypted links."""
# Extract hex key from JavaScript function
# Format: function f(){ return '...hex...'; }
match = re.search(r"return\s*['\"]([0-9a-fA-F]+)['\"]", jk)
if not match:
log(f"Could not extract key from jk: {jk[:100]}...")
raise ValueError("Could not extract key from jk")
key_hex = match.group(1)
key = bytes.fromhex(key_hex)
log(f"Extracted key: {len(key)} bytes")
# Decrypt (AES-128-CBC, key is also IV)
cipher = AES.new(key, AES.MODE_CBC, iv=key)
encrypted = base64.b64decode(crypted)
decrypted = cipher.decrypt(encrypted)
# Remove PKCS7 padding
pad_len = decrypted[-1]
decrypted = decrypted[:-pad_len]
# Split into links
links = decrypted.decode("utf-8").strip().split("\n")
links = [l.strip() for l in links if l.strip()]
log(f"Decrypted {len(links)} links")
return links
def add_to_pyload(self, links, package_name):
"""Add links to pyLoad via API using HTTP Basic Auth."""
if not self.pyload_url:
log("No pyLoad URL configured, printing links:")
for link in links:
log(f" {link}")
return
log(f"Adding package to pyLoad at {self.pyload_url}")
# Build Basic Auth header
credentials = f"{self.pyload_user}:{self.pyload_pass}"
auth_header = base64.b64encode(credentials.encode()).decode()
# Add package using new API endpoint with HTTP Basic Auth
add_url = f"{self.pyload_url}/api/add_package"
add_data = json.dumps({
"name": package_name or "Click'n'Load",
"links": links
}).encode()
req = urllib.request.Request(
add_url,
data=add_data,
headers={
"Content-Type": "application/json",
"Authorization": f"Basic {auth_header}"
}
)
try:
with urllib.request.urlopen(req, timeout=10) as resp:
result = resp.read().decode()
log(f"Added package to pyLoad: {result}")
except urllib.error.HTTPError as e:
body = e.read().decode() if e.fp else ""
log(f"Failed to add package: {e.code} {e.reason} - {body}")
raise
except urllib.error.URLError as e:
log(f"Failed to add package: {e}")
raise
def main():
parser = argparse.ArgumentParser(description="Click'n'Load proxy for pyLoad")
parser.add_argument("--port", type=int, default=9666, help="Port to listen on")
parser.add_argument("--host", default="127.0.0.1", help="Host to bind to")
parser.add_argument("--pyload-url", help="pyLoad URL (e.g., https://pyload.example.com)")
parser.add_argument("--pyload-user", help="pyLoad username")
parser.add_argument("--pyload-pass", help="pyLoad password")
parser.add_argument("--config", help="Config file with pyLoad credentials (JSON)")
args = parser.parse_args()
# Load config from file if provided
if args.config:
with open(args.config) as f:
config = json.load(f)
args.pyload_url = config.get("pyloadUrl", args.pyload_url)
args.pyload_user = config.get("pyloadUser", args.pyload_user)
args.pyload_pass = config.get("pyloadPW", args.pyload_pass)
ClickNLoadHandler.pyload_url = args.pyload_url
ClickNLoadHandler.pyload_user = args.pyload_user
ClickNLoadHandler.pyload_pass = args.pyload_pass
server = HTTPServer((args.host, args.port), ClickNLoadHandler)
log(f"Click'n'Load proxy listening on {args.host}:{args.port}")
if args.pyload_url:
log(f"Forwarding to pyLoad at {args.pyload_url}")
else:
log("No pyLoad URL configured, will print links to stdout")
try:
server.serve_forever()
except KeyboardInterrupt:
log("Shutting down")
server.shutdown()
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,34 @@
{ lib
, python3
, makeWrapper
}:
let
python = python3.withPackages (ps: [ ps.pycryptodome ]);
in
python3.pkgs.buildPythonApplication {
pname = "clicknload-proxy";
version = "1.0.0";
format = "other";
src = ./.;
nativeBuildInputs = [ makeWrapper ];
propagatedBuildInputs = [ python3.pkgs.pycryptodome ];
installPhase = ''
mkdir -p $out/bin
cp clicknload-proxy.py $out/bin/clicknload-proxy
chmod +x $out/bin/clicknload-proxy
wrapProgram $out/bin/clicknload-proxy \
--prefix PYTHONPATH : "${python}/${python.sitePackages}"
'';
meta = with lib; {
description = "Click'n'Load proxy that forwards links to pyLoad";
license = licenses.mit;
mainProgram = "clicknload-proxy";
};
}

View File

@@ -6,8 +6,8 @@ pyload-ng.overridePythonAttrs (oldAttrs: rec {
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "pyload"; owner = "pyload";
repo = "pyload"; repo = "pyload";
rev = "3115740a2210fd57b5d050cd0850a0e61ec493ed"; # [DdownloadCom] fix #4537 rev = "71f2700184ee9344dc313d9833ca7a6bb36007db"; # [DdownloadCom] fix #4537
hash = "sha256-g1eEeNnr3Axtr+0BJzMcNQomTEX4EsUG1Jxt+huPyoc="; hash = "sha256-XAa+XbC3kko+zvEMZkPXRoaHAmEFGsNBDxysX+X06Jc=";
}; };
patches = [ patches = [
@@ -16,6 +16,7 @@ pyload-ng.overridePythonAttrs (oldAttrs: rec {
# Add new dependencies required in newer versions # Add new dependencies required in newer versions
propagatedBuildInputs = (oldAttrs.propagatedBuildInputs or []) ++ (with python3Packages; [ propagatedBuildInputs = (oldAttrs.propagatedBuildInputs or []) ++ (with python3Packages; [
aia-chaser
mini-racer mini-racer
packaging packaging
pydantic pydantic

View File

@@ -1,5 +1,3 @@
diff --git a/src/pyload/core/__init__.py b/src/pyload/core/__init__.py
index 4324fc700..5d915a85e 100644
--- a/src/pyload/core/__init__.py --- a/src/pyload/core/__init__.py
+++ b/src/pyload/core/__init__.py +++ b/src/pyload/core/__init__.py
@@ -130,6 +130,14 @@ class Core: @@ -130,6 +130,14 @@ class Core:
@@ -17,12 +15,13 @@ index 4324fc700..5d915a85e 100644
# If no argument set, read storage dir from config file, # If no argument set, read storage dir from config file,
# otherwise save setting to config dir # otherwise save setting to config dir
if storagedir is None: if storagedir is None:
@@ -227,6 +235,18 @@ class Core: @@ -226,6 +234,20 @@ class Core:
self.acm = self.account_manager = AccountManager(self)
self.thm = self.thread_manager = ThreadManager(self) self.thm = self.thread_manager = ThreadManager(self)
self.cpm = self.captcha_manager = CaptchaManager(self) self.cpm = self.captcha_manager = CaptchaManager(self)
self.adm = self.addon_manager = AddonManager(self)
+ +
+ # Process plugin config environment variables after plugins are loaded (NixOS declarative config) + # Process plugin config environment variables BEFORE AddonManager (NixOS declarative config)
+ # This must happen before AddonManager reads the enabled flag to decide which addons to start
+ # Build case-insensitive lookup map for plugin names + # Build case-insensitive lookup map for plugin names
+ plugin_name_map = {name.lower(): name for name in self.config.plugin.keys()} + plugin_name_map = {name.lower(): name for name in self.config.plugin.keys()}
+ +
@@ -33,6 +32,7 @@ index 4324fc700..5d915a85e 100644
+ if len(parts) == 2 and parts[0] in plugin_name_map: + if len(parts) == 2 and parts[0] in plugin_name_map:
+ actual_plugin_name = plugin_name_map[parts[0]] + actual_plugin_name = plugin_name_map[parts[0]]
+ self.config.set_plugin(actual_plugin_name, parts[1], value) + self.config.set_plugin(actual_plugin_name, parts[1], value)
+
self.adm = self.addon_manager = AddonManager(self)
def _setup_permissions(self): def _setup_permissions(self):
self.log.debug("Setup permissions...")

View File

@@ -7,9 +7,10 @@ GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
# Script directory # Script and repo directories
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$(dirname "${BASH_SOURCE[0]}")"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" PKG_DIR="$(pwd)"
REPO_ROOT="$(cd ../../.. && pwd)"
# Check if commit SHA is provided # Check if commit SHA is provided
if [ $# -ne 1 ]; then if [ $# -ne 1 ]; then
@@ -34,7 +35,7 @@ fi
echo -e "${GREEN}==> Updating pyload-ng to commit: ${COMMIT_SHA}${NC}" echo -e "${GREEN}==> Updating pyload-ng to commit: ${COMMIT_SHA}${NC}"
# File to update # File to update
PKG_FILE="$REPO_ROOT/utils/pkgs/pyload-ng-updated.nix" PKG_FILE="$PKG_DIR/default.nix"
if [ ! -f "$PKG_FILE" ]; then if [ ! -f "$PKG_FILE" ]; then
echo -e "${RED}Error: Package file not found: $PKG_FILE${NC}" echo -e "${RED}Error: Package file not found: $PKG_FILE${NC}"
@@ -53,7 +54,8 @@ echo " ✓ Updated hash in $PKG_FILE"
# Step 3: Build package to discover the correct hash # Step 3: Build package to discover the correct hash
echo -e "${YELLOW}Step 3: Building package to discover hash...${NC}" echo -e "${YELLOW}Step 3: Building package to discover hash...${NC}"
BUILD_OUTPUT=$(nix-build --impure -E "with import <nixpkgs> { overlays = [ (import $REPO_ROOT/utils/overlays/packages.nix) ]; }; callPackage $PKG_FILE { }" 2>&1 || true) cd "$REPO_ROOT"
BUILD_OUTPUT=$(nix-build --impure -E "with import <nixpkgs> { overlays = [ (import ./utils/overlays/packages.nix) ]; }; callPackage ./utils/pkgs/pyload-ng { }" 2>&1 || true)
# Extract hash from error message # Extract hash from error message
HASH=$(echo "$BUILD_OUTPUT" | grep -oP '\s+got:\s+\Ksha256-[A-Za-z0-9+/=]+' | head -1) HASH=$(echo "$BUILD_OUTPUT" | grep -oP '\s+got:\s+\Ksha256-[A-Za-z0-9+/=]+' | head -1)
@@ -74,7 +76,7 @@ echo " ✓ Updated hash in $PKG_FILE"
# Step 5: Verify the build succeeds # Step 5: Verify the build succeeds
echo -e "${YELLOW}Step 5: Verifying build with correct hash...${NC}" echo -e "${YELLOW}Step 5: Verifying build with correct hash...${NC}"
if nix-build --impure -E "with import <nixpkgs> { overlays = [ (import $REPO_ROOT/utils/overlays/packages.nix) ]; }; callPackage $PKG_FILE { }" > /dev/null 2>&1; then if nix-build --impure -E "with import <nixpkgs> { overlays = [ (import ./utils/overlays/packages.nix) ]; }; callPackage ./utils/pkgs/pyload-ng { }" > /dev/null 2>&1; then
echo " ✓ Build verification successful" echo " ✓ Build verification successful"
else else
echo -e "${RED}Error: Build verification failed${NC}" echo -e "${RED}Error: Build verification failed${NC}"
@@ -83,7 +85,6 @@ fi
# Step 6: Test configuration for fw host (which uses pyload) # Step 6: Test configuration for fw host (which uses pyload)
echo -e "${YELLOW}Step 6: Testing fw configuration...${NC}" echo -e "${YELLOW}Step 6: Testing fw configuration...${NC}"
cd "$REPO_ROOT"
if ./scripts/test-configuration fw > /dev/null 2>&1; then if ./scripts/test-configuration fw > /dev/null 2>&1; then
echo " ✓ Configuration test passed" echo " ✓ Configuration test passed"
else else