summaryrefslogtreecommitdiff
path: root/accounts/gkleen@sif/systemd.nix
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/gkleen@sif/systemd.nix')
-rw-r--r--accounts/gkleen@sif/systemd.nix312
1 files changed, 210 insertions, 102 deletions
diff --git a/accounts/gkleen@sif/systemd.nix b/accounts/gkleen@sif/systemd.nix
index cefcf4ea..a2d6e4ff 100644
--- a/accounts/gkleen@sif/systemd.nix
+++ b/accounts/gkleen@sif/systemd.nix
@@ -6,7 +6,7 @@ let
6 cfg = config.home-manager.users.${userName}; 6 cfg = config.home-manager.users.${userName};
7 7
8 autossh-socks-script = pkgs.writeScript "autossh" '' 8 autossh-socks-script = pkgs.writeScript "autossh" ''
9 #!${pkgs.zsh}/bin/zsh -xe 9 #!${lib.getExe pkgs.zsh} -xe
10 10
11 host="''${1%:*}" 11 host="''${1%:*}"
12 port="''${1#*:}" 12 port="''${1#*:}"
@@ -15,31 +15,29 @@ let
15 cmd=() 15 cmd=()
16 16
17 if [[ -n "''${SSHPASS_SECRET}" ]]; then 17 if [[ -n "''${SSHPASS_SECRET}" ]]; then
18 cmd+=(${pkgs.sshpassSecret}/bin/sshpass-secret) 18 cmd+=(${lib.getExe' pkgs.sshpassSecret "sshpass-secret"})
19 cmd+=("''${(@s/:/)SSHPASS_SECRET}") 19 cmd+=("''${(@s/:/)SSHPASS_SECRET}")
20 cmd+=(--) 20 cmd+=(--)
21 fi 21 fi
22 22
23 cmd+=(${pkgs.openssh}/bin/ssh -vN -D localhost:''${port} "''${host}") 23 cmd+=(${lib.getExe' pkgs.openssh "ssh"} -vN -D 127.0.0.1:''${port} "''${host}")
24 24
25 ( exec -a "''${cmd[1]}" -- ''${cmd} ) & 25 ( exec -a "''${cmd[1]}" -- ''${cmd} ) &
26 pid=$! 26 pid=$!
27 27
28 newpid="" 28 newpid=""
29 i=200 29 i=200
30 while ! newpid=$(${pkgs.lsof}/bin/lsof -Pi @localhost:"''${port}" -sTCP:LISTEN -t); do 30 while ! { newpid=$(${lib.getExe' pkgs.iproute2 "ss"} -HO -pln "src localhost sport ''${port}" | ${lib.getExe pkgs.gnused} -r 's/^.*pid=([0-9]+).*$/\1/'); [[ -n $newpid ]] }; do
31 if ! kill -0 "''${pid}"; then 31 if ! kill -0 "''${pid}"; then
32 wait "''${pid}" 32 wait "''${pid}"
33 exit $? 33 exit $?
34 fi 34 fi
35 [[ "''${i}" -gt 0 ]] || exit 1 35 [[ "''${i}" -gt 0 ]] || exit 1
36 i=$((''${i} - 1)) 36 i=$((''${i} - 1))
37 ${pkgs.coreutils}/bin/sleep 0.1 37 ${lib.getExe' pkgs.coreutils "sleep"} 0.1
38 done 38 done
39 39
40 ${config.systemd.package}/bin/systemd-notify --ready 40 ${lib.getExe' config.systemd.package "systemd-notify"} --pid=''${newpid} --ready
41
42 wait "''${pid}" "''${newpid}"
43 ''; 41 '';
44in { 42in {
45 tmpfiles.rules = [ 43 tmpfiles.rules = [
@@ -48,11 +46,11 @@ in {
48 ]; 46 ];
49 47
50 services = { 48 services = {
51 sync-keepass = { 49 "sync-keepass@" = {
52 Service = { 50 Service = {
53 Type = "oneshot"; 51 Type = "oneshot";
54 WorkingDirectory = "~"; 52 WorkingDirectory = "~";
55 ExecStart = toString (pkgs.writers.writePython3 "sync-keepass" { 53 ExecStart = "${pkgs.writers.writePython3 "sync-keepass" {
56 libraries = with pkgs.python3Packages; [ python-dateutil ]; 54 libraries = with pkgs.python3Packages; [ python-dateutil ];
57 } '' 55 } ''
58 import json 56 import json
@@ -61,13 +59,13 @@ in {
61 from datetime import datetime 59 from datetime import datetime
62 from dateutil.tz import tzlocal 60 from dateutil.tz import tzlocal
63 from dateutil.parser import isoparse 61 from dateutil.parser import isoparse
64 from sys import stderr 62 from sys import stderr, argv
65 63
66 64
67 remote_fs = 'surtr' 65 remote_fs = 'surtr' if argv[1] == 'store.kdbx' else 'mathcloud'
68 remote_file = 'store.kdbx' 66 remote_file = argv[1]
69 target_file = expanduser('~/store.kdbx') 67 target_file = expanduser(f'~/{argv[1]}')
70 meta_file = expanduser('~/.store.kdbx.json') 68 meta_file = expanduser(f'~/.{argv[1]}.json')
71 69
72 upload_time = None 70 upload_time = None
73 our_last_upload_time = None 71 our_last_upload_time = None
@@ -117,13 +115,14 @@ in {
117 do_upload() 115 do_upload()
118 elif upload_time is not None and (mod_time is None or upload_time > mod_time) and (our_last_upload_time is None or upload_time > our_last_upload_time): # noqa: E501 116 elif upload_time is not None and (mod_time is None or upload_time > mod_time) and (our_last_upload_time is None or upload_time > our_last_upload_time): # noqa: E501
119 do_download() 117 do_download()
120 ''); 118 ''} \"%I\"";
121 Environment = [ "RCLONE_PASSWORD_COMMAND=\"${pkgs.coreutils}/bin/cat ${config.sops.secrets.gkleen-rclone.path}\"" "PATH=${pkgs.rclone}/bin" ]; 119 Environment = [ "RCLONE_PASSWORD_COMMAND=\"${pkgs.coreutils}/bin/cat ${config.sops.secrets.gkleen-rclone.path}\"" "PATH=${pkgs.rclone}/bin" ];
122 }; 120 };
123 }; 121 };
124 emacs = { 122 emacs = {
125 Unit = { 123 Unit = {
126 After = ["graphical-session-pre.target"]; 124 After = [ "graphical-session.target" ];
125 BindsTo = [ "graphical-session.target" ];
127 }; 126 };
128 }; 127 };
129 keepassxc = { 128 keepassxc = {
@@ -135,8 +134,8 @@ in {
135 Environment = [ "QT_QPA_PLATFORM=wayland" ]; 134 Environment = [ "QT_QPA_PLATFORM=wayland" ];
136 }; 135 };
137 Unit = { 136 Unit = {
138 Requires = ["graphical-session-pre.target"]; 137 After = [ "graphical-session.target" ];
139 After = ["graphical-session-pre.target"]; 138 BindsTo = [ "graphical-session.target" ];
140 }; 139 };
141 }; 140 };
142 mpris-proxy = { 141 mpris-proxy = {
@@ -145,7 +144,7 @@ in {
145 Service.ExecStart = "${pkgs.bluez}/bin/mpris-proxy"; 144 Service.ExecStart = "${pkgs.bluez}/bin/mpris-proxy";
146 Install.WantedBy = [ "default.target" ]; 145 Install.WantedBy = [ "default.target" ];
147 }; 146 };
148 "autossh-socks@proxy.mathw0h:8119" = { 147 "autossh-socks@proxy.ssh.math.lmu.de:8119" = {
149 Service = { 148 Service = {
150 Type = "notify"; 149 Type = "notify";
151 NotifyAccess = "all"; 150 NotifyAccess = "all";
@@ -153,7 +152,7 @@ in {
153 Restart = "always"; 152 Restart = "always";
154 RestartSec = "23s"; 153 RestartSec = "23s";
155 ExecStart = "${autossh-socks-script} \"%I\""; 154 ExecStart = "${autossh-socks-script} \"%I\"";
156 Environment = [ "SSHPASS_SECRET=gkleen@mathw0g.math.lmu.de" ]; 155 Environment = [ "SSHPASS_SECRET=gkleen@ssh.math.lmu.de" ];
157 }; 156 };
158 Unit = { 157 Unit = {
159 StopWhenUnneeded = true; 158 StopWhenUnneeded = true;
@@ -172,102 +171,91 @@ in {
172 }; 171 };
173 Unit = { 172 Unit = {
174 StopWhenUnneeded = true; 173 StopWhenUnneeded = true;
174 StartLimitInterval = "2s";
175 StartLimitBurst = 25;
175 }; 176 };
176 }; 177 };
177 swayidle = { 178 "autossh-socks@proxy.mathw0h:8123" = {
178 Service = { 179 Service = {
179 RuntimeDirectory = "swayidle"; 180 Type = "notify";
181 NotifyAccess = "all";
182 WorkingDirectory = "~";
183 Restart = "always";
184 RestartSec = "23s";
185 ExecStart = "${autossh-socks-script} \"%I\"";
186 Environment = [ "SSHPASS_SECRET=gkleen@mathw0h.mathinst.loc" ];
187 };
188 Unit = {
189 StopWhenUnneeded = true;
190 StartLimitInterval = "180s";
191 StartLimitBurst = 7;
180 }; 192 };
181 }; 193 };
182 psi-notify = { 194 "autossh-socks@proxy.mathw0e:8125" = {
183 Install = { 195 Service = {
184 WantedBy = ["graphical-session.target"]; 196 Type = "notify";
197 NotifyAccess = "all";
198 WorkingDirectory = "~";
199 Restart = "always";
200 RestartSec = "23s";
201 ExecStart = "${autossh-socks-script} \"%I\"";
202 Environment = [ "SSHPASS_SECRET=gkleen@mathw0e.mathinst.loc" ];
185 }; 203 };
186 Unit = { 204 Unit = {
187 Requires = ["graphical-session-pre.target"]; 205 StopWhenUnneeded = true;
188 After = ["graphical-session-pre.target"]; 206 StartLimitInterval = "180s";
207 StartLimitBurst = 7;
189 }; 208 };
209 };
210 "autossh-socks@proxy.cip04:8127" = {
190 Service = { 211 Service = {
191 ExecStart = lib.getExe pkgs.psi-notify;
192 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
193 Type = "notify"; 212 Type = "notify";
213 NotifyAccess = "all";
214 WorkingDirectory = "~";
194 Restart = "always"; 215 Restart = "always";
195 WatchdogSec = "2s"; 216 RestartSec = "23s";
217 ExecStart = "${autossh-socks-script} \"%I\"";
218 Environment = [ "SSHPASS_SECRET=gkleen@cip04.cipmath.loc" ];
219 };
220 Unit = {
221 StopWhenUnneeded = true;
222 StartLimitInterval = "180s";
223 StartLimitBurst = 7;
196 }; 224 };
197 }; 225 };
198 gtklock = { 226 psi-notify = {
227 Install = {
228 WantedBy = ["graphical-session.target"];
229 };
199 Unit = { 230 Unit = {
200 Requisite = ["graphical-session.target"]; 231 After = [ "graphical-session.target" ];
201 PartOf = ["graphical-session.target"]; 232 PartOf = [ "graphical-session.target" ];
202 }; 233 };
203 Service = { 234 Service = {
235 ExecStart = lib.getExe pkgs.psi-notify;
236 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
204 Type = "notify"; 237 Type = "notify";
205 RuntimeDirectory = "gtklock"; 238 Restart = "always";
206 CacheDirectory = "gtklock"; 239 WatchdogSec = "2s";
207 ExecStartPre = [
208 "${pkgs.libsForQt5.qt5.qttools.bin}/bin/qdbus org.keepassxc.KeePassXC.MainWindow /keepassxc org.keepassxc.KeePassXC.MainWindow.lockAllDatabases"
209 "${config.systemd.package}/bin/systemctl --user stop gpg-agent.service"
210 (pkgs.writeShellScript "generate-css" ''
211 set -x
212 export PATH="${lib.makeBinPath [cfg.programs.wpaperd.package pkgs.jq pkgs.coreutils pkgs.imagemagick pkgs.findutils]}:$PATH"
213
214 declare -A monitors
215 monitors=()
216 while IFS= read -r entry; do
217 path=$(jq -r ".path" <<<"$entry")
218 [[ -z "$path" || ! -f "$path" ]] && continue
219 blurred_path="$CACHE_DIRECTORY"/"$(b2sum -l 128 <<<"$path" | cut -d' ' -f1)"."''${path##*.}"
220 monitor=$(jq -r ".display" <<<"$entry")
221 if [[ ! -f "$blurred_path" ]]; then
222 mkdir -p "$(dirname "$blurred_path")"
223 magick "$path" -filter Gaussian -resize 6.25% -define filter:sigma=2.5 -resize 1600% "$blurred_path" &
224 fi
225 monitors+=([$monitor]="$blurred_path")
226 done < <(wpaperctl all-wallpapers -j | jq -c ".[]")
227 wait
228
229 cp --no-preserve=mode ${pkgs.writeText "gtklock.css" ''
230 #window-box {
231 padding: 64px;
232 /* border: 1px solid black; */
233 border-radius: 4px;
234 box-shadow: rgba(0, 0, 0, 0.8) 0px 4px 12px;
235 /* background-color: white; */
236 background-color: rgba(0, 0, 0, 0.5);
237 }
238 ''} "$RUNTIME_DIRECTORY"/style.css
239 for monitor in "''${!monitors[@]}"; do
240 cat >>"$RUNTIME_DIRECTORY"/style.css <<EOF
241 window#''${monitor} {
242 background-image: url("''${monitors[$monitor]}");
243 background-repeat: no-repeat;
244 background-size: 100% 100%;
245 background-origin: content-box;
246 }
247 EOF
248 done
249 '')
250 ];
251 NotifyAccess = "all";
252 ExecStart = ''${lib.getExe pkgs.gtklock} -s "''${RUNTIME_DIRECTORY}/style.css" -L ${pkgs.writeShellScript "after-lock" ''
253 ${cfg.wayland.windowManager.hyprland.package}/bin/hyprctl dispatch dpms off
254 ${config.systemd.package}/bin/systemd-notify --ready
255 ''}'';
256 }; 240 };
257 }; 241 };
258 "yt-dlp@" = { 242 "yt-dlp@" = {
259 Service = { 243 Service = {
260 Type = "notify"; 244 Type = "notify";
261 CacheDirectory = "yt-dlp/%N"; 245 CacheDirectory = "yt-dlp/%N";
246 RuntimeDirectory = "yt-dlp/%N";
262 StandardInput = "socket"; 247 StandardInput = "socket";
263 StandardOutput = "journal"; 248 StandardOutput = "journal";
264 WatchdogSec = "30min"; 249 WatchdogSec = "30min";
250 CPUSchedulingPolicy = "idle";
251 IOSchedulingClass = "idle";
265 Environment = [ 252 Environment = [
266 "PATH=${lib.makeBinPath (with pkgs; [atomicparsley ffmpeg-headless rtmpdump])}" 253 "PATH=${lib.makeBinPath (with pkgs; [atomicparsley ffmpeg-headless rtmpdump])}"
267 "DSCP=8" 254 "DSCP=8"
268 ]; 255 ];
269 ExecStart = ''${lib.getExe pkgs.dscp} ${pkgs.writers.writePython3 "yt-dlp" { 256 ExecStart = ''${lib.getExe pkgs.dscp} ${pkgs.writers.writePython3 "yt-dlp" {
270 libraries = with pkgs.python3Packages; [ yt-dlp sdnotify ]; 257 libraries = with pkgs.python3Packages; [ yt-dlp sdnotify ];
258 flakeIgnore = [ "E501" ];
271 } '' 259 } ''
272 import json 260 import json
273 from yt_dlp import YoutubeDL, parse_options 261 from yt_dlp import YoutubeDL, parse_options
@@ -275,14 +263,46 @@ in {
275 from sdnotify import SystemdNotifier 263 from sdnotify import SystemdNotifier
276 from os import environ 264 from os import environ
277 from pathlib import Path 265 from pathlib import Path
266 import threading
267 import socketserver
268
269
270 status = None
271 status_notifier = threading.Condition()
272
273
274 class StatusRequestHandler(socketserver.BaseRequestHandler):
275 def handle(self):
276 with self.request.makefile('w', encoding='utf-8') as fh:
277 while True:
278 with status_notifier:
279 json.dump(status, fh)
280 fh.write('\n')
281 fh.flush()
282 status_notifier.wait()
278 283
279 284
280 n = SystemdNotifier() 285 class ThreadedUnixStreamServer(socketserver.ThreadingMixIn, socketserver.UnixStreamServer):
286 pass
287
288
289 def progress_hook(d):
290 global status
291 n.notify('WATCHDOG=1\nSTATUS=' + d['status'])
292 with status_notifier:
293 status = {
294 **{k: v for k, v in d.items() if k in {'status', 'downloaded_bytes', 'total_bytes', 'total_bytes_estimate', 'fragment_count', 'fragment_index'}},
295 **{k: v for k, v in (d['info_dict'] if 'info_dict' in d else {}).items() if k in {'title', 'filename'}},
296 }
297 status_notifier.notify_all()
298
299
300 n = SystemdNotifier(debug=True)
281 args = json.load(stdin) 301 args = json.load(stdin)
282 ydl_opts = { 302 ydl_opts = {
283 **parse_options().ydl_opts, 303 **parse_options().ydl_opts,
284 'progress_hooks': [lambda _d: n.notify('WATCHDOG=1')], 304 'progress_hooks': [progress_hook],
285 'postprocessor_hooks': [lambda _d: n.notify('WATCHDOG=1')], 305 'postprocessor_hooks': [progress_hook],
286 'progress_with_newline': True, 306 'progress_with_newline': True,
287 'progress_delta': 5, 307 'progress_delta': 5,
288 'paths': { 308 'paths': {
@@ -292,6 +312,9 @@ in {
292 'noplaylist': True, 312 'noplaylist': True,
293 **(args['params'] if 'params' in args else {}), 313 **(args['params'] if 'params' in args else {}),
294 } 314 }
315 status_server = ThreadedUnixStreamServer(str(Path(environ['RUNTIME_DIRECTORY']) / 'status.sock'), StatusRequestHandler)
316 status_server.daemon_threads = True
317 threading.Thread(target=status_server.serve_forever, daemon=True).start()
295 with YoutubeDL(ydl_opts) as ytdl: 318 with YoutubeDL(ydl_opts) as ytdl:
296 n.notify('READY=1') 319 n.notify('READY=1')
297 ytdl.download(args['urls']) 320 ytdl.download(args['urls'])
@@ -299,38 +322,101 @@ in {
299 ExecStopPost = "${pkgs.coreutils}/bin/rm -rfv \"$CACHE_DIRECTORY\""; 322 ExecStopPost = "${pkgs.coreutils}/bin/rm -rfv \"$CACHE_DIRECTORY\"";
300 }; 323 };
301 }; 324 };
302 wpaperd = { 325 # wpaperd = {
326 # Install = {
327 # WantedBy = ["graphical-session.target"];
328 # };
329 # Unit = {
330 # After = [ "graphical-session.target" ];
331 # PartOf = [ "graphical-session.target" ];
332 # };
333 # Service = {
334 # ExecStart = lib.getExe cfg.services.wpaperd.package;
335 # Type = "simple";
336 # Restart = "always";
337 # RestartSec = "2s";
338 # };
339 # };
340 xembed-sni-proxy = {
341 Unit = {
342 PartOf = lib.mkForce ["tray.target"];
343 };
344 };
345 poweralertd = {
346 Unit = {
347 After = ["graphical-session.target"];
348 };
349 };
350 network-manager-applet = {
351 Unit = {
352 PartOf = lib.mkForce ["tray.target"];
353 };
354 };
355 udiskie = {
356 Unit = {
357 PartOf = lib.mkForce ["tray.target"];
358 };
359 };
360 blueman-applet = {
361 Unit = {
362 PartOf = lib.mkForce ["tray.target"];
363 };
303 Install = { 364 Install = {
304 WantedBy = ["graphical-session.target"]; 365 WantedBy = lib.mkForce ["tray.target"];
305 }; 366 };
367 };
368 alacritty = {
306 Unit = { 369 Unit = {
307 BindsTo = ["graphical-session-pre.target"]; 370 Requisite = ["graphical-session.target"];
308 After = ["graphical-session-pre.target"]; 371 After = [ "graphical-session.target" ];
309 }; 372 };
310 Service = { 373 Service = {
311 ExecStart = lib.getExe cfg.programs.wpaperd.package; 374 ExecStart = "${lib.getExe pkgs.alacritty} --daemon --socket %t/alacritty-activated.sock";
312 Type = "simple"; 375 };
313 Restart = "always"; 376 };
314 RestartSec = "2s"; 377 alacritty-proxy = {
378 Unit = {
379 Requires = ["alacritty.service" "alacritty-proxy.socket"];
380 After = ["alacritty.service" "alacritty-proxy.socket"];
381 };
382 Service = {
383 Type = "notify";
384 ExecStart = "${config.systemd.package}/lib/systemd/systemd-socket-proxyd %t/alacritty-activated.sock";
315 }; 385 };
316 }; 386 };
317 } // listToAttrs (map ({host, port}: nameValuePair "proxy-to-autossh-socks@${toString port}" { 387 } // listToAttrs (map ({host, port}: nameValuePair "proxy-to-autossh-socks@${toString port}" {
318 Unit = { 388 Unit = {
319 Requires = ["autossh-socks@${host}:${toString (port + 1)}.service" "proxy-to-autossh-socks@${toString port}.socket"]; 389 BindsTo = ["autossh-socks@${host}:${toString (port + 1)}.service" "proxy-to-autossh-socks@${toString port}.socket"];
320 After = ["autossh-socks@${host}:${toString (port + 1)}.service" "proxy-to-autossh-socks@${toString port}.socket"]; 390 After = ["autossh-socks@${host}:${toString (port + 1)}.service" "proxy-to-autossh-socks@${toString port}.socket"];
321 }; 391 };
322 Service = { 392 Service = {
323 ExecStart = "${config.systemd.package}/lib/systemd/systemd-socket-proxyd --exit-idle-time=10s localhost:${toString (port + 1)}"; 393 ExecStart = "${config.systemd.package}/lib/systemd/systemd-socket-proxyd --exit-idle-time=60s 127.0.0.1:${toString (port + 1)}";
394 Restart = "always";
395 RestartSec = "23s";
324 }; 396 };
325 }) [{ host = "proxy.mathw0h"; port = 8118; } { host = "proxy.vidhar"; port = 8120; }]); 397 }) [{ host = "proxy.ssh.math.lmu.de"; port = 8118; } { host = "proxy.vidhar"; port = 8120; } { host = "proxy.mathw0h"; port = 8122; } { host = "proxy.mathw0e"; port = 8124; } { host = "proxy.cip04"; port = 8126; }]);
326 sockets = listToAttrs (map (port: nameValuePair "proxy-to-autossh-socks@${toString port}" { 398 sockets = listToAttrs (map (port: nameValuePair "proxy-to-autossh-socks@${toString port}" {
327 Socket = { 399 Socket = {
328 ListenStream = "%I"; 400 ListenStream = "%I";
401 TriggerLimitIntervalSec = 0;
402 PollLimitIntervalSec = "180s";
403 PollLimitBurst = 6;
329 }; 404 };
330 Install = { 405 Install = {
331 WantedBy = ["default.target"]; 406 WantedBy = ["sockets.target"];
407 };
408 }) [8118 8122 8124 8126]) // {
409 "proxy-to-autossh-socks@8120" = {
410 Socket = {
411 ListenStream = "%I";
412 TriggerLimitIntervalSec = 0;
413 PollLimitIntervalSec = "2s";
414 PollLimitBurst = 20;
415 };
416 Install = {
417 WantedBy = ["sockets.target"];
418 };
332 }; 419 };
333 }) [8118 8120]) // {
334 "yt-dlp" = { 420 "yt-dlp" = {
335 Socket = { 421 Socket = {
336 SocketMode = "0600"; 422 SocketMode = "0600";
@@ -342,9 +428,18 @@ in {
342 WantedBy = ["sockets.target"]; 428 WantedBy = ["sockets.target"];
343 }; 429 };
344 }; 430 };
431 "alacritty-proxy" = {
432 Socket = {
433 SocketMode = "0600";
434 ListenStream = "%t/alacritty.sock";
435 };
436 Install = {
437 WantedBy = ["sockets.target"];
438 };
439 };
345 }; 440 };
346 timers = { 441 timers = {
347 sync-keepass = { 442 "sync-keepass@store.kdbx" = {
348 Timer = { 443 Timer = {
349 OnActiveSec = "1m"; 444 OnActiveSec = "1m";
350 OnUnitActiveSec = "1m"; 445 OnUnitActiveSec = "1m";
@@ -354,6 +449,16 @@ in {
354 WantedBy = ["default.target"]; 449 WantedBy = ["default.target"];
355 }; 450 };
356 }; 451 };
452 "sync-keepass@rz.kdbx" = {
453 Timer = {
454 OnActiveSec = "1d";
455 OnUnitActiveSec = "1d";
456 };
457
458 Install = {
459 WantedBy = ["default.target"];
460 };
461 };
357 }; 462 };
358 targets = { 463 targets = {
359 graphical-session = { 464 graphical-session = {
@@ -364,6 +469,9 @@ in {
364 }; 469 };
365 tray = { 470 tray = {
366 Unit = { 471 Unit = {
472 PartOf = [ "graphical-session.target" ];
473 # Requires = [ "waybar.service" ];
474 After = [ "graphical-session.target" ]; # "waybar.service" ];
367 Wants = ["blueman-applet.service" "udiskie.service" "network-manager-applet.service"]; 475 Wants = ["blueman-applet.service" "udiskie.service" "network-manager-applet.service"];
368 }; 476 };
369 }; 477 };