Skip to content

Connect to Managed Databases Locally

Access DO-managed MySQL and Valkey from your local machine via Cloudflare Zero Trust. The tunnel connector (cloudflared) runs in DOKS and exposes DB private IPs to WARP-enrolled devices. No static IP whitelisting required.


Prerequisites

  • terraform apply for cloudflared_tunnel.tf has been run (creates tunnel, WARP enrollment app, device profile, and Access app)
  • cloudflared Argo CD Application is synced and healthy (kubectl -n cloudflared get pods shows 2/2 Running)
  • Your GitHub account is a member of the Backend or Infra team in the unipuka org (verify here)

DB connection details

Tenant DB Private IP Port TLS
oep-stg MySQL 10.10.0.5 25060 VERIFY_CA
oep-stg Valkey 10.10.0.10 25061 TLS
mansety-prd MySQL 10.10.0.4 25060 VERIFY_CA
mansety-prd Valkey 10.10.0.11 25061 TLS
us-prd MySQL 10.10.0.6 25060 VERIFY_CA
us-prd Valkey 10.10.0.12 25061 TLS

Credentials: see Doppler oep.<env>DB_USERNAME, DB_PASSWORD, REDIS_PASSWORD.


Step 1: Install and enroll the Cloudflare One (WARP) client

The WARP enrollment gate (cloudflare_zero_trust_access_application.warp_enrollment) is managed by Terraform and must be applied before enrollment works.

  1. Download Cloudflare One Client for your OS and install it.
  2. Open WARP → click the hamburger menu → PreferencesAccountLogin with Cloudflare Zero Trust
  3. Enter the team domain: unipuka (→ https://unipuka.cloudflareaccess.com)
  4. Authenticate via GitHub — you must be a member of the Backend or Infra team in the unipuka org
  5. Confirm WARP shows Connected in the status bar

Verify the device profile applied:

  1. WARP icon → PreferencesSplit Tunnels — mode should be Include Only
  2. The Include list shows all 6 DB /32 IPs (10.10.0.4, 10.10.0.5, 10.10.0.6, 10.10.0.10, 10.10.0.11, 10.10.0.12)

Quick connectivity test (with WARP connected):

nc -vz 10.10.0.5 25060   # oep-stg MySQL — should print "succeeded"
nc -vz 10.10.0.10 25061  # oep-stg Valkey — should print "succeeded"

Disconnect WARP and run the same commands — they must fail (connection refused / timed out).


Step 2: Obtain the DO CA certificate (MySQL only)

DO-managed MySQL uses TLS with a custom DO internal CA. You need this certificate to connect with VERIFY_CA mode. Valkey/Redis does not use a CA cert — DO does not issue one for Valkey clusters, and connections use TLS without certificate verification (see Steps 3 and 4 for Valkey-specific settings).

Option A — DO control panel

  1. Go to cloud.digitalocean.comDatabases → select any MySQL cluster
  2. Under Connection Details → click Download CA certificate
  3. Save as do-ca.crt

Option B — doctl

# Use a MySQL cluster UUID — Valkey clusters return <nil> for this command
doctl databases get-ca <mysql-cluster-id> --format CACert --no-header > do-ca.crt

MySQL cluster IDs:

Tenant MySQL cluster ID
oep-stg 1760ea21-d142-4bb2-9216-2f9da12043fa
mansety-prd 488c824a-816c-41f2-a195-aaa7946c1b4c
us-prd fa6eacc4-bb2c-4212-bc48-4ad79c4e7a09

Option C — Terraform output (requires oep-infra access)

cd unipuka-infra-do/oep-infra
direnv exec . doppler run --config base -- \
  terraform output -json | jq -r '.tenant_mysql_ca_cert.value["oep-stg"]' > do-ca.crt

Step 3: Connect with DataGrip (MySQL + Valkey)

MySQL

  1. Open DataGrip → +Data SourceMySQL
  2. Fill in the connection:
Field Value
Host 10.10.0.5 (or the target tenant's MySQL IP)
Port 25060
Database mansetk_production (oep-stg / mansety-prd) or us_production (us-prd)
User value of DB_USERNAME from Doppler
Password value of DB_PASSWORD from Doppler
  1. Go to the SSH/SSL tab → Use SSLCA file: point to do-ca.crt from Step 2
  2. Set Mode to Require (or Verify CA for strongest validation)
  3. Click Test Connection — should succeed with WARP connected

If you see SSL connection error: Unable to get local issuer certificate, double-check the CA file path and that the file is not empty.

Valkey (Redis-compatible)

DataGrip supports Redis natively since 2023.1.

  1. Open DataGrip → +Data SourceRedis
  2. Fill in the connection:
Field Value
Connection type Standalone
Host 10.10.0.10 (oep-stg) / 10.10.0.11 (mansety-prd) / 10.10.0.12 (us-prd)
Port 25061
User default
Password value of REDIS_PASSWORD from Doppler
  1. Click Advanced and set the following properties:
Property Value
ssl true
verifyConnectionMode false
verifyServerCertificate false

No CA cert needed — Valkey's TLS cert verification is skipped because doctl databases get-ca returns no cert for Valkey clusters.

  1. Click Test Connection — should succeed with WARP connected

Step 4: Connect with TablePlus (MySQL + Valkey)

MySQL

  1. TablePlus → +MySQL
  2. Connection settings:
Field Value
Host 10.10.0.5 (or target tenant MySQL IP)
Port 25060
Database mansetk_production or us_production
User DB_USERNAME from Doppler
Password DB_PASSWORD from Doppler
  1. SSL tab → Enable SSLCA Cert: select do-ca.crt
  2. Leave SSL Mode as Require or Verify CA
  3. Test → should succeed

Valkey (Redis-compatible)

  1. TablePlus → +Redis
  2. Connection settings:
Field Value
Host 10.10.0.10 (oep-stg) / 10.10.0.11 (mansety-prd) / 10.10.0.12 (us-prd)
Port 25061
User default
Password REDIS_PASSWORD from Doppler
  1. SSL → set mode to SSL_VERIFY_NONE (DO does not issue a CA cert for Valkey)
  2. Test → should succeed

redis-cli alternative

# Install: brew install redis
# --tls --insecure: Valkey uses TLS but no CA cert is available via DO API
redis-cli -h 10.10.0.10 -p 25061 --tls --insecure -a "$REDIS_PASSWORD" ping
# Expected output: PONG

Troubleshooting

Connection times out even with WARP connected

  1. Confirm the device profile is applied: WARP → Preferences → Split Tunnels → mode must be Include Only with the DB IPs listed. If mode is Exclude or empty, the device profile didn't apply. Re-enroll or check Zero Trust > Settings > WARP Client > Device enrollment permissions.

  2. Check tunnel health: CF dashboard → Zero Trust → Networks → Tunnels → oep-db-access → status must be HEALTHY. If DOWN: check cloudflared pods:

kubectl -n cloudflared get pods
kubectl -n cloudflared logs -l app.kubernetes.io/name=cloudflared --tail=50
  1. Verify ExternalSecret synced:
kubectl -n cloudflared get externalsecret cloudflared-tunnel-token
# STATUS should be SecretSynced
  1. Check NetworkPolicy allows egress from cloudflared pods:
kubectl -n cloudflared describe netpol
  1. Verify private route exists for the target IP: CF dashboard → Zero Trust → Networks → Routes → filter by tunnel oep-db-access. If the oep-stg routes are missing, run terraform apply in oep-infra/.

SSL: CERTIFICATE_VERIFY_FAILED or TLS errors

  • Make sure you are using the CA certificate for the correct DO account/region. The cert from do-ca.crt must match the issuer on the DB cluster.
  • In DataGrip, set SSL mode to Require (not Verify CA) if you want to skip hostname verification (the private IP won't match the DO-issued hostname).
  • In mysql CLI: mysql --ssl-ca=do-ca.crt --ssl-mode=VERIFY_CA -h 10.10.0.5 -P 25060 -u app -p

WARP disconnects frequently

  • Go to WARP → Preferences → Connection → Gateway with DoH mode (not Proxy).
  • Check if any corporate firewall blocks UDP 7844 (cloudflared's preferred port). cloudflared falls back to TCP 7844 automatically if QUIC is blocked.

Access logs / audit trail

Network sessions are recorded in CF Zero Trust → Logs → Network. Filter by destination IP (10.10.0.x) to see who connected to which DB.


CLI fallback: cloudflared access tcp

If you cannot run the WARP client (e.g. managed device policy restrictions), you can create a local TCP proxy per-session using the cloudflared CLI. This requires a public hostname route to be configured in the tunnel (separate from the private-network routes — not set up by default).

Future enhancement. The commands below are hypothetical placeholders. A public hostname route for the DB host must first be configured in the oep-db-access tunnel. Contact the platform team to set this up if needed.

# Example for future setup — NOT currently functional.
# Step 1: Install cloudflared
brew install cloudflare/cloudflare/cloudflared

# Step 2: Authenticate once against the Access app
cloudflared access login https://db-access.unipuka.app  # hostname TBD

# Step 3: Start local proxy (port 3306 on localhost → MySQL via CF tunnel)
# Requires a public hostname route to be configured first.
cloudflared access tcp --hostname db-access.unipuka.app --url localhost:3306  # hostname TBD

If configured, connect DataGrip / TablePlus to localhost:3306 without SSL.


Phase 5: Expanding access to mansety-prd + us-prd

After verifying oep-stg end-to-end (Phase 4), a platform admin activates production routes:

  1. In unipuka-infra-do/oep-infra/cloudflared_tunnel.tf, uncomment the mansety-prd-* and us-prd-* entries in local.db_tunnel_routes
  2. terraform apply — adds 4 new tunnel routes
  3. Verify connectivity: nc -vz 10.10.0.4 25060 etc. with WARP connected
  4. Remove the static IP allowlist: set operator_trusted_ips = [] in terraform.tfvars and re-run terraform apply. The ip_addr firewall rules are removed from all 6 MySQL + Valkey clusters.

After Phase 5, direct public-endpoint access from un-enrolled machines is blocked.