feat: convert to shell script and improve documentation

This commit is contained in:
robojerk 2025-06-03 15:14:37 -07:00
parent 96a5720497
commit 0ecdeadfd5
5 changed files with 527 additions and 238 deletions

330
forgejo-ssh-key-setup.sh Normal file
View file

@ -0,0 +1,330 @@
#!/bin/sh
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
NC='\033[0m' # No Color
# Function to validate email format
validate_email() {
echo "$1" | grep -E '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' >/dev/null
return $?
}
# Function to validate token format
validate_token() {
echo "$1" | grep -E '^[a-fA-F0-9]{64}$' >/dev/null
return $?
}
# Function to validate Forgejo URL format
validate_forgejo_url() {
echo "$1" | grep -E '^https?://[a-zA-Z0-9.-]+(:[0-9]+)?$|^[a-zA-Z0-9.-]+(:[0-9]+)?$' >/dev/null
return $?
}
# Function to generate signature
generate_signature() {
local token="$1"
local private_key_path="$2"
# Validate parameters
if [ ! -f "$private_key_path" ]; then
echo -e "${RED}Error: Private key not found at path: $private_key_path${NC}"
exit 1
fi
# Normalize token format
token=$(echo "$token" | tr '[:upper:]' '[:lower:]' | tr -d ' ')
# Debug: Check token format
echo -e "\n${GRAY}Debug: Token format check:${NC}"
echo -e "${GRAY}Length: ${#token}${NC}"
echo -e "${GRAY}Format: $(echo "$token" | grep -E '^[a-f0-9]{64}$' >/dev/null && echo "valid" || echo "invalid")${NC}"
# Generate signature
echo -e "\n${GRAY}Generating signature...${NC}"
signature=$(echo -n "$token" | ssh-keygen -Y sign -n gitea -f "$private_key_path" 2>&1)
# Debug: Check raw output
echo -e "\n${GRAY}Debug: Raw signature output:${NC}"
echo "$signature" | while IFS= read -r line; do
echo -e "${GRAY} $line${NC}"
done
# Filter the output to get only the signature block
signature=$(echo "$signature" | grep -E '^(-----BEGIN SSH SIGNATURE-----|-----END SSH SIGNATURE-----|[A-Za-z0-9+/=]+)$')
# Debug: Check filtered signature
echo -e "\n${GRAY}Debug: Filtered signature:${NC}"
echo "$signature" | while IFS= read -r line; do
echo -e "${GRAY} $line${NC}"
done
# Verify signature format
if ! echo "$signature" | grep -q '^-----BEGIN SSH SIGNATURE-----' || \
! echo "$signature" | grep -q '-----END SSH SIGNATURE-----' || \
! echo "$signature" | grep -E '^-----BEGIN SSH SIGNATURE-----\r?\n[A-Za-z0-9+/=]+\r?\n-----END SSH SIGNATURE-----\r?$' >/dev/null; then
echo -e "${YELLOW}Warning: Signature format may be incorrect or incomplete.${NC}"
fi
echo "$signature"
}
# --- Get Forgejo Location ---
forgejo_location=""
while ! validate_forgejo_url "$forgejo_location"; do
echo -e "\n${CYAN}Please enter your Forgejo location (e.g., forgejo.example.com or 192.168.1.100:3000)${NC}"
read -r forgejo_location
if ! validate_forgejo_url "$forgejo_location"; then
echo -e "${RED}Invalid format. Please enter a valid URL or IP address.${NC}"
fi
done
# Remove http:// or https:// if present
forgejo_location=$(echo "$forgejo_location" | sed -E 's|^https?://||')
# --- SSH Key Generation ---
# Get user's email for key comment
email=""
while ! validate_email "$email"; do
echo -e "\n${CYAN}Please enter your email address for your SSH key comment (e.g., user@example.com)${NC}"
read -r email
if ! validate_email "$email"; then
echo -e "${RED}Invalid email format. Please try again.${NC}"
fi
done
# Generate SSH key
echo -e "\n${CYAN}--- Generating SSH Key ---${NC}"
echo -e "${YELLOW}You'll be prompted for a passphrase. Please remember it and keep it safe!${NC}"
private_key_path="$HOME/.ssh/id_ed25519"
public_key_path="$HOME/.ssh/id_ed25519.pub"
# Check if key already exists
if [ -f "$private_key_path" ]; then
echo -e "\n${YELLOW}Warning: An SSH key already exists at '$private_key_path'.${NC}"
echo -e "${YELLOW}Do you want to overwrite it? (y/N)${NC}"
read -r overwrite
if [ "$overwrite" != "y" ] && [ "$overwrite" != "Y" ]; then
echo -e "${RED}Key generation cancelled. Exiting.${NC}"
exit 1
fi
fi
# Execute ssh-keygen
ssh-keygen -t ed25519 -C "$email" -f "$private_key_path"
if [ $? -ne 0 ]; then
echo -e "${RED}Error generating SSH key. Please check your SSH installation.${NC}"
exit 1
fi
# Add key to SSH agent
echo -e "\n${YELLOW}--- Adding Key to SSH Agent ---${NC}"
echo -e "${YELLOW}This avoids re-entering your passphrase. You might be prompted for your passphrase now.${NC}"
ssh-add "$private_key_path"
if [ $? -ne 0 ]; then
echo -e "${RED}Failed to add key to SSH agent. You may need to start the SSH agent manually.${NC}"
echo -e "${YELLOW}To start the agent manually, run: eval \$(ssh-agent -s)${NC}"
fi
# Display the public key
echo -e "\n${GREEN}--- Your Public Key ---${NC}"
echo -e "${GREEN}Please copy the FOLLOWING ENTIRE KEY and paste it into Forgejo:${NC}"
cat "$public_key_path"
echo -e "${GREEN}---------------------------${NC}"
# --- Forgejo Web Server Instructions ---
echo -e "\n${CYAN}--- Next Steps (Manual on Forgejo Web Server) ---${NC}"
echo "1. Login to your Forgejo web server (e.g., https://$forgejo_location)"
echo "2. Click on your profile avatar (top right corner)"
echo "3. Select 'Settings'"
echo "4. In the left sidebar, click on 'SSH / GPG Keys'"
echo "5. Click the 'Add Key' button"
echo "6. Give your key a descriptive 'Title' (e.g., 'My Laptop Key')"
echo "7. PASTE the public key shown ABOVE into the 'Content' text area"
echo "8. Click 'Add Key'."
echo "9. After adding, click the 'Verify' button next to your new key."
echo "10. Copy the challenge token (the long hexadecimal string) provided by Forgejo."
# --- Key Verification ---
verification_passed=false
max_attempts=3
attempts=0
while [ "$verification_passed" = false ] && [ $attempts -lt $max_attempts ]; do
attempts=$((attempts + 1))
# Get and validate the token
token=""
while ! validate_token "$token"; do
echo -e "\n${YELLOW}--- Key Verification (Attempt $attempts of $max_attempts) ---${NC}"
echo -e "${YELLOW}Please get a fresh token from Forgejo (tokens expire after a few minutes)${NC}"
read -r token
if ! validate_token "$token"; then
echo -e "${RED}Invalid token format. Token should be 64 hexadecimal characters.${NC}"
fi
done
# Verify the token
echo -e "\n${YELLOW}Verifying key with Forgejo...${NC}"
echo -e "${YELLOW}Running verification command using private key: $private_key_path${NC}"
echo -e "${YELLOW}--------------------------------------------------------${NC}"
# Generate signature
verification_output=$(generate_signature "$token" "$private_key_path")
echo -e "\n${GREEN}--- Copy and Paste the Signature ---${NC}"
echo -e "${GREEN}Please copy the FOLLOWING ENTIRE BLOCK (including BEGIN and END lines) and paste it back into the Forgejo web verification box:${NC}"
echo ""
echo "$verification_output"
echo ""
echo -e "${GREEN}------------------------------------${NC}"
echo -e "\n${CYAN}--- Final Steps (Manual on Forgejo Web Server) ---${NC}"
echo "11. Paste the signature above into the verification box in Forgejo."
echo "12. Click 'Verify'. You should see 'Successfully verified'."
echo "13. Once verified, you can now test your SSH connection to Forgejo."
# Check verification status
echo -e "\n${YELLOW}--- Verification Status Check ---${NC}"
echo -e "${YELLOW}Did the verification pass in the Forgejo web interface? (y/N)${NC}"
read -r verification_status
if [ "$verification_status" = "y" ] || [ "$verification_status" = "Y" ]; then
verification_passed=true
else
echo -e "\n${RED}Verification failed. Here are some troubleshooting steps:${NC}"
echo -e "${YELLOW}1. Make sure you copied the ENTIRE signature block, including BEGIN and END lines${NC}"
echo -e "${YELLOW}2. Check that there are no extra spaces or line breaks in the signature${NC}"
echo -e "${YELLOW}3. Verify that the token was entered correctly${NC}"
echo -e "${YELLOW}4. The token may have expired - get a fresh token from Forgejo${NC}"
echo -e "${YELLOW}5. Try again with a new token${NC}"
if [ $attempts -lt $max_attempts ]; then
echo -e "\n${YELLOW}Let's try again with a new token...${NC}"
else
echo -e "\n${RED}Maximum verification attempts reached. Please check your key and try again later.${NC}"
exit 1
fi
fi
done
# --- SSH Config Setup ---
echo -e "\n${YELLOW}--- SSH Config Setup (Optional) ---${NC}"
echo -e "${YELLOW}Would you like to set up your SSH config for easier connections? (y/N)${NC}"
read -r setup_config
if [ "$setup_config" = "y" ] || [ "$setup_config" = "Y" ]; then
echo -e "${YELLOW}Enter your Forgejo username:${NC}"
read -r forgejo_user
ssh_config_path="$HOME/.ssh/config"
ssh_private_key_path="$private_key_path"
# Create config content
config_content="# Forgejo Configuration
Host $forgejo_location
HostName $forgejo_location
User $forgejo_user
IdentityFile $ssh_private_key_path
PreferredAuthentications publickey
PubkeyAuthentication yes
PasswordAuthentication no
"
# Create .ssh directory if it doesn't exist
mkdir -p "$HOME/.ssh"
# Read existing config
if [ -f "$ssh_config_path" ]; then
existing_config=$(cat "$ssh_config_path")
else
existing_config=""
fi
# Remove existing block for this host using sed
updated_config=$(echo "$existing_config" | sed -E "/^Host[[:space:]]+$forgejo_location[[:space:]]*$/,/^[^[:space:]]/d")
# Append new config
updated_config="$updated_config
$config_content"
# Write updated config
echo "$updated_config" > "$ssh_config_path"
echo -e "\n${GREEN}SSH config has been updated. You can now connect using:${NC}"
echo -e "${CYAN}ssh $forgejo_location${NC}"
echo -e "\n${YELLOW}Your SSH config is located at: $ssh_config_path${NC}"
# Wait a moment for the key to be fully processed
echo -e "\n${YELLOW}Waiting a moment for the key to be fully processed...${NC}"
sleep 5
# Test the connection
echo -e "\n${YELLOW}--- Testing SSH Connection ---${NC}"
echo -e "${YELLOW}Testing connection to $forgejo_location with verbose output...${NC}"
test_output=$(ssh -v -T "$forgejo_location" 2>&1)
ssh_exit_code=$?
if [ "$ssh_exit_code" -eq 1 ]; then
# Exit code 1 typically means success for ssh -T without remote command
echo -e "${GREEN}Connection successful! You can now use Git with your Forgejo repository.${NC}"
elif [ "$ssh_exit_code" -eq 0 ]; then
# This can happen if ssh does run an implicit command or due to specific server configs
echo -e "${YELLOW}Warning: SSH command returned exit code 0. This might indicate a successful connection, but verify manually if expected.${NC}"
echo -e "${GREEN}Connection successful! You can now use Git with your Forgejo repository.${NC}"
else
echo -e "${RED}Connection test failed. Here are some troubleshooting steps:${NC}"
# Display the verbose output of the failed ssh command
echo "$test_output" | while IFS= read -r line; do echo -e "${RED} $line${NC}"; done
echo -e "${YELLOW}1. Verify that your SSH key is properly added to your Forgejo account:${NC}"
echo -e "${YELLOW} - Check that the key appears in your SSH keys list${NC}"
echo -e "${YELLOW} - Verify that the key fingerprint matches: $(ssh-keygen -lf "$public_key_path" | cut -d' ' -f2)${NC}"
echo -e "${YELLOW}2. Check your SSH config:${NC}"
echo -e "${YELLOW} - Verify the hostname is correct: $forgejo_location${NC}"
echo -e "${YELLOW} - Verify the username is correct: $forgejo_user${NC}"
echo -e "${YELLOW} - Check that the key path is correct: $ssh_private_key_path${NC}"
echo -e "${YELLOW}3. Try connecting manually with verbose output:${NC}"
echo -e "${CYAN} ssh -v -T $forgejo_user@$forgejo_location${NC}"
echo -e "${YELLOW}Note: SSH returned exit code $ssh_exit_code.${NC}"
exit 1
fi
else
# If user didn't set up SSH config, still offer to test connection
echo -e "\n${YELLOW}--- Testing SSH Connection ---${NC}"
echo -e "${YELLOW}Would you like to test your SSH connection now? (y/N)${NC}"
read -r test_connection
if [ "$test_connection" = "y" ] || [ "$test_connection" = "Y" ]; then
echo -e "${YELLOW}Enter your Forgejo username:${NC}"
read -r forgejo_user
echo -e "\n${YELLOW}Testing connection to $forgejo_user@$forgejo_location with verbose output...${NC}"
test_output=$(ssh -v -T "$forgejo_user@$forgejo_location" 2>&1)
ssh_exit_code=$?
if [ "$ssh_exit_code" -eq 1 ]; then
echo -e "${GREEN}Connection successful! You can now use Git with your Forgejo repository.${NC}"
elif [ "$ssh_exit_code" -eq 0 ]; then
echo -e "${YELLOW}Warning: SSH command returned exit code 0. This might indicate a successful connection, but verify manually if expected.${NC}"
echo -e "${GREEN}Connection successful! You can now use Git with your Forgejo repository.${NC}"
else
echo -e "${RED}Connection test failed. Here are some troubleshooting steps:${NC}"
# Display the verbose output of the failed ssh command
echo "$test_output" | while IFS= read -r line; do echo -e "${RED} $line${NC}"; done
echo -e "${YELLOW}1. Verify that your SSH key is properly added to your Forgejo account:${NC}"
echo -e "${YELLOW} - Check that the key appears in your SSH keys list${NC}"
echo -e "${YELLOW} - Verify that the key fingerprint matches: $(ssh-keygen -lf "$public_key_path" | cut -d' ' -f2)${NC}"
echo -e "${YELLOW}2. Try connecting manually with verbose output:${NC}"
echo -e "${CYAN} ssh -v -T $forgejo_user@$forgejo_location${NC}"
echo -e "${YELLOW}Note: SSH returned exit code $ssh_exit_code.${NC}"
exit 1
fi
fi
fi
echo -e "\n${GREEN}Process for SSH key setup and verification completed!${NC}"