summaryrefslogtreecommitdiff
path: root/modules/nixos/services/github-mirror
diff options
context:
space:
mode:
authorseth <[email protected]>2024-10-27 20:12:19 -0400
committerGitHub <[email protected]>2024-10-28 00:12:19 +0000
commit5ec7ee21e036f7bc1cbdec714271c619cb3fdb3d (patch)
tree3277d8ba68ca466e68c58a8373063010db392d2e /modules/nixos/services/github-mirror
parent75ec48c5f7dd7877f2294b86764b1fdadc6b7e88 (diff)
modules: restructure (#487)
* seth: remove unused pkgs * modules: restructure from archetypes back to profiles make less actual modules for everything use lib.mkDefault like it's supposed to move mixins out of server * nixos/resolved: use modern options
Diffstat (limited to 'modules/nixos/services/github-mirror')
-rw-r--r--modules/nixos/services/github-mirror/default.nix101
-rwxr-xr-xmodules/nixos/services/github-mirror/update-mirror.sh78
2 files changed, 179 insertions, 0 deletions
diff --git a/modules/nixos/services/github-mirror/default.nix b/modules/nixos/services/github-mirror/default.nix
new file mode 100644
index 0000000..9d0d870
--- /dev/null
+++ b/modules/nixos/services/github-mirror/default.nix
@@ -0,0 +1,101 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+let
+ cfg = config.services.github-mirror;
+ cgitInstance = config.services.cgit.${cfg.hostname};
+
+ update-mirror =
+ pkgs.runCommand "update-mirror"
+ {
+ nativeBuildInputs = [ pkgs.patsh ];
+
+ buildInputs = [
+ config.programs.git.package
+ pkgs.curl
+ pkgs.jq
+ ];
+ }
+ ''
+ patsh -s ${builtins.storeDir} ${./update-mirror.sh} $out
+ chmod 755 $out
+ patchShebangs $out
+ '';
+in
+{
+ options.services.github-mirror = {
+ enable = lib.mkEnableOption "the github-mirror service";
+
+ hostname = lib.mkOption {
+ type = lib.types.str;
+ description = "Hostname of the cgit service to create";
+ example = lib.literalExpression "git.example.com";
+ };
+
+ mirroredUsers = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ description = "List of GitHub users to mirror repositories for";
+ example = lib.literalExpression ''[ "edolstra" ]'';
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = cfg.mirroredUsers != [ ];
+ message = "`services.git-mirror.mirroredUsers` must have at least one user";
+ }
+ ];
+
+ services.cgit.${cfg.hostname} = {
+ enable = true;
+
+ scanPath = "/var/lib/cgit/${cfg.hostname}";
+ settings = {
+ robots = "none"; # noindex, nofollow
+ };
+
+ user = "cgit";
+ group = "cgit";
+ };
+
+ systemd = {
+ services.github-mirror = {
+ description = "Mirror a GitHub repository";
+
+ after = [ "network-online.target" ];
+ wants = [ "network-online.target" ];
+
+ script = toString (
+ [
+ "exec"
+ (toString update-mirror)
+ "--directory"
+ cgitInstance.scanPath
+ ]
+ ++ cfg.mirroredUsers
+ );
+
+ serviceConfig = {
+ Type = "oneshot";
+ User = cgitInstance.user;
+ Group = cgitInstance.group;
+ };
+ };
+
+ timers.github-mirror = {
+ description = "Hourly timer for %N";
+ timerConfig.OnCalendar = "hourly";
+ };
+
+ tmpfiles.settings."10-github-mirror" = {
+ ${cgitInstance.scanPath}.d = {
+ inherit (cgitInstance) user group;
+ };
+ };
+ };
+ };
+}
diff --git a/modules/nixos/services/github-mirror/update-mirror.sh b/modules/nixos/services/github-mirror/update-mirror.sh
new file mode 100755
index 0000000..c1e392d
--- /dev/null
+++ b/modules/nixos/services/github-mirror/update-mirror.sh
@@ -0,0 +1,78 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+help() {
+ echo "Mirror a GitHub user's repositories
+
+Usage: $(basename "$0") [options] <user>...
+
+Options:
+ -h --help Show this screen
+ -d --directory DIRECTORY Where to clone repositories (defaults to ./git)"
+}
+
+create_if_not_exists() {
+ if [ ! -d "$1" ]; then
+ mkdir -p "$1"
+ fi
+}
+
+repo_endpoint() {
+ echo "https://api.github.com/users/$1/repos"
+}
+
+users=()
+output_directory="git"
+
+while [ "$#" -gt 0 ]; do
+ case $1 in
+ -h | --help)
+ help
+ exit 0
+ ;;
+ -d | --directory)
+ output_directory="$2"
+ shift
+ shift
+ ;;
+ -*)
+ echo "error: unknown option $1"
+ help
+ exit 1
+ ;;
+ *)
+ users+=("$1")
+ shift
+ ;;
+ esac
+done
+
+if [ "${#users[@]}" -lt 1 ]; then
+ echo "error: at least one user must be specified"
+ help
+ exit 1
+fi
+
+create_if_not_exists "$output_directory"
+cd "$output_directory"
+
+for user in "${users[@]}"; do
+ create_if_not_exists "$user"
+
+ url="$(repo_endpoint "$user")"
+ curl --fail --location --show-error --silent "$url" | jq --raw-output '.[].name' | while read -r repo; do
+ repo_path="$user"/"$repo"
+
+ if [ -d "$repo_path"/.git ]; then
+ pushd "$repo_path" &>/dev/null
+ echo "Pulling $repo_path..."
+ if ! git remote update --prune &>/dev/null; then
+ echo "Unable to pull $repo_path! Continuing..."
+ fi
+ popd &>/dev/null
+ else
+ echo "Cloning $repo_path..."
+ git clone --bare --mirror https://github.com/"$repo_path".git "$repo_path" &>/dev/null
+ fi
+ done
+done