• Press kit
  • Support
  • Privacy
  • Imprint
Cuevello

Set up Cuevello Relay

Why relay? Requirements DNS TLS certificate Docker Firewall Mac Server Pairing Debugging

Why a relay?

Cuevello normally connects directly to the Mac on the local network. A relay is only needed when the client cannot reach the Mac directly, for example over cellular, from another Wi-Fi network, or behind NAT and firewall boundaries.

The Mac Server opens an outbound encrypted control connection to the relay. The client connects to the relay as well. The relay forwards traffic to the registered Mac; pairing, TLS, and certificate pinning remain the security foundation.

Requirements

  • A VPS or server with a public IPv4 address.
  • Docker and Docker Compose.
  • A relay subdomain, for example relay.example.com.
  • A wildcard DNS record for device subdomains.
  • A TLS certificate for the relay domain.
  • Open TCP ports for client and Mac Server control connections.

1. Configure DNS

The client connects to a device-specific subdomain in the form <device-id>.<relay-host>. Create both the relay record and the wildcard record.

relay.example.com      A      203.0.113.10
*.relay.example.com    A      203.0.113.10

Verify DNS:

dig +short relay.example.com A
dig +short abc123.relay.example.com A

2. Create the TLS certificate

The certificate is used for the Mac server control connection and must cover relay.example.com. The client port uses TLS passthrough to the Mac server, so a wildcard TLS certificate is not required.

certbot certonly --manual --preferred-challenges dns \
  -d relay.example.com \
  --agree-tos \
  --email you@example.com \
  --no-eff-email

Certbot shows TXT records for _acme-challenge.relay.example.com. Add all requested TXT values before continuing.

/etc/letsencrypt/live/relay.example.com/fullchain.pem
/etc/letsencrypt/live/relay.example.com/privkey.pem

3. Start the Docker container

The relay container is published from the dedicated repository github.com/hosy/cuevello-relay.

Download Compose template

mkdir -p /opt/cuevello-relay/certs
cd /opt/cuevello-relay
cp /etc/letsencrypt/live/relay.example.com/fullchain.pem ./certs/fullchain.pem
cp /etc/letsencrypt/live/relay.example.com/privkey.pem ./certs/privkey.pem
chmod 600 ./certs/privkey.pem
services:
  cuevello-relay:
    image: ghcr.io/hosy/cuevello-relay:latest
    container_name: cuevello-relay
    restart: unless-stopped
    environment:
      RELAY_SECRET_PEPPER: "replace-with-at-least-32-random-bytes"
      TLS_CERT_FILE: "/certs/fullchain.pem"
      TLS_KEY_FILE: "/certs/privkey.pem"
      MAX_STREAMS_PER_DEVICE: "32"
      CLIENT_RATE_LIMIT_PER_MINUTE: "120"
      CONTROL_RATE_LIMIT_PER_MINUTE: "30"
      REQUIRE_SIGNED_REGISTRATION: "true"
    ports:
      - "9443:443"
      - "9444:8443"
    volumes:
      - ./certs:/certs:ro
      - relay-data:/data

volumes:
  relay-data:

Generate a long secret pepper:

openssl rand -base64 48
docker compose up -d
docker compose ps
docker compose logs --tail=100

4. Open the firewall

  • 9443 for clients.
  • 9444 for Mac Server control connections.
nc -vz relay.example.com 9443
nc -vz relay.example.com 9444

5. Configure the Mac Server

  1. Start Cuevello Server on the Mac.
  2. Open Relay Settings....
  3. Enable Relay.
  4. Set Host to relay.example.com.
  5. Set Client Port to 9443.
  6. Set Control Port to 9444.
  7. Apply the settings.

6. Pair the client

Open the Mac pairing window. When relay is enabled and connected, the QR code contains the relay information. The client can pair through the relay even when it is outside the local network.

Security

  • Knowing a relay URL is not enough to control a Mac. Cuevello still requires end-to-end TLS with a paired client certificate.
  • The public client port uses TLS passthrough. The relay only reads the SNI hostname needed for routing and cannot decrypt Cuevello requests.
  • Mac server control registrations are signed with a persistent device key. The relay secret alone is not sufficient to take over a registered device.
  • The container enforces TLS 1.3, bounded registration requests, per-IP rate limits, and per-device stream limits.
  • Keep RELAY_SECRET_PEPPER, /data/devices.json, and the TLS private key private.

Debugging

DEVICE_ID="replace-with-device-id"
HOST="$DEVICE_ID.relay.example.com"

dig +short "$HOST" A
nc -vz "$HOST" 9443
openssl s_client -connect "$HOST:9443" -servername "$HOST"
cd /opt/cuevello-relay
docker compose logs -f --tail=100

Warum ein Relay?

Cuevello verbindet sich normalerweise direkt mit dem Mac im lokalen Netzwerk. Ein Relay wird nur benötigt, wenn der Client den Mac nicht direkt erreichen kann, zum Beispiel über Mobilfunk, aus einem anderen WLAN oder hinter NAT- und Firewall-Grenzen.

Der Mac Server baut selbst eine ausgehende, verschlüsselte Control-Verbindung zum Relay auf. Der Client verbindet sich ebenfalls mit dem Relay. Das Relay leitet den Verkehr zum registrierten Mac weiter; Pairing, TLS und Zertifikat-Pinning bleiben die Sicherheitsbasis.

