split netty configuration.nix into per-service modules, remove sandbox-agent (#34)

Break the monolithic 495-line configuration.nix into focused modules:
- forgejo.nix: Forgejo service, git user, mirror sync timer
- betternas.nix: control-plane + node agent services
- vaultwarden.nix: Vaultwarden service
- nginx.nix: ACME + all Nginx virtualHosts

Remove sandbox-agent entirely (service, CORS proxy, package).
Keep netty.harivan.sh vhost reserved for future use.
This commit is contained in:
Hari 2026-04-01 23:09:27 -04:00 committed by GitHub
parent c97726766a
commit c3fb0fc358
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 297 additions and 4260 deletions

153
hosts/netty/forgejo.nix Normal file
View file

@ -0,0 +1,153 @@
{
pkgs,
username,
...
}:
let
forgejoDomain = "git.harivan.sh";
forgejoApiUrl = "http://127.0.0.1:19300";
in
{
users.users.git = {
isSystemUser = true;
home = "/var/lib/forgejo";
group = "git";
shell = "${pkgs.bash}/bin/bash";
};
users.groups.git = { };
services.forgejo = {
enable = true;
user = "git";
group = "git";
settings = {
repository = {
FORCE_PRIVATE = true;
DEFAULT_PRIVATE = "private";
DEFAULT_PUSH_CREATE_PRIVATE = true;
};
server = {
DOMAIN = forgejoDomain;
ROOT_URL = "https://${forgejoDomain}/";
HTTP_PORT = 19300;
SSH_DOMAIN = forgejoDomain;
};
service = {
DISABLE_REGISTRATION = true;
REQUIRE_SIGNIN_VIEW = true;
};
session.COOKIE_SECURE = true;
mirror = {
DEFAULT_INTERVAL = "1h";
MIN_INTERVAL = "10m";
};
};
};
# --- Forgejo mirror sync (hourly) ---
systemd.services.forgejo-mirror-sync = {
description = "Sync GitHub mirrors to Forgejo";
after = [ "forgejo.service" ];
requires = [ "forgejo.service" ];
serviceConfig = {
Type = "oneshot";
EnvironmentFile = "/etc/forgejo-mirror.env";
};
path = [
pkgs.curl
pkgs.jq
pkgs.coreutils
pkgs.gnused
];
script = ''
set -euo pipefail
api_call() {
local response http_code body
response=$(curl -sS -w "\n%{http_code}" "$@")
http_code=$(printf '%s\n' "$response" | tail -n1)
body=$(printf '%s\n' "$response" | sed '$d')
if [ "$http_code" -ge 400 ]; then
printf '[forgejo-mirror-sync] HTTP %s\n' "$http_code" >&2
printf '%s\n' "$body" >&2
return 1
fi
printf '%s' "$body"
}
gh_user=$(api_call -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/user" | jq -r '.login')
repos_file=$(mktemp)
trap 'rm -f "$repos_file"' EXIT
page=1
while true; do
batch=$(api_call -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/user/repos?per_page=100&page=$page&visibility=all&affiliation=owner,organization_member")
count=$(printf '%s' "$batch" | jq length)
[ "$count" -eq 0 ] && break
printf '%s' "$batch" | jq -r '.[] | [.full_name, .clone_url] | @tsv' >> "$repos_file"
page=$((page + 1))
done
sort -u "$repos_file" -o "$repos_file"
while IFS=$'\t' read -r full_name clone_url; do
repo_owner="''${full_name%%/*}"
repo_name="''${full_name#*/}"
if [ "$repo_owner" = "$gh_user" ]; then
forgejo_repo_name="$repo_name"
else
forgejo_repo_name="$repo_owner--$repo_name"
fi
status=$(curl -sS -o /dev/null -w '%{http_code}' \
-H "Authorization: token $FORGEJO_TOKEN" \
"${forgejoApiUrl}/api/v1/repos/$FORGEJO_OWNER/$forgejo_repo_name" || true)
if [ "$status" = "404" ]; then
api_call -X POST \
-H "Authorization: token $FORGEJO_TOKEN" \
-H "Content-Type: application/json" \
"${forgejoApiUrl}/api/v1/repos/migrate" \
-d "$(jq -n \
--arg addr "$clone_url" \
--arg name "$forgejo_repo_name" \
--arg owner "$FORGEJO_OWNER" \
--arg token "$GITHUB_TOKEN" \
'{
clone_addr: $addr,
repo_name: $name,
repo_owner: $owner,
private: true,
mirror: true,
auth_token: $token,
service: "github"
}')" \
> /dev/null
echo "Created mirror: $full_name -> $FORGEJO_OWNER/$forgejo_repo_name"
else
if ! api_call -X POST \
-H "Authorization: token $FORGEJO_TOKEN" \
"${forgejoApiUrl}/api/v1/repos/$FORGEJO_OWNER/$forgejo_repo_name/mirror-sync" \
> /dev/null; then
echo "Failed mirror sync: $full_name -> $FORGEJO_OWNER/$forgejo_repo_name" >&2
continue
fi
echo "Synced mirror: $full_name -> $FORGEJO_OWNER/$forgejo_repo_name"
fi
done < "$repos_file"
'';
};
systemd.timers.forgejo-mirror-sync = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "hourly";
Persistent = true;
RandomizedDelaySec = "5m";
};
};
}