# Deploying Rivet in a VPC or Air-Gapped Network

> Source: `src/content/cookbook/vpc-air-gapped.mdx`
> Canonical URL: https://rivet.dev/cookbook/vpc-air-gapped
> Description: Run Rivet entirely inside your own perimeter: single-binary or Docker Compose install, file system storage with no database infrastructure, and no outbound telemetry by default.

---
Patterns for running self-hosted Rivet inside a private network: a VPC without internet egress, an on-premises rack, or a fully air-gapped environment. The engine is one service, the recommended single-node storage backend is the local file system, and the engine makes no outbound connections by default. Self-hosting is the only Rivet deployment model that supports air-gapped networks; see the [Self-Hosting Overview](/docs/self-hosting) for the full comparison with BYOC.

## What Runs Inside the Perimeter

A self-hosted deployment has three components, all of which live inside your network:

| Component | Role | Inside the perimeter |
| --- | --- | --- |
| Your backend | Your application server, including the runner that executes actor code | Yes |
| Rivet Engine | Orchestration service that manages actor lifecycle, routes messages, and serves the dashboard and APIs | Yes |
| Storage | Persistence for actor state. Local file system for single-node, PostgreSQL or FoundationDB for multi-node | Yes |

There is no license server, no Rivet Cloud account, and no callback to `rivet.dev`. Clients inside the perimeter reach actors through the engine's gateway over your private network. See [Architecture](/docs/self-hosting#architecture).

## Single-Binary Install

The engine compiles to a single `rivet-engine` binary. Build it from source outside the perimeter, then copy the binary across the boundary:

```bash
git clone https://github.com/rivet-dev/rivet.git
cd rivet
cargo build --release -p rivet-engine
# Copy target/release/rivet-engine into the perimeter.
```

Prebuilt binaries are coming soon; see [Installing Rivet Engine](/docs/self-hosting/install) for current options.

Run it with the file system backend, which stores everything on local disk and is the production-ready choice for single-node deployments. The [File System](/docs/self-hosting/filesystem) docs list air-gapped environments as a primary use case because it needs no database infrastructure:

```bash
RIVET__database__file_system__path="/var/lib/rivet/data" ./rivet-engine
```

Configuration can also come from files. The engine discovers config at `/etc/rivet/config.json` on Linux (JSON, JSON5, JSONC, YAML, and YML are all supported), and `--config` overrides the path. Environment variables use the `RIVET__` prefix with `__` as the separator. See [Configuration](/docs/self-hosting/configuration).

The engine serves its own dashboard on port `6420`, so inspection and namespace management work with nothing but a browser inside the perimeter.

## Docker Compose Deployment

For Docker hosts without registry access, move the engine image across the boundary the standard way:

```bash
# Outside the perimeter.
docker pull rivetdev/engine:latest
docker save rivetdev/engine:latest -o rivet-engine.tar
# Inside the perimeter.
docker load -i rivet-engine.tar
```

Then run the engine and your app together in one Compose file:

```yaml
services:
  rivet-engine:
    image: rivetdev/engine:latest
    ports:
      - "6420:6420"
    volumes:
      - rivet-data:/data
    environment:
      RIVET__FILE_SYSTEM__PATH: "/data"
    restart: unless-stopped

  my-app:
    build: .
    environment:
      RIVET_ENDPOINT: "http://default:admin@rivet-engine:6420"
    depends_on:
      - rivet-engine
    restart: unless-stopped

volumes:
  rivet-data:
```

`RIVET_ENDPOINT` uses the format `http://namespace:token@host:port` and tells your app to connect to the engine as a runner instead of running standalone. After both services start, register your runner with the engine through the dashboard or its API. The full walkthrough, including PostgreSQL setup for multi-node deployments, is in [Docker Compose](/docs/self-hosting/docker-compose).

## No Outbound Telemetry

The engine exports traces and metrics only when you opt in with OpenTelemetry. Export is disabled unless `RIVET_OTEL_ENABLED=1` is set, and the export target defaults to a local collector at `http://localhost:4317`. With no configuration, nothing crosses the perimeter.

When you want observability, keep it inside the network:

- Set `RIVET_OTEL_ENABLED=1` and point `RIVET_OTEL_GRPC_ENDPOINT` at a collector you run inside the perimeter.
- Adjust `RIVET_OTEL_SAMPLER_RATIO` to control trace sampling.
- Use the engine's health endpoint for liveness and readiness probes.

See the [Production Checklist](/docs/self-hosting/production-checklist) for monitoring guidance.

## Embedding Rivet in a Customer's Environment

If you ship software that runs inside your customers' VPCs, the same setup turns Rivet into an internal component of your product rather than a service your customers must reach over the internet:

- **Ship the engine next to your app.** Add `rivetdev/engine` to the Compose file or chart you already deliver. Your app finds it over the private network via `RIVET_ENDPOINT`, so one artifact deploys the whole stack.
- **One namespace per install.** The endpoint URL carries the namespace and token (`http://namespace:token@host:port`), so a single image works across customer deployments. See [Endpoints](/docs/general/endpoints).
- **Generate a strong admin token per install.** Replace the default token and keep it server-side. Never include the admin token in `RIVET_PUBLIC_ENDPOINT` or anywhere clients can read it.
- **Public endpoint only when needed.** `RIVET_PUBLIC_ENDPOINT` with a public (`pk_`) token is only required when browser clients connect to actors in [serverless runtime mode](/docs/general/runtime-modes). Backend-only deployments can skip it entirely.
- **TLS at the customer's edge.** Terminate TLS with the customer's reverse proxy or load balancer in front of the engine.

## Scaling Past One Node

| Backend | Use when | Status |
| --- | --- | --- |
| [File System](/docs/self-hosting/filesystem) (RocksDB-based) | Single-node deployments, including air-gapped installs | Production-ready, single node only |
| [PostgreSQL](/docs/self-hosting/postgres) | Multi-node deployments | Recommended for multi-node today, but experimental |
| FoundationDB | Largest production deployments | [Enterprise](/sales) |

For multi-node deployments, run two or more engine nodes behind a load balancer and add NATS for pub/sub, which replaces the default PostgreSQL `LISTEN`/`NOTIFY` path at high throughput. Neither is needed for a single-node file system install. See the [Production Checklist](/docs/self-hosting/production-checklist).

## Perimeter Checklist

- **Admin token**: Generate a strong, random token for engine authentication and verify it is not exposed to clients.
- **TLS termination**: Encrypt connections to the engine via a reverse proxy or load balancer.
- **No public exposure**: Keep port `6420` reachable only from inside the perimeter unless clients outside it genuinely need access.
- **Health checks**: Configure liveness and readiness probes against the engine health endpoint.
- **Telemetry**: Leave OpenTelemetry export off, or point it at a collector inside the network.
- **Backups**: With the file system backend, back up the data directory. With PostgreSQL, configure automated backups and failover.

## Full Configuration

- [Self-Hosting Overview](/docs/self-hosting) for architecture and the self-host vs BYOC comparison
- [Installing Rivet Engine](/docs/self-hosting/install) for Docker, binary, and source installs
- [Docker Container](/docs/self-hosting/docker-container) and [Docker Compose](/docs/self-hosting/docker-compose) for container deployments
- [Kubernetes](/docs/self-hosting/kubernetes) for cluster deployments
- [Configuration](/docs/self-hosting/configuration) for every option and the full JSON schema
- [Endpoints](/docs/general/endpoints) for connecting your backend and clients
- [Production Checklist](/docs/self-hosting/production-checklist) before going live

_Source doc path: /cookbook/vpc-air-gapped_
