Skip to content

Architecture

Skyglow separates public web delivery from physical radio control. The VPS serves static assets and terminates the Cloudflare origin path. The Mac keeps the receiver, credentials, history, recordings, and decoders.

Deployment topology

flowchart TB
    subgraph Internet
        Phone[iPhone / browser]
        CF[Cloudflare edge]
    end
    subgraph VPS[ServerCheap VPS]
        Tunnel[cloudflared]
        Caddy[Caddy :8790]
        Static[Versioned static release]
        Reverse[SSH loopback :18790]
    end
    subgraph Home[Mac receiver host]
        Launchd[launchd services]
        API[Skyglow Python :8790]
        DB[(SQLite and media)]
        Decoders[readsb / rtl_fm / rtl_433 / SatDump]
        USB[Nooelec NESDR]
    end
    Phone -->|HTTPS| CF
    CF --> Tunnel --> Caddy
    Caddy --> Static
    Caddy -->|/api and /media| Reverse
    Reverse -->|Encrypted reverse SSH| API
    Launchd --> API
    API --> DB
    API --> Decoders --> USB

Both VPS listeners are bound to loopback. The Mac opens the SSH connection outward, so the home network needs no inbound port or router rule.

Request routing

sequenceDiagram
    actor Browser
    participant Cloudflare
    participant Edge as VPS Caddy
    participant SSH as Reverse SSH
    participant Mac as Mac API
    Browser->>Cloudflare: HTTPS request
    Cloudflare->>Edge: Tunnel request
    alt Static asset or SPA route
        Edge-->>Cloudflare: File from active release
    else /api/* or /media/*
        Edge->>SSH: Proxy to 127.0.0.1:18790
        SSH->>Mac: 127.0.0.1:8790
        Mac-->>Edge: Authorized response
    end
    Edge-->>Browser: Security headers and response

Components

Component Runs on Responsibility
Next/Vinext client VPS and browser Responsive application shell, map, controls, audio, and replay UI
Caddy edge VPS Static files, compression, security headers, and API/media proxy
cloudflared VPS Public HTTPS path without opening VPS web ports directly
Reverse SSH LaunchAgent Mac Persistent encrypted loopback path to the VPS
Python receiver service Mac Authentication, APIs, history, scheduling, decoder lifecycle, and media
SQLite and media tree Mac Positions, alerts, sensors, captures, account, and recordings
Decoder tools Mac Demodulation and decoding for the active receiver mode

Recovery behavior

flowchart TD
    Failure{What failed?}
    Failure -->|Browser or Cloudflare| Static[Edge remains healthy]
    Failure -->|Reverse SSH| Reconnect[launchd restarts SSH]
    Failure -->|Mac API| RestartAPI[launchd restarts Python]
    Failure -->|Temporary decoder| Rollback[Manager stops process and restores aircraft]
    Failure -->|VPS edge| Supervisor[Linux supervisor restarts Caddy]
    Failure -->|VPS reboot| Cron[crontab starts edge and tunnel]
    Reconnect --> Healthy[Health checks recover]
    RestartAPI --> Healthy
    Rollback --> Healthy
    Supervisor --> Healthy
    Cron --> Healthy

The interface can still load from the VPS when the Mac is unavailable, but login, live data, media, and controls depend on the private receiver path.