Step 1 of 210 done

Marcel laptop

Laptop setup

About 20 minutes. Do the steps in order and tick each one off. Passwords go in 1Password, never in a file. The laptop is a ThinkPad X13 Yoga Gen 2 on Windows 11 Pro, with two local accounts: Carlos (admin) and Marcel (standard).

Already done

If a step does not matchThis list has not been followed end to end on the real laptop yet. If a screen does not match a step, stop and note which step it was and what the screen said, so the next session can fix the list.

Arrival checks

Three quick looks at the hardware. The Chrome check comes later, at step 17.

Step 1

Pen in its slot

It sits in the side of the case. Pull it out, push it back in.

Step 2

Battery holds

Unplug the charger. A full battery should read near 100 percent and should not fall more than a few percent in five minutes of sitting idle.

Step 3

Windows is activated and is Pro

Settings, System, Activation says Active. Settings, System, About says Windows 11 Pro. Home would not do the BitLocker step.

Chrome

Step 4

Install Chrome for the whole machine

Take the MSI from the Chrome Enterprise download page so it lives in Program Files and not inside one user's profile.

Marcel's account

Step 5

Make the Marcel account

Settings, Accounts, Other users, Add account, I don't have this person's sign-in information, Add a user without a Microsoft account. Name it Marcel and pick a password.

Check

It must say Standard user. Do not change the type.

Step 6

Build Marcel's profile

Sign in as Marcel once, open Chrome once, sign out.

Tailscale

About 3 minutes.

Step 7

Install Tailscale and sign in

Install it from tailscale.com and sign in to the family tailnet with your account.

Step 8

Turn on Run unattended

Tray icon, Preferences, turn on Run unattended. That keeps it connected on the sign-in screen and with nobody logged in.

Step 9

Rename it and disable key expiry

In the Tailscale admin console, rename the machine marcel-laptop, then open its menu and choose Disable key expiry.

Do not skip

Without that it silently drops off the tailnet after about six months and every push fails.

Step 10

Check it from the rig

marcel-laptop should be listed and online.

On the rig
tailscale status

The script does the rest

About 5 minutes.

Step 11

Download and unpack on the laptop

Use the two download buttons at the top of this page, in the laptop's browser. Then start the Start menu, type PowerShell, right-click it, and choose Run as administrator. Unpack the zip into C:\TutorSetup and put the key file beside it.

Laptop, admin PowerShell
New-Item -ItemType Directory -Force C:\TutorSetup | Out-Null
Expand-Archive -Path "$env:USERPROFILE\Downloads\laptop.zip" -DestinationPath C:\TutorSetup -Force
Copy-Item "$env:USERPROFILE\Downloads\marcel-laptop_ed25519.pub" C:\TutorSetup\
Get-ChildItem C:\TutorSetup -Recurse -File | Unblock-File

The scripts should now be in C:\TutorSetup\laptop\setup. If the browser saved the zip as laptop (1).zip, change the name in the second line to match.

Step 12

Dry run, then read it

This changes nothing. Read what it says it will do.

Laptop, admin PowerShell
Set-ExecutionPolicy -Scope Process Bypass
cd C:\TutorSetup\laptop\setup
.\setup-laptop.ps1 -DryRun -PublicKeyFile C:\TutorSetup\marcel-laptop_ed25519.pub
Step 13

Run it for real

Same window, same line without -DryRun. In order, it installs OpenSSH Server and starts it at boot, opens port 22 to Tailscale addresses only, puts the rig's key in administrators_authorized_keys, runs install-tasks.ps1 (script folder, its permissions, three scheduled tasks), sets Chrome to block everything, and blocks Edge.

Laptop, admin PowerShell
.\setup-laptop.ps1 -PublicKeyFile C:\TutorSetup\marcel-laptop_ed25519.pub
Keep this page on your phone from here on

