Deploy on Render
Render runs the all-in-one image as a web service in the single node and managed Postgres modes. Render has no object storage, so bring an S3 bucket, for example from AWS S3 or Cloudflare R2. Go through the production checklist too.
What Render decides
- Deploys. A service with a persistent disk stops its old instance before it starts the new one. That is what the one shard manager rule needs. Without a disk, Render keeps the old instance running for 60 seconds after the new one takes traffic, and two servers then run on the same database. Attach a disk in both modes, also in mode 2, where it holds only caches. Disks need a paid instance type.
- Scaling. A service with a disk cannot scale beyond one instance. Run one server; it scales vertically.
- Backups. Render snapshots disks once a day and keeps the snapshots for at least seven days, so a lost disk can lose up to a day of the SQLite state. Turn on Litestream in mode 1, or use mode 2.
- Forwarded headers. Render does not document the addresses its load balancer connects from or the forwarded headers it sets, so the server does not trust them. The server routes by the
Hostheader and seeshttpas the scheme. This affects the URLs it builds from the request, such as the address an OIDC login returns to. - Architecture. Render runs prebuilt images for
linux/amd64only.
Single node
Create the bucket
Create an S3 bucket and an access key that can list, read, write and delete its objects. For Cloudflare R2, the endpoint is https://<account id>.r2.cloudflarestorage.com and the region is auto.
Write the environment file
Run the generate-env.sh script:
curl -fsSLO https://raw.githubusercontent.com/golemcloud/golem/main/docker-examples/single-node/generate-env.sh
chmod +x generate-env.sh
umask 077
GOLEM_S3_BUCKET=my-bucket GOLEM_S3_REGION=auto \
GOLEM_S3_ENDPOINT=https://<account id>.r2.cloudflarestorage.com \
./generate-env.sh > golem.env
cat >> golem.env <<'EOF'
AWS_ACCESS_KEY_ID=<access key>
AWS_SECRET_ACCESS_KEY=<secret key>
PORT=10000
GOLEM__ROUTER__PORT=10000
GOLEM__ROUTER__MANAGEMENT_HOST=golem.example.com
GOLEM_LITESTREAM=true
GOLEM_LITESTREAM_REPLICA_URL=s3://my-bucket/litestream?endpoint=https://<account id>.r2.cloudflarestorage.com®ion=auto
EOFSet both variables: GOLEM__ROUTER__PORT sets Golem’s listener, and PORT tells Render which port to use. The server listens on ::, which accepts IPv4 connections too. golem.env contains the admin token, GOLEM__REGISTRY_SERVICE__INITIAL_ACCOUNTS__ROOT__TOKEN. Keep it, and delete the file when the service runs.
Create the web service
The stock golemservices/golem image runs as uid 65534. A new Render disk at /var/lib/golem needs no ownership change. If an existing disk is not writable by that user, follow Volume ownership.
Create a web service from the existing image golemservices/golem:<version> with a paid instance type. Before the first deploy:
- Environment. Add the variables with Add from .env and paste
golem.env. - Disk. Add a persistent disk with the mount path
/var/lib/golem. - Health check. Leave the health check path empty to use Render’s default TCP check. With verified custom domains, Render sends HTTP health checks with one of those domains as
Host. An HTTP API or MCP domain routes/healthcheckto the application, which returns 404, not to the management API. TCP checks confirm only that the listener accepts connections; monitorhttps://golem.example.com/healthcheckseparately for application readiness. The first start on a new disk downloads and inspects the built-in plugins and tools, which can take several minutes.
Add the domains
Add the management host (golem.example.com) and each domain of an HTTP API or MCP deployment as custom domains of the service. Render shows the DNS records to create and gets the certificates.
To use the management API before configuring custom domains, use the service’s generated onrender.com domain as GOLEM__ROUTER__MANAGEMENT_HOST. Use only the host name, without https://. HTTP API and MCP deployments each need a different domain; the management domain cannot serve them.
Set scheme: https in the HTTP API deployment so its OpenAPI document advertises HTTPS; this does not require trusting forwarded headers.
Deploy an application
Check https://golem.example.com/healthcheck, and deploy an application with the admin token. See Connect the CLI.
To upgrade, change the image tag of the service. To restore after the loss of the disk, start the service with an empty disk: the image restores the databases from the Litestream replica before the server starts. The new disk has no cache of the built-in plugins and tools, so that start downloads them again from GitHub.
Litestream is off by default; turn it on from the first start of a new disk. This guide turns it on because the platform’s volumes belong to one host and are backed up only once a day; with a reliable persistent volume, it is not needed. Litestream is backup and restore for one server, not high availability. Exactly one container may write to a replica URL: two containers on the same replica corrupt it. Replication is asynchronous, about once a second, so losing the disk can lose the newest oplog writes, and agents then replay from an earlier point and may run side effects again. Litestream replicates only the SQLite databases, so the blobs must be in S3. It does not replicate the cache of the built-in plugins and tools either, so a restore onto a new disk downloads them again and needs HTTPS connections to GitHub. At startup, the image restores only the databases that are missing from the disk, so a restart with its data restores nothing. For production durability, use the managed Postgres mode. See Litestream limits.
Managed Postgres
Create a Render Postgres database in the region of the service, and pass the host name of its internal connection URL and its credentials to the script:
GOLEM_S3_BUCKET=my-bucket GOLEM_S3_REGION=auto \
GOLEM_S3_ENDPOINT=https://<account id>.r2.cloudflarestorage.com \
GOLEM_POSTGRES_HOST=<internal host name> GOLEM_POSTGRES_DB=<database> \
GOLEM_POSTGRES_USER=<user> GOLEM_POSTGRES_PASSWORD=<password> \
./generate-env.sh > golem.env
cat >> golem.env <<'EOF'
AWS_ACCESS_KEY_ID=<access key>
AWS_SECRET_ACCESS_KEY=<secret key>
PORT=10000
GOLEM__ROUTER__PORT=10000
GOLEM__ROUTER__MANAGEMENT_HOST=golem.example.com
EOFThis command replaces golem.env, so it repeats the bucket credentials, port and management host. Use the actual database name from Render’s connection details, not the database service name. The database can reject all external connections: Golem uses Render’s private network.
Leave out the Litestream variables: the state is in Postgres. Keep the disk at /var/lib/golem: it makes Render stop the old instance before it starts the new one. Point-in-time recovery of the database needs a paid Postgres instance.
The service is unavailable while Postgres restarts.
Fixed cluster
A fixed cluster on Render needs verification. The shard manager records the source address of each executor’s registration, and Render does not document whether its private network keeps that address.