Private network configuration

Overview

A private network is your organization's secure, internal network space - separated from the public internet. Think of it as your company's own protected environment where internal systems can communicate safely, keeping your sensitive data and operations shielded from external access.

When deploying self-hosted Sourcegraph instances in private networks with specific compliance and policy requirements, additional configuration may be required to ensure all networking features function correctly. The reasons for applying the following configuration options depend on the specific functionality of the Sourcegraph service and the unique network and infrastructure requirements of the organization.

The following is a list of Sourcegraph services that initiate outbound connections to external services. Sourcegraph services not included in this list can be assumed to only connect to services within the Sourcegraph deployment's network segment:

  • executor: Sourcegraph Executor batch change or precise indexing jobs may need to connect to services hosted within an organization's private network
  • frontend: The frontend service communicates externally when connecting to:
  • gitserver: Executes git commands against externally hosted code hosts
  • migrator: Connects to Postgres instances (which may be externally hosted) to process database migrations
  • repo-updater: Communicates with code hosts APIs to coordinate repository synchronization
  • worker: Sourcegraph Worker run various background jobs that may require establishing connections to services hosted within an organization's private network

HTTP proxy configuration

All Sourcegraph services respect the conventional HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables for routing Sourcegraph client application HTTP traffic through a proxy server. The steps for configuring proxy environment variables will depend on your Sourcegraph deployment method.

Kubernetes Helm

Add the proxy environment variables to your Sourcegraph Helm chart override file:

YAML
executor|frontend|gitserver|migrator|repo-updater|worker: env: - name: HTTP_PROXY value: http://proxy.example.com:8080 - name: HTTPS_PROXY value: http://proxy.example.com:8080 - name: NO_PROXY value: "blobstore,codeinsights-db,codeintel-db,sourcegraph-frontend-internal,sourcegraph-frontend,github-proxy,gitserver,grafana,indexed-search-indexer,indexed-search,jaeger-query,pgsql,precise-code-intel-worker,prometheus,redis-cache,redis-store,repo-updater,searcher,symbols,syntect-server,worker-executors,worker,cloud-sql-proxy,localhost,127.0.0.1,.svc,.svc.cluster.local,kubernetes.default.svc"

After setting up your proxy in the override file, you may notice some pods like the frontend, gitserver and repo-updater failing health checks. In such a case, you'll need to add an '*' to the NO_PROXY environment variable. This should look like:

SHELL
- name: NO_PROXY value: "blobstore,codeinsights-db,codeintel-db,sourcegraph-frontend-internal,sourcegraph-frontend,github-proxy,gitserver,grafana,indexed-search-indexer,indexed-search,jaeger-query,pgsql,precise-code-intel-worker,prometheus,redis-cache,redis-store,repo-updater,searcher,symbols,syntect-server,worker-executors,worker,cloud-sql-proxy,localhost,127.0.0.1,.svc,.svc.cluster.local,kubernetes.default.svc, *"

Docker Compose

Add the proxy environment variables your docker compose override file.

YAML
services: <service-name>: environment: - HTTP_PROXY=http://proxy.example.com:8080 - HTTPS_PROXY=http://proxy.example.com:8080 - NO_PROXY='blobstore,caddy,cadvisor,codeintel-db,codeintel-db-exporter,codeinsights-db,codeinsights-db-exporter,sourcegraph-frontend-0,sourcegraph-frontend-internal,gitserver-0,grafana,migrator,node-exporter,otel-collector,pgsql,pgsql-exporter,precise-code-intel-worker,prometheus,redis-cache,redis-store,repo-updater,searcher-0,symbols-0,syntect-server,worker,zoekt-indexserver-0,zoekt-webserver-0,localhost,127.0.0.1'
Failure to configure NO_PROXY correctly can cause the proxy configuration to interfere with local networking between internal Sourcegraph services.

Docker networking configuration

If there is an IP conflict on between the host network and the Docker network, you may need to configure the docker CIDR range in the docker-compose override file.

Additional information on docker networking can be found here:

Trusting TLS certificates using internal PKI

If your organization uses internal Public Key Infrastructure to manage TLS certificates, you may need to configure your Sourcegraph instance to trust your internal Root Certificate Authorities, so your instance can connect to other internal services, ex. code hosts, authentication providers, etc.

This method offers several advantages:

  • Works consistently across both Cloud and self-hosted deployments
  • Requires minimal configuration changes
  • Can be managed entirely through the web UI
  • Maintains certificates in a centralized location
  • Aligns with enterprise PKI best practices

