Split into setup-local.sh + setup-remote.sh, add RDP configuration
Renames bootstrap.sh to setup-local.sh to match its actual scope (the travel laptop only) and adds setup-remote.sh for the machine you Remote-SSH/RDP into, since that's a different machine's one-time setup and was already living outside setup-local.sh's reach (same reasoning as the existing Tailscale-SSH prerequisite). setup-remote.sh configures GNOME's system-level RDP (works from a cold GDM login screen, not just an existing session) restricted to the tailscale interface via a ufw rule, a self-signed TLS cert, and RDP credentials that are deliberately separate from the account password and never cached - only prompted if unset. Shares step-tracking helpers with setup-local.sh via a new lib.sh rather than duplicating them. Tested the branching logic (credentials-already-set, RDP-already- enabled, ufw-already-active-with-rule, ufw-inactive-confirm/decline) against realistic stubbed command output. Caught and fixed a real bug in the process: the inactive/active ufw check used a bare `grep -qi active`, which also matches the substring inside "inactive" - it was silently skipping the enable-confirmation gate and going straight to adding a firewall rule on a firewall that was never turned on. Fixed by anchoring the match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
9999e1da41
commit
ef28afb9b8
4 changed files with 263 additions and 24 deletions
71
README.md
71
README.md
|
|
@ -1,10 +1,21 @@
|
|||
# travel laptop bootstrap
|
||||
|
||||
A disposable, extremely light Debian laptop for working on the road. If it's
|
||||
lost, stolen, or dropped in the sea: install Debian, fetch `bootstrap.sh`,
|
||||
lost, stolen, or dropped in the sea: install Debian, fetch `setup-local.sh`,
|
||||
run it, give it a couple of credentials, and you're back to full working
|
||||
order in minutes.
|
||||
|
||||
Two scripts, one per machine role:
|
||||
- **`setup-local.sh`** - run on the disposable travel laptop. Everything in
|
||||
this README that isn't explicitly about the home machine refers to this.
|
||||
- **`setup-remote.sh`** - run once on the machine you Remote-SSH/RDP *into*
|
||||
(e.g. your home desktop). Configures RDP access for occasional full-desktop
|
||||
use (browser sessions already logged into Gmail etc.) - see "Remote
|
||||
desktop access" below.
|
||||
|
||||
Both share `lib.sh` (step-tracking/summary helpers) - all three files need
|
||||
to stay together when you fetch this repo.
|
||||
|
||||
## The idea
|
||||
|
||||
- The travel laptop stays minimal: vim, tmux, mosh, tailscale, VS Code
|
||||
|
|
@ -35,9 +46,10 @@ On a fresh Debian install, once you're on the network:
|
|||
|
||||
```bash
|
||||
sudo apt update && sudo apt install -y curl
|
||||
curl -fsSL https://git.brainpaingames.com/tommy/infra/raw/branch/main/bootstrap.sh -o bootstrap.sh
|
||||
chmod +x bootstrap.sh
|
||||
./bootstrap.sh
|
||||
curl -fsSL https://git.brainpaingames.com/tommy/infra/raw/branch/main/setup-local.sh -o setup-local.sh
|
||||
curl -fsSL https://git.brainpaingames.com/tommy/infra/raw/branch/main/lib.sh -o lib.sh
|
||||
chmod +x setup-local.sh
|
||||
./setup-local.sh
|
||||
```
|
||||
|
||||
It prompts for:
|
||||
|
|
@ -76,8 +88,8 @@ from within an already-open Remote-SSH window - not set up yet.
|
|||
|
||||
## On the home machine side
|
||||
|
||||
One prerequisite that lives outside this script, on whichever machine you
|
||||
Remote-SSH into:
|
||||
One prerequisite for Remote-SSH that lives outside any script, run once on
|
||||
whichever machine you Remote-SSH into:
|
||||
|
||||
```bash
|
||||
sudo tailscale set --ssh
|
||||
|
|
@ -85,10 +97,49 @@ sudo tailscale set --ssh
|
|||
|
||||
This lets Tailscale itself authorize SSH logins via your tailnet identity,
|
||||
so the travel laptop's key never needs to be manually added to
|
||||
`~/.ssh/authorized_keys` there. (The SSH key this script registers to
|
||||
`~/.ssh/authorized_keys` there. (The SSH key `setup-local.sh` registers to
|
||||
Forgejo is for a *different* purpose - git operations against Forgejo, a
|
||||
separate trust relationship from logging into the home machine.)
|
||||
|
||||
## Remote desktop access (occasional, full-desktop use)
|
||||
|
||||
Remote-SSH covers development, but not things like an already-logged-in
|
||||
Gmail session - for that, `setup-remote.sh` configures GNOME's built-in RDP
|
||||
(`gnome-remote-desktop`) on the home machine. Run it there once:
|
||||
|
||||
```bash
|
||||
./setup-remote.sh
|
||||
```
|
||||
|
||||
It restricts the RDP port to the tailscale interface only (via a `ufw`
|
||||
rule - if `ufw` isn't active yet, it asks before turning it on, since that
|
||||
changes this machine's default network posture more broadly), sets up a
|
||||
self-signed TLS cert, and prompts for RDP credentials **only if none are
|
||||
set yet** - these are deliberately never cached anywhere.
|
||||
|
||||
**Two authentication layers, not one**: the RDP username/password you set
|
||||
here just gates the RDP connection itself and gets you to the login
|
||||
screen - it is *not* your account password and doesn't grant a session by
|
||||
itself. You still log in with your real account password once connected,
|
||||
same as sitting at the machine. Keep both: relying on tailnet-reachability
|
||||
alone as the only gate would collapse this to a single point of failure,
|
||||
the same reasoning that already justified keeping SSH keys behind Tailscale
|
||||
SSH rather than trusting tailnet membership alone.
|
||||
|
||||
From the travel laptop: GNOME Connections (ships by default with a GNOME
|
||||
desktop, nothing extra to install) or `xfreerdp`, pointed at the home
|
||||
machine's tailscale address, port 3389.
|
||||
|
||||
**Connecting to a fresh boot with nobody logged in locally** (e.g. a power
|
||||
outage and the machine restarts unattended) works *if* the disk isn't
|
||||
encrypted, since Tailscale and the RDP daemon are both system services that
|
||||
start before any login - `setup-remote.sh` targets exactly this
|
||||
"system/GDM-level" RDP mode rather than the simpler per-session one, which
|
||||
only shares a session that already exists. If this machine is ever
|
||||
LUKS-encrypted later, this recovery path breaks (nothing starts until
|
||||
someone types the disk passphrase locally) unless something like
|
||||
`dropbear-initramfs` is added for remote unlock.
|
||||
|
||||
## Gotchas hit while building this (so they don't get re-debugged)
|
||||
|
||||
- **`usermod`/`visudo`: command not found** after `su` - not missing, just
|
||||
|
|
@ -99,6 +150,12 @@ separate trust relationship from logging into the home machine.)
|
|||
args) in the actual session you're testing in; if `sudo` isn't listed
|
||||
there even though `id <user>` shows it, the session is stale - reboot or
|
||||
fully re-login.
|
||||
- **`grep -qi active` also matches "in`active`"** - a substring check for
|
||||
whether ufw is active matched the *inactive* case too, silently skipping
|
||||
the enable-confirmation step and going straight to adding a firewall rule
|
||||
on a firewall that was never actually turned on. Caught by testing the
|
||||
branch directly rather than assuming; fixed by anchoring the match
|
||||
(`^Status: active`).
|
||||
- **Forgejo API call fails with a vague error** - the script reports the
|
||||
real HTTP status now (401 = bad/expired token, 403 = missing
|
||||
`write:user` scope, 404 = check the instance URL).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue