Offline deployments

Offline deployments

Offline Deployments

All Coder features are supported in offline / behind firewalls / in air-gapped environments. However, some changes to your configuration are necessary.

This is a general comparison. Keep reading for a full tutorial running Coder offline with Kubernetes or Docker.

Public deploymentsOffline deployments
Terraform binaryBy default, Coder downloads Terraform binary from releases.hashicorp.comTerraform binary must be included in PATH for the VM or container image. Supported versions
Terraform registryCoder templates will attempt to download providers from registry.terraform.io or custom source addresses specified in each templateCustom source addresses can be specified in each Coder template, or a custom registry/mirror can be used. More details below
STUNBy default, Coder uses Google's public STUN server for direct workspace connectionsSTUN can be safely disabled, users can still connect via relayed connections. Alternatively, you can set a custom DERP server
DERPBy default, Coder's built-in DERP relay can be used, or Tailscale's public relays.By default, Coder's built-in DERP relay can be used, or custom relays.
PostgreSQLIf no PostgreSQL connection URL is specified, Coder will download Postgres from repo1.maven.orgAn external database is required, you must specify a PostgreSQL connection URL
TelemetryTelemetry is on by default, and can be disabledTelemetry can be disabled
Update checkBy default, Coder checks for updates from GitHub releasesUpdate checks can be disabled

Offline container images

The following instructions walk you through how to build a custom Coder server image for Docker or Kubernetes

First, build and push a container image extending our official image with the following:

Note: Coder includes the latest supported version of Terraform in the official Docker images. If you need to bundle a different version of terraform, you can do so by customizing the image.

Here's an example Dockerfile:

FROM ghcr.io/coder/coder:latest

USER root

RUN apk add curl unzip

# Create directory for the Terraform CLI (and assets)
RUN mkdir -p /opt/terraform

# Terraform is already included in the official Coder image.
# See https://github.com/coder/coder/blob/main/scripts/Dockerfile.base#L15
# If you need to install a different version of Terraform, you can do so here.
# The below step is optional if you wish to keep the existing version.
# See https://github.com/coder/coder/blob/main/provisioner/terraform/install.go#L23-L24
# for supported Terraform versions.
RUN apk update && \
    apk del terraform && \
    curl -LOs https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip \
    && unzip -o terraform_${TERRAFORM_VERSION}_linux_amd64.zip \
    && mv terraform /opt/terraform \
    && rm terraform_${TERRAFORM_VERSION}_linux_amd64.zip
ENV PATH=/opt/terraform:${PATH}

# Additionally, a Terraform mirror needs to be configured
# to download the Terraform providers used in Coder templates.
# There are two options:

# Option 1) Use a filesystem mirror. We can seed this at build-time
#    or by mounting a volume to /opt/terraform/plugins in the container.
#    https://developer.hashicorp.com/terraform/cli/config/config-file#filesystem_mirror
#    Be sure to add all the providers you use in your templates to /opt/terraform/plugins

RUN mkdir -p /opt/terraform/plugins
ADD filesystem-mirror-example.tfrc /opt/terraform/config.tfrc

# Optionally, we can "seed" the filesystem mirror with common providers.
# Comment out lines 40-49 if you plan on only using a volume or network mirror:
RUN mkdir -p /opt/terraform/plugins/registry.terraform.io
WORKDIR /opt/terraform/plugins/registry.terraform.io
RUN echo "Adding coder/coder v${CODER_PROVIDER_VERSION}" \
    && mkdir -p coder/coder && cd coder/coder \
    && curl -LOs https://github.com/coder/terraform-provider-coder/releases/download/v${CODER_PROVIDER_VERSION}/terraform-provider-coder_${CODER_PROVIDER_VERSION}_linux_amd64.zip
RUN echo "Adding kreuzwerker/docker v${DOCKER_PROVIDER_VERSION}" \
    && mkdir -p kreuzwerker/docker && cd kreuzwerker/docker \
    && curl -LOs https://github.com/kreuzwerker/terraform-provider-docker/releases/download/v${DOCKER_PROVIDER_VERSION}/terraform-provider-docker_${DOCKER_PROVIDER_VERSION}_linux_amd64.zip
RUN echo "Adding kubernetes/kubernetes v${KUBERNETES_PROVIDER_VERSION}" \
    && mkdir -p kubernetes/kubernetes && cd kubernetes/kubernetes \
    && curl -LOs https://releases.hashicorp.com/terraform-provider-kubernetes/${KUBERNETES_PROVIDER_VERSION}/terraform-provider-kubernetes_${KUBERNETES_PROVIDER_VERSION}_linux_amd64.zip
RUN echo "Adding aws/aws v${AWS_PROVIDER_VERSION}" \
    && mkdir -p aws/aws && cd aws/aws \
    && curl -LOs https://releases.hashicorp.com/terraform-provider-aws/${AWS_PROVIDER_VERSION}/terraform-provider-aws_${AWS_PROVIDER_VERSION}_linux_amd64.zip

RUN chown -R coder:coder /opt/terraform/plugins
WORKDIR /home/coder

# Option 2) Use a network mirror.
#    https://developer.hashicorp.com/terraform/cli/config/config-file#network_mirror
#    Be sure uncomment line 60 and edit network-mirror-example.tfrc to
#    specify the HTTPS base URL of your mirror.

# ADD network-mirror-example.tfrc /opt/terraform/config.tfrc

USER coder

# Use the tfrc file to inform
ENV TF_CLI_CONFIG_FILE=/opt/terraform/config.tfrc

If you are bundling Terraform providers into your Coder image, be sure the provider version matches any templates or example templates you intend to use.

# filesystem-mirror-example.tfrc
provider_installation {
  filesystem_mirror {
    path = "/opt/terraform/plugins"
# network-mirror-example.tfrc
provider_installation {
  network_mirror {
    url = "https://terraform.example.com/providers/"

Run offline via Docker

Follow our docker-compose documentation and modify the docker-compose file to specify your custom Coder image. Additionally, you can add a volume mount to add providers to the filesystem mirror without re-building the image.

First, make a create an empty plugins directory:

mkdir $HOME/plugins

Next, add a volume mount to docker-compose.yaml:

vim docker-compose.yaml
# docker-compose.yaml
version: "3.9"
    image: registry.example.com/coder:latest
      - ./plugins:/opt/terraform/plugins
    # ...
    CODER_TELEMETRY_ENABLE: "false" # Disable telemetry
    CODER_DERP_SERVER_STUN_ADDRESSES: "" # Only use relayed connections
    CODER_UPDATE_CHECK: "false" # Disable automatic update checks
    image: registry.example.com/postgres:13
    # ...

The terraform providers mirror command can be used to download the required plugins for a Coder template. This can be uploaded into the plugins directory on your offline server.

Run offline via Kubernetes

We publish the Helm chart for download on GitHub Releases. Follow our Kubernetes documentation and modify the Helm values to specify your custom Coder image.

# values.yaml
    repo: "registry.example.com/coder"
    tag: "latest"
    # Disable telemetry
      value: "false"
    # Disable automatic update checks
    - name: "CODER_UPDATE_CHECK"
      value: "false"
    # Only use relayed connections
      value: ""
    # You must set up an external PostgreSQL database
      value: ""
# ...
See an opportunity to improve our docs? Make an edit.