Setup

Six steps from a downloaded installer to a session on your iPad. Most of them take a minute. Step three has the one thing you have to read.

You will be moving between two machines: the Mac you want to reach, and the iPad you want to reach it from. Everything up to step five happens on the Mac.

This is the public version of an internal checklist. If you are running the relay yourself, you want the repository instead.

before you start

  • macOS 12 or newer on the machine you want to reach.
  • Remote Login switched on — System Settings → General → Sharing → Remote Login. Outstation connects to your Mac's own SSH server; with Sharing off there is nothing there to connect to.
  • An early-access password, and the installer from outstation.dev/install.
  • The Outstation app on your iPad.

Turn Remote Login on first. If you leave it off, nothing fails loudly: the agent still connects to the relay, the app still says it is paired, and the session simply comes up carrying nothing. It is the easiest problem here to spend an hour on.

1 · Get the installer, and check it

Enter your password at outstation.dev/install. The page gives you a download link and a SHA-256. The link is good for five minutes — it is signed for that one file and expires, so take it now rather than saving it.

Check what you got before you install it:

shasum -a 256 ~/Downloads/outstationd-<version>.pkg
and compare it to the value the page printed.

The checksum is the weaker of the two checks. It proves the bytes match what we published — but you got the number from us, over the same connection. The stronger evidence is that the installer is signed by Quirl L.L.C. and notarised by Apple: your Mac verifies that against Apple, not against anything we said. If the package had been tampered with, it would not open at all.

what gets installed

  • /usr/local/bin/outstationd — the agent itself.
  • /usr/local/bin/outstation-install-agent — the thing that starts it at every login.

Nothing runs yet. The installer puts two files down and stops; the agent has nowhere to connect to until step two gives it a link.

Gatekeeper should not ask you to right-click → Open. If it does, the file did not arrive intact — download it again rather than working around it.

2 · Set the Mac up

Open Terminal and run:

outstationd init --relay wss://relay.outstation.dev

This makes a key pair, writes a config to ~/.config/outstation/, prints two blocks of text, and then starts the agent in the background so it comes back at every login.

The two blocks are not the same thing and go to different places:

The allowlist entry
A short block of JSON under --- send to the relay operator ---. It holds public keys only. This goes to us — step four.
The pairing blob
One long line of base64 under --- pairing blob ---. It contains a private key. This goes to your iPad and nowhere else — step five.

useful flags

--useryour account
--sshd-port22
--host-keyautodetect
--no-startoff

--user is the account the iPad logs in as, and it defaults to whoever ran the command. If your iPad is set up for a different account, say so here — a disagreement between the two shows up later as a login that is refused for a reason that reads like a key problem.

--no-start writes everything and leaves the agent stopped. Use it if you want to read the output before anything runs.

3 · Check that the host key was pinned

This is the one step that fails silently, so it is the one step to read carefully. Everything else on this page announces itself when it goes wrong. This does not.

Outstation pins your Mac's SSH host key into the pairing blob, so your iPad knows what your Mac's key looks like before it ever connects. That is what stops the relay — or anyone who reaches it — from standing in the middle and impersonating your machine.

It only works if the fingerprint actually made it into the blob. So scroll back through what init printed and find this line:

sshd host key pinned at pairing: SHA256:…

If that line is not there, stop and do it again. Near the top of the output you will instead see WARNING: could not read the sshd host key and WARNING: the app will have to trust on first use. A blob issued after those warnings still works — it just quietly drops back to trusting whatever answers the first time you connect. Nothing later will tell you, and the app cannot tell the difference.

The fix is to point at the key by hand and run it again:

outstationd init --relay wss://relay.outstation.dev \
  --host-key /etc/ssh/ssh_host_ed25519_key.pub

where to look

The two outputs do not sit next to each other, which is what makes this easy to miss:

  • The warnings come out early, on stderr, each stamped with a time like 14:22:07.
  • The pinned line comes out late, on stdout, with no timestamp.
  • It is not the last thing printed. If the agent starts, three more lines follow it. Only --no-start makes it last.

If you piped the output to a file, the two streams can interleave out of order. Search for the words rather than trusting the position.

Your iPad shows the fingerprint it pinned under Settings → Machine's host key, and prints a line into the terminal the first time it verifies against it.

4 · Send us the allowlist entry

The relay refuses anything it has not been told about, so your link has to be added before your iPad can use it. Mail the allowlist entry — the JSON block, not the blob — to outstation@quirl.co.

A person adds it by hand. There is no signup and no console; early access is small enough that this is a human reading mail. Expect it inside a working day. You will get a reply when it is live — nothing on your Mac changes and you do not need to re-run anything.

Adding it disturbs nothing. It takes effect immediately, with no relay restart, so nobody else's session drops because yours arrived.