Voraussetzungen

  • Ein VPS oder Server mit öffentlicher IPv4-Adresse.
  • Docker und Docker Compose.
  • Eine Relay-Subdomain, zum Beispiel relay.example.com.
  • Ein Wildcard-DNS-Eintrag für Device-Subdomains.
  • Ein TLS-Zertifikat für die Relay-Domain.
  • Offene TCP-Ports für Client- und Mac-Server-Control-Verbindungen.

1. DNS einrichten

Der Client verbindet sich mit einer Device-Subdomain im Format <device-id>.<relay-host>. Lege deshalb den Relay-Eintrag und den Wildcard-Eintrag an.

relay.example.com      A      203.0.113.10
*.relay.example.com    A      203.0.113.10

DNS prüfen:

dig +short relay.example.com A
dig +short abc123.relay.example.com A

2. TLS-Zertifikat erstellen

Das Zertifikat wird für die Mac-Server-Control-Verbindung genutzt und muss relay.example.com abdecken. Der Client-Port nutzt TLS-Passthrough zum Mac Server, deshalb ist kein Wildcard-TLS-Zertifikat für das Relay nötig.

certbot certonly --manual --preferred-challenges dns \
  -d relay.example.com \
  --agree-tos \
  --email you@example.com \
  --no-eff-email

Certbot zeigt TXT-Records für _acme-challenge.relay.example.com. Trage alle angeforderten TXT-Werte ein, bevor du fortfährst.

/etc/letsencrypt/live/relay.example.com/fullchain.pem
/etc/letsencrypt/live/relay.example.com/privkey.pem

3. Docker Container starten

Der Relay-Container wird aus dem eigenen Repository github.com/hosy/cuevello-relay veröffentlicht.

Compose-Vorlage herunterladen

mkdir -p /opt/cuevello-relay/certs
cd /opt/cuevello-relay
cp /etc/letsencrypt/live/relay.example.com/fullchain.pem ./certs/fullchain.pem
cp /etc/letsencrypt/live/relay.example.com/privkey.pem ./certs/privkey.pem
chmod 600 ./certs/privkey.pem
services:
  cuevello-relay:
    image: ghcr.io/hosy/cuevello-relay:latest
    container_name: cuevello-relay
    restart: unless-stopped
    environment:
      RELAY_SECRET_PEPPER: "replace-with-at-least-32-random-bytes"
      TLS_CERT_FILE: "/certs/fullchain.pem"
      TLS_KEY_FILE: "/certs/privkey.pem"
      MAX_STREAMS_PER_DEVICE: "32"
      CLIENT_RATE_LIMIT_PER_MINUTE: "120"
      CONTROL_RATE_LIMIT_PER_MINUTE: "30"
      REQUIRE_SIGNED_REGISTRATION: "true"
    ports:
      - "9443:443"
      - "9444:8443"
    volumes:
      - ./certs:/certs:ro
      - relay-data:/data

volumes:
  relay-data:

Erzeuge eine lange zufällige Secret-Pepper-Zeichenkette:

openssl rand -base64 48
docker compose up -d
docker compose ps
docker compose logs --tail=100

4. Firewall freigeben

  • 9443 für Clients.
  • 9444 für Mac-Server-Control-Verbindungen.
nc -vz relay.example.com 9443
nc -vz relay.example.com 9444

5. Mac Server konfigurieren

  1. Cuevello Server auf dem Mac starten.
  2. Relay Settings... öffnen.
  3. Relay aktivieren.
  4. Host auf relay.example.com setzen.
  5. Client Port auf 9443 setzen.
  6. Control Port auf 9444 setzen.
  7. Einstellungen anwenden.

6. Client pairen

Öffne das Pairing-Fenster am Mac. Wenn Relay aktiv und verbunden ist, enthält der QR-Code die Relay-Daten. Der Client kann dann auch außerhalb des lokalen Netzwerks über das Relay pairen.

Sicherheit

  • Die Relay-URL allein reicht nicht aus, um einen Mac zu steuern. Cuevello verlangt weiterhin Ende-zu-Ende-TLS mit einem gepairten Client-Zertifikat.
  • Der öffentliche Client-Port nutzt TLS-Passthrough. Das Relay liest nur den SNI-Hostnamen für das Routing und kann Cuevello-Requests nicht entschlüsseln.
  • Mac-Server-Control-Registrierungen werden mit einem persistenten Device-Key signiert. Das Relay-Secret allein reicht nicht aus, um ein registriertes Device zu übernehmen.
  • Der Container erzwingt TLS 1.3, begrenzte Registrierungs-Requests, IP-basierte Rate-Limits und Limits pro Device-Stream.
  • Halte RELAY_SECRET_PEPPER, /data/devices.json und den privaten TLS-Schlüssel geheim.

Debugging

DEVICE_ID="replace-with-device-id"
HOST="$DEVICE_ID.relay.example.com"

dig +short "$HOST" A
nc -vz "$HOST" 9443
openssl s_client -connect "$HOST:9443" -servername "$HOST"
cd /opt/cuevello-relay
docker compose logs -f --tail=100
Cuevello
Press kit Support Privacy Imprint