summaryrefslogtreecommitdiffstats
path: root/system/services/nix-sync
diff options
context:
space:
mode:
Diffstat (limited to 'system/services/nix-sync')
-rw-r--r--system/services/nix-sync/default.nix159
1 files changed, 115 insertions, 44 deletions
diff --git a/system/services/nix-sync/default.nix b/system/services/nix-sync/default.nix
index 18511b3..5c2ed80 100644
--- a/system/services/nix-sync/default.nix
+++ b/system/services/nix-sync/default.nix
@@ -6,47 +6,85 @@
}: let
cfg = config.services.nix-sync;
+ mkTimer = name: repo: {
+ description = "Nix sync ${name} timer";
+ wantedBy = ["timers.target"];
+ timerConfig = {
+ OnActiveSec = repo.interval;
+ };
+ after = ["network-online.target"];
+ };
+
+ parents = path: let
+ split_path = builtins.split "/" path;
+ filename = builtins.elemAt split_path (builtins.length split_path - 1);
+ in
+ lib.strings.removeSuffix "/" (builtins.replaceStrings [filename] [""] path);
+ esa = lib.strings.escapeShellArg;
mkUnit = name: repo: let
- esa = lib.strings.escapeShellArg;
- execStartScript = lib.writeShellScript "git-sync-exec" ''
- cd ${esa cfg.cachePath}/${esa repo.path};
+ optionalPathSeparator =
+ if lib.strings.hasPrefix "/" repo.path
+ then ""
+ else "/";
+ repoCachePath = cfg.cachePath + optionalPathSeparator + repo.path;
+ execStartScript = pkgs.writeScript "nix-sync-exec" ''
+ #! /usr/bin/env dash
+ export XDG_CACHE_HOME="$CACHE_DIRECTORY";
+ cd ${esa repoCachePath};
- while true; do
- origin="$(git rev-parse @{u})";
- branch="$(git rev-parse @)";
+ git fetch
+ origin="$(git rev-parse @{u})";
+ branch="$(git rev-parse @)";
- if ! [ "$origin" = "$branch" ]; then
- git pull;
+ if ! [ "$origin" = "$branch" ]; then
+ git pull;
- out_paths=$(mktemp);
- nix build . --print-out-paths --experimental-features 'nix-command flakes' > "$out_paths";
- [ "$(wc -l < "$out_paths")" -gt 1 ] && (echo "To many out-paths"; exit 1)
- out_path="$(cat "$out_paths")";
- rm -r ${esa repo.path};
- ln -s "$out_path" ${esa repo.path};
- rm "$out-paths";
- fi
- sleep ${esa repo.interval};
- done
+ out_paths=$(mktemp);
+ nix build . --print-out-paths --experimental-features 'nix-command flakes' > "$out_paths";
+ [ "$(wc -l < "$out_paths")" -gt 1 ] && (echo "To many out-paths"; exit 1)
+ out_path="$(cat "$out_paths")";
+ rm ${esa repo.path};
+ ln -s "$out_path" ${esa repo.path};
+ rm "$out_paths";
+ fi
'';
execStartPreScript = ''
- if ! stat ${esa cfg.cachePath}/${esa repo.path}/.git; then
- mkdir --parents ${esa cfg.cachePath}/${esa repo.path};
- git clone ${esa repo.uri} ${esa cfg.cachePath}/${esa repo.path};
+ export XDG_CACHE_HOME="$CACHE_DIRECTORY";
+
+ if ! [ -d ${esa repoCachePath}/.git ]; then
+ mkdir --parents ${esa repoCachePath};
+ git clone ${esa repo.uri} ${esa repoCachePath};
out_paths=$(mktemp);
- nix build ${esa cfg.cachePath}/${esa repo.path} --print-out-paths --experimental-features 'nix-command flakes' > "$out_paths";
+ nix build ${esa repoCachePath} --print-out-paths --experimental-features 'nix-command flakes' > "$out_paths";
[ "$(wc -l < "$out_paths")" -gt 1 ] && (echo "To many out-paths"; exit 1)
out_path="$(cat "$out_paths")";
ln -s "$out_path" ${esa repo.path};
- rm "$out-paths";
+ rm "$out_paths";
+ fi
+
+ if ! [ -L ${esa repo.path} ]; then
+ cd ${esa repoCachePath};
+
+ git pull;
+
+ out_paths=$(mktemp);
+ nix build . --print-out-paths --experimental-features 'nix-command flakes' > "$out_paths";
+ [ "$(wc -l < "$out_paths")" -gt 1 ] && (echo "To many out-paths"; exit 1)
+ out_path="$(cat "$out_paths")";
+
+ [ -d ${esa repo.path} ] && rm -d ${esa repo.path};
+ [ -e ${esa repo.path} ] && rm ${esa repo.path};
+
+ ln -s "$out_path" ${esa repo.path};
+ rm "$out_paths";
fi
'';
in {
description = "Nix Sync ${name}";
wantedBy = ["default.target"];
after = ["network.target"];
- path = with pkgs; [openssh git nix mktemp coreutils];
+ path = with pkgs; [openssh git nix mktemp coreutils dash];
preStart = execStartPreScript;
serviceConfig = {
@@ -56,16 +94,16 @@
User = cfg.user;
Group = cfg.group;
# Runtime directory and mode
- RuntimeDirectory = "nginx";
+ RuntimeDirectory = "nix-sync";
RuntimeDirectoryMode = "0750";
# Cache directory and mode
- CacheDirectory = "nginx";
+ CacheDirectory = "nix-sync";
CacheDirectoryMode = "0750";
# Logs directory and mode
- LogsDirectory = "nginx";
+ LogsDirectory = "nix-sync";
LogsDirectoryMode = "0750";
# Proc filesystem
- ProcSubset = "pid";
+ ProcSubset = "all";
ProtectProc = "invisible";
# New file permissions
UMask = "0027"; # 0640 / 0750
@@ -75,7 +113,8 @@
# Security
NoNewPrivileges = true;
# Sandboxing (sorted by occurrence in https://www.freedesktop.org/software/systemd/man/systemd.exec.html)
- ReadWritePaths = ["${repo.path}" "${cfg.cachePath}/${repo.path}"];
+ ReadWritePaths = ["${esa (parents repo.path)}" "-${esa repoCachePath}" "-${esa cfg.cachePath}"];
+ ReadOnlyPaths = ["/nix"];
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
@@ -102,10 +141,23 @@
services =
lib.mapAttrs' (name: repo: {
- name = "git-sync-${name}";
+ name = "nix-sync-${name}";
value = mkUnit name repo;
})
cfg.repositories;
+ timers =
+ lib.mapAttrs' (name: repo: {
+ name = "nix-sync-${name}";
+ value = mkTimer name repo;
+ })
+ cfg.repositories;
+
+ # generate the websites directory, so systemd can mount it read write
+ generatedDirectories =
+ lib.mapAttrsToList (
+ _: repo: "d ${esa (parents repo.path)} 0755 ${cfg.user} ${cfg.group}"
+ )
+ cfg.repositories;
repositoryType = lib.types.submodule ({name, ...}: {
options = {
@@ -123,7 +175,7 @@
uri = lib.mkOption {
type = lib.types.str;
- example = "git+ssh://user@example.com:/~[user]/path/to/repo.git";
+ example = "ssh://user@example.com:/~[user]/path/to/repo.git";
description = ''
The URI of the remote to be synchronized. This is only used in the
event that the directory does not already exist. See
@@ -137,24 +189,15 @@
default = 500;
description = ''
The interval, specified in seconds, at which the synchronization will
- be triggered even without filesystem changes.
+ be triggered.
'';
};
};
});
in {
options = {
- services.git-sync = {
- enable = lib.mkEnableOption "git-sync services";
-
- package = lib.mkOption {
- type = lib.types.package;
- default = pkgs.git-sync;
- defaultText = lib.literalExpression "pkgs.git-sync";
- description = ''
- Package containing the <command>git-sync</command> program.
- '';
- };
+ services.nix-sync = {
+ enable = lib.mkEnableOption "nix-sync services";
user = lib.mkOption {
type = lib.types.str;
@@ -172,7 +215,7 @@ in {
type = lib.types.str;
default = "/var/lib/nix-sync";
description = lib.mdDoc ''
- Where to cache git directories.
+ Where to cache git directories. Should not end with a slash ("/")
'';
};
@@ -186,7 +229,35 @@ in {
};
config = lib.mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = !lib.strings.hasSuffix "/" cfg.cachePath;
+ message = "Your cachePath ('${cfg.cachePath}') ends with a slash ('/'), please use: '${lib.strings.removeSuffix "/" cfg.cachePath}'.";
+ }
+ ];
+
+ systemd.tmpfiles.rules =
+ generatedDirectories;
+
systemd.services = services;
+ systemd.timers = timers;
+ users.users =
+ if cfg.user == "nix-sync"
+ then {
+ nix-sync = {
+ group = "${cfg.group}";
+ isSystemUser = true;
+ };
+ }
+ else lib.warnIf (cfg.user != "nix-sync") "The user (${cfg.user}) is not \"nix-sync\", thus you are responible for generating it.";
+ users.groups =
+ if cfg.group == "nix-sync"
+ then {
+ nix-sync = {
+ members = ["${cfg.user}"];
+ };
+ }
+ else lib.warnIf (cfg.group != "nix-sync") "The group (${cfg.group}) is not \"nix-sync\", thus you are responible for generating it.";
};
}
# vim: ts=2