Guides

Private access

Connect Cloudflare Workers and human administrators to the same local PostgreSQL port without opening PostgreSQL to the public internet.

There are two separate paths:

User Path What stage-pg manages
Cloudflare Worker Hyperdrive → Workers VPC → Cloudflare Tunnel → PostgreSQL PostgreSQL, the local cloudflared process, and the token-file boundary.
Administrator Tailscale Serve → PostgreSQL PostgreSQL, the saved port, and the Serve command shape.

Cloudflare and Tailscale setup happens outside the CLI.

1. Find the saved port

After init, read port from the instance configuration. If you have jq installed:

jq '.port' ./stage-data/config.json

Use this same number everywhere. For example, if it is 55432, the local PostgreSQL origin is 127.0.0.1:55432.

2. Let Cloudflare Workers reach PostgreSQL

Create the external Cloudflare path

In Cloudflare, create or choose a Tunnel and a Workers VPC TCP service. Configure the service to use:

  • the Tunnel that runs on the database host;
  • the saved PostgreSQL port;
  • PostgreSQL as the application protocol;
  • the local origin address, normally 127.0.0.1 from the host-side Tunnel configuration.

Point the Tunnel's TCP service at the same local port:

tcp://127.0.0.1:<saved-port>

Then create a Hyperdrive binding that uses the Workers VPC service and the stage_app database credentials.

Give stage-pg the token

Store the Tunnel token in a local file that is readable only by the account running stage-pg:

chmod 600 /etc/stage-pg/cloudflared-token

Pass the file path during initialization:

stage-pg init ./stage-data \
  --tls-cert /etc/stage-pg/postgres.crt \
  --tls-key /etc/stage-pg/postgres.key \
  --cloudflare-token-file /etc/stage-pg/cloudflared-token

When run starts, stage-pg starts the local cloudflared child with that token file. It does not print the token or create the Tunnel.

Keep PostgreSQL TLS enabled

The Tunnel encrypts its own connection to Cloudflare, but it does not replace PostgreSQL TLS. Hyperdrive/Workers VPC must be able to establish a TLS PostgreSQL session with the origin.

Use a certificate and key that the PostgreSQL client path trusts and that match the hostname and TLS settings you choose. stage-pg only consumes the certificate and key; it does not issue or renew them.

3. Let administrators connect through Tailscale

Tailscale Serve is configured separately. Use the saved port on both sides of the forwarder:

tailscale serve --bg \
  --tcp=<saved-port> \
  tcp://127.0.0.1:<saved-port>

Restrict access to the port with your tailnet policy. stage-pg provides the command shape but does not run it, check Serve status, or change grants.

An administrator can then use an ordinary PostgreSQL client. Require TLS in the client:

PGSSLMODE=require psql \
  --host <tailnet-hostname> \
  --port <saved-port> \
  --username stage_admin \
  --dbname staging

The client will prompt for the administrator password. Keep that password in the protected instance secret store.

What run checks

run checks local files, executables, permissions, and port ownership. It does not wait for Cloudflare or Tailscale to report a healthy connection before starting.

Note

Test the complete Worker and administrator paths separately after configuring the external services. A successful local run only proves that the local processes started.