summaryrefslogtreecommitdiffstats
path: root/system
diff options
context:
space:
mode:
authorSoispha <soispha@vhack.eu>2023-07-03 08:49:41 +0200
committerSoispha <soispha@vhack.eu>2023-07-03 14:26:40 +0200
commit3f2fedfb794a1fccf4581a9cef5eaf4fd1c837a7 (patch)
treeba11fac01f887359954073c9e53712d7e8a5e4a3 /system
parentFix(system/fs-layout): Remove persistent dir as it's now in /srv (diff)
downloadnixos-server-3f2fedfb794a1fccf4581a9cef5eaf4fd1c837a7.zip
Feat(system/services/nix-sync): Remodel git-sync to make it useful
Diffstat (limited to '')
-rw-r--r--system/services/git-sync/default.nix99
-rw-r--r--system/services/nix-sync/default.nix193
2 files changed, 193 insertions, 99 deletions
diff --git a/system/services/git-sync/default.nix b/system/services/git-sync/default.nix
deleted file mode 100644
index 4295870..0000000
--- a/system/services/git-sync/default.nix
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
-Taken from:
-https://github.com/nix-community/home-manager/blob/9ba7b3990eb1f4782ea3f5fe7ac4f3c88dd7a32c/modules/services/git-sync.nix
-*/
-{
- config,
- lib,
- pkgs,
- ...
-}: let
- cfg = config.services.git-sync;
-
- mkUnit = name: repo: {
- unitConfig.Description = "Git Sync ${name}";
-
- wantedBy = ["default.target"];
-
- serviceConfig = {
- Environment = [
- "PATH=${lib.makeBinPath (with pkgs; [openssh git])}"
- "GIT_SYNC_DIRECTORY=${repo.path}"
- "GIT_SYNC_COMMAND=${cfg.package}/bin/git-sync"
- "GIT_SYNC_REPOSITORY=${repo.uri}"
- "GIT_SYNC_INTERVAL=${toString repo.interval}"
- ];
- ExecStart = "${cfg.package}/bin/git-sync-on-inotify";
- Restart = "on-abort";
- };
- };
-
- services =
- lib.mapAttrs' (name: repo: {
- name = "git-sync-${name}";
- value = mkUnit name repo;
- })
- cfg.repositories;
-
- repositoryType = lib.types.submodule ({name, ...}: {
- options = {
- name = lib.mkOption {
- internal = true;
- default = name;
- type = lib.types.str;
- description = "The name that should be given to this unit.";
- };
-
- path = lib.mkOption {
- type = lib.types.str;
- description = "The path at which to sync the repository";
- };
-
- uri = lib.mkOption {
- type = lib.types.str;
- example = "git+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
- <link xlink:href="https://git-scm.com/docs/git-clone#_git_urls"/>
- for the supported URIs.
- '';
- };
-
- interval = lib.mkOption {
- type = lib.types.int;
- default = 500;
- description = ''
- The interval, specified in seconds, at which the synchronization will
- be triggered even without filesystem changes.
- '';
- };
- };
- });
-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.
- '';
- };
-
- repositories = lib.mkOption {
- type = with lib.types; attrsOf repositoryType;
- description = ''
- The repositories that should be synchronized.
- '';
- };
- };
- };
-
- config = lib.mkIf cfg.enable {
- systemd.services = services;
- };
-}
diff --git a/system/services/nix-sync/default.nix b/system/services/nix-sync/default.nix
new file mode 100644
index 0000000..18511b3
--- /dev/null
+++ b/system/services/nix-sync/default.nix
@@ -0,0 +1,193 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}: let
+ cfg = config.services.nix-sync;
+
+ mkUnit = name: repo: let
+ esa = lib.strings.escapeShellArg;
+ execStartScript = lib.writeShellScript "git-sync-exec" ''
+ cd ${esa cfg.cachePath}/${esa repo.path};
+
+ while true; do
+ origin="$(git rev-parse @{u})";
+ branch="$(git rev-parse @)";
+
+ 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
+ '';
+ 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};
+
+ out_paths=$(mktemp);
+ nix build ${esa cfg.cachePath}/${esa repo.path} --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";
+ fi
+ '';
+ in {
+ description = "Nix Sync ${name}";
+ wantedBy = ["default.target"];
+ after = ["network.target"];
+ path = with pkgs; [openssh git nix mktemp coreutils];
+ preStart = execStartPreScript;
+
+ serviceConfig = {
+ ExecStart = execStartScript;
+ Restart = "on-abort";
+ # User and group
+ User = cfg.user;
+ Group = cfg.group;
+ # Runtime directory and mode
+ RuntimeDirectory = "nginx";
+ RuntimeDirectoryMode = "0750";
+ # Cache directory and mode
+ CacheDirectory = "nginx";
+ CacheDirectoryMode = "0750";
+ # Logs directory and mode
+ LogsDirectory = "nginx";
+ LogsDirectoryMode = "0750";
+ # Proc filesystem
+ ProcSubset = "pid";
+ ProtectProc = "invisible";
+ # New file permissions
+ UMask = "0027"; # 0640 / 0750
+ # Capabilities
+ AmbientCapabilities = ["CAP_CHOWN"];
+ CapabilityBoundingSet = ["CAP_CHOWN"];
+ # 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}"];
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ PrivateTmp = true;
+ PrivateDevices = true;
+ ProtectHostname = true;
+ ProtectClock = true;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectKernelLogs = true;
+ ProtectControlGroups = true;
+ RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"];
+ RestrictNamespaces = true;
+ LockPersonality = true;
+ MemoryDenyWriteExecute = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ RemoveIPC = true;
+ PrivateMounts = true;
+ # System Call Filtering
+ SystemCallArchitectures = "native";
+ SystemCallFilter = ["~@cpu-emulation @debug @keyring @mount @obsolete @privileged @setuid"];
+ };
+ };
+
+ services =
+ lib.mapAttrs' (name: repo: {
+ name = "git-sync-${name}";
+ value = mkUnit name repo;
+ })
+ cfg.repositories;
+
+ repositoryType = lib.types.submodule ({name, ...}: {
+ options = {
+ name = lib.mkOption {
+ internal = true;
+ default = name;
+ type = lib.types.str;
+ description = "The name that should be given to this unit.";
+ };
+
+ path = lib.mkOption {
+ type = lib.types.str;
+ description = "The path at which to sync the repository";
+ };
+
+ uri = lib.mkOption {
+ type = lib.types.str;
+ example = "git+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
+ <link xlink:href="https://git-scm.com/docs/git-clone#_git_urls"/>
+ for the supported URIs.
+ '';
+ };
+
+ interval = lib.mkOption {
+ type = lib.types.int;
+ default = 500;
+ description = ''
+ The interval, specified in seconds, at which the synchronization will
+ be triggered even without filesystem changes.
+ '';
+ };
+ };
+ });
+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.
+ '';
+ };
+
+ user = lib.mkOption {
+ type = lib.types.str;
+ default = "nix-sync";
+ description = lib.mdDoc "User account under which nix-sync units runs.";
+ };
+
+ group = lib.mkOption {
+ type = lib.types.str;
+ default = "nix-sync";
+ description = lib.mdDoc "Group account under which nix-sync units runs.";
+ };
+
+ cachePath = lib.mkOption {
+ type = lib.types.str;
+ default = "/var/lib/nix-sync";
+ description = lib.mdDoc ''
+ Where to cache git directories.
+ '';
+ };
+
+ repositories = lib.mkOption {
+ type = with lib.types; attrsOf repositoryType;
+ description = ''
+ The repositories that should be synchronized.
+ '';
+ };
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ systemd.services = services;
+ };
+}
+# vim: ts=2
+