This article is part of a series.
View all 7 parts
- Part 1 – Setting up a Raspberry Pi NAS
- Part 2 – Secure Remote Postgres with Cloudflare Tunnel + Access
- Part 3 – Securely Expose Your Raspberry Pi 5 with Cloudflare Tunnel
- Part 4 – Nginx Reverse Proxy on Raspberry Pi (Ubuntu Server)
- Part 5 – Add HTTPS to Your Raspberry Pi with Nginx and Cloudflare
- Part 6 – Switch from Cloudflare Origin Certificates to Let’s Encrypt on Raspberry Pi with Cloudflare Tunnel
- Part 7 – This Article
This guide walks through exposing a PostgreSQL server running on your local network securely over the internet using Cloudflare Tunnel and optionally a reverse proxy. The PostgreSQL server can live on a Raspberry Pi or any other machine in your home lab.
1. Prerequisites
- PostgreSQL server (e.g. on Raspberry Pi or Ubuntu machine)
- Static IP or DHCP reservation for the host
-
Cloudflare account with a domain (e.g.
lolzlab.com) -
cloudflaredinstalled and configured on the local network - PostgreSQL server already configured and listening on a LAN IP
2. Configure PostgreSQL to Accept Cloudflared Traffic Only
On the machine running PostgreSQL:
A. Edit
postgresql.conf
listen_addresses = '192.168.1.104' # Only listen to cloudflared host's IP
B. Edit
pg_hba.conf
# Only allow local cloudflared machine
host all all 192.168.1.100/32 scram-sha-256
Adjust the IPs to match your network:
-
192.168.1.104= Postgres server IP -
192.168.1.100= Cloudflared tunnel host IP
Then:
sudo systemctl restart postgresql
3. Configure Cloudflared for TCP Tunneling
Edit
/etc/cloudflared/config.yml
on the machine running the tunnel:
tunnel: lolz_at_home
credentials-file: /home/ladvien/.cloudflared/<UUID>.json
ingress:
- hostname: postgres.lolzlab.com
service: tcp://192.168.1.104:5432
- service: http_status:404
Then restart the tunnel:
sudo systemctl restart cloudflared
4. Register DNS with Cloudflare
Use this command to create a proxied DNS record:
cloudflared tunnel route dns lolz_at_home postgres.lolzlab.com
Or manually create a
CNAME
record:
-
Name:
postgres -
Type:
CNAME -
Target:
<UUID>.cfargotunnel.com - Proxy: Enabled (orange cloud)
5. Test the Tunnel from a Remote Machine
A. Install Cloudflared
brew install cloudflared # macOS
B. Run a local tunnel
cloudflared access tcp --hostname postgres.lolzlab.com --url localhost:6543
This maps
postgres.lolzlab.com
to
localhost:6543
.
C. Connect to PostgreSQL via
psql
psql "postgresql://agent:*7CLejClrUXmjf*G@localhost:6543/agent_sandbox"
You’re now securely connected to a remote Postgres database tunneled through Cloudflare!
6. Hardening (Recommended)
- Enable Cloudflare Access to restrict public usage
-
Switch authentication to
scram-sha-256 -
Avoid
0.0.0.0/0inpg_hba.conf -
Set firewall rules to block direct access to port
5432
sudo ufw allow from 192.168.1.100 to any port 5432 proto tcp
sudo ufw deny in to any port 5432
7. Optional: GUI Clients
You can use TablePlus, Postico, DBeaver, or DataGrip:
-
Host:
localhost -
Port:
6543 -
User:
agent -
Database:
agent_sandbox -
Tunnel:
Must be running (
cloudflared access tcp ...)
8. Troubleshooting
-
Port in use? → Use a different local port like
6543 -
Role does not exist? →
CREATE ROLE agent WITH LOGIN PASSWORD '...' -
Tunnel not forwarding? → Check
cloudflaredlogs:sudo journalctl -u cloudflared -
Forgot DNS? → Re-run
cloudflared tunnel route dns ...
This setup avoids exposing your home IP and eliminates the need for port-forwarding. It’s production-safe, encrypted, and cloud-hardened — and works great for AI, IoT, or self-hosted apps needing Postgres access anywhere.