# Phase 3 - install CircleCI server

With prerequisites installed, and object storage configured, you can now copy over and install the CircleCI Helm deployment to the Kubernetes cluster in your air-gapped environment.

## 1\. Prepare `values.yaml`

The `values.yaml` file for installing CircleCI should be prepared according to the [Create Helm values](https://circleci.com/docs/server-admin/server-4.5/installation/phase-2-core-services/#create-helm-values) section of the regular installation guide. Once this is complete, you will modify the fields listed in the steps below for air-gapped installation compatibility.

### a. Configure global values

For a full example of a `values.yaml` file for an air-gapped environment, see the [Example `values.yaml`](https://circleci.com/docs/server-admin/server-4.5/air-gapped-installation/example-values/) page.

In the `global.container` section of your `values.yaml` file:

*   Set the `domainName` value to the internal domain name of the installation
    
*   Set `container.org` to `circleci`
    
*   Set `container.registry` to the internal registry hostname (and port if using a non-standard port) of your instance
    

`````````
global:
  ...
  domainName: "server.internal.example.com"
  container:
    registry: "docker.internal.example.com:5000"
    org: "<image-registry-org>"
`````````

If you are using a non-TLS installation for your Docker registry, visit the [Non-TLS Docker Installation](https://circleci.com/docs/server-admin/server-4.5/air-gapped-installation/additional-considerations/#non-tls-docker-registry-installations) section for consideration.

### b. Configure GitHub Enterprise

In the `github` section of your `values.yaml` file, configure settings for your GitHub Enterprise installation.

The `hostname` value should be the internal hostname of your GitHub enterprise installation. The `enterprise` value should be set to true.

If this instance is not using TLS or self-signed certificates, make sure to set the `unsafeDisableWebhookSSLVerification: true` and `selfSignedCert: true` values.

Additionally, an OAuth application and a personal access token should be set in GitHub Enterprise and values provided as shown below. For more information about this process, see the documentation for creating a [GitHub OAuth application](https://circleci.com/docs/server-admin/server-4.5/installation/phase-1-prerequisites/#create-a-new-github-oauth-app).

`````````
# GitHub Enterprise
github:
  hostname: "github.internal.example.com"
  unsafeDisableWebhookSSLVerification: true # If using self-signed certificates
  enterprise: true
  selfSignedCert: true # If using self-signed certificates
  # These must be generated and added manually from GitHub Enterprise
  clientId: "<<github-enterprise-oauth-app-client-id>>"
  clientSecret: "<<github-enterprise-oauth-app-client-secret>>"
  defaultToken: "<<github-enterprise-personal-application-token>>"
`````````

### c. Configure MinIO object storage

In the `object_storage` section of the `values.yaml` file, add the following configuration, modifying ports as necessary.

`````````
object_storage:
  bucketName: circleci-data
  expireAfter: 0
  s3:
    enabled: true
    endpoint: http://<minio-internal-hostname>:9000
    accessKey: <minio-root-user>
    secretKey: <minio-root-password>
`````````

Update the endpoint protocol to `http` or `https` depending on your MinIO installation.

### d. Configure MinIO build agent

In the distributor section of the `values.yaml` file, point `agent_base_url` and `launch_agent_base_url` to the `circleci-data` bucket you created in your MinIO installation.

`````````
distributor:
  agent_base_url: http://<minio-internal-hostname>:9000/circleci-data/
  launch_agent_base_url: http://<minio-internal-hostname>:9000/circleci-data/
`````````

Update the `runner_admin` section of the `values.yaml` file to point `external.launch_agent_base_url` to the `circleci-data` bucket.

`````````
runner_admin:
  external:
    launch_agent_base_url: http://<minio-internal-hostname>:9000/circleci-data/
`````````

Port 9000 is referenced here as that is a default for MinIO. If your MinIO instance is configured differently, this port will need to be updated.

Update the protocol to `http` or `https` depending on your MinIO installation.

### e. Configure the Nomad build agent image

Specify the location of the Nomad build agent image within your registry, copied during phase 1, modifying the port as necessary.

`````````
nomad:
  ...
  buildAgentImage: "<your-internal-registry-hostname>:5000/circleci/picard"
`````````

Update the port on your Docker registry hostname as necessary

If using a non-TLS installation for your Docker registry, visit the [Non-TLS Docker Installation](https://circleci.com/docs/server-admin/server-4.5/air-gapped-installation/additional-considerations/#non-tls-docker-registry-installations) section for consideration.

### f. Disable machine provisioner

In the `machine_provisioner` section of `values.yaml`, set `enabled` to `false` to disable it. This feature requires cloud connectivity.

`````````
# Machine provisioner disabled - Requires cloud connectivity
machine_provisioner:
  enabled: false
`````````

When following these instructions to simply re-host agents in a partially air-gapped environment, you can configure the machine provisioner for MinIO as follows:

`````````
machine_provisioner:
  agent_base_url: http://<minio-internal-hostname>:9000/circleci-data/machine-provisioner
`````````

### g. Configure Docker provisioner

Update the `docker_provisioner` section of the `values.yaml` file to point `agent_base_url` to the MinIO bucket:

`````````
docker_provisioner:
  agent_base_url: http://<minio-internal-hostname>:9000/circleci-data/docker-provisioner
`````````

### h. Add additional nginx annotations

Add any additional nginx annotations as necessary depending on your installation to provision a load balancer. In this example, MetalLB is used. For more information, see the [Service Type Load Balancers in K3s](https://circleci.com/docs/server-admin/server-4.5/air-gapped-installation/additional-considerations/#service-type-load-balancers-k3s) section on the Additional considerations page.

`````````
# Additional nginx annotations
nginx:
  annotations:
    # This example uses MetalLB as a k3s load balancer
    metallb.universe.tf/allow-shared-ip: default
`````````

## 2\. Install CircleCI server

With your completed `values.yaml` file and the copied Helm chart, run the Helm install command in your air-gapped environment to install CircleCI server.

We recommend first creating a namespace (`circleci-server`) and deploying the chart into that namespace.

`````````
helm install circleci-server ./circleci-server/ -n <kubernetes-namespace> --version 4.5.5 -f <path-to-values.yaml>
`````````

## 3\. Post installation steps

After the Helm deployment, depending on your installation, it may be necessary to manually patch the `circleci-proxy` Load Balancer service (such as when using MetalLB). For more information, see the [Service Type Load Balancers in K3s](https://circleci.com/docs/server-admin/server-4.5/air-gapped-installation/additional-considerations/#service-type-load-balancers-k3s) section on the Additional considerations page.

## Next steps

Once the steps on this page are complete, go to the [Phase 4 - Configure Nomad clients](https://circleci.com/docs/server-admin/server-4.5/air-gapped-installation/phase-4-configure-nomad-clients/) guide.