# Render

> Deploy Grovs on Render from the repository's Blueprint, with managed PostgreSQL and Key Value.

Source: https://docs.grovs.io/docs/self-hosting/platforms/render

[Deploy on Render](https://render.com/deploy?repo=https%3A%2F%2Fgithub.com%2Fgrovs-io%2Fself-host)

## When to use

You want a managed platform with no server to maintain. The [render.yaml](https://github.com/grovs-io/self-host/blob/main/render.yaml) Blueprint creates:

- two public services (API and dashboard)
- two workers
- private ClickHouse with a persistent disk
- managed PostgreSQL and Key Value

All services use published images and run in Frankfurt by default. **This is a paid deployment**, plus object storage. Review the plans and disks in the Blueprint before confirming.

## Prerequisites

| Requirement         | Notes                                                                                                                                                                                                                       |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Render account      | Billable plans for every service in the Blueprint                                                                                                                                                                           |
| Amazon S3 bucket    | Private, with bucket-scoped credentials that can list, read, write and delete Grovs objects. It replaces the Compose upload volume, which Render services cannot share ([persistent disks](https://render.com/docs/disks)). |
| Domains you control | Use dedicated subdomains if your main domain already hosts a website.                                                                                                                                                       |

## 1. Prepare DNS and proxy

Choose three hostnames, without a scheme or port:

| Input                           | Example                         |
| ------------------------------- | ------------------------------- |
| `SERVER_HOST`: app domain       | `grovs.example.com`             |
| `DOMAIN_LIVE`: production links | `links.example.com`             |
| `DOMAIN_TEST`: test links       | `test.links.example.com`        |
| Dashboard `API_URL`             | `https://api.grovs.example.com` |

Render's wildcard setup requires the matching root domain to point to Render too ([Render custom domains](https://render.com/docs/custom-domains)). Render issues the certificates in step 4.

## 2. Create the app

Check the image references in the `render.yaml` you connect. Template defaults can lag behind image releases. To follow the latest stable images, set these `image.url` values in your copy of the Blueprint (fork the self-host repository to edit it):

| Services                                        | `image.url`                         |
| ----------------------------------------------- | ----------------------------------- |
| `grovs-web`, `grovs-worker-1`, `grovs-worker-2` | `ghcr.io/grovs-io/backend:latest`   |
| `grovs-dashboard`                               | `ghcr.io/grovs-io/dashboard:latest` |

For a fixed pair, replace `latest` on all four services with the version from the [latest completed release](https://github.com/grovs-io/self-host/releases/latest). Keep the database versions as supplied. `GROVS_VERSION` in the runtime environment does not change a Blueprint's image URL.

Open **Deploy on Render**, or select **New → Blueprint** and connect the self-host repository (or your fork) using `render.yaml`.

## 3. Configure environment

Fill in the Blueprint prompts:

| Prompt              | Value                                                                  |
| ------------------- | ---------------------------------------------------------------------- |
| Domains             | The three hostnames from step 1                                        |
| Dashboard `API_URL` | From the table in step 1                                               |
| Bucket              | `AWS_S3_KEY_ID`, `AWS_S3_ACCESS_KEY`, `AWS_S3_REGION`, `AWS_S3_BUCKET` |
| Admin email         | Your email for the first dashboard login                               |

For S3-compatible storage, also set `S3_ENDPOINT` and, if required, `S3_FORCE_PATH_STYLE` on **all three backend services** before you deploy them.

Render generates secrets once. The workers and dashboard reference the web service's values, including the shared OAuth credentials. Datastores connect through private service references; no database port is published.

## 4. Deploy and verify

### 1. Deploy

The API's pre-deploy command runs PostgreSQL migrations, seeds and ClickHouse setup. Workers wait for the API's health endpoint. Once healthy, copy `BOOTSTRAP_ADMIN_PASSWORD` from **grovs-web → Environment**.

### 2. Add custom domains

In each web service's **Settings → Custom Domains**, add:

| Service           | Domains                                                                                                                        |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `grovs-dashboard` | `dashboard.grovs.example.com`                                                                                                  |
| `grovs-web`       | `api.grovs.example.com`, `sdk.grovs.example.com`, `mcp.grovs.example.com`, `go.grovs.example.com`, `preview.grovs.example.com` |
| `grovs-web`       | `links.example.com`, `*.links.example.com`, `test.links.example.com`, `*.test.links.example.com`                               |

Copy the exact DNS records Render supplies, including wildcard certificate-verification records. Both wildcard levels need separate entries. Wait for verification and certificates before you test project links.

### 3. Verify

Check `https://api.grovs.example.com/up`. Sign in to the dashboard, create a project, test production and test links, and confirm analytics arrive. Upload an image and check it is still served after you redeploy the API.

## Upgrades

1. Back up first. See [Backups](https://docs.grovs.io/docs/self-hosting/operate/backups#platforms).
2. Suspend both workers so old and new scheduler processes do not overlap.
3. Update the two image tags together in the Blueprint and sync it. With `:latest`, explicitly deploy the newest image for each application service; syncing an unchanged Blueprint does not select a new image.
4. Deploy the API and check that migrations succeed.
5. Resume the workers and deploy the dashboard.

Automatic image deployments are disabled.

## Platform-specific gotchas

- If ClickHouse or PostgreSQL is still starting when the first pre-deploy step runs, wait for both and deploy the API again. Read the pre-deploy log before retrying a migration failure.
- Keep `grovs-worker-1`, the scheduler, at one instance.
- The generated `onrender.com` URL does not replace Grovs' hostname routes.
- Back up PostgreSQL, ClickHouse and uploads separately, and keep copies of the generated secrets and bucket configuration. A disk snapshot alone is not a reliable database backup ([Render ClickHouse guidance](https://render.com/docs/deploy-clickhouse)).
- Deleting the Blueprint's resources can delete data. Export first, and check which disks, database backups and external bucket remain. See the [Blueprint reference](https://render.com/docs/blueprint-spec).
