qalatra/docs/Remote instances

Remote instances & headless server

Run Qalatra Server on a Linux box and connect desktop clients over HTTPS.

Remote instances and headless Linux server installs are available in the current public beta. If your desktop app does not show Settings → Instances, update Qalatra first.

Qalatra can run as a server/client system. The desktop app still feels local, but the data path can go through Qalatra Server: an authenticated HTTP API that owns SQLite, MCP, background workers, agent jobs, attachments, backups, tokens, and encryption key access.

What changes

  • Local desktop: Electron starts a local Qalatra Server and connects to it over the same API path remote clients use.
  • Remote server: a Linux user service runs Qalatra without the Electron UI.
  • Instances: Settings → Instances stores server URLs and bearer tokens so the desktop app can switch between local and remote data sources.
  • MCP: the server starts MCP locally, but MCP is not exposed publicly.

Trust model

Use separate channels for operator access and the Qalatra API.

ChannelExampleCloudflare AccessAuth owner
Operator accessSSH, noVNC, admin desktopOnCloudflare Access + SSH keys
Qalatra APIapi.example.comOffQalatra bearer tokens
Do not put the Qalatra API hostname behind a Cloudflare Access login wall. Electron and future clients expect JSON API responses and authenticate with Qalatra bearer tokens.

Linux headless install

Run the installer as the normal Linux user that should own Qalatra. Do not run it with sudo.

export QALATRA_TUNNEL_HOSTNAME=api.example.com

curl -fsSL https://raw.githubusercontent.com/pirateandfox/qalatra/develop/scripts/bootstrap-linux-server.sh | bash

The bootstrap script:

  • clones or updates Qalatra in ~/qalatra
  • installs dependencies without Electron postinstall rebuilds
  • rebuilds native modules for system Node
  • installs and starts qalatra-server.service
  • creates or reuses a Cloudflare Tunnel named qalatra-api
  • routes the API hostname to 127.0.0.1:3456
  • installs and starts qalatra-cloudflared.service

Reboot survival

loginctl enable-linger "$USER"

systemctl --user status qalatra-server.service --no-pager -l
systemctl --user status qalatra-cloudflared.service --no-pager -l

Smoke tests

On the Linux server:

curl -fsS http://127.0.0.1:3456/health

TOKEN=$(cat ~/.local/share/qalatra/db/admin-token.txt)

curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:3456/api/instance

From another machine, test the public API hostname:

curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  https://api.example.com/api/instance

Connect desktop to a remote server

Settings -> Instances -> Add Server

URL:   https://api.example.com
Token: contents of ~/.local/share/qalatra/db/admin-token.txt from the Linux server

Prefer creating a dedicated expiring token for each client, then revoking the bootstrap token when it is no longer needed.

MCP stays local

Qalatra Server starts MCP locally at http://127.0.0.1:3457/mcp. If Claude Code is running on the Linux machine, configure that local URL. Do not expose port 3457 through Cloudflare Tunnel.

Troubleshooting

API is not healthy

systemctl --user status qalatra-server.service --no-pager -l
journalctl --user -u qalatra-server.service -n 160 --no-pager

Tunnel routes to the wrong service

cat ~/.config/qalatra/cloudflared/config.yml
cloudflared tunnel info qalatra-api
dig +short CNAME api.example.com

Native module ABI errors

cd ~/qalatra
npm run rebuild:node
systemctl --user restart qalatra-server.service