updated ssh setup

This commit is contained in:
LeonL committed 2026-11-06 10:18:02 -08:00
1 parent 044de4e730
commit 2e8e3faff0
2 files changed
+110 -9

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
@echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0git-ssh-setup.ps1" %*
pause
+107 -9
View File
@@ -1,9 +1,9 @@
<# <#
.SYNOPSIS .SYNOPSIS
Sets up SSH for Git on Windows: creates a key in ~/.ssh, loads it into the Sets up SSH for Git on Windows: creates a key in ~/.ssh, loads it into the
Windows ssh-agent, adds a host entry to ~/.ssh/config, and points Git at Windows ssh-agent, adds a host entry to ~/.ssh/config, points Git at
Windows' OpenSSH so pushes (and Git LFS) use the agent instead of asking Windows' OpenSSH so pushes (and Git LFS) use the agent instead of asking
for the passphrase every time. for the passphrase every time, and signs Gitea's key-verification token.
.DESCRIPTION .DESCRIPTION
Safe to re-run: an existing key is reused (unless -Force), a key already in Safe to re-run: an existing key is reused (unless -Force), a key already in
@@ -13,14 +13,22 @@
Run it as your normal user, NOT "Run as administrator". It asks for admin Run it as your normal user, NOT "Run as administrator". It asks for admin
rights (UAC prompt) only if the ssh-agent service needs to be enabled. rights (UAC prompt) only if the ssh-agent service needs to be enabled.
.EXAMPLE Execution policy: start it through powershell.exe with -ExecutionPolicy
powershell -ExecutionPolicy Bypass -File .\setup-git-ssh.ps1 Bypass as in the examples, or double-click git-ssh-setup.cmd. Either way the
bypass applies to this one run only; the system setting is not changed.
.EXAMPLE .EXAMPLE
powershell -ExecutionPolicy Bypass -File .\setup-git-ssh.ps1 -Comment "you@example.com" powershell -NoProfile -ExecutionPolicy Bypass -File .\git-ssh-setup.ps1
.EXAMPLE .EXAMPLE
powershell -ExecutionPolicy Bypass -File .\setup-git-ssh.ps1 -HostName github.com -KeyName id_ed25519_github powershell -NoProfile -ExecutionPolicy Bypass -File .\git-ssh-setup.ps1 -Comment "you@example.com"
.EXAMPLE
# Verify the key later: click Verify next to it in Gitea and pass the token it shows.
powershell -NoProfile -ExecutionPolicy Bypass -File .\git-ssh-setup.ps1 -NoTest -Token d0d4b8e7...
.EXAMPLE
powershell -NoProfile -ExecutionPolicy Bypass -File .\git-ssh-setup.ps1 -HostName github.com -KeyName id_ed25519_github -NoVerify
#> #>
[CmdletBinding()] [CmdletBinding()]
param( param(
@@ -41,9 +49,15 @@ param(
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$Comment = "$env:USERNAME@$env:COMPUTERNAME", [string]$Comment = "$env:USERNAME@$env:COMPUTERNAME",
# Token from Gitea's Verify button. If omitted, the script asks for it.
[string]$Token,
# Replace an existing key with the same name instead of reusing it. # Replace an existing key with the same name instead of reusing it.
[switch]$Force, [switch]$Force,
# Skip the Gitea key-verification step.
[switch]$NoVerify,
# Skip the connection test at the end. # Skip the connection test at the end.
[switch]$NoTest [switch]$NoTest
) )
@@ -56,6 +70,32 @@ function Stop-Setup([string]$Message) {
exit 1 exit 1
} }
# Signs $Text exactly as given and returns the armored signature, or $null if
# ssh-keygen failed. The text is written to a file with no trailing newline and
# no BOM: piping it into ssh-keygen from PowerShell would add a newline and
# change what gets signed.
function Get-SshSignature([string]$Text, [string]$Keygen, [string]$KeyFile, [string]$Namespace = 'gitea') {
$file = Join-Path ([IO.Path]::GetTempPath()) ("gitea-verify-" + [guid]::NewGuid().ToString('N'))
$sigFile = "$file.sig"
try {
[IO.File]::WriteAllText($file, $Text, (New-Object Text.UTF8Encoding($false)))
# A .pub key file makes ssh-keygen sign through ssh-agent (no passphrase prompt).
& $Keygen -Y sign -n $Namespace -f $KeyFile $file | Out-Host
if ($LASTEXITCODE -eq 0 -and (Test-Path $sigFile)) {
return (Get-Content -Path $sigFile -Raw).Trim()
}
return $null
} finally {
Remove-Item -LiteralPath $file, $sigFile -Force -ErrorAction SilentlyContinue
}
}
# Accept the token with stray spaces or quotes, but nothing that isn't hex.
$Token = "$Token" -replace '[\s''"]', ''
if ($Token -and $Token -notmatch '^[0-9a-fA-F]+$') {
Stop-Setup "-Token should be just the hex string from Gitea's Token box."
}
$openSshDir = Join-Path $env:WINDIR 'System32\OpenSSH' $openSshDir = Join-Path $env:WINDIR 'System32\OpenSSH'
$sshExe = Join-Path $openSshDir 'ssh.exe' $sshExe = Join-Path $openSshDir 'ssh.exe'
$keygenExe = Join-Path $openSshDir 'ssh-keygen.exe' $keygenExe = Join-Path $openSshDir 'ssh-keygen.exe'
@@ -210,10 +250,68 @@ try {
} }
Write-Host " Add it in Gitea: your avatar > Settings > SSH / GPG Keys > Add Key" Write-Host " Add it in Gitea: your avatar > Settings > SSH / GPG Keys > Add Key"
# --- 7. Test ----------------------------------------------------------------- # --- 7. Verify the key in Gitea (optional) -----------------------------------
# Gitea's Verify button shows a token. Signing it with this key proves you own
# the key, and Gitea then marks the key as verified.
if (-not $NoVerify) {
Write-Step "Verifying the key in Gitea (optional)"
if (-not $Token) {
Write-Host " 1. Add the key in Gitea first (it's on your clipboard)."
Write-Host " 2. Click Verify next to the key and copy the token Gitea shows."
while ($true) {
$Token = "$(Read-Host ' Paste the token here, or press Enter to skip')" -replace '[\s''"]', ''
if (-not $Token -or $Token -match '^[0-9a-fA-F]+$') { break }
Write-Note "That doesn't look like a token. Paste only the hex string from the Token box."
}
}
if (-not $Token) {
Write-Note "Skipped. To verify later, click Verify in Gitea and re-run with -NoTest -Token <token>."
} else {
$signature = Get-SshSignature -Text $Token -Keygen $keygenExe -KeyFile $pubPath
if (-not $signature) {
# Windows OpenSSH older than 8.1 has no 'ssh-keygen -Y'; Git for Windows ships a newer one.
$gitKeygen = $null
$gitCmd = Get-Command git -ErrorAction SilentlyContinue
if ($gitCmd) {
$dir = Split-Path $gitCmd.Source
foreach ($i in 1..3) {
if (-not $dir) { break }
$candidate = Join-Path $dir 'usr\bin\ssh-keygen.exe'
if (Test-Path $candidate) { $gitKeygen = $candidate; break }
$dir = Split-Path $dir
}
}
if ($gitKeygen) {
Write-Note "Retrying with Git for Windows' ssh-keygen (it may ask for the key's passphrase)."
$signature = Get-SshSignature -Text $Token -Keygen $gitKeygen -KeyFile $keyPath
}
}
if ($signature) {
Write-Host "`n$signature`n"
try {
Set-Clipboard -Value $signature
Write-Ok "Signature copied to the clipboard."
} catch {
Write-Note "Couldn't copy to the clipboard - copy the block above."
}
Write-Host " Paste it into Gitea's 'Armored SSH signature' box and click Verify."
Write-Note "The token only stays valid for a short time. If Gitea rejects the signature,"
Write-Note "click Verify again for a new token and re-run with -NoTest -Token <new token>."
} else {
Write-Note "Couldn't sign the token, so the key wasn't verified. Everything else is set up."
}
}
}
# --- 8. Test -----------------------------------------------------------------
if ($HostName -and -not $NoTest) { if ($HostName -and -not $NoTest) {
Write-Host "" Write-Step "Testing the connection to $HostName"
Read-Host "Press Enter once the key is added to test the connection (Ctrl+C to skip)" | Out-Null if ($NoVerify) {
Read-Host "Press Enter once the key is added in Gitea (Ctrl+C to skip)" | Out-Null
}
& $sshExe -T -p $Port "$User@$HostName" & $sshExe -T -p $Port "$User@$HostName"
Write-Host "" Write-Host ""
Write-Note "A 'Hi there, <name>! You've successfully authenticated' message means it worked." Write-Note "A 'Hi there, <name>! You've successfully authenticated' message means it worked."