# Complete Guide to Self-Hosting Plane in Production: Key Configurations and Setup

> Learn to self-host Plane in production. Configure environment variables, deploy Docker Compose, run migrations, and set up Caddy for TLS termination. Your essential production guide.

- Repository: [Plane/plane](https://github.com/makeplane/plane)
- Tags: how-to-guide
- Published: 2026-06-18

---

**To self-host Plane in production, configure environment variables in `.env` (database, Redis, RabbitMQ, MinIO credentials), deploy the multi-service Docker Compose stack, run database migrations, and optionally enable the Caddy reverse proxy for TLS termination.**

Plane is an open-source project management platform developed by Makeplane. Self-hosting Plane in production requires orchestrating a full-stack architecture defined in the official [`docker-compose.yml`](https://github.com/makeplane/plane/blob/main/docker-compose.yml) from the `makeplane/plane` repository, including PostgreSQL, Valkey (Redis), RabbitMQ, and MinIO services.

## Environment Variable Configuration

The `.env.example` file serves as the definitive blueprint for production settings. All sensitive credentials and endpoint URLs must be declared here before starting the stack.

### Critical Secrets and Endpoints

You must define **database credentials** (`POSTGRES_PASSWORD`, `POSTGRES_USER`, `POSTGRES_DB`), **object storage keys** (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`), and **message broker credentials** (`RABBITMQ_USER`, `RABBITMQ_PASSWORD`). The `SITE_ADDRESS` variable is mandatory—it tells Plane which public host and port to bind to (e.g., `https://plane.mycompany.com`).

### Feature Toggles

Set `USE_MINIO=1` to utilize the bundled MinIO instance for object storage, or set it to `0` to integrate with external S3-compatible storage. The `DOCKERIZED` flag remains for backward compatibility with legacy deployment scripts.

## Core Services Architecture

The [`docker-compose.yml`](https://github.com/makeplane/plane/blob/main/docker-compose.yml) defines twelve interconnected services that comprise the Plane application stack:

- **web**: Next.js frontend application
- **admin**: Django-based administrative interface
- **space**: Collaboration and workspace features
- **api**: Main Django REST API backend
- **worker**: Background task processor
- **beat-worker**: Scheduled task runner (celery beat)
- **migrator**: Database migration handler (runs once)
- **live**: Real-time collaboration server
- **plane-db**: PostgreSQL 15.7-alpine database
- **plane-redis**: Valkey (Redis fork) for caching and queues
- **plane-mq**: RabbitMQ 3.13.6-management-alpine message broker
- **plane-minio**: MinIO object storage server
- **proxy** (optional): Caddy reverse proxy for TLS termination

### Database Layer

The `plane-db` service runs PostgreSQL 15.7-alpine with persistent storage mounted via the `pgdata` Docker volume. The database name, user, and password are injected from your `.env` file into the container environment.

### Cache and Message Queue

**Valkey** (a Redis fork) handles caching, session storage, and background task queues via the `plane-redis` service. Configure connection parameters using `REDIS_HOST` and `REDIS_PORT` environment variables. **RabbitMQ** manages asynchronous task processing via `plane-mq`, storing persistent data in the `rabbitmq_data` volume.

### Object Storage

**MinIO** runs as the `plane-minio` service, providing S3-compatible object storage. The default bucket name is `uploads`. The API service uses the same `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` credentials to authenticate upload requests, while `FILE_SIZE_LIMIT` controls maximum upload sizes.

## Reverse Proxy and TLS Termination

The optional `proxy` service uses Caddy (built from `apps/proxy/Dockerfile.ce`) to handle SSL/TLS termination. Configure automatic Let's Encrypt certificate issuance by setting `CERT_EMAIL` and `CERT_ACME_CA` in your environment. The proxy listens on `${LISTEN_HTTP_PORT}` and `${LISTEN_HTTPS_PORT}`, forwarding traffic to the appropriate backend services.

If you use an external reverse proxy such as Nginx or Traefik, comment out the `proxy` service in [`docker-compose.yml`](https://github.com/makeplane/plane/blob/main/docker-compose.yml) and expose ports `8000` (HTTP) and `8443` (HTTPS) directly from the `web` container.

## Production Deployment Steps

Follow these steps to deploy Plane on your infrastructure:

1. **Prepare environment variables**:
   ```bash
   cp .env.example .env
   # Edit .env to set POSTGRES_PASSWORD, AWS_ACCESS_KEY_ID, SITE_ADDRESS, CERT_EMAIL, etc.

   ```

2. **Launch the stack**:
   ```bash
   docker compose -f docker-compose.yml up -d
   ```

3. **Run database migrations** once the database container is healthy:
   ```bash
   docker compose exec api ./bin/docker-entrypoint-migrator.sh
   ```

4. **Verify the deployment** by checking for the startup completion message:
   ```bash
   docker compose logs -f api | grep "Application Startup Complete"
   ```

For Kubernetes environments, refer to the alternative manifests in [`deployments/kubernetes/community/README.md`](https://github.com/makeplane/plane/blob/main/deployments/kubernetes/community/README.md).

## Key Source Files

- **`.env.example`**: Template for all required environment variables and secrets
- **[`docker-compose.yml`](https://github.com/makeplane/plane/blob/main/docker-compose.yml)**: Primary production orchestration defining all services, volumes, and network configurations
- **[`setup.sh`](https://github.com/makeplane/plane/blob/main/setup.sh)**: Helper script displaying Docker commands for stack management
- **`apps/proxy/Dockerfile.ce`**: Caddy reverse proxy image definition for TLS termination
- **`apps/api/.env`**: API-specific environment configuration (generated from top-level `.env`)

## Summary

- **Environment variables** drive all configuration via `.env.example`, including database credentials, `SITE_ADDRESS`, and storage keys.
- **Docker Compose** orchestrates twelve services including PostgreSQL 15, Valkey, RabbitMQ 3.13, and MinIO.
- **TLS termination** is handled by the optional Caddy `proxy` service with automatic Let's Encrypt support, or disabled for external reverse proxies.
- **Database migrations** must be executed manually via [`./bin/docker-entrypoint-migrator.sh`](https://github.com/makeplane/plane/blob/main/./bin/docker-entrypoint-migrator.sh) inside the API container after initial startup.
- **Object storage** defaults to MinIO with the `uploads` bucket, configurable via `USE_MINIO` for external S3.

## Frequently Asked Questions

### How do I configure SSL certificates for a self-hosted Plane instance?

Configure the `CERT_EMAIL` and `CERT_ACME_CA` environment variables in your `.env` file, then enable the `proxy` service in [`docker-compose.yml`](https://github.com/makeplane/plane/blob/main/docker-compose.yml). This Caddy-based service automatically provisions and renews Let's Encrypt certificates. If you prefer using Nginx or Traefik, disable the proxy service and expose ports `8000` and `8443` from the web container.

### What database version does Plane require for production?

The official [`docker-compose.yml`](https://github.com/makeplane/plane/blob/main/docker-compose.yml) specifies PostgreSQL 15.7-alpine for the `plane-db` service. You must use this version or compatible PostgreSQL 15.x releases to ensure compatibility with Plane's schema migrations and query optimizations.

### Can I use external Redis or S3 storage instead of the bundled services?

Yes. Set `USE_MINIO=0` and provide your external S3 endpoint credentials (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and S3 endpoint URLs) in the `.env` file. For Redis, modify `REDIS_HOST` and `REDIS_PORT` to point to your external Valkey or Redis instance instead of the `plane-redis` service.

### How do I run database migrations when upgrading Plane?

Execute the migration script inside the running API container: `docker compose exec api ./bin/docker-entrypoint-migrator.sh`. Run this command only once after the database container is healthy and before using the application.