From fafc04cb0dd3e51b742957be6526fc71c80eec68 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 8 Jan 2026 17:32:18 -0800 Subject: [PATCH] Add Forgejo integration to dev user provisioning - Add programs.ssh.knownHosts for git.clarun.xyz (prevents SSH prompts) - Expose forgejo-api-token via sops-nix for provisioning - dev-add.sh: Create Forgejo account + upload SSH key via API - dev-add.sh: Set up .gitconfig with user.name/email - dev-remove.sh: Print warning to manually suspend Forgejo account Addresses ops-jrz1-qts. Co-Authored-By: Claude Opus 4.5 --- hosts/ops-jrz1.nix | 10 +++++ scripts/dev-add.sh | 86 +++++++++++++++++++++++++++++++++++++++++++ scripts/dev-remove.sh | 13 +++++++ 3 files changed, 109 insertions(+) diff --git a/hosts/ops-jrz1.nix b/hosts/ops-jrz1.nix index fadee0f..ad2118b 100644 --- a/hosts/ops-jrz1.nix +++ b/hosts/ops-jrz1.nix @@ -52,6 +52,9 @@ group = "devs"; mode = "0440"; }; + + # Forgejo API token for dev user provisioning (root only) + forgejo-api-token.mode = "0400"; }; }; @@ -103,6 +106,13 @@ # security.fail2ban-enhanced.enable = true; # security.ssh-hardening.enable = true; + # SSH known hosts for git.clarun.xyz (prevents interactive prompt for devs/agents) + programs.ssh.knownHosts = { + "git.clarun.xyz" = { + publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINs/geVYoQh1ldL2TgyAJy+ErCxaJt91ocgpFRvHDUXl"; + }; + }; + # nix-ld for VS Code Remote-SSH (runs pre-compiled VS Code Server binary) programs.nix-ld.enable = true; programs.nix-ld.libraries = with pkgs; [ diff --git a/scripts/dev-add.sh b/scripts/dev-add.sh index c643786..39c0119 100755 --- a/scripts/dev-add.sh +++ b/scripts/dev-add.sh @@ -7,6 +7,8 @@ # Creates/updates: # - Unix user account with SSH key # - Adds to devs group (Slack token access) +# - Git config (user.name, user.email) +# - Forgejo account for git.clarun.xyz access # - Outputs onboarding instructions set -euo pipefail @@ -159,6 +161,21 @@ Heavy processes may be killed automatically. AGENTS_EOF chown "$username:users" "/home/$username/AGENTS.md" + # Set up git config for proper commit attribution + local gitconfig="/home/$username/.gitconfig" + cat > "$gitconfig" << EOF +[user] + name = $username + email = $username@clarun.xyz +[init] + defaultBranch = main +EOF + chown "$username:users" "$gitconfig" + log_info "Git config created" + + # Provision Forgejo account for git.clarun.xyz access + provision_forgejo "$username" "$ssh_key" + if [[ "$user_exists" == true ]]; then log_info "User updated" else @@ -166,6 +183,67 @@ AGENTS_EOF fi } +provision_forgejo() { + local username="$1" + local ssh_key="$2" + local token_file="/run/secrets/forgejo-api-token" + local forgejo_url="http://localhost:3000" + + # Check if token file exists + if [[ ! -r "$token_file" ]]; then + log_warn "Forgejo API token not found at $token_file" + log_warn "Skipping Forgejo provisioning - user can self-register at https://git.clarun.xyz" + return 0 + fi + + local token + token=$(cat "$token_file") + + # Try to create Forgejo user (ignore if already exists) + local random_pass + random_pass=$(openssl rand -base64 16) + + local http_code + http_code=$(curl -s -o /dev/null -w "%{http_code}" \ + -X POST "$forgejo_url/api/v1/admin/users" \ + -H "Authorization: token $token" \ + -H "Content-Type: application/json" \ + -d "{ + \"username\": \"$username\", + \"email\": \"$username@clarun.xyz\", + \"password\": \"$random_pass\", + \"must_change_password\": true, + \"send_notify\": false + }" 2>/dev/null) || true + + if [[ "$http_code" == "201" ]]; then + log_info "Forgejo user created" + elif [[ "$http_code" == "422" ]]; then + log_info "Forgejo user already exists" + else + log_warn "Forgejo user creation returned HTTP $http_code (may already exist)" + fi + + # Upload SSH key to Forgejo (ignore if already exists) + http_code=$(curl -s -o /dev/null -w "%{http_code}" \ + -X POST "$forgejo_url/api/v1/admin/users/$username/keys" \ + -H "Authorization: token $token" \ + -H "Content-Type: application/json" \ + -d "{ + \"title\": \"dev-server-key\", + \"key\": \"$ssh_key\", + \"read_only\": false + }" 2>/dev/null) || true + + if [[ "$http_code" == "201" ]]; then + log_info "SSH key added to Forgejo" + elif [[ "$http_code" == "422" ]]; then + log_info "SSH key already in Forgejo" + else + log_warn "Forgejo key upload returned HTTP $http_code (may already exist)" + fi +} + print_onboarding() { local username="$1" local server_ip @@ -197,6 +275,14 @@ print_onboarding() { echo " claude # or: gemini" echo " # Follow prompts to authenticate" echo "" + echo "## Git Access" + echo "" + echo " Clone repos from git.clarun.xyz:" + echo " git clone git@git.clarun.xyz:dan/repo-name.git" + echo "" + echo " Your Forgejo account: $username" + echo " Web UI: https://git.clarun.xyz (reset password on first login)" + echo "" echo "## Tools Available" echo " System: python3, uv, git, bun, node, opencode, bd" echo " Install more: bun install -g " diff --git a/scripts/dev-remove.sh b/scripts/dev-remove.sh index 2b08696..328bbea 100755 --- a/scripts/dev-remove.sh +++ b/scripts/dev-remove.sh @@ -6,6 +6,9 @@ # - Unix user account # - Home directory (or archives if --archive flag) # - Maubot plugin symlinks +# +# NOTE: Does NOT delete Forgejo account automatically (too dangerous). +# Manual suspension required via Forgejo admin UI. set -euo pipefail @@ -230,8 +233,18 @@ main() { if [[ "$DRY_RUN" == true ]]; then log_dry "Dry run complete - no changes made" + log_dry "Would print Forgejo suspension reminder" else log_info "Dev '$username' removed successfully" + + # Remind admin to handle Forgejo account + echo "" + log_warn "ACTION REQUIRED: Suspend Forgejo account for '$username'" + echo " Visit: https://git.clarun.xyz/admin/users" + echo " Find user '$username' and either:" + echo " - Prohibit login (keeps repos/PRs intact)" + echo " - Delete user (WARNING: may delete their repos)" + echo "" fi }