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:
Joe DiPrima
2026-08-06 11:48:13 -05:00
co-authored by Claude Fable 5
parent 38b08c96d1
commit 99956d54e3
+113
View File
@@ -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)