An air-gapped system is a computing environment physically isolated from external networks, including the public internet. This setup is commonly used by organizations with heightened security needs, such as government agencies, defense sectors, and operators of critical infrastructure.
Rocket.Chat supports deployment in air-gapped environments but requires a premium (Starter, Pro, or Enterprise) license due to the following reasons:
Commercial code inclusion: Rocket.Chat’s codebase includes both open-source and commercial components. A premium license grants access to the full codebase with advanced features and allows organizations to audit the code for compliance.
Intellectual property protection: Without internet access, Rocket.Chat cannot verify license usage for commercial features. The premium license ensures compliance and protects Rocket.Chat’s intellectual property.
Access to premium features: A Premium license is required to unlock all premium-grade features, including advanced security tools, scalability options, advanced customizations, and dedicated premium support channels.
For organizations using Community workspaces, there are two options:
Purchase a premium license: Upgrade to the premium plan to ensure compliance and unlock advanced features in your workspace. To upgrade to the free Starter plan, refer to Upgrade to Starter from Community workspace.
Build and maintain a FOSS Version: For teams that prefer a fully open-source route, Rocket.Chat can be built directly from the Github repository without requiring a license. However, this option does not include access to any premium features, dedicated support, or commercial components.
Deploy an air-gapped Rocket.Chat workspace with Docker
This guide details two methods for deploying a Rocket.Chat workspace within an air-gapped environment using Docker. Choose the method that best aligns with your network and policy requirements:
Transfer required Docker images and configuration files from an internet-connected server.
Deploy with a private registry within the air-gapped network.
Option 1: Copy Rocket.Chat Docker images from a server with internet access
Given that an air-gapped environment has no internet access, this approach involves downloading all required Docker images and configuration files on a server with internet access, then manually transferring them to the air-gapped server for deployment.
Prerequisites
An internet-connected server with Git installed
An air-gapped server to deploy Rocket.Chat
Docker and Docker Compose installed on both servers. To install Docker and Docker Compose on Ubuntu:
curl -L https://get.docker.com | shA secure method to transfer files from the internet-connected to the air-gapped server (e.g., USB drive, scp).
Step 1: Fetch the Rocket.Chat compose configuration files
The official rocketchat-compose repository contains all configuration files needed to deploy Rocket.Chat using Docker Compose.
On the internet-connected server, clone the repository and navigate to the directory:
git clone --depth 1 https://github.com/RocketChat/rocketchat-compose.git cd rocketchat-composeThe repository includes:
compose.yml: The main configuration file for Docker Compose to deploy Rocket.Chat..env.example: A template environment file for customizing your deployment.Additional configs: Additional service configurations (e.g., database, monitoring, Traefik).
To customize your deployment without editing
compose.ymldirectly, copy the example environment file:cp .env.example .envThis creates a
.envfile where you’ll define your deployment variables.
Step 2: Configure Rocket.Chat
Edit the newly created .env file to customize your deployment.
nano .envA. Set Rocket.Chat version
Modify the RELEASE variable to specify the exact version of Rocket.Chat you wish to deploy. Refer to the Rocket.Chat releases page for a list of available stable versions.
RELEASE=7.5.0Use a fixed version (e.g.,
7.5.0) instead oflatestfor production.
B. Configure access URLs
The next step is to define how users will access your workspace. Configure these variables in the .env file:
ROOT_URL: Your domain or subdomain name. Do not include https:// or any trailing slashes.DOMAIN: The complete URL your users will use to access the server, including the protocol (http:// or https://).
DOMAIN=localhost:3000
ROOT_URL=http://localhost:3000 Your workspace will be accessible at http://localhost:3000 once succesfully deployed.
C. Enable monitoring
The rocketchat-compose setup includes Prometheus (for metrics collection) and Grafana (for visualization).
You can configure Grafana either through a URL path (e.g., http://your-domain.com/grafana) or a subdomain (e.g., http://grafana.your-domain.com).
This option is ideal for local development or if you prefer to keep all services under a single domain, accessing your Grafana dashboard as a subdirectory (e.g., http://your-domain.com/grafana).
To configure this, follow these steps in the .env file:
You can use the default values for the following variables:
GRAFANA_DOMAIN: Leave this variable empty.GRAFANA_PATH: Set this to your desired path, ensuring there is no trailing slash (e.g.,/grafana).GRAFANA_DOMAIN= GRAFANA_PATH=/grafana
Set a strong password for the Grafana
adminuser by updating theGRAFANA_ADMIN_PASSWORDvariable:GRAFANA_ADMIN_PASSWORD=your_secure_password
Accessing your Grafana dashboard through a dedicated subdomain is the recommended approach for production environments, as it provides a cleaner and more secure access point.
To set this up, follow these steps:
Verify that your subdomain's A record is correctly pointed to the public IP address of your server.
Open your
.envfile and configure the following Grafana variables:GRAFANA_DOMAIN: Set this to your desired subdomain for accessing the Grafana dashboard. (e.g.,grafana.your-domain.com).GRAFANA_PATH: Leave this variable empty.GRAFANA_DOMAIN=grafana.your-domain.com GRAFANA_PATH=
Set a strong password for the Grafana
adminuser by updating theGRAFANA_ADMIN_PASSWORDvariable:GRAFANA_ADMIN_PASSWORD=your_secure_password
Step 3: Download and package the required Docker images
From the rocketchat-compose directory on the internet-connected server, download all required images:
docker compose -f compose.database.yml -f compose.monitoring.yml -f compose.traefik.yml -f compose.yml pullRun
docker imagesto verify the images you just downloaded.
.png)
Package the images into a
.tarfile archive:
docker save $(docker compose -f compose.database.yml -f compose.monitoring.yml -f compose.traefik.yml -f compose.yml config --images) -o all-images.tarRun
lsto check that the archive file exists. You should seeall-images.taralongside the compose files.
.png)
Step 4: Transfer the files to the airgapped server
The next step is to transfer the entire rocketchat-compose directory to the air-gapped server.
If both servers cannot communicate directly and are not on the same network:
Copy the
rocketchat-composedirectory to a USB drive and transfer them to the air-gapped server using the USB drive.Proceed to deploy Rocket.Chat on the air-gapped server.
If both servers can communicate, transfer the directory with scp using this command:
scp -r -i <key> rocketchat-compose <user_name@target_ip_address:/destination_path>Replace the following with the appropriate values:
key: The key to access the air-gapped server where the file should be sent.user_name@target_ip_address: The username and IP address of the air-gapped server where the file should be sent.destination_path: The directory path on the air-gapped server where you want to save the file.
For example, scp -i firstServer.pem rocketchat-compose.tar ubuntu@176.37.27.133:/home/ubuntu
Step 5: Deploy Rocket.Chat on the air-gapped server
Navigate to the transfer destination on the air-gapped server.
Confirm that the transfered directory contains
all-images.tar, the configuration files, and.env.cd rocketchat-compose lsLoad the Docker images:
docker load -i all-images.tardocker load -i all-images.tarRun
docker imagesto view the images.Deploy Rocket.Chat:
docker compose -f compose.database.yml -f compose.monitoring.yml -f compose.traefik.yml -f compose.yml up -dHere’s a brief summary of what each file in the command does:
File
Description
compose.yml
Launches the Rocket.Chat application
compose.database.yml
Manages MongoDB, the database that Rocket.Chat relies on. It also includes NATS, an internal message broker used for communication between services.
compose.monitoring.yml
Enables Prometheus and Grafana monitoring
compose.traefik.yml
Manages the Traefik reverse proxy, which handles secure routing and automatic HTTPS certificate generation from Let's Encrypt.
You can easily customize your deployment by including only the services you need. For example, if you did not configure monitoring or Traefik (e.g., you are using a separate Nginx proxy), you can omit those
.ymlfiles:docker compose -f compose.database.yml -f compose.yml up -dTo check that all services have successfully started, use this command to list all running containers:
docker psTo see the log/status of your Rocket.Chat container, execute this command:
docker compose logs -f rocketchat
.png)
The log output includes your Site URL where users can access your workspace on the browser.
Great! You have successfully deployed Rocket.Chat in your air-gapped environment. Access your workspace using the ROOT_URL configured in the .env file. The first user to log in automatically becomes the workspace administrator.
Option 2: Deploy Rocket.Chat with a private Docker registry
A Docker registry is a system for storing and distributing Docker images with specific names. This method demonstrates how to use a private Docker registry hosted within your air-gapped network to store and distribute the necessary Docker images for deploying Rocket.Chat.
Prerequisites
One internet-connected server to download and push images to your private registry
One air-gapped server to host the private registry
One air-gapped server to deploy Rocket.Chat
Docker and Docker Compose installed on all three servers
The diagram below highlights an overview of the servers:

