summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accounts/gkleen@sif/niri/default.nix3
-rw-r--r--accounts/gkleen@sif/niri/mako.nix4
-rw-r--r--hosts/surtr/default.nix2
-rw-r--r--hosts/surtr/dns/default.nix2
-rw-r--r--hosts/surtr/dns/keys/hledger.yggdrasil.li_acme24
-rw-r--r--hosts/surtr/dns/zones/li.yggdrasil.soa10
-rw-r--r--hosts/surtr/hledger.nix66
-rw-r--r--hosts/surtr/tls/tsig_keys/hledger.yggdrasil.li24
-rw-r--r--hosts/vidhar/default.nix2
-rw-r--r--hosts/vidhar/hledger/default.nix83
-rw-r--r--hosts/vidhar/hledger/htpasswd24
-rw-r--r--hosts/vidhar/network/ruleset.nft4
-rwxr-xr-xoverlays/worktime/worktime/__main__.py10
13 files changed, 251 insertions, 7 deletions
diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix
index bbfc28d6..e4a93a49 100644
--- a/accounts/gkleen@sif/niri/default.nix
+++ b/accounts/gkleen@sif/niri/default.nix
@@ -412,6 +412,9 @@ in {
412 (leaf "scroll-method" "on-button-down") 412 (leaf "scroll-method" "on-button-down")
413 (leaf "scroll-button" 278) 413 (leaf "scroll-button" 278)
414 ]) 414 ])
415 (plain "touch" [
416 (leaf "map-to-output" "eDP-1")
417 ])
415 ]) 418 ])
416 419
417 (plain "environment" (lib.mapAttrsToList leaf { 420 (plain "environment" (lib.mapAttrsToList leaf {
diff --git a/accounts/gkleen@sif/niri/mako.nix b/accounts/gkleen@sif/niri/mako.nix
index 0a10555a..2788fb82 100644
--- a/accounts/gkleen@sif/niri/mako.nix
+++ b/accounts/gkleen@sif/niri/mako.nix
@@ -27,6 +27,10 @@
27 [app-name=Element] 27 [app-name=Element]
28 group-by=summary 28 group-by=summary
29 29
30 [app-name=poweralertd]
31 ignore-timeout=1
32 default-timeout=2000
33
30 [mode=silent] 34 [mode=silent]
31 invisible=1 35 invisible=1
32 ''; 36 '';
diff --git a/hosts/surtr/default.nix b/hosts/surtr/default.nix
index 1b33630a..3bbd51a4 100644
--- a/hosts/surtr/default.nix
+++ b/hosts/surtr/default.nix
@@ -7,7 +7,7 @@ with lib;
7 tmpfs-root qemu-guest openssh rebuild-machines zfs 7 tmpfs-root qemu-guest openssh rebuild-machines zfs
8 ./zfs.nix ./dns ./tls ./http ./bifrost ./matrix ./postgresql 8 ./zfs.nix ./dns ./tls ./http ./bifrost ./matrix ./postgresql
9 ./prometheus ./email ./vpn ./borg.nix ./etebase ./immich.nix 9 ./prometheus ./email ./vpn ./borg.nix ./etebase ./immich.nix
10 ./paperless.nix 10 ./paperless.nix ./hledger.nix
11 ]; 11 ];
12 12
13 config = { 13 config = {
diff --git a/hosts/surtr/dns/default.nix b/hosts/surtr/dns/default.nix
index 64864272..5dd60190 100644
--- a/hosts/surtr/dns/default.nix
+++ b/hosts/surtr/dns/default.nix
@@ -157,7 +157,7 @@ in {
157 ${concatMapStringsSep "\n" mkZone [ 157 ${concatMapStringsSep "\n" mkZone [
158 { domain = "yggdrasil.li"; 158 { domain = "yggdrasil.li";
159 addACLs = { "yggdrasil.li" = ["ymir_acme_acl"]; }; 159 addACLs = { "yggdrasil.li" = ["ymir_acme_acl"]; };
160 acmeDomains = ["surtr.yggdrasil.li" "yggdrasil.li" "etesync.yggdrasil.li" "immich.yggdrasil.li" "app.etesync.yggdrasil.li" "paperless.yggdrasil.li"]; 160 acmeDomains = ["surtr.yggdrasil.li" "yggdrasil.li" "etesync.yggdrasil.li" "immich.yggdrasil.li" "app.etesync.yggdrasil.li" "paperless.yggdrasil.li" "hledger.yggdrasil.li"];
161 } 161 }
162 { domain = "nights.email"; 162 { domain = "nights.email";
163 addACLs = { "nights.email" = ["ymir_acme_acl"]; }; 163 addACLs = { "nights.email" = ["ymir_acme_acl"]; };
diff --git a/hosts/surtr/dns/keys/hledger.yggdrasil.li_acme b/hosts/surtr/dns/keys/hledger.yggdrasil.li_acme
new file mode 100644
index 00000000..b3f4cfb6
--- /dev/null
+++ b/hosts/surtr/dns/keys/hledger.yggdrasil.li_acme
@@ -0,0 +1,24 @@
1{
2 "data": "ENC[AES256_GCM,data:lCj8VYJL9z29FJ154XQtxKQLwwitCRGy4krJ6u8yw2FMzoHprEpFgm33+mFspxSKk/It2G8cfTGMZSeVkYJEHb66HNKHl0A2Fz3hwjpRjh1MZAw0wiZJlnS/LNqoGstQ2PJmTQTW3aJRMoT1GS7q/gSp/3rqySA5EOm0GgUiA3Vi7nGpkBenKDEbQbcIBXRdMOk66BCdiz5XGm/1VLQQLO9oVwY2KBnLaZSISohyGVhbIy7GT2ygoWHHxHn0c5CRVNvGNwesM1gO1NnTFrISLMWSrsDPaAtQ,iv:fa8LFjzqsf2ccfbEe5MOmerb7FzXb4xr24y1GWIMT1Q=,tag:7oQ54DKBb76Pbw1lmEHt+Q==,type:str]",
3 "sops": {
4 "kms": null,
5 "gcp_kms": null,
6 "azure_kv": null,
7 "hc_vault": null,
8 "age": [
9 {
10 "recipient": "age1rmmhetcmllq0ahl5qznlr0eya2zdxwl9h6y5wnl97d2wtyx5t99sm2u866",
11 "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzcHJLRHh0VkpDNDU3cGZS\nMWFlVWpFemZ2RnpnSllDWU1EWGoyWUxyejNzClBGandzaFI5NXY1bG51Y3VxRk9r\nc29NbXBOaEZDblBuaVowemQydkxBdjgKLS0tICtVb2xkMmh4T0Q0cU4xQnBzZExI\namFRUnRYTWIyQ3RHNUVHWTFrUzhhK1UKqmATNmxlhkxM5PP1U6w7fSYVA8AgIRAt\nJ9WZrTffQfXMdw4RmjWcoVHFH39Fe4SteedxliCCcqjkjgSEB4Rgow==\n-----END AGE ENCRYPTED FILE-----\n"
12 },
13 {
14 "recipient": "age19a7j77w267z04zls7m28a8hj4a0g5af6ltye2d5wypg33c3l89csd4r9zq",
15 "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjWlhpQWI4c0x0ZXRGYVE2\nR1dHZzZud0ZxQWsrREhJWUowWE1zem5FVFI0CkJBUnIwY1FGS3N2VnpuSkZjRllZ\ncVgyeVg4cTVjRitzL0RKb0ZQb3BsOEkKLS0tIGs3SDBkamVBNDhQUlh5dmVVZXJs\nM3VKdlFKc21GcFY0UUtiaHFvYWI4V0kKKuWYEncxe9NT2ZS3X3+l/gT4BQOrdCg8\nj2jGL+Yzy/356GO3PFTn2HHLam6KWDKaYB5TlK/zSohfUt5giQH2Lw==\n-----END AGE ENCRYPTED FILE-----\n"
16 }
17 ],
18 "lastmodified": "2025-02-19T17:13:51Z",
19 "mac": "ENC[AES256_GCM,data:XsBdMCBjB+YuBMZQrjJ5uZtaYKSqsdWVvm+IEoJflCKPIhPk2rBZ3nY8KngXFbq2fWgsYyTM83kb2trEGIEHUPuERt+mgfCI3bSlylriwgsDWihCjyBecNE+BbdXE0+YcNl8pIwBU4M+3f2StQMH22YamToLJ9i9kfKcBrirDuU=,iv:VTIdBVY3kVBMYWhYUmrP2vZ9rpH90DzF68y1aDf2EAs=,tag:YkL+nw6LNXAceZtx9vgf6A==,type:str]",
20 "pgp": null,
21 "unencrypted_suffix": "_unencrypted",
22 "version": "3.9.4"
23 }
24} \ No newline at end of file
diff --git a/hosts/surtr/dns/zones/li.yggdrasil.soa b/hosts/surtr/dns/zones/li.yggdrasil.soa
index c77c9b82..2ef120e6 100644
--- a/hosts/surtr/dns/zones/li.yggdrasil.soa
+++ b/hosts/surtr/dns/zones/li.yggdrasil.soa
@@ -1,7 +1,7 @@
1$ORIGIN yggdrasil.li. 1$ORIGIN yggdrasil.li.
2$TTL 3600 2$TTL 3600
3@ IN SOA ns.yggdrasil.li. hostmaster.yggdrasil.li ( 3@ IN SOA ns.yggdrasil.li. hostmaster.yggdrasil.li (
4 2025021300 ; serial 4 2025021901 ; serial
5 10800 ; refresh 5 10800 ; refresh
6 3600 ; retry 6 3600 ; retry
7 604800 ; expire 7 604800 ; expire
@@ -85,6 +85,14 @@ _acme-challenge.paperless IN NS ns.yggdrasil.li.
85 85
86paperless IN HTTPS 1 . alpn="h2,h3" ipv4hint="202.61.241.61" ipv6hint="2a03:4000:52:ada::" 86paperless IN HTTPS 1 . alpn="h2,h3" ipv4hint="202.61.241.61" ipv6hint="2a03:4000:52:ada::"
87 87
88hledger IN A 202.61.241.61
89hledger IN AAAA 2a03:4000:52:ada::
90hledger IN MX 0 surtr.yggdrasil.li
91hledger IN TXT "v=spf1 redirect=surtr.yggdrasil.li"
92_acme-challenge.hledger IN NS ns.yggdrasil.li.
93
94hledger IN HTTPS 1 . alpn="h2,h3" ipv4hint="202.61.241.61" ipv6hint="2a03:4000:52:ada::"
95
88vidhar IN AAAA 2a03:4000:52:ada:4:1:: 96vidhar IN AAAA 2a03:4000:52:ada:4:1::
89vidhar IN MX 0 ymir.yggdrasil.li 97vidhar IN MX 0 ymir.yggdrasil.li
90vidhar IN TXT "v=spf1 redirect=yggdrasil.li" 98vidhar IN TXT "v=spf1 redirect=yggdrasil.li"
diff --git a/hosts/surtr/hledger.nix b/hosts/surtr/hledger.nix
new file mode 100644
index 00000000..e44933c3
--- /dev/null
+++ b/hosts/surtr/hledger.nix
@@ -0,0 +1,66 @@
1{ config, ... }:
2
3{
4 config = {
5 security.acme.rfc2136Domains = {
6 "hledger.yggdrasil.li" = {
7 restartUnits = ["nginx.service"];
8 };
9 };
10
11 services.nginx = {
12 upstreams."hledger" = {
13 servers = {
14 "[2a03:4000:52:ada:4:1::]:5000" = {};
15 };
16 extraConfig = ''
17 keepalive 8;
18 '';
19 };
20 virtualHosts = {
21 "hledger.yggdrasil.li" = {
22 kTLS = true;
23 http3 = true;
24 forceSSL = true;
25 sslCertificate = "/run/credentials/nginx.service/hledger.yggdrasil.li.pem";
26 sslCertificateKey = "/run/credentials/nginx.service/hledger.yggdrasil.li.key.pem";
27 sslTrustedCertificate = "/run/credentials/nginx.service/hledger.yggdrasil.li.chain.pem";
28 extraConfig = ''
29 charset utf-8;
30 '';
31
32 locations = {
33 "/".extraConfig = ''
34 proxy_pass http://hledger;
35
36 proxy_http_version 1.1;
37 proxy_set_header Upgrade $http_upgrade;
38 proxy_set_header Connection "upgrade";
39
40 proxy_redirect off;
41 proxy_set_header Host $host;
42 proxy_set_header X-Real-IP $remote_addr;
43 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
44 proxy_set_header X-Forwarded-Host $server_name;
45 proxy_set_header X-Forwarded-Proto $scheme;
46
47 client_max_body_size 0;
48 proxy_request_buffering off;
49 proxy_buffering off;
50 '';
51 };
52 };
53 };
54 };
55
56 systemd.services.nginx = {
57 serviceConfig = {
58 LoadCredential = [
59 "hledger.yggdrasil.li.key.pem:${config.security.acme.certs."hledger.yggdrasil.li".directory}/key.pem"
60 "hledger.yggdrasil.li.pem:${config.security.acme.certs."hledger.yggdrasil.li".directory}/fullchain.pem"
61 "hledger.yggdrasil.li.chain.pem:${config.security.acme.certs."hledger.yggdrasil.li".directory}/chain.pem"
62 ];
63 };
64 };
65 };
66}
diff --git a/hosts/surtr/tls/tsig_keys/hledger.yggdrasil.li b/hosts/surtr/tls/tsig_keys/hledger.yggdrasil.li
new file mode 100644
index 00000000..ab6cdd68
--- /dev/null
+++ b/hosts/surtr/tls/tsig_keys/hledger.yggdrasil.li
@@ -0,0 +1,24 @@
1{
2 "data": "ENC[AES256_GCM,data:Yd70QIj9DE6a5IN+Mf2M5p95vkRMHRg9BXaM686W7BRtthOw9m54/5FK6JWr,iv:cIOIKinkqFFPgTZdewWVY0h6kM5hGfVzuA4iYNhwK5c=,tag:Ds/oI+TOERbIdcGbI4WoEg==,type:str]",
3 "sops": {
4 "kms": null,
5 "gcp_kms": null,
6 "azure_kv": null,
7 "hc_vault": null,
8 "age": [
9 {
10 "recipient": "age1rmmhetcmllq0ahl5qznlr0eya2zdxwl9h6y5wnl97d2wtyx5t99sm2u866",
11 "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1NnJ4SmsvSlh3ZlliSm9C\nNG45clh3NEZWZ05jaHhVK0xqTVRFL2wxN1ZrCk5hL2p2ZjhtcDBjTEZscXFTNkY5\nemVZSUUwV2V5cFBTdWo4RWxsM2xROVEKLS0tIDBFSFlkUVJ0ajJEUENlelVFKzVk\ndnJhMURMU2o3WVBKZGNVRXBiNytqUFEKHivcSTYy5D770C0h7RsmLBmkIG9+MDoV\ngJHvfkGzXPKwmDTMKdHbIk+ctI+u0/1jMn/K2Q9OFnOIYxP3gHiFag==\n-----END AGE ENCRYPTED FILE-----\n"
12 },
13 {
14 "recipient": "age19a7j77w267z04zls7m28a8hj4a0g5af6ltye2d5wypg33c3l89csd4r9zq",
15 "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArYUNCQ1U2MXpQdmM4SHR0\nTnJWZlFGTUQ1NjVqZ3Z2MGt5NFpBVFp0b0YwCkdseitkbzI1RkZyL3V5Z1pNMG9R\nVnEzRUxrTDQrS3BiMXB1QUFPeUcxZUkKLS0tIGJFODkwNFY3c0tBLzFBNjFiYjJk\nZW82bTdia2F1NHpNSG1IYmhWb1ZCTHMK9ovFx3+x5PrV4y6+RH5XA5DK2wRPXlAt\ncxxpRZIlmnvhZXIeCYE9yhHFmz3uAn0Oib1RUDblca9FlnF9tyYD6g==\n-----END AGE ENCRYPTED FILE-----\n"
16 }
17 ],
18 "lastmodified": "2025-02-19T17:13:51Z",
19 "mac": "ENC[AES256_GCM,data:ReRuK9qdZV8AbMzA9Yur0AZW+1RF3aRnfBvsKJkQtXsFdkmJQ4QkRGtL27RmjFdvQ3kXBIyhib7hYA60AJ0amduYrSScY0dtz8AurjyE4f2BGQ9/QeKRBfKXHxLvj4/xWNvS4+PVdGKkKbqIs8isz9n77WQQ3lTHop2K/TjaTuQ=,iv:gUhDK9oeUHdpQ2Fp8mFDIgPFo2JjHE0jjooL7FmvmrE=,tag:2lkwSl3j3oqamdLbM9wbow==,type:str]",
20 "pgp": null,
21 "unencrypted_suffix": "_unencrypted",
22 "version": "3.9.4"
23 }
24} \ No newline at end of file
diff --git a/hosts/vidhar/default.nix b/hosts/vidhar/default.nix
index 9660931d..90ab40dd 100644
--- a/hosts/vidhar/default.nix
+++ b/hosts/vidhar/default.nix
@@ -4,7 +4,7 @@ with lib;
4 4
5{ 5{
6 imports = with flake.nixosModules.systemProfiles; [ 6 imports = with flake.nixosModules.systemProfiles; [
7 ./zfs.nix ./network ./samba.nix ./dns ./prometheus ./borg ./pgbackrest ./postgresql.nix ./immich.nix ./paperless 7 ./zfs.nix ./network ./samba.nix ./dns ./prometheus ./borg ./pgbackrest ./postgresql.nix ./immich.nix ./paperless ./hledger
8 tmpfs-root zfs 8 tmpfs-root zfs
9 initrd-all-crypto-modules default-locale openssh rebuild-machines 9 initrd-all-crypto-modules default-locale openssh rebuild-machines
10 build-server 10 build-server
diff --git a/hosts/vidhar/hledger/default.nix b/hosts/vidhar/hledger/default.nix
new file mode 100644
index 00000000..ae080f66
--- /dev/null
+++ b/hosts/vidhar/hledger/default.nix
@@ -0,0 +1,83 @@
1{ config, lib, pkgs, ... }:
2{
3 config = {
4 services.hledger-web = {
5 enable = true;
6 allow = "view";
7 stateDir = "/var/lib/hledger";
8 journalFiles = lib.mkForce ["web.journal"];
9 baseUrl = "https://hledger.yggdrasil.li";
10 extraOptions = [
11 "--socket=/run/hledger-web/http.sock"
12 ];
13 };
14 users = {
15 users.hledger.uid = 982;
16 groups.hledger.gid = 979;
17 };
18 systemd.services.hledger-web = {
19 serviceConfig = {
20 UMask = "0002";
21 ReadOnlyPaths = [ config.services.hledger-web.stateDir ];
22 RuntimeDirectory = [ "hledger-web" ];
23 PrivateDevices = true;
24 StateDirectory = "hledger";
25 CapabilityBoundingSet = "";
26 AmbientCapabilities = "";
27 ProtectSystem = "strict";
28 ProtectKernelTunables = true;
29 ProtectKernelModules = true;
30 ProtectControlGroups = true;
31 ProtectClock = true;
32 ProtectHostname = true;
33 ProtectHome = "tmpfs";
34 ProtectKernelLogs = true;
35 ProtectProc = "invisible";
36 ProcSubset = "pid";
37 PrivateNetwork = false;
38 RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX";
39 SystemCallArchitectures = "native";
40 SystemCallFilter = [
41 "@system-service @resources"
42 "~@obsolete @privileged"
43 ];
44 RestrictSUIDSGID = true;
45 RemoveIPC = true;
46 NoNewPrivileges = true;
47 RestrictRealtime = true;
48 RestrictNamespaces = true;
49 LockPersonality = true;
50 PrivateUsers = true;
51 TemporaryFileSystem = [ "/var/lib/hledger/.cache:mode=0750,uid=${toString (config.users.users.hledger.uid)},gid=${toString (config.users.groups.hledger.gid)}" ];
52 };
53 };
54 services.nginx = {
55 upstreams.hledger = {
56 servers = { "unix:/run/hledger-web/http.sock" = {}; };
57 };
58 virtualHosts."hledger.yggdrasil.li" = {
59 listen = [
60 { addr = "[2a03:4000:52:ada:4:1::]"; port = 5000; }
61 ];
62 extraConfig = ''
63 set_real_ip_from 2a03:4000:52:ada:4::;
64 auth_basic "hledger";
65 auth_basic_user_file "/run/credentials/nginx.service/hledger_users";
66 '';
67 locations."/" = {
68 proxyPass = "http://hledger/";
69 proxyWebsockets = true;
70 };
71 };
72 };
73 systemd.services.nginx.serviceConfig = {
74 SupplementaryGroups = [ "hledger" ];
75 LoadCredential = [ "hledger_users:${config.sops.secrets."hledger_users".path}" ];
76 };
77 sops.secrets."hledger_users" = {
78 format = "binary";
79 sopsFile = ./htpasswd;
80 reloadUnits = [ "nginx.service" ];
81 };
82 };
83}
diff --git a/hosts/vidhar/hledger/htpasswd b/hosts/vidhar/hledger/htpasswd
new file mode 100644
index 00000000..016cb525
--- /dev/null
+++ b/hosts/vidhar/hledger/htpasswd
@@ -0,0 +1,24 @@
1{
2 "data": "ENC[AES256_GCM,data:9MNDIAc7ePYk3xQDorX2pU8ybJkJb33RKiJxc2DYauXFNQYxtGwCYhZwod7p7fPh3KqZxBNMRoZXr+/RnV+trsqjAcOOjnXTWLbX6nubq/xm+q0BxEjOPn7FvJF9XOblBeupldo+byGh2CMH9qQv5Fov,iv:3Tym+Mfr48OJet3qDFZPg0XjYr4sNQdNdiu0vUxmzbY=,tag:E0sxRY/jeMVlqH6uAYvD/Q==,type:str]",
3 "sops": {
4 "kms": null,
5 "gcp_kms": null,
6 "azure_kv": null,
7 "hc_vault": null,
8 "age": [
9 {
10 "recipient": "age1rmmhetcmllq0ahl5qznlr0eya2zdxwl9h6y5wnl97d2wtyx5t99sm2u866",
11 "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3eFBsOEM2ZUNVT2V3LytC\nTUJvUDdKc0VzMyt2cDFKYU03djBjZVFpeVY4CjByMXhPVXRJVjhKQWZvQ2xuOTE3\ncXdJV1lZaHR3cVl0Z0hQaG00M2dGbjQKLS0tIEIzenVxb3cwM3pXTUl1YUZlSlk2\nbDc3VmE5NkEyZ2tRd01OUGZibmhtUlEKxdesIdvzm8s0SmXU5R+tSbmS5Dj24jrb\nEiMERYy1g8GyHR3d2/mU5iOIdsBegSZReUVzomaMT9L7/TmubgOP3g==\n-----END AGE ENCRYPTED FILE-----\n"
12 },
13 {
14 "recipient": "age1qffdqvy9arld9zd5a5cylt0n98xhcns5shxhrhwjq5g4qa844ejselaa4l",
15 "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPa2RDZzR6cEFYTFA1QkND\nbndVeHVrMVJ0MWZvRmw5VXRhOHlRYllIRWxRCjU4dks4R25LS1RZMHFnbmpQRVZz\nNXhubkJvZFc2amRwMDVtQlE0NnBKNzQKLS0tIHRyeDUxTEFPMEMzWUVkZURzODdm\nSHdqbUpvNmFTS1QveFRpRHdnWHpHb28KnvdUkMkKGiBVHQD7Yv7n6WZjihCGJAR2\nMKl2WAn4g4jzgcXPwwIAIjUrMGSIdGpwCTUDcDnlKWAbRYO2B6P17A==\n-----END AGE ENCRYPTED FILE-----\n"
16 }
17 ],
18 "lastmodified": "2025-02-19T17:11:17Z",
19 "mac": "ENC[AES256_GCM,data:yBIEqHhr4igoMlRcgg2SigKfejqeuNmuleYolsLJo+QOaW4BHITJTvLxRV1JHPpcMVQkF//zx4ZfUUrb8tTN0znGu3Jnpd0JVagbfCVyEuT6d1SB/GzyUVvoQ2GlcA9us+5gjI4oEJTQCfVqnLDBWsw+jXdr3nEIWo6Mvbqo3lI=,iv:I6Swk4wyd+96+tJKRY/FHlS7ZShMDROcbl+l+ZLRxhM=,tag:P1uQvB4NLdkPEKRMI6lLxw==,type:str]",
20 "pgp": null,
21 "unencrypted_suffix": "_unencrypted",
22 "version": "3.9.4"
23 }
24} \ No newline at end of file
diff --git a/hosts/vidhar/network/ruleset.nft b/hosts/vidhar/network/ruleset.nft
index 3ead8fac..1edae167 100644
--- a/hosts/vidhar/network/ruleset.nft
+++ b/hosts/vidhar/network/ruleset.nft
@@ -93,6 +93,7 @@ table inet filter {
93 counter pgbackrest-rx {} 93 counter pgbackrest-rx {}
94 counter immich-rx {} 94 counter immich-rx {}
95 counter paperless-rx {} 95 counter paperless-rx {}
96 counter hledger-rx {}
96 97
97 counter established-rx {} 98 counter established-rx {}
98 99
@@ -123,6 +124,7 @@ table inet filter {
123 counter pgbackrest-tx {} 124 counter pgbackrest-tx {}
124 counter immich-tx {} 125 counter immich-tx {}
125 counter paperless-tx {} 126 counter paperless-tx {}
127 counter hledger-tx {}
126 128
127 counter tx {} 129 counter tx {}
128 130
@@ -200,6 +202,7 @@ table inet filter {
200 202
201 iifname bifrost tcp dport 2283 ip6 saddr $bifrost_surtr counter name immich-rx accept 203 iifname bifrost tcp dport 2283 ip6 saddr $bifrost_surtr counter name immich-rx accept
202 iifname bifrost tcp dport 28981 ip6 saddr $bifrost_surtr counter name paperless-rx accept 204 iifname bifrost tcp dport 28981 ip6 saddr $bifrost_surtr counter name paperless-rx accept
205 iifname bifrost tcp dport 5000 ip6 saddr $bifrost_surtr counter name hledger-rx accept
203 206
204 ct state { established, related } counter name established-rx accept 207 ct state { established, related } counter name established-rx accept
205 208
@@ -250,6 +253,7 @@ table inet filter {
250 253
251 iifname bifrost tcp sport 2283 ip6 daddr $bifrost_surtr counter name immich-tx accept 254 iifname bifrost tcp sport 2283 ip6 daddr $bifrost_surtr counter name immich-tx accept
252 iifname bifrost tcp sport 28981 ip6 daddr $bifrost_surtr counter name paperless-tx accept 255 iifname bifrost tcp sport 28981 ip6 daddr $bifrost_surtr counter name paperless-tx accept
256 iifname bifrost tcp sport 5000 ip6 daddr $bifrost_surtr counter name hledger-tx accept
253 257
254 258
255 counter name tx 259 counter name tx
diff --git a/overlays/worktime/worktime/__main__.py b/overlays/worktime/worktime/__main__.py
index f0363777..cca5ab5a 100755
--- a/overlays/worktime/worktime/__main__.py
+++ b/overlays/worktime/worktime/__main__.py
@@ -542,7 +542,7 @@ def worktime(pull_forward_cutoff, waybar, **args):
542 542
543 return difference_string 543 return difference_string
544 544
545 difference = worktime.time_to_work - worktime.time_worked 545 difference = worktime.time_to_work - worktime.time_worked + sum(worktime.pull_forward.values(), start=timedelta(milliseconds=0))
546 total_minutes_difference = 5 * ceil(difference / timedelta(minutes = 5)) 546 total_minutes_difference = 5 * ceil(difference / timedelta(minutes = 5))
547 547
548 if worktime.running_entry and abs(difference) < timedelta(days = 1) and (total_minutes_difference > 0 or abs(worktime.running_entry) >= abs(difference)) : 548 if worktime.running_entry and abs(difference) < timedelta(days = 1) and (total_minutes_difference > 0 or abs(worktime.running_entry) >= abs(difference)) :
@@ -578,6 +578,7 @@ def worktime(pull_forward_cutoff, waybar, **args):
578 worktime_no_pulled_forward = deepcopy(worktime) 578 worktime_no_pulled_forward = deepcopy(worktime)
579 worktime_no_pulled_forward.time_to_work -= worktime_no_pulled_forward.time_pulled_forward 579 worktime_no_pulled_forward.time_to_work -= worktime_no_pulled_forward.time_pulled_forward
580 worktime_no_pulled_forward.time_pulled_forward = timedelta() 580 worktime_no_pulled_forward.time_pulled_forward = timedelta()
581 worktime_no_pulled_forward.pull_forward = dict()
581 582
582 difference_string = format_worktime(worktime) 583 difference_string = format_worktime(worktime)
583 difference_string_no_pulled_forward = format_worktime(worktime_no_pulled_forward) 584 difference_string_no_pulled_forward = format_worktime(worktime_no_pulled_forward)
@@ -631,6 +632,7 @@ def time_worked(now, waybar, **args):
631 def round_clockout_time(difference): 632 def round_clockout_time(difference):
632 clockout_time = None 633 clockout_time = None
633 clockout_difference = None 634 clockout_difference = None
635 exact_clockout_time = None
634 if then.now_is_workday or now.now_is_workday: 636 if then.now_is_workday or now.now_is_workday:
635 clockout_difference = 5 * ceil(difference / timedelta(minutes = 5)) 637 clockout_difference = 5 * ceil(difference / timedelta(minutes = 5))
636 clockout_time = now.now + difference 638 clockout_time = now.now + difference
@@ -642,13 +644,15 @@ def time_worked(now, waybar, **args):
642 644
643 clockout_time, exact_clockout_time, clockout_difference = round_clockout_time(difference) 645 clockout_time, exact_clockout_time, clockout_difference = round_clockout_time(difference)
644 clockout_time_pull_forward, exact_clockout_time_pull_forward, clockout_difference_pull_forward = round_clockout_time(difference_pull_forward) 646 clockout_time_pull_forward, exact_clockout_time_pull_forward, clockout_difference_pull_forward = round_clockout_time(difference_pull_forward)
647 clockout_pull_forward_sum, exact_clockout_pull_forward_sum, _ = round_clockout_time(now.time_to_work - now.time_worked + sum(now.pull_forward.values(), start=timedelta(milliseconds=0)))
648
645 if now.running_entry and clockout_time and (clockout_difference >= 0 or clockout_difference_pull_forward >= 0): 649 if now.running_entry and clockout_time and (clockout_difference >= 0 or clockout_difference_pull_forward >= 0):
646 out_text = f"{difference_string}/{clockout_time:%H:%M}" 650 out_text = f"{difference_string}/{clockout_time:%H:%M}"
647 tooltip = f"{tooltip_timedelta(worked)}/{exact_clockout_time:%H:%M:%S}" 651 tooltip = f"{tooltip_timedelta(worked)}/{exact_clockout_time:%H:%M:%S}"
648 652
649 if clockout_time_pull_forward != clockout_time: 653 if clockout_pull_forward_sum >= clockout_time_pull_forward and clockout_time_pull_forward != clockout_time:
650 out_text += f"…{clockout_time_pull_forward:%H:%M}" 654 out_text += f"…{clockout_time_pull_forward:%H:%M}"
651 if exact_clockout_time_pull_forward != exact_clockout_time: 655 if exact_clockout_pull_forward_sum >= exact_clockout_time_pull_forward and exact_clockout_time_pull_forward != exact_clockout_time:
652 tooltip += f"…{exact_clockout_time_pull_forward:%H:%M:%S}" 656 tooltip += f"…{exact_clockout_time_pull_forward:%H:%M:%S}"
653 else: 657 else:
654 out_text = difference_string 658 out_text = difference_string