Skip to main content

Self-Host Speakeasy

Self-host vs Speakeasy Cloud: Self-hosting Speakeasy means managing the service yourself and take care of upgrades, scaling, security etc. If you are less technical or looking for a hands-off experience, we recommend Speakeasy Cloud.


Getting a production environment of Speakeasy up and running is probably one of the first things you want to do! This section goes through the different options available depending on where you'll be hosting Speakeasy, and includes guides on several of the most popular services.

Currently the self-hosting guides are manual deployment procedures. We plan on having a terraform module very soon to support deploying Speakeasy with IaC.


  • Helm 3.0
  • kubectl
  • A PostgreSQL database
    • We strongly recommend a long-term installation of Speakeasy uses an externally managed database (eg. Google CloudSQL, AWS RDS). Tying the storage of your data to the lifecycle of persistent volumes may result in data-loss. For testing purposes however, this chart allows the user to enable Postgres on K8s.


Helm must be installed to use the charts. Please refer to Helm's documentation to get started.

Once Helm has been set up correctly, add the repo as follows:

helm repo add speakeasy

If you had already added this repo earlier, run helm repo update to retrieve the latest versions of the packages. You can then run helm search repo speakeasy to see the charts.

For specific instructions regarding installation of speakeasy-k8s, please refer to the Installation section below.


Configure the SDK

The SDK provides a way to redirect the requests it captures to a self-hosted deployment of the Speakeasy Platform. This is done through the use of environment variables listed below. These are to be set in the environment of your services that have integrated the SDK:

  • SPEAKEASY_SERVER_URL - The url of the on-premise Speakeasy Platform's GRPC Endpoint. By default this is
  • SPEAKEASY_SERVER_SECURE - Whether or not to use TLS for the on-premise Speakeasy Platform. By default this is true set to SPEAKEASY_SERVER_SECURE="false" if you are using an insecure connection.

Configure Infrastructure

Provide an overlay for the changes needed to values.yaml by following the sections below.


Speakeasy uses Github OAuth to provide authentication for your org. Under settings for the Github Organization you'd like to authenticate, click "Developer Settings" > "Oauth Apps" > "New Oauth App". Fill in the fields (example in screenshot below). Please ensure the "Authorization callback URL" has a value in the form of https://<DOMAIN>/v1/auth/callback/github, where <DOMAIN> is replaced by the domain name of the A record (added in the Ingress Section below).


You will also need to specify values for auth.SignInURL, auth.GithubClientId, auth.GithubClientSecret, and auth.GithubCallbackURL in your overlay to be equivalent to the above populated values. auth.SignInURL should just be https://<DOMAIN> (see example overlay).


If provisioning ingress resources from our chart, set the value for registry.ingress.enabled to true. Also, set the values for registry.ingress.apiHostnames, registry.ingress.webHostnames, and registry.ingress.grpcHostnames to your specified domain names for Speakeasy's registry API, web, and gRPC services.


If using Ambassador mappings, ensure registry.ingress.enabled and cert-manager.enabled are both false. See the Ambassador Installation section below for the steps required to use Ambassador for your Speakeasy deployment.


To enable Postgres on K8s (not recommended), set the value for postgresql.enabled to true. If using an externally managed Postgres (recommended), set postgresql.enabled to false and the value for the POSTGRES_DSN environment variable.


To enable Bigquery for request/response storage, set values for BIGQUERY_PROJECT and BIGQUERY_DATASET under the registry.envVars block. They should be equivalent to the GCP project ID and Bigquery dataset ID, respectively, under which bounded_requests and unbounded_requests tables must exist with the following schema:

bounded_requests login

unbounded_requests login

Currently, the Speakeasy application assumes these tables with the above schemas exist under the specified BIGQUERY_PROJECT and BIGQUERY_DATASET. If they do not exist execute the following steps:

  1. Follow the docs to install the bq command line tool:
  2. Run the following commands, replacing <DATASET_ID> with your dataset:
