Venelx Docs

Cloudflare Tunnel

Expose a self-hosted venelx-backend (127.0.0.1:4000) as https://api.venelx.com — outbound-only, no port forwarding, no static IP. The dashboard stays on Vercel at app.venelx.com.

Only api.venelx.com goes through the tunnel. app.venelx.com (dashboard) and docs.venelx.com (this site) live on Vercel and need no tunnel configuration.

Concepts

FieldValue
Tunnel namevenelx-api (any name works)
Tunnel ID<tunnel-id> — a UUID assigned by Cloudflare at creation
Credentials file~/.cloudflared/<tunnel-id>.json (per machine — never commit it)
DNSCNAME api<tunnel-id>.cfargotunnel.com (proxied)
Ingressapi.venelx.comhttp://127.0.0.1:4000

Setup

One-time login (stores a cert in ~/.cloudflared), then the repo script creates the tunnel, writes the config, and routes DNS:

bash
cloudflared tunnel login

cd <repo-root>
chmod +x scripts/setup-tunnel.sh
./scripts/setup-tunnel.sh              # create tunnel + DNS + config if missing
./scripts/setup-tunnel.sh --recreate   # delete the existing tunnel and start fresh

Then start the connector:

bash
cloudflared tunnel run venelx-api
# production (launchd):
sudo launchctl kickstart -k system/com.venelx.app.cloudflared

./setup.sh calls setup-tunnel.sh automatically during a fresh install. To use a different hostname: VENELX_TUNNEL_HOST=api2.example.com VENELX_TUNNEL_NAME=venelx-api-2 ./scripts/setup-tunnel.sh.

Config file

infra/cloudflare-tunnel.venelx.yml is copied to ~/.cloudflared/config.yml:

yaml
tunnel: <tunnel-id>
credentials-file: ~/.cloudflared/<tunnel-id>.json

ingress:
  - hostname: api.venelx.com
    service: http://127.0.0.1:4000
  - service: http_status:404

The LaunchDaemon runs cloudflared tunnel run <tunnel-name> (see infra/launchd/com.venelx.app.cloudflared.plist).

DNS

Automated (recommended):

bash
cloudflared tunnel route dns -f venelx-api api.venelx.com

Or manually, in the Cloudflare dashboard → your zone → DNS:

TypeNameTargetProxy
CNAMEapi<tunnel-id>.cfargotunnel.comProxied

Route DNS only in the zone that owns the hostname.

Backend + Vercel env

env
# venelx-backend/.env
PUBLIC_DOMAIN=api.venelx.com
PUBLIC_API_URL=https://api.venelx.com
CORS_ORIGINS=https://app.venelx.com,https://*.vercel.app

# Vercel (venelx-frontend project)
NEXT_PUBLIC_API_URL=https://api.venelx.com
NEXT_PUBLIC_WS_URL=wss://api.venelx.com

Verify

bash
curl -s https://api.venelx.com/api/health
dig @1.1.1.1 api.venelx.com +short
cloudflared tunnel info venelx-api

Expect {"status":"ok",...} and non-empty tunnel CONNECTIONS.

Troubleshooting

IssueFix
502 / connection refusedAPI not listening on :4000curl http://127.0.0.1:4000/api/health
Tunnel has no connectionscloudflared tunnel run venelx-api, or kickstart the LaunchDaemon
DNS points to an old tunnelrerun ./scripts/setup-tunnel.sh (uses -f to overwrite the CNAME)
Wrong zoneroute DNS only in the zone that owns api.venelx.com
Local Mac can't resolve the name (dig empty, but dig @1.1.1.1 works)router/ISP DNS hasn't picked up the record — see below

Mac: dig empty but dig @1.1.1.1 works

Your router/ISP resolver has not picked up the new api CNAME yet (or cached an NXDOMAIN). Flushing the local cache alone won't help until the Mac asks a resolver that has the record. Point the Mac at Cloudflare's resolver:

bash
sudo networksetup -setdnsservers Wi-Fi 1.1.1.1 1.0.0.1
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder

dig api.venelx.com +short
curl -s https://api.venelx.com/api/health

Or via System Settings → Wi-Fi → Details → DNS — add 1.1.1.1 and 1.0.0.1. (The repo also ships ./scripts/fix-local-dns.sh for this.)