{ config, pkgs, ... }: let swayTgt = "sway-session.target"; paths = { inaccessible = [ "-/lost+found" "/dev/shm" "-%h/.ssh" "-%h/.gnupg" "-%h/Documents" # "-%h/Downloads" "-%h/Pictures" "-%h/Videos" "-%h/Sync" "-%h/sync" ]; }; in { systemd.user.services = { kanshi = { Unit = { Description = "Dynamic output configuration for Wayland compositors"; # Documentation = "man:kanshi(1)"; Documentation = "https://sr.ht/~emersion/kanshi"; BindsTo = config.services.kanshi.systemdTarget; }; Service = { Type = "simple"; # ExecStart = "/usr/sbin/kanshi"; ExecStart = "${config.services.kanshi.package}/bin/kanshi"; Restart = "always"; RestartSec = "5s"; LockPersonality = true; PrivateTmp = "yes"; DevicePolicy = "closed"; }; Install = {WantedBy = [config.services.kanshi.systemdTarget];}; }; waybar = { Unit = { Description = "Highly customizable Wayland bar for Sway and Wlroots based compositors."; Documentation = "https://github.com/Alexays/Waybar/wiki/"; PartOf = swayTgt; After = swayTgt; }; Service = { ExecStart = "${pkgs.waybar}/bin/waybar"; ExecReload = "kill -SIGUSR2 $MAINPID"; Restart = "on-failure"; RestartSec = "3s"; LockPersonality = true; PrivateTmp = "yes"; DevicePolicy = "closed"; }; Install = {WantedBy = [swayTgt];}; }; autotiling = { Unit = { Description = "Script for sway and i3 to automatically switch the horizontal / vertical window split orientation"; Documentation = "https://github.com/nwg-piotr/autotiling"; BindsTo = swayTgt; }; Service = { Type = "simple"; ExecStart = "${pkgs.autotiling}/bin/autotiling"; Restart = "always"; RestartSec = "5s"; LockPersonality = true; PrivateTmp = "yes"; DevicePolicy = "closed"; }; Install = {WantedBy = [swayTgt];}; }; albert = { Unit = { Description = "A C++/Qt based desktop agnostic keyboard launcher that helps you to accomplish your workflows in a breeze"; Documentation = "https://albertlauncher.github.io/"; BindsTo = swayTgt; }; Service = { Type = "simple"; # after hm stateVersion bump to 23.05, albert doesn't seem to support explicit wayland. Environment = "QT_QPA_PLATFORM=xcb"; ExecStart = "${pkgs.albert}/bin/albert"; Restart = "always"; RestartSec = "3s"; LockPersonality = true; PrivateTmp = "yes"; DevicePolicy = "closed"; }; Install = {WantedBy = [swayTgt];}; }; avizo = { Unit = { # Description = "brightness/volume OSD"; # Documentation = "https://github.com/misterdanb/avizo"; BindsTo = swayTgt; }; Service = { # Type = "simple"; # ExecStart = "${pkgs.avizo}/bin/avizo-service"; Restart = "always"; RestartSec = "5s"; PrivateTmp = "yes"; # DevicePolicy = "closed"; # NoNewPrivileges = true; # LockPersonality = true; InaccessiblePaths = [ "-/lost+found" "/dev/shm" "-%h/.ssh" "-%h/.gnupg" ]; # KeyringMode = "private"; # SystemCallFilter = "~memfd_create @reboot"; TimeoutStopFailureMode = "abort"; }; Install = {WantedBy = [swayTgt];}; }; gopls = let sock = "/tmp/.gopls-daemon.sock"; in { Unit = { Description = "Go language server"; }; Service = { Type = "simple"; ExecStartPre = "bash -c 'rm -v -f /tmp/.gopls-daemon.sock || true'"; ExecStart = "%h/go/bin/gopls -listen='unix;/tmp/.gopls-daemon.sock'"; ExecStopPost = "bash -c 'rm -v -f /tmp/.gopls-daemon.sock || true'"; Restart = "on-failure"; RestartSec = "1m"; TimeoutStopFailureMode = "abort"; SystemCallFilter = "~@reboot @obsolete"; ProtectProc = "invisible"; ProcSubset = "pid"; ProtectHome = true; RestrictNamespaces = true; NoNewPrivileges = "yes"; ProtectSystem = "strict"; DevicePolicy = "closed"; LockPersonality = true; MemoryDenyWriteExecute = true; #RestrictAddressFamilies="AF_UNIX AF_INET AF_INET6"; RestrictAddressFamilies = "AF_UNIX"; RestrictRealtime = true; RestrictSUIDSGID = true; SystemCallArchitectures = "native"; }; # Install = {WantedBy = [swayTgt];}; Install = {WantedBy = ["default.target"];}; }; ff_nn = let flavour = "firefox-nightly"; in { Unit = { Description = "sh*tbrowser (${flavour})"; PartOf = swayTgt; After = [swayTgt]; }; Service = { # Type = "simple"; Environment = [ "MOZ_ENABLE_WAYLAND=1" "MOZ_DBUS_REMOTE=1" "MOZ_USE_XINPUT2=1" "QT_QPA_PLATFORM=wayland" "XDG_SESSION_TYPE=wayland" "SDL_VIDEODRIVER=wayland" "NO_AT_BRIDGE=1" ]; ExecStart = "-%h/Downloads/${flavour}/firefox-bin -desktop"; Restart = "on-failure"; RestartSec = "5s"; StartLimitBurst = 3; StartLimitInterval = "60s"; TimeoutStopFailureMode = "abort"; KeyringMode = "private"; RestrictNamespaces = true; DevicePolicy = "closed"; ProtectSystem = "strict"; ProtectHome = "tmpfs"; InaccessiblePaths = paths.inaccessible; BindPaths = [ "-%h/Downloads/${flavour}" "-%h/Downloads/toClear" "-%h/.mozilla/firefox" "-%h/.cache/mozilla/firefox" "-%h/.local" "-%h/.fonts" "-%h/.config" ]; NoNewPrivileges = true; ProtectProc = "invisible"; ProcSubset = "pid"; PrivateTmp = "yes"; LockPersonality = true; SystemCallFilter = "~@reboot @obsolete"; SystemCallArchitectures = "native"; }; # Install = {WantedBy = [swayTgt];}; }; voidff = let execPath = "Downloads/lrg/void/firefox"; in { Unit = { Description = "voidfox"; PartOf = swayTgt; After = swayTgt; }; Service = { # Type = "simple"; Environment = [ "MOZ_ENABLE_WAYLAND=1" "MOZ_DBUS_REMOTE=1" "MOZ_USE_XINPUT2=1" "QT_QPA_PLATFORM=wayland" "XDG_SESSION_TYPE=wayland" "SDL_VIDEODRIVER=wayland" "NO_AT_BRIDGE=1" ]; ExecStart = "-%h/${execPath}/firefox-bin -desktop"; Restart = "on-failure"; RestartSec = "5s"; StartLimitBurst = 3; StartLimitInterval = "60s"; TimeoutStopFailureMode = "abort"; RestrictNamespaces = true; DevicePolicy = "closed"; ProtectSystem = "strict"; # ProtectHome = true; ProtectHome = "tmpfs"; InaccessiblePaths = paths.inaccessible; BindPaths = [ "-%h/${execPath}" "-%h/Downloads/toClear" "-%h/.mozilla/firefox" "-%h/.cache/mozilla/firefox" "-%h/.local" "-%h/.fonts" "-%h/.config" ]; NoNewPrivileges = true; ProtectProc = "invisible"; ProcSubset = "pid"; PrivateTmp = "yes"; LockPersonality = true; SystemCallFilter = "~@reboot @obsolete"; SystemCallArchitectures = "native"; }; # Install = {WantedBy = [swayTgt];}; }; battery = { Unit = { Description = "Power Profiles service"; PartOf = swayTgt; }; Service = { Type = "simple"; ExecStart = "%h/.local/bin/battery.sh"; Restart = "on-failure"; RestartSec = "15s"; TimeoutStopFailureMode = "abort"; LockPersonality = true; PrivateTmp = "yes"; DevicePolicy = "closed"; }; }; nextcloud = let composeF = "%h/.nextcloud/docker-compose.yml"; in { Unit = { Description = "Podman container Nextcloud"; PartOf = swayTgt; Wants = "network-online.target"; After = "network-online.target"; RequiresMountsFor = "/run/user/1000/containers"; }; Service = { CPUQuota = "2%"; Slice = "nextcloud.slice"; Environment = "PODMAN_SYSTEMD_UNIT=%n"; Restart = "on-failure"; RestartSec = 5; TimeoutStartSec = 600; # TimeoutStopSec=10; ExecStartPre = "/usr/bin/podman-compose -f ${composeF} -p nextcloud down"; ExecStart = "/usr/bin/podman-compose --podman-run-args=\"--replace\" -f ${composeF} -p nextcloud up --remove-orphans"; ExecStop = "/usr/bin/podman-compose -f ${composeF} -p nextcloud down"; Type = "simple"; Delegate = "no"; ProtectSystem = "strict"; ProtectProc = "invisible"; ProcSubset = "pid"; DevicePolicy = "closed"; NoNewPrivileges = true; LockPersonality = true; InaccessiblePaths = [ "-/lost+found" "/dev/shm" "-%h/.ssh" "-%h/.gnupg" ]; KeyringMode = "private"; SystemCallFilter = "~memfd_create @reboot"; TimeoutStopFailureMode = "abort"; }; Install = { WantedBy = ["default.target"]; }; }; himalaya-watch = { Unit = { Description = "Himalaya watcher"; After = "network.target"; }; Service = { ExecStart = "${pkgs.himalaya}/bin/himalaya watch -a w"; Restart = "always"; RestartSec = 300; Environment = "RUST_LOG=debug"; # ReadWritePaths = "/tmp/himalaya-counter-w"; ProtectHome = "true"; ProtectSystem = "true"; DevicePolicy = "closed"; NoNewPrivileges = true; LockPersonality = true; InaccessiblePaths = [ "-/lost+found" "/dev/shm" "-%h/.ssh" "-%h/.gnupg" ]; # KeyringMode = "private"; }; Install = { WantedBy = ["default.target"]; }; }; himalaya-notify = { Unit = { Description = "Himalaya new message notifier"; After = "network.target"; }; Service = { ExecStart = "${pkgs.himalaya}/bin/himalaya notify"; Restart = "always"; RestartSec = 10; Environment = "RUST_LOG=debug"; ProtectHome = "true"; ProtectSystem = "true"; DevicePolicy = "closed"; NoNewPrivileges = true; LockPersonality = true; InaccessiblePaths = [ "-/lost+found" "/dev/shm" "-%h/.ssh" "-%h/.gnupg" ]; # KeyringMode = "private"; }; Install = { WantedBy = ["default.target"]; }; }; trackerMask = { Unit = {Description = "";}; Service = { Type = "oneshot"; ExecStart = "bash -c 'systemctl --user mask tracker-extract-3.service tracker-miner-fs-3.service tracker-miner-rss-3.service tracker-writeback-3.service tracker-xdg-portal-3.service tracker-miner-fs-control-3.service'"; DevicePolicy = "closed"; NoNewPrivileges = true; LockPersonality = true; InaccessiblePaths = [ "-/lost+found" "/dev/shm" "-%h/.ssh" "-%h/.gnupg" ]; KeyringMode = "private"; }; }; appr120Mask = { Unit = {Description = "";}; Service = { Type = "oneshot"; ExecStart = "bash -c 'systemctl --user mask app-r120@autostart'"; DevicePolicy = "closed"; NoNewPrivileges = true; LockPersonality = true; InaccessiblePaths = [ "-/lost+found" "/dev/shm" "-%h/.ssh" "-%h/.gnupg" ]; KeyringMode = "private"; }; }; }; systemd.user.slices = { chromium = { Unit = { Description = "Slice that limits chromium's resources"; Before = "slices.target"; }; Slice = { CPUAccounting = "yes"; CPUQuota = "220%"; MemoryAccounting = "yes"; MemoryHigh = "6G"; MemoryMax = "6.1G"; }; }; nextcloud = { Unit = {Description = "Slice that limits nextcloud's resources";}; Slice = { MemoryAccounting = "yes"; # MemoryHigh works only in "unified" cgroups mode, NOT in "hybrid" mode MemoryHigh = "250M"; # MemoryMax works in "hybrid" cgroups mode, too MemoryMax = "300M"; CPUAccounting = "yes"; # CPUQuota=15%; CPUQuota = "3%"; }; }; podman = { # refs: # https://baykara.medium.com/docker-resource-management-via-cgroups-and-systemd-633b093a835c # https://docs.docker.com/engine/reference/commandline/dockerd/#docker-runtime-execution-op> Unit = { Description = "Slice that limits podman resources"; Before = "slices.target"; }; Slice = { MemoryAccounting = "yes"; MemoryHigh = "10G"; MemoryMax = "12G"; MemorySwapMax = "1G"; # 100% is an equivalent of full utilization on a single core # we allow for 85% here - applies to all docker.service-spawn # processes cumulatively CPUAccounting = "yes"; # CPUQuota=85%; CPUQuota = "50%"; }; }; }; systemd.user.timers = { battery = { Unit = { Description = "Power Profiles timer"; }; Timer = { OnActiveSec = "20s"; OnUnitActiveSec = "5m"; Unit = "battery.service"; }; Install = { WantedBy = ["timers.target"]; }; }; }; systemd.user.targets = { sway-session = { Unit = { Description = "Sway compositor session"; Documentation = "man:systemd.special(7)"; BindsTo = "graphical-session.target"; Wants = "graphical-session-pre.target"; After = "graphical-session-pre.target"; Before = "xdg-desktop-autostart.target"; }; }; }; }