tools: podshell_setup.ps1 -- one-shot remote-shell setup for the pod PC
OpenSSH server + a single authorized key + a private/domain-only firewall rule, so bring-up can run over a tailnet instead of by hand through Chrome Remote Desktop (CRD paints a canvas -- unreadable to tooling; text and logs need a real shell). Handles the Windows administrators_authorized_keys ACL quirk, refuses to run on pre-Win10 (the period-pod case, which stays on the clipboard/probe route), never opens the public profile, and prints the exact ssh line including the Tailscale address. Undo steps in the header. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
38b08c96d1
commit
99956d54e3
@@ -0,0 +1,113 @@
|
||||
# podshell_setup.ps1 -- give the pod / crash-cart PC a remote shell for BT411
|
||||
# bring-up. Run ON THE POD PC, in an ADMINISTRATOR PowerShell, ONCE:
|
||||
#
|
||||
# powershell -ExecutionPolicy Bypass -File podshell_setup.ps1
|
||||
#
|
||||
# What it does (and nothing else):
|
||||
# 1. installs + starts the Windows OpenSSH SERVER (built into Win10/11)
|
||||
# 2. authorizes ONE public key (the laptop's bt411 key, below)
|
||||
# 3. opens SSH on PRIVATE/tailnet profiles only -- never the public internet
|
||||
# 4. prints the Tailscale address to connect to
|
||||
#
|
||||
# It does NOT install Tailscale (do that first, see the header notes) and it
|
||||
# does NOT enable password logins or touch any other service.
|
||||
#
|
||||
# Undo when the pod work is finished:
|
||||
# Remove-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
|
||||
# Remove-Item C:\ProgramData\ssh\administrators_authorized_keys
|
||||
# (and uninstall / `tailscale logout` if you like)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# --- the ONE key that may log in (BT411 bring-up, laptop-held, no passphrase) ---
|
||||
$PUBKEY = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICmGkinDbZMwQ/UhwqU/oECUIeAN+pBjLgsekj41di7W bt411-claude-code@laptop'
|
||||
|
||||
function Say($m) { Write-Host " $m" }
|
||||
|
||||
Write-Host "=== BT411 pod shell setup ==="
|
||||
|
||||
# 0. admin check -- everything below needs it
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] `
|
||||
[Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
if (-not $isAdmin) {
|
||||
Write-Host "!! Run this in an ADMINISTRATOR PowerShell (right-click > Run as administrator)." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
$os = [Version](Get-CimInstance Win32_OperatingSystem).Version
|
||||
Say ("windows {0}" -f $os)
|
||||
if ($os.Major -lt 10) {
|
||||
Write-Host "!! Windows 10+ required for the built-in OpenSSH server." -ForegroundColor Red
|
||||
Write-Host " (If this is the period pod PC, stop here -- use the clipboard/probe route instead.)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 1. OpenSSH server
|
||||
Say "installing OpenSSH server (if missing) ..."
|
||||
$cap = Get-WindowsCapability -Online -Name OpenSSH.Server* | Select-Object -First 1
|
||||
if ($cap.State -ne 'Installed') { Add-WindowsCapability -Online -Name $cap.Name | Out-Null }
|
||||
Set-Service -Name sshd -StartupType Automatic
|
||||
Start-Service sshd
|
||||
Say ("sshd: {0}" -f (Get-Service sshd).Status)
|
||||
|
||||
# 2. authorize the key. Windows OpenSSH quirk: for accounts in the
|
||||
# Administrators group the file is administrators_authorized_keys, and sshd
|
||||
# REFUSES it unless the ACL is exactly SYSTEM + Administrators.
|
||||
$me = "$env:USERDOMAIN\$env:USERNAME"
|
||||
$inAdmins = (Get-LocalGroupMember -Group 'Administrators' -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.Name -eq $me }) -ne $null
|
||||
if ($inAdmins) {
|
||||
$akf = 'C:\ProgramData\ssh\administrators_authorized_keys'
|
||||
Say "account is an Administrator -> using administrators_authorized_keys"
|
||||
} else {
|
||||
$akf = Join-Path $env:USERPROFILE '.ssh\authorized_keys'
|
||||
New-Item -ItemType Directory -Force -Path (Split-Path $akf) | Out-Null
|
||||
Say "standard account -> using $akf"
|
||||
}
|
||||
|
||||
$existing = ''
|
||||
if (Test-Path $akf) { $existing = Get-Content $akf -Raw }
|
||||
if ($existing -notlike "*$PUBKEY*") {
|
||||
Add-Content -Path $akf -Value $PUBKEY -Encoding ASCII
|
||||
Say "key added"
|
||||
} else { Say "key already present" }
|
||||
|
||||
if ($inAdmins) {
|
||||
icacls $akf /inheritance:r /grant 'SYSTEM:F' /grant 'BUILTIN\Administrators:F' | Out-Null
|
||||
Say "ACL locked to SYSTEM + Administrators (sshd requires this)"
|
||||
}
|
||||
|
||||
# 3. firewall: private/domain only. Explicitly NOT public -- the tailnet
|
||||
# interface is what we connect over.
|
||||
$rule = Get-NetFirewallRule -Name 'BT411-SSH' -ErrorAction SilentlyContinue
|
||||
if (-not $rule) {
|
||||
New-NetFirewallRule -Name 'BT411-SSH' -DisplayName 'BT411 SSH (private/tailnet only)' `
|
||||
-Enabled True -Direction Inbound -Protocol TCP -LocalPort 22 `
|
||||
-Action Allow -Profile Private,Domain | Out-Null
|
||||
Say "firewall rule added (private/domain profiles only)"
|
||||
} else { Say "firewall rule already present" }
|
||||
|
||||
# 4. how to reach it
|
||||
Write-Host ""
|
||||
Write-Host "=== CONNECT WITH ==="
|
||||
$ts = 'C:\Program Files\Tailscale\tailscale.exe'
|
||||
if (Test-Path $ts) {
|
||||
$ip = (& $ts ip -4 2>$null | Select-Object -First 1)
|
||||
$st = (& $ts status --json 2>$null | ConvertFrom-Json)
|
||||
$dns = $null
|
||||
if ($st -and $st.Self -and $st.Self.DNSName) { $dns = $st.Self.DNSName.TrimEnd('.') }
|
||||
if ($ip) { Write-Host (" ssh -i ~/.ssh/bt411_pod {0}@{1}" -f $env:USERNAME, $ip) }
|
||||
if ($dns) { Write-Host (" ssh -i ~/.ssh/bt411_pod {0}@{1}" -f $env:USERNAME, $dns) }
|
||||
if (-not $ip) { Write-Host " ! Tailscale installed but not connected -- run: tailscale up" }
|
||||
} else {
|
||||
Write-Host " ! Tailscale not installed yet."
|
||||
Write-Host " winget install --id Tailscale.Tailscale -e (then: tailscale up)"
|
||||
Write-Host " Sign in with the SAME account used on the laptop."
|
||||
Write-Host (" LAN fallback: ssh -i ~/.ssh/bt411_pod {0}@{1}" -f $env:USERNAME,
|
||||
((Get-NetIPAddress -AddressFamily IPv4 |
|
||||
Where-Object { $_.IPAddress -notlike '127.*' -and $_.IPAddress -notlike '169.254.*' } |
|
||||
Select-Object -First 1).IPAddress))
|
||||
}
|
||||
Write-Host ""
|
||||
Say ("user: {0} host: {1}" -f $env:USERNAME, $env:COMPUTERNAME)
|
||||
Reference in New Issue
Block a user