Remote daemon
Run the daemon on a server and use adf (the terminal app or one-shot commands) from your laptop.
On this page
Run the daemon on a server and use adf (the terminal app or one-shot
commands) from your laptop. Every client needs two things: the daemon’s URL
and its access token.
adf --url <url> --token <token> # terminal app
adf --url <url> --token <token> agents # a command
export ADF_DAEMON_URL=<url> ADF_DAEMON_TOKEN=<token> # or once per shell
Get the token on the server with adf daemon token (it prints only the
token). adf never starts a daemon for a remote URL (or a tunnelled local
port), and never sends your machine’s own token file to another host. In the app, /url <url> --token <token> switches daemons live.
Option 1: SSH tunnel (recommended)
The daemon stays on the server’s loopback, where it is by default; SSH does the transport and encryption.
# on your laptop: local port 7386 → the server's daemon on 7385
ssh -N -L 7386:127.0.0.1:7385 user@server &
adf --url http://127.0.0.1:7386 --token "$(ssh user@server adf daemon token)"
# or once per shell
export ADF_DAEMON_URL=http://127.0.0.1:7386
export ADF_DAEMON_TOKEN="$(ssh user@server adf daemon token)"
adf
- Use a local port other than your own daemon’s (7385, or
ADF_DAEMON_PORT).adftreats any other loopback port as a tunnel: it never auto-starts a daemon there (a down tunnel gives “Cannot reach…”), and never sends your laptop’s token file there. - So the token is required:
--tokenorADF_DAEMON_TOKEN. Without it the daemon answers401andadfpoints you toadf daemon token. - Through the tunnel the daemon sees a loopback connection, so owner identity
create / restore / unlock and
adf daemon stopwork as on the server.
Option 2: bind to the network
For a trusted network only (a LAN, a tailnet): the daemon speaks plain HTTP, so the token travels unencrypted.
# on the server, in the foreground (or under systemd / a service manager)
export ADF_DAEMON_TOKEN="$(openssl rand -base64 32 | tr '+/' '-_' | tr -d '=')"
ADF_DAEMON_ALLOWED_HOSTS=server.lan adf daemon --host 0.0.0.0
- A non-loopback
--hostrequiresADF_DAEMON_TOKEN: the daemon refuses to start without it. The background start (adf daemon start) is loopback only; runadf daemon --host …in the foreground or as a service. - Clients may use the server’s IP address; host names they use (here
server.lan) must be inADF_DAEMON_ALLOWED_HOSTS(comma or space separated;nameorname:port). - Owner identity create / restore / unlock and
adf daemon stopare refused from other machines: run them on the server.
Option 3: TLS reverse proxy
Keep the daemon on 127.0.0.1:7385 and put a TLS proxy in front, for
example Caddy:
adf.example.com {
reverse_proxy 127.0.0.1:7385
}
- Start the daemon with
ADF_DAEMON_ALLOWED_HOSTS=adf.example.comso it accepts the proxiedHost. - The token is the install’s file token:
adf daemon tokenon the server. Clients:adf --url https://adf.example.com --token <token>. - Live events are a streaming response (
/events). Caddy streams them as is; with nginx setproxy_buffering offfor the daemon location. - The daemon sees the proxy’s loopback connection. Start it with
ADF_DAEMON_BEHIND_PROXY=1so the routes it keeps to its own machine (owner identity create / restore / unlock / lock,adf daemon stop) stay there: they then also need a proof file only this host can read, whichadfon the server sends by itself. Run those commands on the server, against127.0.0.1:7385, not through the proxy. A request that carries proxy headers (X-Forwarded-For,Forwarded,X-Real-IP, …) is never treated as local, with or without the setting.
Sign in to ChatGPT
ChatGPT sign-in redirects the browser to a local callback. Against a remote
daemon, adf auth login chatgpt and the app’s /login chatgpt receive that
callback on your machine and hand the code to the daemon (relay mode, the
default for a non-loopback --url). Only the short-lived authorization code
travels, useless without the verifier the daemon kept. Through an SSH tunnel
the URL looks local, so the daemon serves the callback on the server’s port
1455: force relay (CLI only), or tunnel that port too (needed for the app’s
/login chatgpt):
adf auth login chatgpt --relay
# or
ssh -N -L 7386:127.0.0.1:7385 -L 1455:127.0.0.1:1455 user@server &
adf auth login chatgpt --loopback
Grok’s device code works anywhere.
Things that stay on the server
- Agents’ files and folders:
/track,/loadandadf new --dirtake paths on the daemon’s machine. - The external editor (
ein Files) runs on your laptop; the file goes back to the daemon on save. adf daemon logs,statusdetails (data dir, log) andtokenread the local machine: run them on the server.