bq mk -t <DATASET_ID>.bounded_requests request_id:STRING,workspace_id:STRING,api_id:STRING,version_id:STRING,api_endpoint_id:STRING,api_endpoint_path:STRING,method:STRING,path:STRING,status:INTEGER,request_start_time:TIMESTAMP,response_finish_time:TIMESTAMP,created_at:TIMESTAMP,customer_id:STRING,latency:INTEGER
bq mk -t <DATASET_ID>.unbounded_requests request_id:STRING,workspace_id:STRING,har:STRING,har_size_bytes:INTEGER,created_at:TIMESTAMP

We will soon add support for automating the creation of these tables in your GCP project and dataset if they do not exist.

Enable HTTPS

If registry.ingress.enabled is true, set the value for cert-manager.enabled to true (and notificationEmail to receive updates about cert expiry) for LetsEncrypt to provide SSL certificates to enable HTTPS.

If following the Ambassador Installation, ensure cert-manager.enabled is false. Some manual steps will be required to ensure certificates can successfully provision with Ambassador mappings.

Speakeasy Version

Set values for registry.image.tag with the version of Speakeasy you'd like to install.

The following is a sample overlay file for a configuration requiring ingress to be spun up by this chart and connecting to an externally managed Postgres:

tag: 1.0.0
value: postgres://postgres:postgres@
enabled: true
GithubClientId: b0234253z345c
GithubClientSecret: *****************
enabled: false
enabled: true


The process to install Speakeasy will differ depending on whether ingress, Ambassador, or neither are enabled.

Without Ingress

If not enabling ingress or Ambassador, execute the following command:

helm install speakeasy speakeasy/speakeasy-k8s -f <OVERLAY> -n <NAMESPACE> --debug

If postgresql.enabled is true, you will also need to edit the Speakeasy deployment to modify the IP in POSTGRES_DSN with the external IP of the LoadBalancer service. First, get the IP via:

kubectl get svc -n <NAMESPACE> postgres-postgresql -o "go-template={{range .status.loadBalancer.ingress}}{{or .ip .hostname}}{{end}}"

Then, modify the Speakeasy deployment via:

kubectl edit deploy -n <NAMESPACE> speakeasy-k8s-service

Swap out the under the value for POSTGRES_DSN with the IP obtained from the previous command.

With Ingress

In your overlay, set postgresql.enabled to false, even if using Postgres on K8s. If using K8s Postgres, follow necessary instructions to install the postgresql helm chart. The following is a sample command using an already existing PV and PVC:

helm repo add bitnami
helm repo update
helm install -n <NAMESPACE> postgres bitnami/postgresql --set persistence.existingClaim=postgres-pvc --set auth.postgresPassword=postgres \
--set volumePermissions.enabled=true --set primary.service.type=LoadBalancer

For K8s Postgres, get the external IP of the LoadBalancer via:

kubectl get svc -n <NAMESPACE> postgres-postgresql -o "go-template={{range .status.loadBalancer.ingress}}{{or .ip .hostname}}{{end}}"

Otherwise, simply get the appropriate IP from your externally managed Postgres.

In your overlay, modify POSTGRES_DSN value to use the IP obtained in the above instructions, and continue to follow the below instructions for your ingress controller type.


If enabling cert-manager, there are strict requirements regarding the ordering of resources. See Resource Ordering Constraints for an explanation. As a result, please execute the following steps:

  1. First, install ingress-nginx:
    helm repo add ingress-nginx
    helm repo update
    helm install -n <NAMESPACE> ingress ingress-nginx/ingress-nginx --set controller.config.use-forwarded-headers=true \
    --set controller.config.use-http2=true --set fullnameOverride=speakeasy-ingress-nginx
  2. Get the external IP of the LoadBalancer via:
    kubectl get svc speakeasy-ingress-nginx-controller -o "go-template={{range .status.loadBalancer.ingress}}{{or .ip .hostname}}{{end}}"
    Then, create an A record on your DNS to point your desired domain for Speakeasy to this IP. For example domain names, refer to the sample overlay in the end of the Configuration section above.


