Private Network Deployment
This guide covers deploying your Convox rack and Rack Gateway on a completely private network, with no public internet exposure.
Why Go Fully Private?
Section titled “Why Go Fully Private?”By default, the Convox API is exposed publicly via nginx ingress with authentication via the rack password. While protected by authentication, this presents security concerns:
- Discoverable endpoint - The API is subject to brute force attempts
- Token compromise risk - Any rack token compromise grants API access from anywhere
- No network-level access control - Cannot enforce IP restrictions for sensitive operations
- Compliance requirements - Some organizations require all internal tools to be on private networks
With a fully private deployment:
- The Convox API is only accessible through your VPN/private network
- Even if the rack token is compromised, attackers can’t reach the API
- You gain defense-in-depth: network security + authentication + RBAC
Architecture Overview
Section titled “Architecture Overview”The private_api Feature
Section titled “The private_api Feature”There’s an open PR (#935) to add a private_api parameter to Convox that disables public access to the API entirely.
Using DocSpring’s Fork
Section titled “Using DocSpring’s Fork”DocSpring maintains a public fork of Convox that includes the private_api feature along with other improvements:
private_api- Disable public nginx ingress for the Convox API- CloudFlare DNS-01 resolver - Alternative certificate validation method
- Various bug fixes and enhancements
Deployment with Tailscale
Section titled “Deployment with Tailscale”-
Set up Tailscale Operator in your cluster
Follow the Tailscale Kubernetes operator guide to install the operator in your EKS cluster.
-
Configure your Convox rack with
private_apiUse DocSpring’s fork in your Terraform configuration:
module "system" {source = "github.com/DocSpring/convox//terraform/system/aws?ref=docspring"image = "docspringcom/convox"release = "docspring-004"name = "production"region = "us-east-1"# Private EKS API access (existing Convox feature)private_eks_host = "https://eks-production.your-tailnet.ts.net"disable_public_access = true# Private Convox API access (DocSpring fork feature)private_api = true# ... other configuration ...} -
Create Tailscale ingress for the Convox API
resource "kubernetes_ingress_v1" "convox_api_tailscale" {metadata {name = "convox-api"namespace = "rack-system" # or your rack namespaceannotations = {"tailscale.com/expose" = "true""tailscale.com/hostname" = "convox-api-production""tailscale.com/tags" = "tag:convox-api"}}spec {ingress_class_name = "tailscale"rule {host = "convox-api-production.your-tailnet.ts.net"http {path {path = "/"path_type = "Prefix"backend {service {name = "api"port { name = "https" }}}}}}tls {hosts = ["convox-api-production.your-tailnet.ts.net"]}}} -
Deploy Rack Gateway with Tailscale access
Configure Rack Gateway to connect to the private Convox API:
Terminal window # In your Rack Gateway environmentRACK_HOST=https://convox-api-production.your-tailnet.ts.netRACK_TOKEN=your-rack-tokenAnd expose Rack Gateway itself via Tailscale:
resource "kubernetes_ingress_v1" "rack_gateway_tailscale" {metadata {name = "rack-gateway"namespace = "rack-gateway"annotations = {"tailscale.com/expose" = "true""tailscale.com/hostname" = "gateway-production""tailscale.com/tags" = "tag:rack-gateway"}}spec {ingress_class_name = "tailscale"rule {host = "gateway-production.your-tailnet.ts.net"http {path {path = "/"path_type = "Prefix"backend {service {name = "rack-gateway"port { number = 8447 }}}}}}tls {hosts = ["gateway-production.your-tailnet.ts.net"]}}} -
Configure Tailscale ACLs
In your Tailscale admin console, set up ACLs to control who can access what:
{"acls": [{"action": "accept","src": ["group:developers"],"dst": ["tag:rack-gateway:443"]},{"action": "accept","src": ["tag:rack-gateway"],"dst": ["tag:convox-api:443"]}],"tagOwners": {"tag:convox-api": ["group:infrastructure"],"tag:rack-gateway": ["group:infrastructure"]}}
Verifying the Setup
Section titled “Verifying the Setup”Check that public access is disabled
Section titled “Check that public access is disabled”# Should timeout or return DNS errorcurl https://api.your-rack-domain.convox.cloud# Connection refused or timeout expectedVerify private access works
Section titled “Verify private access works”# Connect to Tailscale firsttailscale up
# Test Convox API via Tailscalecurl https://convox-api-production.your-tailnet.ts.net/system
# Test Rack Gateway via Tailscalecurl https://gateway-production.your-tailnet.ts.net/api/v1/healthConfigure the rack-gateway CLI
Section titled “Configure the rack-gateway CLI”# Login using the Tailscale hostnamerack-gateway login production https://gateway-production.your-tailnet.ts.net
# Verify commands workrack-gateway convox appsAlternative Private Network Options
Section titled “Alternative Private Network Options”While we recommend Tailscale for its simplicity, you can achieve private network access with other methods:
Pros:
- Zero-config mesh VPN
- Works across cloud providers
- Built-in ACLs and audit logging
- Easy to set up Kubernetes operator
Cons:
- Requires Tailscale subscription for teams
- External dependency
Pros:
- Native AWS service
- No external dependencies
- Low latency within AWS
Cons:
- AWS-only
- More complex setup
- Additional cost per endpoint
Pros:
- Works with existing corporate VPN
- No per-user setup required
Cons:
- Complex network configuration
- Requires VPN infrastructure
- Can be single point of failure
Pros:
- Simple concept
- Works with any network
Cons:
- Additional hop adds latency
- Requires SSH key management
- Less convenient for CLI usage
Security Benefits
Section titled “Security Benefits”With a fully private deployment, you achieve defense-in-depth:
| Layer | Protection |
|---|---|
| Network | API only accessible via private network |
| Authentication | Google Workspace OAuth via Rack Gateway |
| Authorization | RBAC controls what each user can do |
| Audit | Every action logged with user attribution |
| MFA | Additional verification for sensitive operations |
Even if an attacker obtains:
- Rack token alone → Can’t reach the API (network blocked)
- Tailscale access alone → Can’t authenticate (no OAuth session)
- OAuth session alone → Limited by RBAC permissions
- All of the above → Actions are logged and auditable
Next Steps
Section titled “Next Steps”- Terraform Infrastructure - Full Terraform setup guide
- S3 WORM Storage - Immutable audit log storage
- Production Checklist - Pre-launch security review