It is not a secret the way the pairing blob is, and it is not nothing either. It carries public keys and an identifier for your link — no private key, so it cannot be used to reach your Mac. But the identifier is half of a credential, so send it the way you would send an account number: fine in your mail, not fine in a public issue tracker.

handling the pairing blob

The pairing blob contains a private key. Anyone holding it can open a connection to your Mac's SSH server through the relay. They still need an SSH key to log in — it is not a way past your authorized_keys — but it puts them at your front door.

  • Move it over something you trust. AirDrop and a password manager are both fine; a group chat is not.
  • Do not leave it in a paste buffer or a note.
  • If you think it has leaked, mail us. Revoking a link takes effect immediately and drops the sessions using it.

Its size is not a mistake — it is a key, base64-encoded, not a code you are meant to type.

5 · Pair the iPad, and give it a way in

These are two separate things, and doing only the first is the most common way to get stuck. Pairing gets Outstation to your Mac. It does not get it logged in. Your Mac's SSH server still wants a key, exactly as it would from any other machine.

In Outstation, open Settings, then:

  1. Under Outstation Connect, paste the pairing blob and tap Pair.
  2. Under SSH key, tap Copy public key. This is a key the iPad made and keeps in its Secure Enclave; it never leaves the device.
  3. On the Mac, append that line to ~/.ssh/authorized_keys.
  4. Connect.

One key serves every machine you add, so step three is once per Mac, not once per session. Outstation runs tmux new -A -s <session> on the far end, which is why your work survives closing the app.

appending the key

If the file does not exist yet, this creates it with the permissions sshd insists on:

mkdir -p ~/.ssh && chmod 700 ~/.ssh
pbpaste >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

pbpaste works if you moved the key over to the Mac's clipboard; otherwise paste it into an editor. It is one line — if it arrives wrapped across several, join it back up, because sshd will ignore a broken one without complaining.

You cannot use an SSH key you already have. Outstation's key is generated on the iPad and held by the Secure Enclave, which is the point: it cannot be copied off the device, not even by us.

6 · When it does not work

Listed by what you see, because from the iPad you cannot tell which half is broken.

It connects, then nothing happens
Remote Login is off. The agent reaches the relay perfectly well and then finds nothing listening on the Mac, so the session opens and stays empty. System Settings → General → Sharing → Remote Login.
"The server rejected the Outstation key"
The iPad's public key is not in ~/.ssh/authorized_keys, or it got wrapped onto two lines when you pasted it. Step five.
The Mac says the agent is connected, but the iPad cannot reach it
Your allowlist entry has not been added yet. This is normal for the first day — nothing is wrong with your setup and re-running init will not help. It makes a new link, which we have also not been told about.
"This machine's pairing has been revoked"
The link was removed at the relay. The agent notices and backs off to retrying every five minutes rather than hammering. Run outstationd init again and send the new allowlist entry.
"The pairing for this machine isn't on this device"
The machine is in your list but its pairing is not on this iPad — a new device, or a reinstall. Pair it again in Settings.
It worked, then the Mac restarted and stopped
The agent runs while you are logged in. A restart that stops at the login window leaves it down until somebody logs in. This is deliberate: it runs as you, with your permissions, and nothing here needs to run as root.
Logging in asks for a password, or refuses the wrong account
The account in the pairing does not match the one you meant. Outstation will show you both and let you pick; if you want to fix it at the source, re-run init with --user.

what to look at

The agent's log, which is where its side of the story is:

tail -f ~/Library/Logs/outstation/outstationd.log

Whether it is actually loaded:

launchctl print gui/$(id -u)/dev.outstation.outstationd | head -20

Whether your Mac is accepting SSH at all, from the Mac itself:

ssh localhost

That last one is worth doing before anything else. If it fails, the problem is between you and your own Mac, and Outstation is not involved.

Still stuck? outstation@quirl.co. Send the log — it names no hostnames and no keys.

Removing it

Stopping the agent is one command:

outstation-install-agent --uninstall

That stops it running and leaves everything else in place, which is right for an upgrade and wrong if you are actually done. There is no uninstaller, so the rest is four removals by hand:

sudo rm /usr/local/bin/outstationd
sudo rm /usr/local/bin/outstation-install-agent
rm -rf ~/.config/outstation
rm -rf ~/Library/Logs/outstation

Then, on the iPad, Unpair this machine in Settings, and remove the Outstation line from ~/.ssh/authorized_keys if you are not going to use it again.

Your link stays on the relay until we remove it. Deleting the files on your Mac does not tell us anything. Mail outstation@quirl.co and it goes immediately — worth doing, because a link nobody is using is still a link somebody could use.

elsewhere

Found something on this page that is wrong, or a failure it does not cover? Tell us — that is the fastest way it gets better, and the list above came from people getting stuck.

outstation