Systemd Services#
Using Systemd seemed like the only choice available for the setup of some of these services. Systemd provided the service management, dependency handling, and monitoring I needed.
Service Management#
Most of these scripts only need to run if the server is unconfigured. Using systemd I can set these scripts to be oneshot services.
serviceConfig = {
Type = "oneshot"
}Below is an example service for k3s to ensure the API is online before attempting to apply the manifest files.
systemd.services = builtins.listToAttrs (map (file: let
manifestName = file;
in {
name = "k3s_Install_${lib.replaceStrings ["."] ["_"] manifestName}";
value = {
description = "Copy ${manifestName} manifest and restart k3s";
after = ["systemd-tmpfiles-setup.service" "network.target" "k3s.service" "boot-unlock-service.service"];
wantedBy = ["multi-user.target"];
serviceConfig = {
Type = "oneshot";
ExecStartPre = "${pkgs.bash}/bin/bash -c 'until ${pkgs.kubectl}/bin/kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get nodes &>/dev/null; do echo Waiting for K3s API...; sleep 2; done'";
ExecStart = ''
${pkgs.coreutils}/bin/install -Dm644 /etc/k3s/${manifestName} /var/lib/rancher/k3s/server/manifests/${manifestName}
'';
ExecStartPost = "${pkgs.kubectl}/bin/kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml apply -f /var/lib/rancher/k3s/server/manifests/${manifestName}";
};
};
})
configFiles);Dependency Handling#
Being able to use wants, after, ExecStartPre, ExecStarPost allows for management of dependencies.
Most of the time in the scripts and tools we need networking or other services available.
Using the same example as above this code shows the dependencies needed before this service can start.
In this case it is systemd-tmpfiles-setup, network, k3s, boot-unlock-service
systemd.services = builtins.listToAttrs (map (file: let
manifestName = file;
in {
name = "k3s_Install_${lib.replaceStrings ["."] ["_"] manifestName}";
value = {
description = "Copy ${manifestName} manifest and restart k3s";
after = ["systemd-tmpfiles-setup.service" "network.target" "k3s.service" "boot-unlock-service.service"];
wantedBy = ["multi-user.target"];
serviceConfig = {
Type = "oneshot";
ExecStartPre = "${pkgs.bash}/bin/bash -c 'until ${pkgs.kubectl}/bin/kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get nodes &>/dev/null; do echo Waiting for K3s API...; sleep 2; done'";
ExecStart = ''
${pkgs.coreutils}/bin/install -Dm644 /etc/k3s/${manifestName} /var/lib/rancher/k3s/server/manifests/${manifestName}
'';
ExecStartPost = "${pkgs.kubectl}/bin/kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml apply -f /var/lib/rancher/k3s/server/manifests/${manifestName}";
};
};
})
configFiles);Monitoring#
All of the services are able to be monitored through journalctl.