Reaching a computer

A computer has no address of its own, and nothing outside can reach it until you ask. The ways in: a shell from your own terminal, SSH (for VS Code, Cursor, scp and rsync too), files copied in and out, a port you share on the web, a TCP port on the internet, and the project's private network from your laptop.

Three ways in go through Alf, with nothing open on the internet. A shell: alf shell (or the dashboard) goes through Alf to the computer's server and opens a shell as dev. SSH: alf ssh goes the same way to the computer's SSH server on port 22. A shared port: anyone with the address, like …--5173.smartalfred.com, goes through Alf to the server and to localhost:5173 inside the computer. Two go straight to the computer's server. A public port: any client connects to the server's IP on a port between 20000 and 29999, and only the addresses on the allowlist get through to the port. Network access: alf connect joins your laptop to the project's network over WireGuard (UDP 51820), and every port of the computer is reachable.

From your own terminal

With the command-line tool, it's one command, which the computer's page shows along the bottom (Connect from your own terminal) with its name filled in:

alf shell shop/computer

Without installing anything, Or a one-time line, nothing to install there gives you a line to paste instead:

curl -fsSL https://runalf.com/connect.sh | sh -s -- 'wss://api.runalf.com/api/v1/sessions/attach?token=…'

It opens a shell in the same container as the one on the computer's page, so what you start in one is there in the other. The window follows your terminal's size, and the shell's exit code is the command's.

Closing the terminal — here or on the computer's page — ends that shell and what it was running in the foreground. The computer carries on, and so does anything you started to outlive the shell.

Sharing a port

A shell is where you build the thing you then want somebody to look at. Start it on a port — npm run dev, say — and share that port: it gets an https address of its own.

alf share 5173

prints the address, https://<computer>-<project>-<organization>--5173.smartalfred.com. It answers within about 15 seconds, for as long as something listens on the port.

Anyone with the address can reach the port. Nothing is shared until you or something in the computer asks. Share every port automatically, under Ports, shares each port as something starts listening on it, except debuggers' (9229, 9222), databases' (5432, 3306, 6379, 27017) and SSH's — a debugger's port lets whoever finds it run code in the computer. Those can still be shared by name.

What you build in a computer goes to production as a service in the project, with its own domain there.

SSH, VS Code and Cursor

Every computer has an SSH server, reached through Alf — nothing is open to the internet, and whoever may open a shell in it may SSH into it. With the command-line tool:

alf ssh shop/computer

logs you in as dev, the computer's user, with sudo. Anything after the name goes to ssh: alf ssh shop/computer -L 3000:localhost:3000 forwards your port 3000 to the computer's, -A forwards your SSH agent (for git push from the computer with your own key), and alf ssh shop/computer uptime runs one command.

For everything else that speaks SSH, make the computer an SSH host once:

alf ssh-config shop/computer --add

It goes into ~/.ssh/config as computer.shop.smartalfred, and then ssh computer.shop.smartalfred, scp notes.txt computer.shop.smartalfred:, rsync -a site/ computer.shop.smartalfred:site/ work, and so does Remote-SSH: Connect to Host… in VS Code or Cursor, with the editor's server running in the computer. Without --add it prints the entry for you to put there yourself.

ssh (or VS Code, scp, rsync) runs alf as its ProxyCommand. The tool puts its own key in the computer's authorized_keys, then opens a stream signed in as you: a WebSocket over HTTPS to Alf, and on from there over the connection the computer's server keeps open. In the computer, alf pipe 22 connects that stream to the computer's SSH server on port 22, which is never on the internet, and it logs you in as dev. SSH runs end to end inside the stream, from your ssh to the computer's SSH server: Alf only carries the bytes. Whoever may open a shell in the computer may SSH into it.

Files in and out

alf cp ./site shop/computer:            # into /workspace
alf cp ./notes.txt shop/computer:/tmp/
alf cp shop/computer:report.pdf .       # out

One side is the computer and a path in it, as with scp; a path that isn't absolute is in /workspace, and a folder goes with everything in it. In the dashboard, drop files on the computer's shell to copy them into /workspace, or use Files at the top of its page for another folder, and to download a file (a folder comes as a .tar).

A TCP port on the internet

For something that isn't HTTP — a database you're trying out, a game server, an SSH server of a different kind — Settings → Public ports opens a TCP or UDP port on the computer's server to the addresses you allow, as for any service. It reaches the computer's port even if what listens there only listens on localhost.

Every port, from your laptop

With network access, your laptop joins the computer's project network, and every port of the computer is reachable at its own name while it runs, without sharing anything on the web:

alf connect shop --all

Then any program at computer.shop.internal (computer being the computer's name, shop its project's) — ssh dev@computer.shop.internal included, with a key in its ~/.ssh/authorized_keys. Making the network interface needs sudo; the names go into /etc/hosts and come out again when you leave.