The configuration process involves identifying and adding the public key of your organization's root Certificate Authority (CA) to Sourcegraph's site configuration. This approach is particularly efficient because:

  • Root CA certificates typically have long expiration periods (often measured in years)
  • A single root CA certificate usually covers multiple internal services
  • The configuration can be managed without container modifications or filesystem changes

Obtain the certificate chain

Use the OpenSSL command to extract the certificate chain from your code host. Replace the domain and port with your internal code host's values:

BASH
openssl s_client -showcerts -connect example.com:8443 \ -nameopt lname < /dev/null > certs.log 2>&1

Identify the root certificate

In the generated certs.log file, locate the root CA certificate:

Certificate chains typically include 3 certificates:

  • Root certificate authority (depth=2)
  • Intermediate certificate authority (depth=1)
  • Server (leaf) certificate (depth=0)

The last certificate in the chain will be the root CA certificate and will typically have:

  • A long expiration period (years)
  • A descriptive common name (e.g., "Enterprise Root CA 2023")

Example root CA certificate for github.com:

TEXT
Connecting to 140.82.114.3 depth=2 countryName=US, stateOrProvinceName=New Jersey, localityName=Jersey City, organizationName=The USERTRUST Network, commonName=USERTrust ECC Certification Authority verify return:1 depth=1 countryName=GB, stateOrProvinceName=Greater Manchester, localityName=Salford, organizationName=Sectigo Limited, commonName=Sectigo ECC Domain Validation Secure Server CA verify return:1 depth=0 commonName=github.com verify return:1 CONNECTED(00000005) --- ... 2 s:countryName=US, stateOrProvinceName=New Jersey, localityName=Jersey City, organizationName=The USERTRUST Network, commonName=USERTrust ECC Certification Authority i:countryName=GB, stateOrProvinceName=Greater Manchester, localityName=Salford, organizationName=Comodo CA Limited, commonName=AAA Certificate Services a:PKEY: id-ecPublicKey, 384 (bit); sigalg: RSA-SHA384 v:NotBefore: Mar 12 00:00:00 2019 GMT; NotAfter: Dec 31 23:59:59 2028 GMT -----BEGIN CERTIFICATE----- MII...c= -----END CERTIFICATE-----

Format the certificate

Once you've identified the root CA certificate:

  • Extract the certificate content including the BEGIN and END markers.
  • Format the certificate for the site configuration:
    • Replace newlines with \n characters
    • Enclose the entire certificate in double quotes
    • Add a trailing comma

The following command can be used to easily obtain, extract, and format the root certificate from a 3 certificate chain. Be sure to adjust the hostname and port to match your internal code host. If your certificate chain is of a different depth, adjust the awk command accordingly. awk '/BEGIN CERTIFICATE/{i++} i==X'

BASH
openssl s_client -showcerts -connect example.com:8443 \ -nameopt lname < /dev/null 2>&1 \ | awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/' \ | awk '/BEGIN CERTIFICATE/{i++} i==2' \ | awk '{printf "%s\\n", $0}' | sed 's/\\n$//' \ | awk '{print "\"" $0 "\","}'

Add the certificate to the site configuration

Add the formatted certificate to your Sourcegraph site configuration.

JSON
{ "experimentalFeatures": { "tls.external": { "certificates": [ "-----BEGIN CERTIFICATE-----\naZ...==\n-----END CERTIFICATE-----" ] } } }

For organizations with multiple root CAs (uncommon), additional certificates can be added to the array:

JSON
{ "experimentalFeatures": { "tls.external": { "certificates": [ "-----BEGIN CERTIFICATE-----\naZ...==\n-----END CERTIFICATE-----", "-----BEGIN CERTIFICATE-----\nMI...I7\n-----END CERTIFICATE-----" ] } } }

Validation of certificate configuration

These steps confirms that configuring the root CA certificate through tls.external is sufficient for all standard Sourcegraph operations that require secure connections to internal services.

  1. Code host connectivity

    • Verify using the UI "Test Connection" button
    • Trigger validate completed sync jobs
      Executed by: frontend service
  2. Repository operations

    • Verify individual repository synchronization
    • Verify cloning operations
      Executed by: gitserver service
  3. Permission synchronization

    • Verify user-centric permission sync jobs
      Executed by: worker service

Repository-centric permission sync jobs are expected to behave identically, as they use the same underlying TLS configuration mechanisms.

  • Only include root CA certificates, not intermediate or server certificates.
  • Avoid using insecureSkipVerify: true and add TLS certificates if needed, as it bypasses important security checks.
  • Document certificate sources and expiration dates in your organization's runbooks.
  • Plan for certificate rotation well before root CA expiration.
  • Most enterprises use a single root CA, so adding one certificate often covers all internal services.
  • Keep the certificate list minimal and well-maintained.