Choose a runtime and configure access
There are two separate choices when hosting Ficus: where its API and worker run, and where agents execute commands. Installing the app on a server does not automatically choose a safe agent runtime or make the browser interface publicly reachable.
Choose an agent runtime
Section titled “Choose an agent runtime”Every instance needs FICUS_SANDBOX_RUNTIME. Ficus refuses to start if it is missing or invalid. The current choice applies to the instance; per-squad runtime switching is not part of this setup flow.
| Runtime | Agent environment | What you need |
|---|---|---|
host | Commands run as Ficus’s user on its own machine. There is no isolation from that user’s files or network access. | Bash; a local Chromium-family browser for browser tools; tmux for local deployments. |
docker-socket | Container workspaces with the host’s Docker socket available inside. Docker access can control the host. | A working Docker daemon and sandbox image. |
docker-sysbox | Containers with user namespaces and their own Docker daemon. | Linux, Docker and the Sysbox runtime. |
vm | A box runs as a dedicated Unix user on a registered machine. Multiple boxes can share one machine. | An SSH-accessible machine fleet, bootstrap and box provisioning. |
k8s | Sandboxes run as Kubernetes pods. | A configured cluster, storage and sandbox deployment resources. |
The local installer prepares host, docker-socket, docker-sysbox or local k3d. Its k3d choice writes k8s as the runtime and configures local cluster access. VM fleets and existing Kubernetes clusters are advanced deployments; selecting their environment value alone does not create the infrastructure.
Host mode is suited to trusted personal work. It does not provide container toolchains or container-log streaming. Docker-socket is useful for compatibility, but its container boundary should not be treated as protection against an agent with Docker access.
Changing the runtime is not a workspace migration tool. Before changing an established instance, finish active work and preserve files from the existing environment. Remote VM files may not live in the local data directory.
Keep local access simple
Section titled “Keep local access simple”Fresh local setup uses one browser address, normally http://localhost:3000. Core serves the built web app, API and WebSockets together. Outside Kubernetes, the API and worker bind to loopback by default.
Check the actual address and runtime with:
ficus server statusUse the URL from setup consistently when registering and using passkeys. A different hostname is a different browser origin, even when it reaches the same computer.
Put a remote instance behind HTTPS
Section titled “Put a remote instance behind HTTPS”For browser access from another device, use a hostname you control and an HTTPS reverse proxy. This example assumes the proxy and Ficus run on the same machine, with Core listening on port 3000.
- Point your hostname at the server and arrange an HTTPS certificate with your proxy.
- Make sure
FICUS_SERVE_WEB=1is set in the Ficus checkout’s.env(setup sets it). - Proxy the whole hostname to
http://127.0.0.1:3000. Forward ordinary HTTP requests and WebSocket upgrades for both/wsand/ws/*, including terminal connections, and for/api/app/*, where squad local apps open their own WebSockets (for example, dev-server hot reload). - Sign in at the server’s current address as an administrator, open Settings → Administration → Server address, and set the Public address to
https://ficus.example.com. Review the confirmation, which lists the passkey, Ficus account and integration callback changes, and save. It takes effect immediately; no restart is needed. - Open the HTTPS address and test login, live task updates and a terminal session.
If you manage configuration as files instead, set the address in .env and restart with ficus server restart. An environment value locks the setting, and Settings shows it as Set by the server environment:
APP_URL=https://ficus.example.comFICUS_WEB_ORIGIN=https://ficus.example.comWith Caddy, the single-origin proxy portion is:
ficus.example.com { reverse_proxy 127.0.0.1:3000}FICUS_WEB_ORIGIN must be a bare origin: scheme, host and optional port, without a path. Passkey registration depends on it. APP_URL controls user-facing links; FICUS_API_URL serves other API-client/runtime connections and does not need to be changed to the public hostname for this same-machine proxy example.
Serve Ficus under a path prefix
Section titled “Serve Ficus under a path prefix”To serve Ficus at a path such as https://ficus.example.com/ficus, set the Public address (or APP_URL) to that address, path included. The same web build serves every path, so nothing needs to be rebuilt, and the server’s local address (for example Ficus Desktop’s http://localhost:<port>/) keeps working at the root at the same time. Links, phone pairing, integration OAuth callbacks and webhook URLs use the path. This documentation is served under the path too, at https://ficus.example.com/ficus/docs/, with working links and search.
Your reverse proxy can either remove the prefix before forwarding or forward it unchanged; Ficus accepts both. With Caddy:
# Prefix removed: Ficus sees /squads/1 and recognizes the address from the Host header.ficus.example.com { handle_path /ficus/* { reverse_proxy 127.0.0.1:3000 }}
# Or prefix forwarded unchanged: Ficus sees /ficus/squads/1 and removes it itself.ficus.example.com { handle /ficus/* { reverse_proxy 127.0.0.1:3000 }}When the proxy removes the prefix, it must keep the original Host header (Caddy and nginx’s proxy_set_header Host $host do) or send X-Forwarded-Host; otherwise Ficus cannot tell the request came through the prefixed address. A proxy that forwards the prefix needs neither.
With a prefix configured, /ficus/… reaches every Ficus route exactly as the unprefixed path does, on every listener. Any proxy path rule (blocks, authentication, rate limits, IP allow-lists) must cover both forms, or forward only the prefixed form to Ficus.
When you move an existing server to a new path:
- Open tabs and installed home-screen apps at the old path must be reopened or re-added from the new address.
- Squad apps that Ficus runs restart automatically so their links use the new path. Apps you started yourself and attached must be restarted by hand.
- A path that is also a Ficus page or API path (such as
/settingsor/api) works only behind a proxy that removes the prefix. Settings warns about this.
APP_BASE_PATH is no longer needed when the public address carries the path. Servers that set it keep working: it still sets the build-time path of the web app and is the path for origins listed in FICUS_WEB_ORIGIN.
Where the public address comes from
Section titled “Where the public address comes from”Ficus uses one public address for links, sign-in, integration OAuth callbacks, webhooks and the Ficus app. It is resolved in this order:
| Source | Locks the setting | Notes |
|---|---|---|
APP_URL environment variable | Yes | Shown as Set by the server environment. Remove it to manage the address in Settings. |
PUBLIC_URL environment variable | Yes | Older name, used only when APP_URL is unset. |
| Public address in Settings → Administration → Server address | — | Changed by administrators; takes effect without a restart. Every change is recorded with who made it. |
FICUS_LOCAL_APP_URL environment variable | No | The local address a launcher (Ficus Desktop, ficus setup) provides. It is used only when nothing above is set, and stays allowed for sign-in after a public address is set. |
On the first start after upgrading, a non-local APP_URL or PUBLIC_URL is also copied into the setting once, so the server keeps its address if you later remove the variable. Ficus Cloud servers are always managed by Ficus Cloud.
Ficus checks the address format only (scheme, host, optional port and path; no credentials, query or fragment). It does not check that the address reaches the server.
After a change:
-
Passkeys don’t carry over to a new hostname. Existing passkeys keep working at the local address (
FICUS_LOCAL_APP_URL, for example Ficus Desktop’shttp://localhost:<port>) and at the hostname they were made on while it stays allowed; you can keep signing in and pairing phones from there. -
To use a passkey at the new address, add one from an address where your passkeys still work (the address you used to make the change, or the local address):
- Open Settings → Account → Passkeys and choose Add a passkey for another address.
- Confirm with one of your passkeys. Ficus shows a one-time link and a code, valid for 15 minutes.
- Open the link at the new address, or go to
https://<new address>/add-passkeyand type the code, then create the passkey. You’re signed in there.
This adds a passkey. Your other passkeys and sessions stay as they are. Each person adds their own. A code works once, only for the account that created it, and creating another code cancels the previous one.
-
Lost your passkey? on the sign-in page is a last resort. It needs email delivery from the server, and it replaces all of your existing passkeys and signs out every session. Without email it sends nothing.
-
If the address you were using stops being allowed and you can’t sign in, set
APP_URLin the server environment and restart Ficus; the environment value overrides the setting. -
Ficus account (Mobile & Pro): connect the account again. Pending approvals for the old address are cancelled. Devices and Instance Pro slots stay with the old address in your Ficus account and do not move.
-
Integrations: update OAuth redirect URLs and GitHub or Linear webhook URLs with your providers. The confirmation lists the old and new values.
-
Links that were already sent keep the old address. Agents and sandboxes see the new address on their next command or session.
-
If the address has a path (for example
/ficus), the web app is served under it without a rebuild. See Serve Ficus under a path prefix.
The worker and internal event ports are not browser endpoints. Keep them on the private side of the deployment. If your proxy runs in another container or machine, configure a reachable private API bind address and firewall rules for that topology; 127.0.0.1 in the proxy then refers to the proxy itself.
Recognize a partial access problem
Section titled “Recognize a partial access problem”- The app loads but task updates or terminals disconnect: check WebSocket forwarding, including the bare
/wsroute. - Passkey registration fails: check the exact HTTPS origin, the Public address (or
APP_URL/FICUS_WEB_ORIGIN), and whether you switched hostnames after registration. - An API responds but the page is missing: ensure the web build exists and
FICUS_SERVE_WEBis enabled. - A host-mode agent cannot browse: install a supported browser or configure
FICUS_BROWSER_EXECUTABLE_PATH.
Use the configuration reference for the relevant settings and troubleshooting for diagnostic steps.