Deployment

The marketing/docs site and the local dashboard app are different deploy surfaces. The Astro site deploys to Cloudflare for neondeck.dev. The local app runs on the user's machine.

Astro site

The site lives in docs/ and builds to static assets.

npm run docs:build
npm run docs:preview

Cloudflare deploy

npm run docs:deploy

Wrangler config lives at docs/wrangler.jsonc. It deploys the built docs/dist assets to the neondeck-site Worker with custom domains for neondeck.dev and www.neondeck.dev. Merges to main that change the site or its build inputs are automatically built and deployed by the docs deployment workflow. Use npm run docs:deploy for a controlled manual redeploy.

Validation

cd docs
npx wrangler deploy --dry-run

Use a dry run before important deploys to validate the Worker config and asset bundle without publishing.

Local app packaging

The local app builds the React dashboard and Flue Node server. It uses runtime-home config and secrets on the user's machine, not Cloudflare Worker secrets.

npm run build:dashboard
npm run package:app
npm run release:app

Use SSH forwarding for remote access

SSH forwarding is the simplest option for one operator and keeps Neondeck inside its default loopback trust boundary. It requires neither nginx nor server.trustedOrigins. First, keep the packaged Neondeck service running on the exe.dev instance:

neondeck service install
neondeck service status

From the computer running the browser, forward a local port to Neondeck's loopback port on the instance. Replace user@instance with the SSH destination used for that exe.dev instance:

ssh -N \
  -o ExitOnForwardFailure=yes \
  -o ServerAliveInterval=30 \
  -L 8000:127.0.0.1:3583 \
  user@instance

Leave that SSH process running and open http://127.0.0.1:8000/ in the local browser. The left side of -L is the local browser port; change it if port 8000 is already in use. The right side remains 127.0.0.1:3583, the packaged Neondeck server on the remote instance.

curl http://127.0.0.1:8000/api/health

Run Neondeck on exe.dev with nginx

A packaged Neondeck server exposes the complete dashboard and API on loopback port 3583. Port 5173 belongs only to the Vite source-development dashboard. On an exe.dev instance, nginx can accept the instance's authenticated HTTPS traffic on port 8000 and proxy it to Neondeck. Unlike SSH forwarding, this stable external origin must be explicitly trusted by Neondeck.

Trust the external browser origin

Add the exact exe.dev origin to runtime-home config.json, replacing the example hostname with the one assigned to the instance. Merge the server block into the existing file rather than replacing its generated token or other settings:

{
  "version": 1,
  "server": {
    "trustedOrigins": ["https://example.exe.xyz"]
  }
}

Configure nginx

Preserve the public Host header so Neondeck can match it to the configured origin. Disable proxy buffering and extend the read timeout for dashboard server-sent events and long-poll responses. WebSocket upgrade headers are not required.

server {
    listen 8000;
    server_name _;

    location / {
        proxy_pass http://127.0.0.1:3583;
        proxy_http_version 1.1;

        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Connection "";

        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 1h;
        proxy_send_timeout 1h;
    }
}

Restart and validate

sudo nginx -t
sudo systemctl reload nginx
neondeck service install
neondeck service status

curl -i \
  -H 'Host: example.exe.xyz' \
  http://127.0.0.1:8000/api/health

Restart or reinstall the Neondeck service after changing server.trustedOrigins; the trust policy is loaded at process startup. The health request should return a successful response instead of the intentionally opaque 404 used for untrusted hosts.

Domain

The public docs domain is neondeck.dev. The local packaged dashboard normally runs at http://127.0.0.1:3583/. During source development, Vite serves the dashboard on http://127.0.0.1:5173/ and proxies API traffic to port 3583.