Air-gapped deployment with private registry servers
Step 1: Create a private registry
Given that the server to host the registry doesn't have internet access, it is impossible to download images from Docker Hub or any public registry. As a result, you need to download the registry image on a server with internet access and transfer it to the air-gapped registry host server before proceeding with the installation.
Follow these steps to complete the process:
On the server that has internet access, pull the image that'll be used to create the registry with this command:
docker pull registry:2Run
docker imagesto see that the image has been downloaded..png)
Create a
.tarfile of the registry image:docker save -o registry_image.tar registry:2If your server with internet access and the air-gapped server cannot communicate and are not on the same network, copy the downloaded
.tarfile to a USB drive and transfer it to the air-gapped server using the USB drive.
Alternatively, if the two servers can communicate with each other, you can transfer the.tarfile to the air-gapped registry host server using the following command:scp -i [key] <registry_tar_file_path> <user_name@target_ip_address:/destination_path>Update the following with the appropriate values:
key: The key to access the registry host server where the file should be sent.registry_tar_file_path: Theregistry_image.tarfile path.user_name@target_ip_address: The username and IP address of the registry host server where the file should be sent.destination_path: The directory path on the registry host server where the file should be located.
For example,
scp -i firstServer.pem registry_image.tar ubuntu@172.31.81.10:/home/ubuntuTransfer methods may vary depending on your company's policies and network configurations.
Now, go to the air-gapped registry host server. Run the following commands to confirm that you don't have the registry image or container yet:
docker images docker psGo to the destination path where you sent the
.tarfile and run thelscommand and verify that the transfer was successful.To load the tar file on the air-gapped registry host server, execute this command in your preferred directory:
docker load -i registry_image.tarNow run
docker imagesto see the registry image that you downloaded and transferred from the first server..png)
To start the registry container for this image, execute this command:
docker run -d -p 5000:5000 --restart=always --name private-registry registry:2It's not mandatory to run the container on port 5000. The suggested port is an example and can be updated according to your specific requirements.
Update
private-registrywith your preferred name for the registry container.For production environments, ensure the persistence of images by either specifying a local folder on the host for storage or by implementing other suitable persistence mechanisms.
Run
docker psto see the new registry container running..png)
Now, you have a functioning registry on an air-gapped server ready to store the Rocket.Chat and MongoDB images.
Step 2: Prepare Rocket.Chat Images on the Internet-Connected Server
You’ll now pull all the required images from the internet, tag them for your registry, and push them there.
Clone the Rocket.Chat Compose repository:
git clone --depth 1 https://github.com/RocketChat/rocketchat-compose.git cd rocketchat-composePull all required images
The rocketchat-compose setup includes Rocket.Chat, MongoDB, NATS, Traefik, and monitoring services (Prometheus and Grafana).
Run the following command to pull all images used in the Compose stack:
docker compose -f compose.database.yml -f compose.monitoring.yml -f compose.traefik.yml -f compose.yml pullYou can verify the downloaded images by running
docker images.Tag images for your private registry:
for image in $(docker compose -f compose.database.yml -f compose.monitoring.yml -f compose.traefik.yml -f compose.yml config --images); do docker tag $image <registry_ip_address>:5000/$image doneReplace <registry_ip_address:5000> with your registry host’s address:
Push images to the private registry
If your registry uses HTTP, allow insecure access before pushing:
sudo mkdir -p /etc/docker echo '{ "insecure-registries": ["<registry_ip_address>:5000"] }' | sudo tee /etc/docker/daemon.json sudo systemctl restart dockerThen push all tagged images:
for image in $(docker compose -f compose.database.yml -f compose.monitoring.yml -f compose.traefik.yml -f compose.yml config --images); do docker push <registry_ip_address>:5000/$image done
Once complete, your private registry will hold all the images needed to deploy Rocket.Chat.
Step 3: Configure the air-gapped deployment server
On the air-gapped server that will host Rocket.Chat:
Allow insecure registry access (if applicable):
sudo mkdir -p /etc/docker echo '{ "insecure-registries": ["<registry_ip_address>:5000"] }' | sudo tee /etc/docker/daemon.json sudo systemctl restart dockerTransfer the configuration files
Copy the entire rocketchat-compose directory from the internet-connected server to the air-gapped one (via scp or USB).
scp -r rocketchat-compose <user_name@target_ip_address:/destination_path>Edit the .env file in the transferred directory:
cd /destination_path/rocketchat-compose cp .env.example .env nano .envSet key variables:
RELEASE=7.5.0 DOMAIN=localhost ROOT_URL=http://localhostThen add or update these lines to point services to your private registry:
REGISTRY_URL=<registry_ip_address>:5000
You can later update the Compose files or environment overrides to prepend this registry to all images if needed.
Step 4: Deploy Rocket.Chat from the private registry
Run the deployment as usual, but the images will now pull from your private registry instead of Docker Hub. Start the services:
docker compose -f compose.database.yml -f compose.monitoring.yml -f compose.traefik.yml -f compose.yml up -dVerify containers are running:
docker psCheck Rocket.Chat logs:
docker compose logs -f rocketchat
Once the logs show “server running” or display your site URL, open it in a browser to access your workspace. For example: http://localhost:3000
Now, you have successfully deployed Rocket.Chat in your air-gapped environment. Log into your workspace using your site URL, and the first user to log in becomes the workspace administrator.
Next steps
Once your air-gapped workspace is deployed successfully,
Register your workspace following the Air-Gapped Workspace Registration guide.
Apply the workspace license to unlock premium features.
Congratulations, you are ready to begin using your workspace! You can also refer to Air-Gapped Workspace Configuration for making additional configurations to your workspace.
To learn more about your workspace, you can refer to the following:
User Guides: Learn the basics of your Rocket.Chat account, the types of rooms, and how to communicate with your workspace users.
Workspace Administration: Administrators and owners can set and manage various configurations.
Upgrade from Community air-gapped workspace to Starter
From 7.0, air-gapped Community workspaces will be in read-only mode. Community workspaces must be subscribed to a premium plan to access the air-gapped features. Workspace admins can follow these steps to upgrade the workspaces:
Log in to the Rocket.Chat Cloud portal and select the Workspaces tab.
Click the kebab menu against the Community workspace that you want to upgrade.
Select Upgrade to Starter. Your workspace will be subscribed to the Starter plan.
Once your workspace is subscribed to the Starter plan, follow these steps to get the air-gapped license and activate the workspace:
In the cloud portal, select the upgraded workspace. The workspace details page opens.
Click the Get License button from the Rocket.Chat License section.
An Apply Offline License pop-up opens. Copy the License Code.
In your workspace, go to Workspace > Settings > Premium.
Under the Premium section, in the Premium License field, paste the license code you copied from the cloud portal.
Save the changes.
You have successfully activated your air-gapped workspace! For other premium plans, you can refer to the Air-Gapped License document.