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 applyforcloudflared_tunnel.tfhas been run (creates tunnel, WARP enrollment app, device profile, and Access app)cloudflaredArgo CD Application is synced and healthy (kubectl -n cloudflared get podsshows 2/2 Running)- Your GitHub account is a member of the
BackendorInfrateam in theunipukaorg (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.
- Download Cloudflare One Client for your OS and install it.
- Open WARP → click the hamburger menu → Preferences → Account → Login with Cloudflare Zero Trust
- Enter the team domain:
unipuka(→https://unipuka.cloudflareaccess.com) - Authenticate via GitHub — you must be a member of the
BackendorInfrateam in theunipukaorg - Confirm WARP shows Connected in the status bar
Verify the device profile applied:
- WARP icon → Preferences → Split Tunnels — mode should be Include Only
- The Include list shows all 6 DB
/32IPs (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¶
- Go to cloud.digitalocean.com → Databases → select any MySQL cluster
- Under Connection Details → click Download CA certificate
- 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¶
- Open DataGrip → + → Data Source → MySQL
- 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 |
- Go to the SSH/SSL tab → Use SSL → CA file: point to
do-ca.crtfrom Step 2 - Set Mode to Require (or Verify CA for strongest validation)
- 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.
- Open DataGrip → + → Data Source → Redis
- 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 |
- 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-careturns no cert for Valkey clusters.
- Click Test Connection — should succeed with WARP connected
Step 4: Connect with TablePlus (MySQL + Valkey)¶
MySQL¶
- TablePlus → + → MySQL
- 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 |
- SSL tab → Enable SSL → CA Cert: select
do-ca.crt - Leave SSL Mode as Require or Verify CA
- Test → should succeed
Valkey (Redis-compatible)¶
- TablePlus → + → Redis
- 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 |
- SSL → set mode to SSL_VERIFY_NONE (DO does not issue a CA cert for Valkey)
- 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¶
-
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.
-
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
- Verify ExternalSecret synced:
- Check NetworkPolicy allows egress from cloudflared pods:
- 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, runterraform applyinoep-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.crtmust 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
mysqlCLI: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-accesstunnel. 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:
- In
unipuka-infra-do/oep-infra/cloudflared_tunnel.tf, uncomment themansety-prd-*andus-prd-*entries inlocal.db_tunnel_routes terraform apply— adds 4 new tunnel routes- Verify connectivity:
nc -vz 10.10.0.4 25060etc. with WARP connected - Remove the static IP allowlist: set
operator_trusted_ips = []interraform.tfvarsand re-runterraform apply. Theip_addrfirewall rules are removed from all 6 MySQL + Valkey clusters.
After Phase 5, direct public-endpoint access from un-enrolled machines is blocked.