dotfiles/nix/systemd.nix
2024-04-02 18:14:56 +02:00

525 lines
14 KiB
Nix

{
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";
};
};
};
}