Caret is designed to be self-hosted on a single Linux virtual machine with minimal operational overhead. The production stack runs on a Hetzner Cloud VPS, uses Coolify as a self-hosted open-source PaaS to manage deployments and domains, and relies on Cloudflare for DNS. The database, authentication, and vector search are all delegated to Supabase Cloud — a managed service that runs entirely outside the VPS. This architecture keeps infrastructure costs low while giving you full control over the application layer.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/arrozet/caret/llms.txt
Use this file to discover all available pages before exploring further.
Supabase Cloud is external to the VPS. Do not attempt to run PostgreSQL, the Supabase Auth server, or pgvector on the same machine as the Caret services. Mixing managed and self-hosted Supabase is a significant operational burden and is not part of the supported Caret deployment model. Use the Supabase Cloud project you created during local development as-is.
Production Infrastructure at a Glance
| Layer | Choice | Notes |
|---|---|---|
| Hosting | Hetzner Cloud VPS | Single VM, approximately 9 EUR/month; sufficient for the full Caret stack |
| PaaS | Coolify | Self-hosted open-source PaaS; manages deployments, domains, logs, and Docker Compose resources |
| Containers | Docker Compose | docker-compose.prod.yml is the production deployment unit |
| CI/CD | GitHub Actions + Coolify | Automatic production deploys triggered on pushes to the prod branch |
| DNS | Cloudflare | Manages caret.page and all subdomains |
| Database / Auth | Supabase Cloud | Managed PostgreSQL, Auth, and pgvector — runs outside the VPS |
Production Domains
The production deployment exposes five public domains, each mapped to a specific service:| Domain | Service | Purpose |
|---|---|---|
caret.page | Frontend | Main user-facing application |
www.caret.page | Frontend alias | CNAME to caret.page |
api.caret.page | API Gateway | Public HTTP REST entrypoint for all /api/v1/... routes |
ws.caret.page | Collab Service | Public WebSocket endpoint for real-time collaboration |
ops.caret.page | Coolify | PaaS control plane — deployment dashboard and operations |
The frontend must call
api.caret.page for all HTTP API traffic and connect directly to ws.caret.page for collaboration WebSocket connections. The collab service is intentionally not routed through the API Gateway: WebSocket connections are long-lived and use a different protocol from HTTP REST calls, so keeping them on a dedicated domain avoids unnecessary proxy complexity.Step-by-Step Deployment
Provision a Hetzner VPS
Create a new VPS in Hetzner Cloud. A shared-CPU instance with 2 vCPUs and 4 GB RAM is sufficient for the full Caret stack at launch scale. Choose a Linux image (Ubuntu LTS recommended) and note the public IPv4 address of your new instance.
Configure the Hetzner Firewall
In the Hetzner Cloud console, apply a firewall to your VPS that allows only the required inbound traffic. Restrict all other ingress by default.
Do not expose internal service ports (3000, 3001, 3002, 3003, 8000) directly. All public traffic must enter through Coolify’s built-in reverse proxy.
| Protocol | Port / Type | Purpose |
|---|---|---|
| TCP | 22 | SSH administration |
| TCP | 80 | HTTP (required for ACME TLS certificate validation) |
| TCP | 443 | HTTPS (all public web traffic) |
| ICMP | — | Basic reachability / ping |
Install Coolify on the VPS
SSH into your VPS and follow the Coolify installation guide to install Coolify. Once running, Coolify is accessible at
http://<your-vps-ip>:8000 during initial setup. After configuring your domain, it will be available at https://ops.caret.page.Point the Cloudflare DNS A record for ops.caret.page to your VPS public IPv4 address and let Coolify provision its own TLS certificate via ACME.Configure Cloudflare DNS
In your Cloudflare dashboard for
Use DNS-only mode (grey cloud) for all records unless you have verified that Cloudflare proxying is compatible with your WebSocket configuration on
caret.page, create the following DNS records — all pointing to your Hetzner VPS public IPv4 address:| Type | Name | Target |
|---|---|---|
| A | caret.page | <VPS IPv4> |
| CNAME | www | caret.page |
| A | api | <VPS IPv4> |
| A | ws | <VPS IPv4> |
| A | ops | <VPS IPv4> |
ws.caret.page.Create the Caret Project in Coolify
In the Coolify dashboard:
- Add your GitHub repository (
arrozet/caret) as a source. - Create a new Resource of type Docker Compose.
- Set the Compose file path to
/docker-compose.prod.yml. - Set the deployment branch to
prod. - Configure the domain for each service in Coolify:
- Frontend →
https://caret.page - API Gateway →
https://api.caret.page - Collab Service →
https://ws.caret.page
- Frontend →
- Enable automatic deployments so that every push to the
prodbranch triggers a redeploy.
Set Production Environment Variables
Add the following environment variables in Coolify’s environment variable management UI (or via GitHub Actions secrets for CI-only values). Never commit secrets to the repository.The production compose file (
docker-compose.prod.yml) marks several variables as required using the :? syntax — Docker Compose will refuse to start if they are missing. This acts as a safety net against accidental misconfigurations.Deploy and Verify
Push to the
prod branch (or trigger a manual deploy in Coolify) to start the first production deployment. Monitor the build logs in the Coolify dashboard.Once deployed, verify each surface:https://caret.page— loads the Caret frontendhttps://api.caret.page/health— returns200 OKfrom the API Gatewayhttps://ws.caret.page/health— returns200 OKfrom the Collab service- Sign in, create a workspace and document, and confirm that real-time collaboration and the AI panel are functioning end-to-end
Network Routing Summary
Monitoring
Caret’s production observability relies on two primary tools:- Coolify service logs — Each service’s stdout/stderr is captured and streamed in the Coolify dashboard. Use this for operational debugging and deployment verification.
- Sentry — Error tracking is integrated on both the frontend and backend services. Configure your Sentry DSN as an environment variable to enable automatic error reporting and alerting.