Skip to content

Developers

Minh Tu Le edited this page Apr 10, 2026 · 6 revisions

Installation

  • Install asdf and asdf-golang. Then run asdf install to install the versions specified in .tool-versions.
  • Install Docker to run the KinD cluster
  • Install KinD to set up a local Kubernetes cluster
  • Install kubectl to interact with the cluster
  • Install helm-unittest plugin for unit-testing the Helm chart
    helm plugin install https://github.com/helm-unittest/helm-unittest.git
    
  • Install Caddy to run a local reverse proxy for the fake Controller in local development and testing
    • Before running Caddy, add the following line to the /etc/hosts file:
      127.0.0.1 acme.test
      

Running locally

tools/local/main.go script runs fake implementations of Twingate components (Client and Controller) to simulate a full end-to-end flow locally from protocol clients to protected resources via a Gateway. The script sets up the necessary infrastructure for each supported protocol (e.g., a KinD cluster for Kubernetes, a Docker-based OpenSSH server for SSH).

To run the local setup, from the project's root directory:

  • Run sudo caddy run to start the Caddy reverse proxy using the configuration in Caddyfile. Make sure to update the /etc/hosts file.
  • Run go run ./tools/local
  • Run the command go run main.go start ... shown in the output to start the Gateway
    • To run the Gateway in GoLand,
      • Create a Go Build configuration
      • Set program arguments to start ... shown in the output. Alternatively, set environment variables instead of command flags.
  • Run the verification commands shown in the tool output to confirm each protocol is working (e.g., kubectl for Kubernetes, ssh for SSH).

Testing

Unit testing

  • Run make test to run Go unit tests.

Integration testing

  • Goal: Test Gateway functionality against real upstream services for each supported protocol. The Gateway runs as part of Go tests so code coverage is included.

  • Prerequisites:

    • Caddy
    • kubectl CLI
    • Note that KinD clusters are created and instrumented by each test so no need to set up a cluster manually.
  • Test environment:

    • Gateway runs outside the cluster as part of Go tests
    • Caddy runs outside the cluster
    • Mock Client and Controller run outside the cluster
  • Running:

    • From the project's root directory, run sudo caddy run to start the Caddy reverse proxy using the configuration in Caddyfile. Make sure to update the /etc/hosts file (see Installation section above).
    • Run make test-integration to run integration tests.

End-to-end (E2E) testing

  • Goal: Test the full end-to-end flow from protocol clients (kubectl) to the protected resource (a KinD cluster) via a Gateway within the cluster. E2E tests currently cover Kubernetes only. The Gateway is packaged as a Docker image and deployed in the KinD cluster as a Helm chart. E2E tests cover both Docker image and Helm chart.

  • Prerequisites:

    • Caddy
    • kubectl CLI
    • kind CLI
      • Note that like integration tests, KinD clusters are auto-created. However, the tests need kind CLI to load the Docker image into the cluster.
  • Test environment:

    • Gateway runs within the cluster as a Helm chart
    • Caddy runs outside the cluster
    • Mock Client and Controller run outside the cluster
  • Running:

    • From the project's root directory, run sudo caddy run to start the Caddy reverse proxy using the configuration in Caddyfile. Make sure to update the /etc/hosts file (see Installation section above).
    • Run make build to build the Docker image.
    • Run make test-e2e to run E2E tests.

Helm testing

  • Run make test-helm to test changes to the Helm chart.
  • If the test snapshot changes are expected, run make test-helm-and-update-snapshots to update the snapshots.

Debugging

make build produces debug image variants (tagged with -debug) that include the Delve debugger. You can use these images to debug the Gateway running inside a Kubernetes cluster, which is useful for troubleshooting issues related to networking, Helm chart configuration, probes, and RBAC that aren't reproducible when running the Gateway locally. The following guide assumes you already have a Connector and a Gateway deployed in your cluster.

Debugging with Minikube

  1. Point Docker to Minikube's Docker Daemon

    This lets you build images directly in the Minikube environment:

    eval $(minikube docker-env)
  2. Build the Debug Image

    Build the debug image using the provided Makefile target. Make sure you have goreleaser installed before running this command.

    make build

    It will create the twingate/gateway image with the following tags:

    • <version>-linux-arm64
    • <version>-linux-amd64
    • <version>-linux-amd64-debug
    • <version>-linux-arm64-debug
  3. Update the Gateway Deployment

    Load the image you want to run into Minikube:

    minikube image load <the image:tag from the previous step>

    Upgrade (or install) the Gateway deployment to use your local debug image and enable diagnostic mode (Delve debugger):

    helm upgrade <release-name> ./deploy/gateway/ --install -f <values.yaml> \
      --set image.tag="<one of the tags from the previous step>" \
      --set livenessProbe.timeoutSeconds=3600 \
      --set readinessProbe.timeoutSeconds=3600

    Note: Replace <release-name> and <values.yaml> with your actual release name and values file.

  4. Port Forward to the Debugger

    Forward port 2345 from the Gateway pod to your local machine:

    kubectl port-forward pod/<gateway-pod> 2345:2345
  5. Connect Your Debugger

    Use your Go debugger (e.g., GoLand, VS Code, or Delve CLI) to connect to 127.0.0.1:2345.

What Happens When Diagnostic Mode Is Enabled?

  • The Gateway container will start with the Delve debugger in headless mode, listening on port 2345.
  • You can set breakpoints and debug the Go process remotely.

Troubleshooting

  • If you have trouble connecting, ensure the pod is running and port 2345 is not already in use locally.
  • If you see connection errors, double-check that diagnostic mode is enabled and the correct image is deployed.

Releasing

We use tags to release. Makefile has shortcut commands to release development or production releases. The next version is determined using semantic versioning (see go tool svu next).

  • make cut-release - release a dev release (ex: v0.2.1-dev+7a5384c)
  • make cut-release-prod - release a production release (ex: v0.2.2)

Clone this wiki locally