Edgeweir
Deployment

Render

Deploy the console on Render with the console image and Render Postgres 18: one-click Deploy to Render, manual creation in the Dashboard, and the Render CLI equivalents.

Deploy to Render

Requirements

ItemRequirement
RenderAn account that can use paid plans. Free web services spin down after 15 minutes without traffic and Free Postgres expires 30 days after creation; neither can be used
Console imageghcr.io/marvinli001/edgeweir:<YYYYMMDD>-<commit>, public; Render runs linux/amd64, which the image includes. Tag rules: Versions, upgrades and rollback
PostgreSQLRender Postgres, PostgreSQL 18
Nodesedgeweir-node 0.2.0 or later: Render does not forward TCP, so nodes reach the node channel through the WebSocket entry
Master keyGenerated by the Blueprint, or with openssl rand -base64 32; keep it outside Render, apart from database backups
Local commandscurl; openssl for manual creation; the Render CLI is optional

Topology

Render resourceTargetCarries
Web service edgeweir, source the console image, plan 0.5c-512mb, 1 instance—ROLE=all (image default): web UI, API, node channel, pg-boss worker
<name>.onrender.com or a custom domain, HTTPS terminated by RenderContainer port 3000 (PORT=3000)Browsers, /api/v1, /install.sh, /healthz; the node channel's WebSocket entry /node-channel
Render Postgres edgeweir-db, PostgreSQL 18, plan 0.1c-256mb, private network onlyInternal connection string, DATABASE_URLDatabase

Render forwards one HTTP port per web service and terminates TLS at its load balancer. The node channel's 8443 is not exposed: nodes enroll with wss://<name>.onrender.com, and the node channel's TLS runs inside the WebSocket, terminated by the console with mTLS; see The node channel's WebSocket entry.

One-click creation

render.yaml at the repository root is the Blueprint:

ResourceSettings
Web service edgeweirruntime: image, ghcr.io/marvinli001/edgeweir:latest; plan: 0.5c-512mb; healthCheckPath: /healthz
VariablesPORT=3000; EDGEWEIR_MASTER_KEY generated by Render (a base64-encoded random 256-bit value); DATABASE_URL from the internal connection string of edgeweir-db; EDGEWEIR_PUBLIC_URL from the service's own RENDER_EXTERNAL_URL; EDGEWEIR_NODE_API_WEBSOCKET=true
Database edgeweir-dbPostgreSQL 18, database and user edgeweir, plan: 0.1c-256mb, ipAllowList: [] (private network only)