The browser block is machine-wide, so after this step Chrome and Edge on the laptop will likely refuse to load a fresh copy of this page. Keep it open on your phone. The laptop-side commands left are short enough to type.

The key gotcha

For an admin account, sshd reads C:\ProgramData\ssh\administrators_authorized_keys, not the key file in the user's home folder. It also ignores that file unless only Administrators and SYSTEM can write it. The script sets that. If the rig later asks for a password, or says Permission denied (publickey), run this by hand:

Laptop, admin PowerShell
icacls.exe C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"
Restart-Service sshd
Step 14

Prove SSH from the rig

First time, type yes to the host key question.

On the rig
ssh -i C:\Users\Admin\.ssh\marcel-laptop_ed25519 Carlos@marcel-laptop whoami

It should print <computer name>\carlos, with no password asked.

Step 15

Make SSH key-only

Once step 14 works with no password, run the script one more time on the laptop with the same key file so SSH accepts the key only.

Laptop, admin PowerShell
cd C:\TutorSetup\laptop\setup
.\setup-laptop.ps1 -PublicKeyFile C:\TutorSetup\marcel-laptop_ed25519.pub -DisablePasswordAuth
Step 16

Prove a push from the rig

Copy the example config to the real one. It already says user Carlos and points at the key from before. Then make khan.json holding the three Khan Academy domains.

On the rig
cd G:\_NuOS\_Personal\Marcel-Laptop\_Build
Copy-Item rig\laptop.config.example.json rig\laptop.config.json
Set-Content -Path khan.json -Encoding ascii -Value '["khanacademy.org","www.khanacademy.org","cdn.kastatic.org"]'

See the command it would run first:

On the rig, from _Build
node rig/push.js set-allowlist --config rig/laptop.config.json --domains-file khan.json --dry-run

Then the same line without --dry-run. It prints "ok":true.

On the rig, from _Build
node rig/push.js set-allowlist --config rig/laptop.config.json --domains-file khan.json
Step 17

Arrival check 4: Chrome shows the allowlist

Sign in as Marcel and check each of these:

  • A Khan Academy lesson loads and its video plays.
  • youtube.com says it is blocked.
  • Edge opens a "blocked by your organization" page.

Then open chrome://policy in Chrome. If it shows URLAllowlist and URLBlocklist with the domains, that is the check. If Chrome says the page is blocked, that is the chrome://* rule doing its job, and the check is this instead:

Laptop, admin PowerShell
reg query HKLM\Software\Policies\Google\Chrome\URLAllowlist

If a change does not show, close and reopen Chrome.

Step 18

Prove the lock

Sign Marcel out first

Locking logs them off without warning.

From the rig, lock. The sign-in screen should no longer offer Marcel.

On the rig, from _Build
node rig/push.js lock --config rig/laptop.config.json

Then unlock. That brings Marcel back.

On the rig, from _Build
node rig/push.js unlock --config rig/laptop.config.json

Protect it

About 4 minutes.

Step 19

BitLocker

Start, type Manage BitLocker, turn it on for C:. Save the recovery key to a file, copy it into 1Password, then delete the file. There is no USB stick this time, so save it to a folder you can delete from, such as Documents.

No startup PIN

Do not add one. The laptop has to reboot and rejoin Tailscale with nobody there.

Check that it says Protection On:

Laptop, admin PowerShell
manage-bde -status C:
Step 20

Family Safety web filter stays off

Settings, Accounts, Family should list nobody, and Windows Security, Family options should show no filtering. Both accounts are local, so there is nothing to switch on. The filter would block Chrome, so keep it off.

Step 21

Firmware password and USB boot off

Do this last

It ends in a restart.

Restart and tap F1 at the Lenovo logo. Security, Password, set a Supervisor password (into 1Password). Startup, Boot: disable the USB boot entries (menu names vary by BIOS version). Save and exit.

A USB stick still works inside Windows. It just cannot start the machine.

Done when

Later