FeatherDB

Connect to a containerized database

A Postgres inside a Docker container usually has no public port — good. This page is how to reach it anyway, without changing that.

The short version: never expose 5432 to the internet. Pick the row that matches where the container runs; every path below works with FeatherDB as shipped.

Where the container runsThe pathFeatherDB connection
Your own VPS (Coolify, plain Docker)loopback port + SSHSSH tunnel
A PaaS with a CLI (Fly, Railway, GCP, AWS)the provider's tunnel CLIDirect → 127.0.0.1, TLS disable
Kuberneteskubectl port-forwardDirect → 127.0.0.1, TLS disable
A managed database productthe provider's endpointDirect over TLS

Your own VPS (Coolify, Docker Compose)

The container network is private and should stay that way. Publish the database port on the server's loopback only — it becomes reachable from the server itself and from nowhere else — then let SSH carry you there. In the service's compose file:

services:
  postgres:
    ports:
      - "127.0.0.1:5433:5432"   # loopback only — invisible to the internet

Redeploy, then in FeatherDB add an SSH tunnel connection: your server as the SSH host, and 127.0.0.1 port 5433 as the database host as seen from the server. Nothing new is exposed; the SSH key is the only door.

In Coolify specifically, avoid the database resource's “make it publicly available” switch — it binds the port on every interface, which is exactly the thing this page exists to avoid.

A platform you don't manage (Fly, Railway, GCP, AWS, …)

No SSH access to the host — but every serious platform ships a tunnel in its CLI. It opens a port on your Mac and carries the traffic inside your authenticated platform session:

fly proxy 5433:5432 -a my-db          # Fly.io
railway connect postgres               # Railway
cloud-sql-proxy INSTANCE --port 5433   # Google Cloud SQL
aws ssm start-session …                # AWS, via SSM port forwarding

Then add a Direct connection to host 127.0.0.1, the forwarded port, and set TLS to disable (local proxy/tunnel only). That setting exists for exactly this shape: the tunnel itself carries the encryption, the local leg is plaintext, and a database that has no TLS configured would refuse an encrypted handshake outright.

Kubernetes

kubectl port-forward svc/postgres 5433:5432

Same as above: Direct → 127.0.0.1:5433, TLS disable. The forward lives as long as the kubectl process does.

Long-lived setups: an overlay network

If you connect to the same stack every day, a mesh VPN (Tailscale, WireGuard) is the low-friction path: run its agent as a sidecar next to the database and the container gets a private IP only your machines can reach. Connect Direct to that IP — no public port, no CLI to keep running.

Managed databases

Supabase, Neon, RDS and friends hand you a public endpoint on purpose — TLS required, strong auth, a pooler in front. That is not the risky kind of exposure; it is the product. Use a Direct connection with TLS require, or verify-full when the provider gives you a CA to pin.

If you truly must expose a port

No CLI tunnel, no sidecar, no managed endpoint — rare, but it happens. Then do it the defensible way: TLS on the server (verify-full from FeatherDB), scram-sha-256 auth, and a firewall allowlist holding exactly your IP. A bare containerized Postgres published on 0.0.0.0:5432 with a password as its only layer is the one configuration this page is written against.

← featherdb.dev