Both resources are created in Render's default region, oregon, which cannot be changed afterwards; for another region use manual creation.

  1. Click Deploy to Render at the top of this page (https://render.com/deploy?repo=https://github.com/marvinli001/edgeweir) and sign in to Render.
  2. Enter a Blueprint name, check that edgeweir and edgeweir-db will be created, and click Deploy Blueprint.
  3. Turn off automatic sync: on the Blueprint's Settings page, set Auto Sync to No. Otherwise every change to this repository's render.yaml syncs to your deployment and overwrites the same settings changed in the Dashboard (image, variables).
  4. Save the master key: on the edgeweir service's Environment page, copy the value of EDGEWEIR_MASTER_KEY and keep it offline, apart from database backups; see Backup and recovery.
  5. Pin the version, then initialize.

Manual creation

Equivalent to one-click creation, with a region of your choice.

  1. Generate the master key:

    umask 077
    openssl rand -base64 32 > edgeweir-master-key
  2. Database: Dashboard + New → Postgres. Name edgeweir-db, PostgreSQL Version 18, pick the region and plan, click Create Database.

    • Copy the internal connection string (Internal) from the Connect menu at the top right of the database page.
    • A new database accepts password connections from any address (0.0.0.0/0): in the Networking section of the database's Info page, remove that entry and keep the private network only, like ipAllowList: [] in one-click creation.
  3. Console: + New → Web Service, under Source Code pick Existing Image, enter ghcr.io/marvinli001/edgeweir:20260929-a1b2c3d (replace with the target tag) as Image URL, click Connect.

  4. Name edgeweir, Region the same as the database, plan 0.5c-512mb or larger.

  5. Advanced:

    • environment variables below;
    • Health Check Path /healthz.
    PORT=3000
    DATABASE_URL=<internal connection string>
    EDGEWEIR_MASTER_KEY=<contents of edgeweir-master-key>
    EDGEWEIR_PUBLIC_URL=https://edgeweir.onrender.com
    EDGEWEIR_NODE_API_WEBSOCKET=true

    EDGEWEIR_PUBLIC_URL follows the service name; when the name is taken, Render assigns another subdomain. Look up the actual address on the service page after creation, correct it on Environment, and choose Save and deploy.

  6. Click Create Web Service.

Pin the version

One-click creation runs the latest image. Once the first deploy succeeds, pin the tag it runs:

  1. Read the running version:

    curl -fsS https://<name>.onrender.com/healthz

    The version field is the tag, e.g. 20260929-a1b2c3d.

  2. In the Deploy section of the edgeweir service's Settings page, change the image URL to ghcr.io/marvinli001/edgeweir:<that tag> and save.

Initialization

An uninitialized console logs the same setup token on every start.

  1. edgeweir service Logs, search for first-run setup.
  2. The line's setupToken field is the setup token and its url field the setup wizard (<EDGEWEIR_PUBLIC_URL>/setup).
  3. Open the wizard and enter the setup token; see Quick start.

Variables

VariableValueNotes
PORT3000Render's default port is 10000; set 3000, as the image's health check expects.
DATABASE_URLInternal connection string of edgeweir-dbRequired. Private network, same region.
EDGEWEIR_MASTER_KEYGenerated by the Blueprint, or the output of openssl rand -base64 32Required.
EDGEWEIR_PUBLIC_URLhttps://<name>.onrender.comRequired. The Blueprint takes RENDER_EXTERNAL_URL (never a custom domain); with a custom domain, set the literal value.
EDGEWEIR_NODE_API_WEBSOCKETtrueThe default node channel URL is wss://<host of EDGEWEIR_PUBLIC_URL>, and the WebSocket entry is always open.
EDGEWEIR_NODE_API_URLUnsetWhen set, it replaces the default of the previous row; it must be a wss:// URL.
EDGEWEIR_TRUSTED_PROXIESEmptySee Limitations.
EDGEWEIR_VERSIONUnsetThe running version built into the image; the image tag decides it.
BETTER_AUTH_SECRETUnsetKeep the original value when migrating from a deployment that set it.

ROLE, HOST, and NODE_API_PORT keep the image defaults all, 0.0.0.0, and 8443; only the WebSocket entry connects to 8443, inside the container. All variables: Environment variables.

Verification

CheckWhere or commandExpected
Deployedgeweir service DeploysThe current deploy is live
Web and APIcurl -fsS https://<name>.onrender.com/healthz{"status":"ok","version":"20260929-a1b2c3d"}
WebSocket entrycurl -s -o /dev/null -w '%{http_code}\n' https://<name>.onrender.com/node-channel426
Node channel URL"Node channel" in System settingswss://<name>.onrender.com, connection check "Reachable"
Node enrollmentClusters and nodes → Add node--server wss://<name>.onrender.com; run it on the node as in Adding nodes

Custom domain

Do this before enrolling nodes; enrolled nodes connect to the address they enrolled with, see Node channel URL and certificate.

  1. edgeweir service Settings → Custom Domains → + Add Custom Domain, enter console.example.com; add the CNAME the page shows to DNS and click Verify.

  2. Change on Environment, choose Save and deploy:

    EDGEWEIR_PUBLIC_URL=https://console.example.com

    The default node channel URL becomes wss://console.example.com. The Blueprint's Auto Sync must be No, or the next sync sets EDGEWEIR_PUBLIC_URL back to RENDER_EXTERNAL_URL.

  3. Verify: run the commands of Verification with the new domain.

With nodes already enrolled through wss://<name>.onrender.com, save wss://console.example.com under "Node channel" in System settings instead of changing environment variables: the old name stays in the node channel certificate. Keep the onrender.com subdomain on (do not set Render Subdomain to Disabled).

Upgrade

  1. Back up the database: database page Recovery → Create export, download the export; paid plans also have Point-in-Time Recovery. See Backup and recovery.

  2. In the Deploy section of the edgeweir service's Settings page, change the image URL to the new tag and save; on the Deploys page, Manual Deploy → Deploy latest reference.

  3. Verify:

    curl -fsS https://<name>.onrender.com/healthz

    Expected: version is the new tag.

Migrations, signature verification, and rollback: Versions, upgrades and rollback.

Render CLI

TaskCommand
Validate the Blueprintrender blueprints validate render.yaml
Read the setup tokenrender logs --resources <service ID> --output json | grep setupToken
Upgraderender services update <service ID> --image ghcr.io/marvinli001/edgeweir:<new tag>, then render deploys create <service ID> --wait

Limitations

ItemBehaviorImpact
Node channelA web service forwards one HTTP port and no TCPNodes connect through the WebSocket entry only, with edgeweir-node 0.2.0 or later
WebSocket connectionsRender sets no maximum duration; they close when the instance is replaced (deploys, restarts, platform maintenance)Nodes reconnect; meanwhile they serve with their last good configuration
Deploy switchoverThe new instance gets traffic once healthy; after 60 seconds the old one receives SIGTERM and is killed after the shutdown delay (30 seconds by default)Old and new versions run side by side for a short while; node connections on the old instance drop and reconnect to the new one
Client IPRequests reach the container through Cloudflare and Render's load balancer; the source ranges the load balancer connects from are not publishedLeave EDGEWEIR_TRUSTED_PROXIES empty; audit IPs, sign-in rate limiting, and the nodes' "connection source address" use the load balancer's address; see Trusted proxies and client IP
Blueprint syncWith Auto Sync on Yes, changes to render.yaml sync to the resources and overwrite conflicting Dashboard settings; a deleted Blueprint-managed resource is recreated by the next syncSet Auto Sync to No after creation
RegionCannot be changed after creation; the web service and the database must share it to use the private networkOne-click creation uses oregon
Database accessipAllowList: [] allows the private network onlyA local pg_dump needs an allowed source address added on the database page first; or use the exports on the Recovery page
LogsKept per workspace plan (7 days on Hobby)The setup token is logged again on every start
/downloads/*The container has no downloads mirror; EDGEWEIR_DOWNLOADS_DIR is unset404; install.sh downloads from GitHub, see Adding nodes
Edit on GitHub

On this page