Three ways to run keel serve
keel servelistens only on your own computer (127.0.0.1). Nothing else can reach it, so there is no login. This is how Keel has always worked.keel serve --public-url https://<name>is for a tunnel in front of Keel. Login turns on for every request, even from your own computer, because the tunnel makes the same port reachable from the internet.keel serve --host 0.0.0.0listens on your network. Keel refuses to start until there is HTTPS (--certand--key, or--public-url) and at least one login (a passkey or codes).
The parts
The folder and its files can only be read by you. None of it is synced to other devices: a passkey belongs to one computer’s address.
Pairing a phone
- The link’s secret sits after the
#in the address, so it is never sent in a request. The tunnel and any logs never see it, and the page removes it from the address bar. - The link works once and for 10 minutes. Pressing Ctrl+C in the terminal cancels it at once.
- Face ID makes a new key pair on the phone. The private half never leaves the phone; Keel only stores the public half, which can check signatures but can’t make them.
- Pairing also signs the phone in to Goals, so it’s ready to use.
Signing in with a passkey
- Each challenge is random, works once and lasts 5 minutes, so a recorded sign-in can’t be replayed.
- The phone only offers the passkey at the address it was made for. A look-alike site gets nothing, which is why passkeys can’t be phished.
- Keel checks that Face ID (or the screen lock) was used, not just that the phone was unlocked.
- After 10 failed attempts in a minute, Keel answers “Too many tries” until the minute is up.
Codes from an authenticator app
Codes are optional. They help in a browser without passkeys, and at local addresses (localhost, 192.168.x.x) where passkeys can’t work.
Turning codes on, in your terminal
Signing in with a code
- Your app and Keel share one secret key and the clock. Every 30 seconds both work out the same six digits; nothing is sent between them.
- A code is accepted for 30 seconds either side of its time, in case the phone’s clock is a little off.
- Each code works once, even if Keel restarts in between.
- A code sign-in always lasts 12 hours, also for Goals, because a code is easier to copy than a passkey.
- Running
keel servereads the key from the Keychain at each code sign-in, so turning codes on needs no restart.
Every request
- The page itself always loads, so you can see the sign-in screen. Your data only comes through the API, which needs a session.
- The session lives in a cookie the page’s scripts can’t read (
HttpOnly), that is only sent over HTTPS (Secure), and that other sites can’t use to send commands. - A browser terminal session also opens Goals, but not the other way round.
- Opening Goals without a session takes you to the sign-in page, and back to the same Goals page afterwards. So does a session that ends while Goals is open.
How long a sign-in lasts
The right address
Ending access
What login doesn’t protect
Login keeps other people out ofkeel serve. It doesn’t encrypt your data on the disk: anyone who can use your unlocked computer can read Keel’s files, as before. Lock your computer, and keep your tunnel name to yourself.
For the full reasoning, see ADR 0002 in the repository.