diff --git a/images/activate-license/download-license.webp b/images/activate-license/download-license.webp
new file mode 100644
index 0000000..27ffdce
Binary files /dev/null and b/images/activate-license/download-license.webp differ
diff --git a/images/airgapped/airgapped-cluster.webp b/images/airgapped/airgapped-cluster.webp
new file mode 100644
index 0000000..b308bc3
Binary files /dev/null and b/images/airgapped/airgapped-cluster.webp differ
diff --git a/images/airgapped/plane-architecture.webp b/images/airgapped/plane-architecture.webp
new file mode 100644
index 0000000..c54526e
Binary files /dev/null and b/images/airgapped/plane-architecture.webp differ
diff --git a/mint.json b/mint.json
index 334e606..88b2838 100644
--- a/mint.json
+++ b/mint.json
@@ -63,8 +63,8 @@
"group": "Self-host Plane",
"pages": [
"self-hosting/overview",
- "self-hosting/editions-and-versions"
-
+ "self-hosting/editions-and-versions",
+ "self-hosting/plane-architecture"
]
},
{
@@ -83,8 +83,10 @@
{
"group": "Airgapped Edition",
"pages": [
+ "self-hosting/methods/airgapped-requirements",
"self-hosting/methods/airgapped-edition",
- "self-hosting/methods/airgapped-edition-kubernetes"
+ "self-hosting/methods/airgapped-edition-kubernetes",
+ "self-hosting/methods/clone-docker-images"
]
},
{
diff --git a/self-hosting/methods/airgapped-edition-kubernetes.mdx b/self-hosting/methods/airgapped-edition-kubernetes.mdx
index c39f716..4aea8a1 100644
--- a/self-hosting/methods/airgapped-edition-kubernetes.mdx
+++ b/self-hosting/methods/airgapped-edition-kubernetes.mdx
@@ -3,145 +3,244 @@ title: Deploy Plane Commercial in an Airgapped Kubernetes Environment
sidebarTitle: For Kubernetes
---
-This guide walks you through installing Plane Enterprise in a Kubernetes cluster without internet access. You'll use Helm charts and pre-packaged Docker images to deploy a fully functional Plane instance.
+
+**IMPORTANT**
+Airgapped deployments are available exclusively for Business plan customers. Contact our [sales team](mailto:sales@plane.so) for pricing and licensing information.
+
+
+This guide walks you through deploying Plane Enterprise in an airgapped Kubernetes environment using Helm charts and pre-packaged Docker images.
## What you'll need
Before starting, ensure you have:
+- Kubernetes cluster (v1.31 - v1.33)
- Helm 3.x installed
-- kubectl with access to your target Kubernetes cluster
+- `kubectl` configured to access your cluster
+- `cert-manager` available in the cluster
+- A valid and working ingress controller (nginx, traefik, etc)
+- Required ports opened to access the application (80, 443)
+- SMTP ports opened if using email intake (25, 465, 587)
+
+
+While Kubernetes can run stateful services with persistent volumes, and Plane's Helm chart supports deploying PostgreSQL, MinIO, RabbitMQ, and Redis, we strongly recommend using external managed services for better reliability in backup/restore operations and disaster recovery.
+
+Consider these alternatives:
+- **MinIO**: Replace with AWS S3, Google Cloud Storage, or any S3-compatible service
+- **Redis**: Replace with Valkey or a managed Redis service
+- **PostgreSQL**: Use a managed PostgreSQL service
+- **RabbitMQ**: Use a managed message queue service
+
## Install Plane
-1. Get the Plane Enterprise Helm chart from the official release:
+1. **Download Plane Enterprise Helm chart**
+
+ Get the Plane Enterprise Helm chart from the official release. Check for the latest version at [Artifact Hub](https://artifacthub.io/packages/helm/makeplane/plane-enterprise).
```bash
# Using wget
- wget https://github.com/makeplane/helm-charts/releases/download/plane-enterprise-1.4.1/plane-enterprise-1.4.1.tgz
+ wget https://github.com/makeplane/helm-charts/releases/download/plane-enterprise-1.6.4/plane-enterprise-1.6.4.tgz
# Using curl
- curl -L -O https://github.com/makeplane/helm-charts/releases/download/plane-enterprise-1.4.1/plane-enterprise-1.4.1.tgz
+ curl -L -O https://github.com/makeplane/helm-charts/releases/download/plane-enterprise-1.6.4/plane-enterprise-1.6.4.tgz
```
-2. Contact [**sales@plane.so**](mailto:sales@plane.so) to get your installation download URL and license file.
-
-2. On a machine with internet access, download the installation package:
-
- ```bash
- curl -LO
- ```
-
- The download may take 15 minutes. Once complete, you no longer need internet access.
-
-3. Transfer the `airgapped-{arch}.tar.gz` file to your air-gapped machine.
+2. **Prepare Docker images for airgapped environment**
-4. Extract the package on your air-gapped machine:
-
- ```bash
- mkdir -p airgapped
- tar -xvzf airgapped-amd64.tar.gz -C airgapped
- cd airgapped
- ```
-
- You'll find these Docker image .tar files for your airgapped installation in this folder.
-
- - `admin-commercial-.tar` - Admin service image
- - `backend-commercial-.tar` - API/worker/beat-worker/migrator service image
- - `email-commercial-.tar` - Email service image
- - `live-commercial-.tar` - Live service image
- - `monitor-commercial-.tar` - Monitor service image
- - `proxy-commercial-.tar` - Plane-proxy service image
- - `silo-commercial-.tar` - Silo service image
- - `space-commercial-.tar` - Space service image
- - `web-commercial-.tar` - Web service image
- - `minio-latest.tar` - Plane-minio service image
- - `postgres-15.7-alpine.tar` - Plane-db service image
- - `rabbitmq-3.13.6-management-alpine.tar` - Plane-mq service image
- - `valkey-7.2.5-alpine.tar` - Plane-redis service image
+ Refer to [this document](https://app.plane.so/plane/wiki/0fc896e0-ca79-4783-8860-43c51b372ec1/) to download the Docker images from the public repository to your internal repository.
- For this installation, you can ignore the extra files in this folder (e.g., `docker-compose.yml`, `install.sh`, `plane.env`, etc.).
+ **Important**
+ This process will NOT download or clone these infrastructure images:
+ - `valkey:7.2.5-alpine`
+ - `postgres:15.7-alpine`
+ - `rabbitmq:3.13.6-management-alpine`
+ - `minio/minio:latest`
+ - `minio/mc:latest`
+
+ If you're using `local_setup: true` for any of these services, you'll need to pull and transfer these images separately.
-5. Load the images into your local Docker registry or private registry:
-
- ```bash
- # Load each image into Docker
- docker load -i .tar
- # Tag and push each image to your private registry
- docker tag /
- docker push /
- ```
+3. **Configure custom values file**
-6. Create Custom Values File
+ a. Extract the default values from the Helm chart.
```bash
- # Extract the Helm chart to access the values file
- helm show values plane-enterprise-1.4.1.tgz > custom-values.yaml
+ helm show values plane-enterprise-1.6.4.tgz > custom-values.yaml
```
-7. Edit the `custom-values.yaml` file to point to your local/private registry images and configure important settings:
+ b. Update Docker image references
+ Edit the `custom-values.yaml` file to point to your local or private registry images and configure important settings.
+
+ **Basic configuration:**
```yaml
- # Example of image updates in custom-values.yaml
- license:
- licenseDomain: 'plane.example.com'
+ # Specify the Plane version
+ planeVersion:
+ # Enable airgapped mode (REQUIRED)
airgapped:
- enabled: true
- # if using Custom Root CA for S3 storage
+ enabled: true # Must be TRUE for airgapped installations
+ # If using custom root CA for S3 storage
s3SecretName: "s3-custom-ca"
s3SecretKey: "s3-custom-ca.crt"
+ ```
+ **Service images:**
+ ```yaml
services:
web:
- image: /web-commercial:
+ image: /web-commercial
api:
- image: /backend-commercial:
+ image: /backend-commercial
space:
- image: /space-commercial:
+ image: /space-commercial
admin:
- image: /admin-commercial:
+ image: /admin-commercial
live:
- image: /live-commercial:
+ image: /live-commercial
monitor:
- image: /monitor-commercial:
+ image: /monitor-commercial
+
+ email_service:
+ enabled: true
+ image: /email-commercial
silo:
- image: /silo-commercial:
+ enabled: true
+ image: /silo-commercial
iframely:
- image: /iframely:v1.2.0
-
- # Database and infrastructure images
- redis:
- image: /valkey:7.2.5-alpine
-
- postgres:
- image: /postgres:15.7-alpine
-
- rabbitmq:
- image: /rabbitmq:3.13.6-management-alpine
-
- minio:
- image: /minio:latest
- image_mc: /mc:latest
+ enabled: true
+ image: /iframely:v1.2.0
+ ```
+
+ **Infrastructure services:**
+
+ Configure whether to use local (in-cluster) or external services:
+ ```yaml
+ services:
+ # Database and infrastructure images
+ redis:
+ local_setup: true # Set to false if using external service
+ image: valkey/valkey:7.2.11-alpine
+
+ postgres:
+ local_setup: true # Set to false if using external service
+ image: postgres:15.7-alpine
+
+ rabbitmq:
+ local_setup: true # Set to false if using external service
+ image: rabbitmq:3.13.6-management-alpine
+ external_rabbitmq_url: '' # Required only if using remote RabbitMQ
+
+ minio:
+ local_setup: true # Set to false if using external service
+ image: minio/minio:latest
+ image_mc: minio/mc:latest
+ ```
+
+ **Environment variables:**
+ ```yaml
+ env:
+ storageClass: ''
+ remote_redis_url: '' # Required only if using remote Redis
+ pgdb_remote_url: '' # Required only if using remote PostgreSQL
+ # Required if MinIO local_setup is false
+ aws_access_key: ''
+ aws_secret_access_key: ''
+ aws_region: ''
+ aws_s3_endpoint_url: ''
+ ```
+
+ c. **Configure integrations and importers**
+
+ To set up integrations with external systems like Slack, GitHub, and GitLab, configure these values in `custom-values.yaml`:
+ ```yaml
+ services:
+ silo:
+ enabled: true
+ connectors:
+ slack:
+ enabled: false
+ client_id: ''
+ client_secret: ''
+ github:
+ enabled: false
+ client_id: ''
+ client_secret: ''
+ app_name: ''
+ app_id: ''
+ private_key: ''
+ gitlab:
+ enabled: false
+ client_id: ''
+ client_secret: ''
env:
- storageClass: ''
+ silo_envs:
+ batch_size: 100
+ mq_prefetch_count: 1
+ request_interval: 400
+ hmac_secret_key: ''
+ aes_secret_key: 'dsOdt7YrvxsTIFJ37pOaEVvLxN8KGBCr'
```
-8. Install Plane Commercial Airgapped edition using your customized values file:
+ d. **Configure intake email**
+
+ The email intake feature in Plane lets you capture incoming emails. Before or after setting up the application, configure DNS settings following [this guide](https://developers.plane.so/self-hosting/govern/configure-dns-email-service).
+
+ Add these required values to `custom-values.yaml`:
+ ```yaml
+ ingress:
+ enabled: true
+ ingressClass: 'nginx' # Or as per your cluster
+ ingress_annotations: {}
+
+ ssl:
+ tls_secret_name: '' # If you have a custom TLS secret name
+ # If you want to use Let's Encrypt, set createIssuer and generateCerts to true
+ createIssuer: false
+ issuer: http # Allowed: cloudflare, digitalocean, http
+ token: '' # Not required for http
+ server: https://acme-v02.api.letsencrypt.org/directory
+ email: plane@example.com # A valid email address
+ generateCerts: true
+
+ services:
+ email_service:
+ enabled: true
+ replicas: 1
+ memoryLimit: 1000Mi
+ cpuLimit: 500m
+ memoryRequest: 50Mi
+ cpuRequest: 50m
+ image: /email-commercial:
+ pullPolicy: Always
+ nodeSelector: {}
+ tolerations: []
+ affinity: {}
+ labels: {}
+ annotations: {}
+
+ env:
+ email_service_envs:
+ smtp_domain: ''
+ ```
+4. **Install or upgrade with custom values**
+
+ Install Plane Enterprise using your customized values file:
```bash
- helm install plane-app plane-enterprise-1.4.1.tgz \
+ helm upgrade plane-app plane-enterprise-1.6.4.tgz \
+ --install \
--create-namespace \
--namespace plane \
-f custom-values.yaml \
@@ -150,48 +249,45 @@ Before starting, ensure you have:
--wait-for-jobs
```
-## Verify installation
+5. **Verify installation**
-Check that all components are running properly:
+ Check that all components are running:
+ ```bash
+ # Check all pods
+ kubectl get pods -n plane
-```bash
-# Check all pods
-kubectl get pods -n plane
+ # Check services
+ kubectl get services -n plane
-# Check services
-kubectl get services -n plane
+ # Check ingress
+ kubectl get ingress -n plane
-# Check ingress
-kubectl get ingress -n plane
+ # Check persistent volumes
+ kubectl get pv,pvc -n plane
-# Check persistent volumes
-kubectl get pv,pvc -n plane
+ # Get the ingress URL
+ kubectl get ingress -n plane -o wide
+ ```
-# Get the ingress URL
-kubectl get ingress -n plane -o wide
-```
+## Activate your license
-## Additional configuration
+Once your air-gapped installation is running, you'll need to activate your workspace with the license file.
-For more advanced Plane configuration options, refer to the [Kubernetes documentation](https://developers.plane.so/self-hosting/methods/kubernetes#configuration-settings).
+1. Login to the [Prime portal](https://prime.plane.so/licenses) with the same email address you used to purchase the paid plan.
+2. Go to [Manage licenses](https://prime.plane.so/licenses).
+3. Click **Download license** to download the license file for your Plane version.
+ 
+4. Navigate to the [Workspace Settings](https://docs.plane.so/core-concepts/workspaces/overview#workspace-settings) in the Plane application.
+6. Select **Billing and plans** on the right pane.
+6. Click the **Activate this workspace** button.
+ 
+7. Upload the license file to activate your workspace.
+You now have Plane running in your air-gapped environment. If you run into any issues, check the logs using the commands above, or reach out to our support team for assistance.
-## Activate your license
-Once your air-gapped installation is running, you'll need to activate your workspace with the provided license file.
-
-You should have received the `license_key.json` file as part of your air-gapped package. If you don't have this file, contact our support team.
-
+## Additional configuration
-1. Go to your [Workspace Settings](https://docs.plane.so/core-concepts/workspaces/overview#workspace-settings) in the Plane application.
-2. Select **Billing and plans** on the right pane.
-3. Click the **Activate this workspace** button.
- 
-4. Upload the license file `license_key.json` to activate your workspace.
+For more advanced Plane configuration options, refer to the [Kubernetes documentation](https://developers.plane.so/self-hosting/methods/kubernetes#configuration-settings).
-You now have Plane running in your air-gapped environment. If you run into any issues, check the logs using the commands above, or reach out to our support team for assistance.
-
-*Optional*
-Once everything is working, you can safely delete the `airgapped` folder that contains the installation script and image files to free up space.
-
diff --git a/self-hosting/methods/airgapped-edition.mdx b/self-hosting/methods/airgapped-edition.mdx
index 9c1a4ad..77913d0 100644
--- a/self-hosting/methods/airgapped-edition.mdx
+++ b/self-hosting/methods/airgapped-edition.mdx
@@ -3,11 +3,12 @@ title: Deploy Plane Commercial in an Airgapped Docker Environment
sidebarTitle: For Docker
---
-This guide walks you through setting up the Commercial Airgapped Edition in an offline environment using our pre-packaged installation bundle.
-
+
**IMPORTANT**
-These instructions are for new installations only. If you're migrating from an existing Community Edition to an air-gapped setup, follow [this guide](/self-hosting/manage/community-to-airgapped).
-
+Airgapped deployments are available exclusively for Business plan customers. Contact our [sales team](mailto:sales@plane.so) for pricing and licensing information.
+
+
+This guide walks you through setting up the Commercial Airgapped Edition in an offline environment using our pre-packaged installation bundle.
## Prerequisites
Before we get started, make sure your air-gapped machine has:
@@ -160,20 +161,16 @@ Once both services are running smoothly, you can access Plane by opening your br
## Activate your license
-Once your air-gapped installation is running, you'll need to activate your workspace with the provided license file.
-
-You should have received the `license_key.json` file as part of your air-gapped package. If you don't have this file, contact our support team.
-
+Once your air-gapped installation is running, you'll need to activate your workspace with the license file.
-1. Go to your [Workspace Settings](https://docs.plane.so/core-concepts/workspaces/overview#workspace-settings) in the Plane application.
-2. Select **Billing and plans** on the right pane.
-3. Click the **Activate this workspace** button.
+1. Login to the [Prime portal](https://prime.plane.so/licenses) with the same email address you used to purchase the paid plan.
+2. Go to [Manage licenses](https://prime.plane.so/licenses).
+3. Click **Download license** to download the license file for your Plane version.
+ 
+4. Navigate to the [Workspace Settings](https://docs.plane.so/core-concepts/workspaces/overview#workspace-settings) in the Plane application.
+6. Select **Billing and plans** on the right pane.
+6. Click the **Activate this workspace** button.

-4. Upload the license file `license_key.json` to activate your workspace.
-
-You now have Plane running in your air-gapped environment. If you run into any issues, check the logs using the commands above, or reach out to our support team for assistance.
+7. Upload the license file to activate your workspace.
-
-*Optional*
-Once everything is working, you can safely delete the `airgapped` folder that contains the installation script and image files to free up space.
-
\ No newline at end of file
+You now have Plane running in your air-gapped environment. If you run into any issues, check the logs using the commands above, or reach out to our support team for assistance.
\ No newline at end of file
diff --git a/self-hosting/methods/airgapped-requirements.mdx b/self-hosting/methods/airgapped-requirements.mdx
new file mode 100644
index 0000000..8688d60
--- /dev/null
+++ b/self-hosting/methods/airgapped-requirements.mdx
@@ -0,0 +1,104 @@
+---
+title: Airgapped deployment architecture
+sidebarTitle: Overview
+---
+
+
+**IMPORTANT**
+Airgapped deployments are available exclusively for Business plan customers. Contact our [sales team](mailto:sales@plane.so) for pricing and licensing information.
+
+
+This document explains Plane's architecture and specific requirements for airgapped deployments. Review this before beginning your airgapped installation on [Docker](/self-hosting/methods/airgapped-edition) or [Kubernetes](/self-hosting/methods/airgapped-edition-kubernetes).
+
+## What is an airgapped deployment?
+
+An airgapped deployment operates in a completely isolated network environment with no external internet connectivity. This isolation is common in highly regulated industries, government facilities, and organizations with strict security requirements.
+
+Plane supports fully airgapped deployments where all components - application services, databases, storage, and integrations - operate entirely within your isolated network perimeter.
+
+## Airgapped cluster architecture
+
+Here's how Plane operates in an airgapped environment with internal enterprise applications:
+
+
+
+This diagram illustrates a critical principle: **all OAuth flows and API communication remain internal to the airgapped cluster**. When integrating with self-hosted GitHub Enterprise, GitLab, or other internal services, the entire authentication and data exchange happens within your isolated network — no internet access required.
+
+For a detailed breakdown of Plane's services and infrastructure dependencies, see [Plane self-hosted architecture](/self-hosting/plane-architecture).
+
+**Critical guarantees for airgapped environments**
+
+- **No telemetry**
+Plane does not send application data, usage metrics, or telemetry outside the cluster. No analytics, crash reports, or usage statistics leave your network.
+
+- **Offline licensing**
+License validation happens through uploaded license files downloaded from the Prime portal. No internet connection required after initial license file transfer.
+
+- **Zero external dependencies**
+After initial image import, no external network connectivity is required for Plane to operate. All features work entirely within your isolated environment.
+
+- **Internal-only communication**
+All service-to-service communication stays within your cluster. Services never attempt to reach external APIs, CDNs, or third-party services.
+
+### How integrations stay internal
+
+The airgapped cluster diagram above shows the complete data flow. Key points:
+
+- **OAuth providers** - Your internal GitHub Enterprise or GitLab instance acts as the OAuth provider
+- **Authorization endpoints** - All OAuth URLs point to internal systems, never external SaaS services
+- **API communication** - Plane makes API calls only to your internal instances
+- **Webhook delivery** - Internal systems send webhooks to Plane's internal endpoints
+- **No SaaS fallback** - Plane never attempts to reach github.com, gitlab.com, or slack.com APIs
+
+This architecture ensures complete network isolation while maintaining full integration functionality.
+
+---
+
+## Kubernetes-specific requirements
+
+### Base environment
+
+Deploying airgapped Plane via Kubernetes requires preparing all dependencies to operate without any external network access.
+
+#### Container images and artifacts
+
+- Maintain an internal OCI or container registry to host all Plane service images
+- Prepare a controlled process to pull, verify, and mirror Plane container images and Helm charts from an online staging environment into the airgapped registry
+
+#### Kubernetes environment
+
+**Supported versions:** Kubernetes 1.31 – 1.33
+
+**Required components:**
+- IngressClass configured
+- StorageClass available
+- cert-manager configured with an internal CA
+
+**Node requirements:**
+- Ensure node OS dependencies and container runtime packages are available from mirrored package repositories like apt, yum, or offline bundles
+
+### Scaling
+
+Horizontal scaling is handled via replica counts configurable in `values.yaml`.
+
+Plane avoids using StatefulSets where possible due to the complexity of scaling stateful workloads in Kubernetes. The `monitor` service uses a StatefulSet.
+
+**For airgapped clusters:**
+- Ensure metrics-server images are mirrored if using HPA
+- If using node autoscaling, ensure node images are pre-loaded and registries accessible on bootstrap
+
+### Secrets management
+
+Plane supports using existing external secret stores, provided they are reachable within the airgapped environment:
+
+- AWS Secrets Manager for private VPC with no internet
+- HashiCorp Vault
+- Self-hosted Bitwarden
+- Kubernetes Secrets
+- SOPS, sealed-secrets, if preferred
+
+### Additional considerations
+
+- Ensure all secret providers can function without external network access
+- cert-manager must use an internal certificate authority
+- Keys and secret rotation policies should be part of the airgap operational procedures
\ No newline at end of file
diff --git a/self-hosting/methods/clone-docker-images.mdx b/self-hosting/methods/clone-docker-images.mdx
new file mode 100644
index 0000000..aed2571
--- /dev/null
+++ b/self-hosting/methods/clone-docker-images.mdx
@@ -0,0 +1,295 @@
+---
+title: Clone Docker images to your private registry
+sidebarTitle: Clone Docker images
+description: Transfer Plane Enterprise Docker images from the artifact registry to your private registry for airgapped deployments using the crane tool.
+---
+
+
+**Part of airgapped deployment:**
+This guide is part of the airgapped deployment process. If you're setting up Plane in an airgapped environment, return to that guide after copying your images.
+
+
+This guide shows you how to copy Docker images from the Plane artifact registry to your destination registry using the `crane` tool.
+
+## Prerequisites
+
+### Install crane
+
+Crane is a tool for interacting with remote container images and registries. Install it on a machine with internet access.
+
+**macOS:**
+```bash
+brew install crane
+```
+
+**Linux:**
+```bash
+# Download the latest release
+VERSION=$(curl -s https://api.github.com/repos/google/go-containerregistry/releases/latest | grep '"tag_name"' | cut -d'"' -f4)
+curl -sL "https://github.com/google/go-containerregistry/releases/download/${VERSION}/go-containerregistry_Linux_x86_64.tar.gz" | tar xz crane
+sudo mv crane /usr/local/bin/
+
+# Verify installation
+crane version
+```
+
+**Windows (using WSL or Git Bash):**
+```bash
+# Download and extract
+curl -sL "https://github.com/google/go-containerregistry/releases/latest/download/go-containerregistry_Windows_x86_64.tar.gz" | tar xz crane.exe
+```
+
+## Plane images to copy
+
+The following Plane Commercial images need to be transferred to your private registry:
+```
+artifacts.plane.so/makeplane/admin-commercial:${APP_RELEASE_VERSION}
+artifacts.plane.so/makeplane/web-commercial:${APP_RELEASE_VERSION}
+artifacts.plane.so/makeplane/space-commercial:${APP_RELEASE_VERSION}
+artifacts.plane.so/makeplane/live-commercial:${APP_RELEASE_VERSION}
+artifacts.plane.so/makeplane/monitor-commercial:${APP_RELEASE_VERSION}
+artifacts.plane.so/makeplane/backend-commercial:${APP_RELEASE_VERSION}
+artifacts.plane.so/makeplane/iframely:v1.2.0
+artifacts.plane.so/makeplane/silo-commercial:${APP_RELEASE_VERSION}
+artifacts.plane.so/makeplane/email-commercial:${APP_RELEASE_VERSION}
+```
+
+
+**Infrastructure images not included:** The Plane artifact registry does not include infrastructure images. If you're using `local_setup: true` for any infrastructure services, you'll need to pull these separately from public registries:
+
+- `valkey/valkey:7.2.11-alpine`
+- `postgres:15.7-alpine`
+- `rabbitmq:3.13.6-management-alpine`
+- `minio/minio:latest`
+- `minio/mc:latest`
+
+
+## Configure environment variables
+
+Set your version and destination registry before copying images.
+```bash
+# Set your Plane version
+export APP_RELEASE_VERSION="v2.1.0" # Replace with your desired version
+
+# Set your destination registry
+export DESTINATION_REGISTRY="your-registry.io/your-namespace"
+```
+
+**Example destination registry values:**
+```bash
+# Docker Hub
+export DESTINATION_REGISTRY="docker.io/yourcompany"
+
+# Google Container Registry
+export DESTINATION_REGISTRY="gcr.io/your-project"
+
+# Private registry
+export DESTINATION_REGISTRY="your-private-registry.com/plane"
+
+# AWS ECR
+export DESTINATION_REGISTRY="123456789012.dkr.ecr.us-east-1.amazonaws.com/plane"
+
+# Azure Container Registry
+export DESTINATION_REGISTRY="yourregistry.azurecr.io/plane"
+```
+
+## Authenticate to your destination registry
+
+Before copying images, authenticate crane to your destination registry.
+
+**Docker Hub:**
+```bash
+crane auth login docker.io -u YOUR_USERNAME -p YOUR_PASSWORD
+```
+
+**Google Container Registry:**
+```bash
+gcloud auth configure-docker
+```
+
+**AWS ECR:**
+```bash
+aws ecr get-login-password --region REGION | crane auth login --username AWS --password-stdin AWS_ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com
+```
+
+**Azure Container Registry:**
+```bash
+az acr login --name YOUR_REGISTRY_NAME
+```
+
+**Harbor or other private registries:**
+```bash
+crane auth login your-registry.com -u YOUR_USERNAME -p YOUR_PASSWORD
+```
+
+## Copy images to your registry
+
+You can copy images individually or use the provided script to copy all images at once.
+
+### Option 1: Copy individual images
+
+**Basic image copy:**
+```bash
+crane copy \
+ artifacts.plane.so/makeplane/backend-commercial:${APP_RELEASE_VERSION} \
+ ${DESTINATION_REGISTRY}/backend-commercial:${APP_RELEASE_VERSION}
+```
+
+**Copy with specific platform (architecture):**
+```bash
+crane copy \
+ --platform linux/amd64 \
+ artifacts.plane.so/makeplane/backend-commercial:${APP_RELEASE_VERSION} \
+ ${DESTINATION_REGISTRY}/backend-commercial:${APP_RELEASE_VERSION}
+```
+
+**Verify source image before copying:**
+```bash
+# Check if source image exists
+crane manifest artifacts.plane.so/makeplane/backend-commercial:${APP_RELEASE_VERSION}
+
+# List all available tags
+crane ls artifacts.plane.so/makeplane/backend-commercial
+```
+
+**Verify image after copying:**
+```bash
+# Get image digest
+crane digest ${DESTINATION_REGISTRY}/backend-commercial:${APP_RELEASE_VERSION}
+
+# Verify manifest
+crane manifest ${DESTINATION_REGISTRY}/backend-commercial:${APP_RELEASE_VERSION}
+```
+
+### Option 2: Copy all images with a script
+
+Create a file named `copy-plane-images.sh`:
+```bash
+#!/bin/bash
+
+set -e
+
+# Configuration
+APP_RELEASE_VERSION="${APP_RELEASE_VERSION:-v2.1.0}"
+DESTINATION_REGISTRY="${DESTINATION_REGISTRY}"
+
+if [ -z "$DESTINATION_REGISTRY" ]; then
+ echo "Error: DESTINATION_REGISTRY environment variable is not set"
+ echo "Example: export DESTINATION_REGISTRY='docker.io/yourcompany'"
+ exit 1
+fi
+
+# Source registry
+SOURCE_REGISTRY="artifacts.plane.so/makeplane"
+
+# Image list
+declare -a IMAGES=(
+ "admin-commercial:${APP_RELEASE_VERSION}"
+ "web-commercial:${APP_RELEASE_VERSION}"
+ "space-commercial:${APP_RELEASE_VERSION}"
+ "live-commercial:${APP_RELEASE_VERSION}"
+ "monitor-commercial:${APP_RELEASE_VERSION}"
+ "backend-commercial:${APP_RELEASE_VERSION}"
+ "iframely:v1.2.0"
+ "silo-commercial:${APP_RELEASE_VERSION}"
+ "email-commercial:${APP_RELEASE_VERSION}"
+)
+
+echo "Starting image copy process..."
+echo "Source: ${SOURCE_REGISTRY}"
+echo "Destination: ${DESTINATION_REGISTRY}"
+echo "Version: ${APP_RELEASE_VERSION}"
+echo ""
+
+# Copy each image
+for IMAGE in "${IMAGES[@]}"; do
+ SOURCE="${SOURCE_REGISTRY}/${IMAGE}"
+ DESTINATION="${DESTINATION_REGISTRY}/${IMAGE}"
+
+ echo "Copying: ${SOURCE} -> ${DESTINATION}"
+ crane copy "${SOURCE}" "${DESTINATION}"
+
+ if [ $? -eq 0 ]; then
+ echo "✓ Successfully copied ${IMAGE}"
+ else
+ echo "✗ Failed to copy ${IMAGE}"
+ exit 1
+ fi
+ echo ""
+done
+
+echo "All images copied successfully!"
+```
+
+Make the script executable and run it:
+```bash
+chmod +x copy-plane-images.sh
+./copy-plane-images.sh
+```
+
+The script will copy all Plane images to your destination registry. Each image copy is verified, and the script exits if any copy fails.
+
+## Troubleshooting
+
+### Authentication issues
+
+**Error:** `unauthorized: authentication required`
+
+**Solution:** Re-authenticate to your destination registry:
+```bash
+crane auth login your-destination-registry.com
+```
+
+Verify your credentials are correct and that you have push permissions to the registry.
+
+### Network timeouts
+
+**Error:** Large images timing out during transfer
+
+**Solution:** Crane handles retries automatically, but you can also:
+
+- Check your network connection stability
+- Try copying during off-peak hours
+- Use a machine with better network connectivity
+- Copy images individually rather than using the batch script
+
+### Permission denied
+
+**Error:** `denied: requested access to the resource is denied`
+
+**Solution:**
+
+- Ensure you have push permissions to the destination registry
+- Verify your authentication credentials are correct
+- Check that the destination repository exists, or that you have permission to create it
+- For organizational registries, confirm your account has the necessary roles
+
+### Image not found
+
+**Error:** `MANIFEST_UNKNOWN: manifest unknown`
+
+**Solution:**
+
+- Verify the source image exists:
+```bash
+ crane ls artifacts.plane.so/makeplane/backend-commercial
+```
+- Check that you're using the correct version tag
+- Ensure `APP_RELEASE_VERSION` is set correctly
+- Verify the image name is spelled correctly
+
+### Rate limiting
+
+**Error:** `429 Too Many Requests`
+
+**Solution:**
+
+- Wait a few minutes and retry
+- Authenticate to increase rate limits
+- For Docker Hub, ensure you're using an authenticated account (free accounts have higher limits than anonymous)
+- Spread out image copies over time if hitting limits repeatedly
+
+## Additional resources
+
+- [Crane documentation](https://github.com/google/go-containerregistry/blob/main/cmd/crane/doc/crane.md)
+- [Crane GitHub repository](https://github.com/google/go-containerregistry)
diff --git a/self-hosting/plane-architecture.mdx b/self-hosting/plane-architecture.mdx
new file mode 100644
index 0000000..ca11202
--- /dev/null
+++ b/self-hosting/plane-architecture.mdx
@@ -0,0 +1,67 @@
+---
+title: Plane self-hosted architecture
+sidebarTitle: Plane Architecture
+---
+
+Plane consists of multiple services working together to provide project management capabilities.
+
+
+
+### Frontend services
+
+**Web**
+The main application interface where users interact with projects, work items, and pages. This service serves the UI and handles client-side routing.
+
+**Space**
+This powers public sharing. It lets you publish projects, views, pages to the web, so others can view without needing to log in.
+
+**Admin**
+Instance administration interface for workspace owners and administrators. Manages billing, licensing, workspace settings, and user permissions.
+
+### API server
+
+**API**
+The core REST API that handles all data operations. All frontend services communicate with this API for creating, reading, updating, and deleting data.
+
+**Worker**
+Background job processor that handles async operations like file processing, notification dispatch, and data imports. Workers pull jobs from RabbitMQ and execute them independently.
+
+**Beat worker**
+Scheduled task executor that runs periodic jobs like data cleanup, report generation, and reminder notifications. Uses a cron-like scheduling system.
+
+**Migrator**
+Database schema management service that runs on deployment to apply schema changes and data migrations. Runs once during upgrades then exits.
+
+### Supporting services
+
+**Proxy**
+Handles incoming traffic and routes it to the appropriate services. Manages certificates and reverse proxying. In Docker deployments, Plane uses Caddy for automatic SSL certificate management and traffic routing.
+
+**Live**
+Real-time collaboration service powered by WebSockets. Handles cursor positions, live updates, and presence indicators for multiple users working simultaneously.
+
+**Monitor**
+Used for license validation and activation. It checks the license status and ensures your instance is compliant.
+
+**Silo**
+Integration backend that manages connections to GitHub, GitLab, and Slack. Handles OAuth flows, webhook processing, and API communication with external systems.
+
+**Intake**
+Email ingestion service that converts incoming emails into work items or comments. Requires SMTP configuration and DNS setup.
+
+### Infrastructure dependencies
+
+**PostgreSQL**
+Primary relational database storing all application data including projects, work items, users, and configuration. Plane requires PostgreSQL 15.7+ or 16.x.
+
+**Redis/Valkey**
+In-memory cache and session store. Used for caching frequently accessed data, storing user sessions, and managing real-time collaboration state.
+
+**RabbitMQ**
+Message queue for asynchronous task processing. Workers pull jobs from queues for background operations like imports, exports, and notifications.
+
+**MinIO/S3**
+Object storage for file uploads, attachments, and generated exports. Can be replaced with any S3-compatible storage system.
+
+**OpenSearch**
+Optional search indexing service for enhanced search capabilities. Not required for basic Plane functionality.
\ No newline at end of file