To use Ambassador's emissary-ingress controller, please ensure the following values are set to false:


Execute the following steps:

  1. First, add CRDs for emissary-ingress:

    helm repo add datawire
    helm repo update
    kubectl apply -f
  2. Install emissary-ingress:

    helm install -n <NAMESPACE> emissary-ingress datawire/emissary-ingress && kubectl wait --for condition=available --timeout=90s deploy \
  3. Get the external IP of the LoadBalancer via:

    kubectl get svc -n <NAMESPACE> emissary-ingress -o "go-template={{range .status.loadBalancer.ingress}}{{or .ip .hostname}}{{end}}"

    Then, create an A record on your DNS to point your desired domain for Speakeasy to this IP. For example domain names, refer to the sample overlay in the end of the Configuration section above.

  4. Install cert-manager with the following overlay:

    installCRDs: true
    podDnsPolicy: None

    Execute the following:

    helm repo add jetstack
    helm repo update
    helm install -n <NAMESPACE> cert-manager jetstack/cert-manager -f <OVERLAY>
  5. cert-manager must issue an HTTP-01 challenge to verify domain ownership. We will need to apply CRDs from both cert-manager and emissary-ingress to enable this. Replace the "$YOUR_EMAIL_HERE$" in ./ambassador/cert-manager-ambassador-crds.yaml to the email updates to manage the LetsEncrypt certificate (90 day expiration) will be sent.

    Then, apply the file:

    kubectl apply -f <path/to/ambassador/cert-manager-ambassador-crds.yaml> --namespace=<NAMESPACE>
  6. Now, we have to provision the certificate for our Speakeasy domain.

    In ambassador/ambassador-web-cert.yaml, ensure the "$" wrapped value in spec.dnsNames is replaced with the corresponding domain name for the A record you issued above.

    Then deploy the certificate:

    kubectl apply -f speakeasy-k8s/ambassador/ambassador-web-cert.yaml --namespace <NAMESPACE>

    You may monitor the status of the certificate by issuing the following command and watching the "READY" column:

    kubectl get certificates -n <NAMESPACE> --watch
  7. The certificate from the previous step should now be ready. In ./ambassador/ambassador-mappings-and-hosts.yaml, replace all the "$" wrapped values for spec.hostname, and ensure they're equivalent to the domain name for the A record you issued above.

    Then, apply the file:

    kubectl apply -f <path/to/ambassador/ambassador-mappings-and-hosts.yaml> --namespace=<NAMESPACE>

Finally, execute the following install for speakeasy-k8s:

helm install speakeasy speakeasy/speakeasy-k8s -f <OVERLAY> -n <NAMESPACE> --timeout 5m --wait --wait-for-jobs --debug \
--set fullnameOverride=speakeasy

After waiting a couple minutes, Speakeasy should now be running successfully in your environment. You should now be able to access the HTTPS endpoint for your web or root web hostname.

To uninstall the charts:

helm delete speakeasy -n <NAMESPACE>
helm delete ingress -n <NAMESPACE> # if using ingress-nginx controller
helm delete postgres -n <NAMESPACE>
helm delete emissary-ingress -n <NAMESPACE> # if using emissary-ingress controller

Resource Ordering Constraints

cert-manager installs CRDs to enable certificate provisioning via LetsEncrypt. One such CRD is the ClusterIssuer which must be installed last, otherwise the CRD will not be present in the K8s API server. However, the CertificateRequest will issue a status check to the ClusterIssuer. When this status check fails, we found the CertificateRequest status would hang and prevent a successful installation. Since this status check proceeds directly upon installation of Speakeasy, we need to ensure the POSTGRES_DSN is pointing to an already existing Postgres service and A records are created for the ingress-nginx controller beforehand for a successful Speakeasy installation.