--- title: "Bill of Materials and Registry Mirroring" sidebar_position: 2 description: Gather the packages, images, and certificates you need before crossing the air gap, and set up a private registry or package mirror. --- import Tabs from '@theme/Tabs'; On an internet-connected machine, you must gather all required packages, container images, and dependencies needed for the installation process. The resources you'll need will depend on your deployment method. ## Bill of materials Using our provided tarball is recommended as the simplest installation method for air-gapped environments. You can install the Mattermost Server in a few minutes on any air-gapped 64-bit Linux system. **Prerequisites** - [Mattermost tarball](/product-overview/version-archive). We recommend using the latest [ESR](/product-overview/release-policy#extended-support-releases) for extended support where server upgrades may be infrequent. - Database: PostgreSQL [installation packages](https://www.postgresql.org/download/) or container images for your Linux distribution. - File Storage: Local filesystem storage is sufficient for deployments under 2,000 users. For larger deployments requiring high availability, we recommend using an S3-compatible object storage solution or an NFS (Network File System) server for shared storage needs. - Load balancer: If you already have a load balancer running in your air-gapped environment you can skip this resource, otherwise we recommend deploying [NGINX](/deployment-guide/server/setup-nginx-proxy) from these [Linux packages](https://nginx.org/en/linux_packages.html). - Desktop app: Download the [required package](https://github.com/mattermost/desktop/releases) based on your deployment method. **(Optional) Supporting services** Consider downloading these additional resources if you plan to enable these optional components: - [Mattermost Calls](/deployment-guide/calls/calls-deployment-guide): [mattermost-calls-offloader](https://github.com/mattermost/calls-offloader/releases) (required for recording, transcription, and live captions) and [mattermost-rtcd](https://github.com/mattermost/rtcd/releases) (required for performance and scalability). - [Elasticsearch](https://www.elastic.co/downloads/elasticsearch) can be [deployed](https://www.elastic.co/docs/deploy-manage/deploy/self-managed/installing-elasticsearch) for enhanced search performance at scale. - [Prometheus](https://prometheus.io/download/) and [Grafana](https://grafana.com/grafana/download) for monitoring and observability. Kubernetes is recommended for a highly scalable and robust deployment if your organization is already running a Kubernetes cluster in the air-gapped environment. **Prerequisites** - [Mattermost Operator](https://github.com/mattermost/mattermost-helm/tree/master/charts/mattermost-operator) and [values](https://github.com/mattermost/mattermost-helm/blob/master/charts/mattermost-operator/values.yaml). - Database: We recommend options such as the [Postgres Operator](https://access.crunchydata.com/documentation/postgres-operator/latest/quickstart) from Crunchy Data, [CloudNativePG](https://cloudnative-pg.io/documentation/1.27/installation_upgrade/), or [pgEdge](https://github.com/pgEdge/pgedge-helm). - File Storage: We recommend using an S3-compatible storage service or a mounted NFS volume for shared storage needs. - Load balancer: If you already have a load balancer running in your air-gapped environment you can skip this resource, otherwise we recommend deploying [NGINX](/deployment-guide/server/setup-nginx-proxy), using the [NGINX Ingress Controller operator](https://docs.nginx.com/nginx-ingress-controller/installation/installing-nic/installation-with-operator/). - Desktop app: Download the [required package](https://github.com/mattermost/desktop/releases) based on your deployment method. **(Optional) Supporting services** Consider downloading these additional resources if you plan to enable these optional components: - [Mattermost Calls](/deployment-guide/calls/calls-deployment-guide) helm charts: [mattermost-calls-offloader](https://github.com/mattermost/mattermost-helm/tree/master/charts/mattermost-calls-offloader) and [values](https://github.com/mattermost/mattermost-helm/blob/master/charts/mattermost-calls-offloader/values.yaml) (required for recording, transcription, and live captions), [mattermost-rtcd](https://github.com/mattermost/mattermost-helm/tree/master/charts/mattermost-rtcd) and [values](https://github.com/mattermost/mattermost-helm/blob/master/charts/mattermost-rtcd/values.yaml) (required for performance and scalability). - [Elasticsearch](https://www.elastic.co/docs/deploy-manage/deploy/cloud-on-k8s) can be [deployed in air-gapped k8s environments](https://www.elastic.co/guide/en/cloud-on-k8s/2.8/k8s-air-gapped.html) for enhanced search performance at scale. - [Prometheus](https://github.com/prometheus-operator/prometheus-operator) and [Grafana](https://github.com/grafana/grafana-operator) operators for monitoring and observability. Docker can be used if you don't have a running Kubernetes cluster in the air-gapped environment, but want to use containers for simplified installation and dependency management. Docker is not recommended for production environments at high scale, as it doesn't support clustered deployments or High Availability (HA) configurations out-of-the-box. **Prerequisites** - [Mattermost Enterprise Edition](https://hub.docker.com/r/mattermost/mattermost-enterprise-edition) image. - Database: [PostgreSQL](https://hub.docker.com/_/postgres) image. - Load balancer: If you already have a load balancer running in your air-gapped environment you can skip this resource, otherwise we recommend deploying [NGINX](/deployment-guide/server/setup-nginx-proxy) from these [images](https://hub.docker.com/_/nginx). - Desktop app: Download the [required package](https://github.com/mattermost/desktop/releases) based on your deployment method. **(Optional) Supporting services** Consider downloading these additional resources if you plan to enable these optional components: - [Mattermost Calls](/deployment-guide/calls/calls-deployment-guide) images: [calls-offloader](https://hub.docker.com/r/mattermost/calls-offloader) (required for recording, transcription, and live captions) and [rtcd](https://hub.docker.com/r/mattermost/rtcd) (required for performance and scalability). - [Elasticsearch](https://hub.docker.com/_/elasticsearch) image for enhanced search performance at scale. - [Prometheus](https://hub.docker.com/r/prom/prometheus) and [Grafana](https://hub.docker.com/r/grafana/grafana) images for monitoring and observability. ## Mattermost plugins Mattermost includes a number of [pre-built integrations](/integrations-guide/popular-integrations) for mission-critical tools. If you'd like to use any plugins beyond those that are pre-built in the Mattermost package, you'll need to download the plugin binaries from the [Mattermost Marketplace](https://mattermost.com/marketplace/). Once you have Mattermost deployed, these plugin binaries can be uploaded directly in the System Console. ## SSL/TLS certificates and keys If your deployment requires SSL, ensure you have the necessary certificates. This includes certificates and keys for enabling HTTPS with Mattermost, as well as any CA files or certificates needed to access internal services such as LDAP or SAML. See [Setup TLS](/deployment-guide/server/setup-tls) for configuration details. ## Local documentation Mattermost documentation can be built and served locally so that installation and configuration guidance is available inside the air-gapped environment. Clone the [mattermost/mattermost repository](https://github.com/mattermost/mattermost) on your internet-connected machine, build the documentation site, and transfer the generated static output across the air gap alongside the rest of your bill of materials. **Prerequisites** - Git [\[download\]](https://git-scm.com/downloads) - Node.js 20 or later [\[download\]](https://nodejs.org/en/download) ```bash git clone https://github.com/mattermost/mattermost.git cd mattermost/docs/site npm ci npm run build ``` The build writes a self-contained static site to `docs/site/build/`, which you can serve from any web server in the air-gapped environment. See the [documentation site README](https://github.com/mattermost/mattermost/blob/master/docs/site/README.md) for the full build options, including how to skip the API reference generation step if you don't need it. ## Set up a private registry or mirror A private container registry securely stores the Docker images necessary for air-gapped deployments, ensuring compliance with data isolation requirements. Similarly, a private package mirror stores operating system packages necessary for air-gapped deployments in Ubuntu or RHEL/CentOS Linux environments. Setting up a local registry or mirror is a critical step in deploying Mattermost to ensure all images, dependencies, and packages are available to you in the air-gapped environment. The steps below outline the process required to set up a local registry or mirror, depending on the deployment method you are using. These steps are a rough guide, and can be supplemented with online resources depending on your specific deployment needs. **(Ubuntu) Set up a private Debian package mirror** We will use Aptly to create a local mirror, although you can also use other options such as debmirror. 1. **Install Aptly** (on an internet-connected machine): ```bash apt-get update apt-get install aptly gnupg ``` 2. **Create a GPG key for signing packages**: ```bash gpg --gen-key ``` 3. **Create a mirror configuration**: ```bash aptly mirror create -architectures=amd64 debian-bullseye http://deb.debian.org/debian bullseye main contrib non-free ``` 4. **Update the mirror to download packages**: ```bash aptly mirror update debian-bullseye ``` 5. **Create and publish a snapshot**: ```bash aptly snapshot create debian-bullseye-$(date +%Y%m%d) from mirror debian-bullseye aptly publish snapshot debian-bullseye-$(date +%Y%m%d) ``` 6. **Serve the repository**: ```bash aptly serve ``` 7. **Client configuration:** Configure apt to use your local mirror: ```bash cat > /etc/apt/sources.list << EOF deb http://mirror.example.com/debian bullseye main contrib non-free EOF ``` **(RHEL/CentOS) Set up a private RHEL package mirror** We will use reposync for a local mirror. 1. **Install required tools** (on an internet-connected RHEL system): ```bash yum install yum-utils createrepo ``` 2. **Download packages**: ```bash mkdir -p /var/www/html/repos/rhel8 reposync -p /var/www/html/repos/rhel8 --download-metadata --repo=rhel-8-for-x86_64-baseos-rpms reposync -p /var/www/html/repos/rhel8 --download-metadata --repo=rhel-8-for-x86_64-appstream-rpms ``` 3. **Create repository metadata**: ```bash createrepo /var/www/html/repos/rhel8/rhel-8-for-x86_64-baseos-rpms createrepo /var/www/html/repos/rhel8/rhel-8-for-x86_64-appstream-rpms ``` 4. **Set up a web server**: ```bash yum install httpd systemctl enable httpd systemctl start httpd ``` 5. **Client configuration:** Disable existing repositories: ```bash cd /etc/yum.repos.d/ mkdir backup mv *.repo backup/ ``` 6. **Client configuration:** Create new repository files: ```bash cat > /etc/yum.repos.d/local-baseos.repo << EOF [local-baseos] name=Red Hat Enterprise Linux 8 BaseOS baseurl=http://mirror.example.com/repos/rhel8/rhel-8-for-x86_64-baseos-rpms enabled=1 gpgcheck=0 EOF cat > /etc/yum.repos.d/local-appstream.repo << EOF [local-appstream] name=Red Hat Enterprise Linux 8 AppStream baseurl=http://mirror.example.com/repos/rhel8/rhel-8-for-x86_64-appstream-rpms enabled=1 gpgcheck=0 EOF ``` 7. **Client configuration:** Clear cache and test: ```bash yum clean all yum repolist ``` **Set up a self-hosted private container registry** 1. **Install Docker Registry**: ```bash docker run -d -p 5000:5000 --restart=always --name registry registry:2 ``` 2. **Configure persistent storage**: ```bash docker run -d -p 5000:5000 --restart=always --name registry \ -v /mnt/registry:/var/lib/registry \ registry:2 ``` 3. **Add TLS security** (recommended): a. Generate self-signed certificates: ```bash mkdir -p certs openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \ -x509 -days 365 -out certs/domain.crt ``` b. Run the registry with TLS: ```bash docker run -d -p 5000:5000 --restart=always --name registry \ -v /mnt/registry:/var/lib/registry \ -v $(pwd)/certs:/certs \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ registry:2 ``` **Configure Kubernetes to use private image registries** When using Kubernetes in an air-gapped environment, you need to configure it to use your private registry. 1. **Create a Kubernetes secret for registry authentication**: ```bash kubectl create secret docker-registry regcred \ --docker-server=registry.example.com:5000 \ --docker-username=your_username \ --docker-password=your_password \ --docker-email=your_email@example.com ``` 2. **Reference the secret in pod specifications**: ```yaml apiVersion: v1 kind: Pod metadata: name: mattermost-pod spec: containers: - name: mattermost image: registry.example.com:5000/mattermost/mattermost-enterprise-edition:latest imagePullSecrets: - name: regcred ``` 3. **For Helm deployments**, specify the registry in `values.yaml`: ```yaml image: repository: registry.example.com:5000/mattermost/mattermost-enterprise-edition tag: latest pullPolicy: IfNotPresent imagePullSecrets: - name: regcred ``` **Set up a self-hosted private container registry** 1. **Install Docker Registry**: ```bash docker run -d -p 5000:5000 --restart=always --name registry registry:2 ``` 2. **Configure persistent storage**: ```bash docker run -d -p 5000:5000 --restart=always --name registry \ -v /mnt/registry:/var/lib/registry \ registry:2 ``` 3. **Add TLS security** (recommended): a. Generate self-signed certificates: ```bash mkdir -p certs openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \ -x509 -days 365 -out certs/domain.crt ``` b. Run the registry with TLS: ```bash docker run -d -p 5000:5000 --restart=always --name registry \ -v /mnt/registry:/var/lib/registry \ -v $(pwd)/certs:/certs \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ registry:2 ``` **Populate your private registry** Ensure the required images from the [Bill of Materials](#bill-of-materials) are downloaded and pushed to the private registry. **Configure Docker to use private image registries** Configure Docker on all hosts to trust and use your private registry. 1. **Add your registry to Docker's trusted registries**: Edit or create `/etc/docker/daemon.json`: ```json { "insecure-registries": ["registry.example.com:5000"] } ``` For registries using self-signed certificates: ```bash mkdir -p /etc/docker/certs.d/registry.example.com:5000 cp domain.crt /etc/docker/certs.d/registry.example.com:5000/ca.crt ``` 2. **Restart Docker daemon**: ```bash systemctl restart docker ``` 3. **Test the configuration**: ```bash docker pull registry.example.com:5000/mattermost/mattermost-enterprise-edition:latest ```