Access from your phone

Your laptop's SSH tunnel isn't reachable from your phone. Once your first task works, choose one way to reach the server from other devices.

You wantUseExtra setup
Laptop only; SSH is fineThe SSH tunnel you already haveNone
Private access from your phone and laptopsTailscaleTailscale on the server and each device
Browser access on your own domain, with no app on each deviceCloudflareA Cloudflare domain, cloudflared and an Access policy
You already run a VPN or HTTPS reverse proxyYour own networkPoint it at the loopback API

Each option keeps the API on loopback. You never need to open ports 8787 or 8788 to the internet. Connectivity can vary by network (for example, from mainland China), so test your choice on the network where you'll use it.

Managed connection is proposed, not available. A paid service that pairs your server once and handles HTTPS for you is being designed. See the managed connection design. The options on this page are the supported way to connect today.

#Tailscale

A private https:// address that only your own devices can open. No domain needed.

  1. Install Tailscale on the server and on each device, signed in to the same tailnet. See Install Tailscale.
  2. Turn on MagicDNS and HTTPS certificates for your tailnet. You need Tailscale 1.52 or newer.
  3. On the server, in the ccr-cloud folder:

    SHELL
    npm run setup -- --tailscale
  4. Open the printed https://HOST.TAILNET.ts.net/ address on a device in your tailnet and connect with the same owner token. Run a scratch task to check.

Setup uses Tailscale Serve and never enables Funnel, so the address isn't public. It won't replace another handler on that address. If Tailscale refuses the change, setup prints the permission fix to run, such as sudo tailscale set --operator=$USER.

To remove the address later (your tasks aren't affected):

SHELL
tailscale serve --https=443 off

#Cloudflare

Browser access on a hostname you control, such as ccr.example.com, without installing anything on each device. This path takes more setup.

Cloudflare terminates HTTPS, so it can see your traffic, including your owner token. Protect the whole hostname with a Cloudflare Access policy that allows only you.

  1. Install cloudflared on the server and run cloudflared tunnel login there. See Cloudflare's locally managed tunnel prerequisites.
  2. Create a self-hosted Access application for the hostname. Leave its path empty so it covers every path, and allow only your own email. Don't add bypass rules for specific paths.
  3. On the server, in the ccr-cloud folder:

    SHELL
    npm run setup -- --cloudflare ccr.example.com

    Setup creates or reuses a named tunnel, adds the DNS record and writes the tunnel configuration. It then checks that the site and each API path ask for an Access login. DNS changes can take a few minutes to appear; rerun setup until it reports Cloudflare Access: a login is required.

  4. Run the tunnel start command that setup prints, on the server.
  5. On your other device, open the HTTPS address, sign in to Cloudflare Access, then enter your owner token.

There are two logins: Access protects the hostname, and the owner token authorizes ccr-cloud. Setup refuses to overwrite existing DNS records or to reuse a tunnel whose credentials aren't on this server. Quick trycloudflare.com tunnels aren't supported. The API and the tunnel are separate processes, and both must be running.

#Your own VPN or reverse proxy

  • VPN: set CCR_CLOUD_HOST in server.env to the server's VPN address and limit access with your VPN's rules. Keep the runner endpoint on loopback.
  • HTTPS reverse proxy: proxy a dedicated HTTPS origin to 127.0.0.1:8787. Allow streaming responses and long read timeouts, because the app uses server-sent events.

Restart the service after editing server.env.

#Install the app

On an HTTPS address (or localhost), install ccr-cloud as an app from your browser's menu. On iPhone or iPad, use Share → Add to Home Screen, then open the installed app. You need to install it before notifications can work there.

The installed app opens offline, but viewing tasks and sending commands need a connection to your server. It never stores task content for offline use.

#Next steps

Edit this page on GitHub ↗