Development Setup¶
This guide covers setting up a development environment for the Cloudflare Tunnel Gateway Controller.
Prerequisites¶
- Go 1.25.4 or later
- kubectl configured with cluster access
- A Kubernetes cluster (kind, minikube, or remote)
- Cloudflare account with a tunnel configured
- golangci-lint (for linting)
Quick Start¶
# Clone the repository
git clone https://github.com/lexfrei/cloudflare-tunnel-gateway-controller.git
cd cloudflare-tunnel-gateway-controller
# Install dependencies
go mod download
# Build
go build -o bin/controller ./cmd/controller
# Run tests
go test -v ./...
# Run linter
golangci-lint run
Building¶
Binary¶
# Development build
go build -o bin/controller ./cmd/controller
# Production build with version info
VERSION=v0.1.0
GITSHA=$(git rev-parse HEAD)
go build -ldflags "-s -w -X main.Version=${VERSION} -X main.Gitsha=${GITSHA}" \
-trimpath -o bin/controller ./cmd/controller
Container Image¶
# Build with podman
podman build --tag cloudflare-tunnel-gateway-controller:dev --file Containerfile .
# Build with docker
docker build --tag cloudflare-tunnel-gateway-controller:dev --file Containerfile .
# Multi-arch build
docker buildx build --platform linux/amd64,linux/arm64 \
--tag ghcr.io/lexfrei/cloudflare-tunnel-gateway-controller:dev \
--file Containerfile .
Running Locally¶
With kubeconfig¶
# Set required environment variables
export CF_TUNNEL_ID="your-tunnel-id"
export CF_API_TOKEN="your-api-token"
# Run controller
./bin/controller \
--log-level=debug \
--log-format=text \
--gateway-class-name=cloudflare-tunnel
In Cluster (Development)¶
# Install Gateway API CRDs
kubectl apply --filename https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml
# Create namespace
kubectl create namespace cloudflare-tunnel-system
# Create secret with credentials
kubectl create secret generic cloudflare-credentials \
--namespace=cloudflare-tunnel-system \
--from-literal=api-token="${CF_API_TOKEN}"
# Apply RBAC
kubectl apply --filename deploy/rbac/
# Run controller locally against cluster
./bin/controller \
--tunnel-id="${CF_TUNNEL_ID}" \
--log-level=debug
Linting¶
The project uses golangci-lint with strict configuration:
# Run linter
golangci-lint run
# Run with timeout for CI
golangci-lint run --timeout=5m
# Auto-fix issues
golangci-lint run --fix
Key Linter Settings¶
| Linter | Setting | Description |
|---|---|---|
funlen | max 60 | Maximum function length |
gocyclo | max 15 | Maximum cyclomatic complexity |
gosec | enabled | Security checks |
nolintlint | enabled | Requires //nolint explanations |
Debugging¶
Enable Debug Logging¶
Inspect Controller State¶
# Check Gateway status
kubectl get gateway --all-namespaces --output yaml
# Check HTTPRoute status
kubectl get httproute --all-namespaces --output yaml
# Check controller logs
kubectl logs --namespace cloudflare-tunnel-system \
deployment/cloudflare-tunnel-gateway-controller
# Check events
kubectl get events --namespace cloudflare-tunnel-system \
--sort-by='.lastTimestamp'
Debug with Delve¶
# Install delve
go install github.com/go-delve/delve/cmd/dlv@latest
# Run with debugger
dlv debug ./cmd/controller -- \
--tunnel-id="${CF_TUNNEL_ID}" \
--log-level=debug
IDE Setup¶
VS Code¶
Recommended extensions:
- Go (golang.go)
- YAML (redhat.vscode-yaml)
- Kubernetes (ms-kubernetes-tools.vscode-kubernetes-tools)
Settings (.vscode/settings.json):
{
"go.lintTool": "golangci-lint",
"go.lintFlags": ["--fast"],
"go.useLanguageServer": true,
"gopls": {
"ui.semanticTokens": true
}
}
GoLand¶
- Enable golangci-lint integration:
- Settings → Go → Linters → Enable golangci-lint
- Configure run configuration:
- Add environment variables:
CF_TUNNEL_ID,CF_API_TOKEN - Set working directory to project root
Common Tasks¶
Add a New Flag¶
-
Add flag in
cmd/controller/cmd/root.go: -
Add viper binding and default:
-
Add to
controller.Configstruct ininternal/controller/manager.go -
Pass value in
runController()function
Update Dependencies¶
# Update all dependencies
go get -u ./...
go mod tidy
# Update specific dependency
go get -u github.com/cloudflare/cloudflare-go/v4@latest
go mod tidy
Helm Chart Versioning¶
Do Not Manually Bump Versions
Do not manually change version or appVersion in Chart.yaml. The release workflow automatically sets both values based on the release tag. Manual changes will cause conflicts.