Skip to content

Remote Access

comfuture edited this page Aug 10, 2026 · 1 revision

Remote Access

Codori does not create private connectivity on its own. Tailscale must already be installed, running, and joined to a tailnet. Typical patterns are access over a Tailscale tailnet, or access through another tunnel you manage yourself.

Option 1: Tailscale Serve (recommended)

Start Codori normally. Eligible Tailscale hosts configure persistent private HTTPS automatically:

codori start --root ~/Project

Use --tailscale-serve to require this path and fail when Tailscale, MagicDNS, HTTPS, or the safe mapping contract is unavailable. Use --no-tailscale-serve to skip automatic detection and Serve mutation. codori serve remains a deprecated alias for codori start.

This mode forces the Codori origin to 127.0.0.1, inspects the existing structured Serve status, and then configures:

tailscale serve --bg --yes --https=443 http://127.0.0.1:4310

Codori prints the resulting private MagicDNS URL:

https://my-codori-host.your-tailnet.ts.net/

The mapping operation is idempotent when that exact root proxy already exists. Automatic mode leaves conflicts untouched, continues on the local listener, and prints the reason. Required --tailscale-serve mode fails without changing Tailscale when port 443 has a conflicting root mapping, a foreground listener, Funnel exposure, or a non-HTTPS listener. Codori never runs tailscale serve reset and does not remove unrelated path handlers.

Operator permission

Writing a Serve config requires root or a Tailscale operator, so an unprivileged launch is refused with Access denied: serve config denied even though status reads fine. Grant the account that runs Codori ongoing control once:

sudo tailscale set --operator=$USER

Codori keeps serving on loopback until that is set; only the private HTTPS URL is unavailable.

Scope and cleanup

Tailscale Serve is private to the tailnet, uses tailnet access-control rules, and provisions TLS for the MagicDNS name. Codori still has no built-in authentication, so restrict tailnet access to trusted operators. Tailscale Funnel and public exposure are outside this command's contract and require the future application-authentication boundary tracked in issue #77.

To remove the root mapping later, use targeted cleanup:

tailscale serve --https=443 off

The background mapping persists across Codori and Tailscale restarts. When Codori is stopped, the URL remains configured but its loopback backend is unavailable until Codori starts again.

Current behavior and syntax are documented by Tailscale in Tailscale Serve and the Serve CLI reference.

Option 2: Direct tailnet HTTP

If secure-context features such as WebXR and remote microphone access are not needed, Codori can bind directly to the current node's Tailscale IPv4:

codori start --host "$(tailscale ip -4 | head -n1)" --port 4310

From another device in the same tailnet, open the short or fully qualified MagicDNS name:

http://my-codori-host:4310
http://my-codori-host.your-tailnet.ts.net:4310

This opens Codori on the Tailscale interface rather than every network interface, but plain remote HTTP is not a browser secure context. Prefer --tailscale-serve for realtime voice and WebXR.

Bind overrides

codori start --root ~/Project --host 0.0.0.0 --port 4310

An explicit non-loopback --host is an ingress override and disables automatic Tailscale Serve. Prefer the automatic loopback-backed HTTPS path for tailnet access, and use direct binding only when you intentionally manage that boundary.

Notes

  • Tailscale Serve is for private tailnet access, not public internet access.
  • Serve defaults to automatic for direct and service launches; --tailscale-serve makes it required and --no-tailscale-serve disables it.
  • If you want public exposure, that is a different problem and should be handled deliberately with a public ingress layer.

Clone this wiki locally