For each Gitpod installation, you need a domain. In this guide, we use gitpod.example.com as a placeholder for your domain. Gitpod also uses different subdomains for some components as well as dynamically for the running workspaces. That’s why you need to configure your DNS server and your TLS certificates for your Gitpod domain with the following wildcards:

gitpod.example.com
*.gitpod.example.com
*.ws.gitpod.example.com

Cluster ports

The entry point for all traffic is the proxy component which has a service of type LoadBalancer that allows inbound traffic on ports 80 (HTTP) and 443 (HTTPS) as well as port 22 (SSH access to the workspaces).

SSH access is required to work with desktop IDEs, such as VS Code Desktop and JetBrains via JetBrains Gateway. To enable SSH, your load balancer needs to be capable of working with L4 protocols.

Cloud provider specific instructions
  • GCP
  • AWS
  • Azure

In this guide, we use load balancing through a standalone network endpoint group (NEG). For this, the Gitpod proxy service will get the following annotation by default:

language icon language: 
bash
cloud.google.com/neg: '{"exposed_ports": {"80":{},"443": {}}}'

For Gitpod, we support Calico as CNI only. You need to make sure that you DO NOT use GKE Dataplan V2. That means, do not add the --enable-dataplane-v2 flag during the cluster creation.

External DNS

You also need to configure your DNS server. If you have your own DNS server for your domain, make sure the domain with all wildcards points to your load balancer.

Creating a dedicated DNS zone is recommended when using cert-manager or external-dns but is not required. A pre-existing DNS zone may be used as long as the cert-manager and/or external-dns services are authorized to manage DNS records within that zone. If you are providing your own TLS certificates and will manually create A records pointing to Gitpod’s public load balancer IP addresses then creating a zone is unnecessary.

Cloud provider specific instructions
  • GCP
  • AWS
  • Azure

In this reference architecture, we use Google Cloud DNS for domain name resolution. To automatically configure Cloud DNS, we use External DNS for Kubernetes.

First, we need a service account with role roles/dns.admin. This service account is needed by cert-manager to alter the DNS settings for the DNS-01 resolution.

language icon language: 
bash
DNS_SA=gitpod-dns01-solver
DNS_SA_EMAIL="${DNS_SA}"@"${PROJECT_NAME}".iam.gserviceaccount.com
gcloud iam service-accounts create "${DNS_SA}" --display-name "${DNS_SA}"
gcloud projects add-iam-policy-binding "${PROJECT_NAME}" \
    --member serviceAccount:"${DNS_SA_EMAIL}" --role="roles/dns.admin"

Save the service account key to the file ./dns-credentials.json:

language icon language: 
bash
gcloud iam service-accounts keys create --iam-account "${DNS_SA_EMAIL}" \
    ./dns-credentials.json

After that, we create a managed zone.

language icon language: 
bash
DOMAIN=gitpod.example.com
gcloud dns managed-zones create "${CLUSTER_NAME}" \
    --dns-name "${DOMAIN}." \
    --description "Automatically managed zone by kubernetes.io/external-dns"

Now we are ready to install External DNS. Please refer to the External DNS GKE docs.

Example on how to install External DNS with helm
language icon language: 
bash
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm upgrade \
    --atomic \
    --cleanup-on-fail \
    --create-namespace \
    --install \
    --namespace external-dns \
    --reset-values \
    --set provider=google \
    --set google.project="${PROJECT_NAME}" \
    --set logFormat=json \
    --set google.serviceAccountSecretKey=dns-credentials.json \
    --wait \
    external-dns \
    bitnami/external-dns

Depending on what your DNS setup for your domain looks like, you most probably want to configure the nameservers for your domain. Run the following command to get a list of nameservers used by your Cloud DNS setup:

language icon language: 
bash
gcloud dns managed-zones describe ${CLUSTER_NAME} --format json | jq '.nameServers'

cert-manager

Gitpod uses TLS secure external traffic bound for Gitpod as well as identifying, authorizing, and securing internal traffic between Gitpod’s internal components. While you can provide your own TLS certificate for securing external connections to Gitpod, cert-manager is required to generate internal TLS certificates.

Refer to the cert-manager DNS01 docs for more information.

Cloud provider specific instructions
  • GCP
  • AWS
  • Azure

Example on how to install cert-manager on GCP:

language icon language: 
bash
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm upgrade \
    --atomic \
    --cleanup-on-fail \
    --create-namespace \
    --install \
    --namespace cert-manager \
    --reset-values \
    --set installCRDs=true \
    --set 'extraArgs={--dns01-recursive-nameservers-only=true,--dns01-recursive-nameservers=8.8.8.8:53\,1.1.1.1:53}' \
    --wait \
    cert-manager \
    jetstack/cert-manager

TLS certificate

In this reference architecture, we use cert-manager to also create TLS certificates for the Gitpod domain. Since we need wildcard certificates for the subdomains, you must use the DNS-01 challenge.

Using a certificate issued by Let’s Encrypt is recommended as it minimizes overhead involving TLS certificates and managing CA certificate trust, but is not required. If you already have TLS certificates for your Gitpod installation with suitable DNS names you can skip this step and use your own certificates during the installation.

Cloud provider specific instructions
  • GCP
  • AWS
  • Azure

Now, we are configuring Google Cloud DNS for the DNS-01 challenge. For this, we need to create a secret that contains the key for the DNS service account:

language icon language: 
bash
CLOUD_DNS_SECRET=clouddns-dns01-solver
kubectl create secret generic "${CLOUD_DNS_SECRET}" \
    --namespace=cert-manager \
    --from-file=key.json="./dns-credentials.json"

After that, we are telling cert-manager which service account it should use:

language icon language: 
bash
kubectl annotate serviceaccount --namespace=cert-manager cert-manager \
    --overwrite "iam.gke.io/gcp-service-account=${DNS_SA_EMAIL}"

The next step is to create an issuer. In this guide, we create a cluster issuer. Create a file issuer.yaml like this:

language icon language: 
yml
# Replace $LETSENCRYPT_EMAIL with your email and $PROJECT_NAME with your GCP project name
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
    name: gitpod-issuer
spec:
    acme:
        email: $LETSENCRYPT_EMAIL
        server: https://acme-v02.api.letsencrypt.org/directory
        privateKeySecretRef:
            name: issuer-account-key
        solvers:
            - dns01:
                  cloudDNS:
                      project: $PROJECT_NAME

… and run:

language icon language: 
bash
kubectl apply -f issuer.yaml

Was this helpful?