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 <noreply@anthropic.com>
This commit is contained in:
Dan 2026-01-08 17:32:18 -08:00
parent ba949239a5
commit fafc04cb0d
3 changed files with 109 additions and 0 deletions

View file

@ -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; [

View file

@ -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 <package>"

View file

@ -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
}