WireGuard Access to Digital Ocean DBs

End-to-End WireGuard & NGINX Proxy Setup Manual

This document provides a comprehensive, step-by-step guide to:

  • Install and configure WireGuard on a DigitalOcean Droplet (Public IP: 165.**.***.***)
  • Install and configure WireGuard on a Pop!_OS 22.04 laptop
  • Configure partial traffic routing so only 10.0.0.0/24 travels through WireGuard
  • Set up NGINX stream proxy to forward traffic to Redis and PostgreSQL over both the public interface and the WireGuard interface

By following this manual, you will be able to connect to your databases (Redis, PostgreSQL) via the WireGuard VPN (using IP 10.0.0.1) as well as the public IP (165.**.***.***) if needed.


1. Overview of the Setup

  • Droplet IP: 165.**.***.***
  • WireGuard (Server Interface) IP: 10.0.0.1/24
  • WireGuard (Laptop/Client Interface) IP: 10.0.0.2/24
  • Traffic to 10.0.0.x will go over the VPN; everything else goes over regular internet.
  • NGINX is configured to listen on:

    • The public IP (165.**.***.***)

    • The WireGuard IP (10.0.0.1)


    for both Redis and PostgreSQL proxies.

Note: If you are using DigitalOcean-managed databases, be sure to whitelist (add to “trusted sources”) the Droplet’s public IP (165.**.***.***) in the database control panel. Otherwise, the database will reject connections.


2. WireGuard Server Setup on the Droplet

2.1 System Preparation


  1. SSH into your Droplet:
    ssh root@165.**.***.***


  2. Update the system:
    sudo apt update && sudo apt upgrade -y


  3. Install WireGuard:
    sudo apt install wireguard -y

2.2 Generate Server Keys

  1. Create private and public keys:
  2. wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey

  3. View and save them (you will need the public key for the client):
    cat /etc/wireguard/privatekey
    cat /etc/wireguard/publickey

2.3 Server Configuration

  1. Create the /etc/wireguard/wg0.conf file:
    sudo nano /etc/wireguard/wg0.conf

  2. Place the following content (replace <server_private_key> with the private key you generated above):
    [Interface]
    Address = 10.0.0.1/24
    ListenPort = 51820
    PrivateKey = <server_private_key>


  3. Enable IP forwarding in /etc/sysctl.conf:
    sudo nano /etc/sysctl.conf

    # Uncomment or add:
    net.ipv4.ip_forward=1

    # Then apply:
    sudo sysctl -p


  4. Secure files and start WireGuard:
    sudo chmod 600 /etc/wireguard/{privatekey,wg0.conf}
    sudo systemctl enable wg-quick@wg0
    sudo systemctl start wg-quick@wg0


  5. Check WireGuard status:
    sudo wg show

    You should see wg0 with IP 10.0.0.1.

If you are using UFW, run:

sudo ufw allow 51820/udp

to open the WireGuard port.


3. WireGuard Client Setup on Pop!_OS (Laptop)

3.1 Install WireGuard

sudo apt update
sudo apt install wireguard

3.2 Generate Client Keys


  1. wg genkey | tee ~/client_privatekey | wg pubkey > ~/client_publickey


  2. Note these keys:
    cat ~/client_privatekey
    cat ~/client_publickey

3.3 Add the Laptop as a Peer on the Droplet

  1. SSH back into the droplet:
    ssh root@165.**.***.***

  2. Edit /etc/wireguard/wg0.conf to add a new peer. Replace <client_public_key> with the client’s ~/client_publickey:
    [Peer]
    PublicKey = <client_public_key>
    AllowedIPs = 10.0.0.2/32

  3. Restart WireGuard on the droplet:
    sudo systemctl restart wg-quick@wg0

3.4 Create the Client Configuration on Your Laptop


  1. sudo nano /etc/wireguard/wg0.conf

  2. Place the following content. Replace <client_private_key> and <server_public_key> with the actual keys you noted:
    [Interface]
    PrivateKey = <client_private_key>
    Address = 10.0.0.2/24
    # If routing ONLY 10.0.0.0/24 over the VPN, remove "DNS = 8.8.8.8" or route 8.8.8.8 as well.
    # DNS = 8.8.8.8

    [Peer]
    PublicKey = <server_public_key>
    Endpoint = 165.**.***.***:51820
    AllowedIPs = 10.0.0.0/24
    PersistentKeepalive = 25


  3. Secure the file and bring up the interface:
    sudo chmod 600 /etc/wireguard/wg0.conf
    sudo wg-quick up wg0


  4. Verify:
    wg show
    ping 10.0.0.1

    You should see successful pings to 10.0.0.1.

If using DNS = 8.8.8.8 in the client config and AllowedIPs is only 10.0.0.0/24, DNS lookups may break since 8.8.8.8 would be routed incorrectly. You can either remove the DNS line or add 8.8.8.8/32 to AllowedIPs and configure NAT on the droplet. For partial routing only, it’s usually easiest to remove DNS=8.8.8.8.


4. NGINX Stream Configuration (Redis & PostgreSQL) on the Droplet

We’ll configure NGINX stream blocks so that they listen on:

  • The Droplet’s public IP: 165.**.***.***
  • The Droplet’s WireGuard IP: 10.0.0.1

Then NGINX proxies traffic to DigitalOcean-managed Redis and PostgreSQL databases. Make sure you have whitelisted 165.**.***.*** in the DO database trusted sources.

4.1 Install NGINX (if not installed)

sudo apt update
sudo apt install nginx

Be sure you have stream module support. On Ubuntu, /etc/nginx/modules-enabled/50-mod-stream.conf typically loads it.

4.2 Example Stream Configuration

Below is an example /etc/nginx/streams-available/default (or a separate file if you prefer). It listens on ports for Redis and PostgreSQL, both public & WireGuard IPs.

############################
# nginx proxy for db forwarding

upstream redis_servers {
    server do-user-1459265-0.c.db.ondigitalocean.com:25061;
}

upstream dev_redis_servers {
    server do-user-1459265-0.i.db.ondigitalocean.com:25061;
}

upstream postgres_servers {
    server persistent-backup-do-user-1459265-0.i.db.ondigitalocean.com:25060;
}

upstream dev_postgres_servers {
    server persistent-backup-do-user-1459265-0.e.db.ondigitalocean.com:25060;
}

# Redis proxy (both public and WireGuard)
server {
    listen 165.**.***.***:6501;
    listen 10.0.0.1:6501;
    proxy_pass redis_servers;
    proxy_timeout 30s;
}

server {
    listen 165.**.***.***:7501;
    listen 10.0.0.1:7501;
    proxy_pass dev_redis_servers;
    proxy_timeout 30s;
}

# PostgreSQL proxy (both public and WireGuard)
server {
    listen 165.**.***.***:8501;
    listen 10.0.0.1:8501;
    # If DO Postgres requires traffic from the droplet's public IP:
    # proxy_bind 165.**.***.***;
    proxy_pass postgres_servers;
    proxy_timeout 30s;
}

server {
    listen 165.**.***.***:9501;
    listen 10.0.0.1:9501;
    # If DO Postgres requires traffic from the droplet's public IP:
    # proxy_bind 165.**.***.***;
    proxy_pass dev_postgres_servers;
    proxy_timeout 30s;
}

############################

Whitelist Note: If your managed Postgres instance requires traffic to originate from 165.**.***.***, uncomment proxy_bind 165.**.***.***; in the PostgreSQL blocks. Also ensure that 165.**.***.*** is in the database’s trusted sources. Otherwise, the DB will reject the connection.

4.3 Enable & Test the Configuration


  1. Link or copy the file into /etc/nginx/streams-enabled/ or ensure include /etc/nginx/streams-available/default; is in your main /etc/nginx/nginx.conf.

  2. Test the config:
    sudo nginx -t


  3. Reload/Restart NGINX:
    sudo service nginx restart


  4. Verify that NGINX is listening on both IPs:
    sudo netstat -tlnp | grep 6501
    sudo netstat -tlnp | grep 8501

    You should see references to both 165.**.***.*** and 10.0.0.1.

5. Connecting to Redis & PostgreSQL

5.1 Connect Over Public IP

  • Redis on 6501:
    redis-cli -h 165.**.***.*** -p 6501

  • Redis Dev on 7501:
    redis-cli -h 165.**.***.*** -p 7501

  • Postgres on 8501:
    psql -h 165.**.***.*** -p 8501 -U username -d dbname

  • Postgres Dev on 9501:
    psql -h 165.**.***.*** -p 9501 -U username -d dbname

5.2 Connect Over WireGuard IP

  • Redis on 6501:
    redis-cli -h 10.0.0.1 -p 6501

  • Redis Dev on 7501:
    redis-cli -h 10.0.0.1 -p 7501

  • Postgres on 8501:
    psql -h 10.0.0.1 -p 8501 -U username -d dbname

  • Postgres Dev on 9501:
    psql -h 10.0.0.1 -p 9501 -U username -d dbname

Connections arriving on 10.0.0.1 travel securely over the WireGuard tunnel. The droplet then proxies to DigitalOcean’s internal database endpoints. If the database requires traffic from 165.**.***.***, ensure you have proxy_bind 165.**.***.***; and that the DB has 165.**.***.*** whitelisted.


6. Caveats & Additional Notes

  • Firewall Rules: Ensure the droplet’s firewall (UFW or DO firewall) allows inbound connections on the ports you have configured (6501, 7501, 8501, 9501) if you need external access. If you only want VPN access, you can restrict these ports to your internal interface or the DO firewall can block them publicly.
  • DNS Over WireGuard: If you configure DNS=8.8.8.8 in WireGuard without also routing 8.8.8.8 or using NAT, DNS might break. Simply remove DNS=8.8.8.8 if only partial routing is desired.
  • Cloud Database Trust Settings: Remember to add 165.**.***.*** as a trusted source in the DigitalOcean database panel. If you forget, the DB connection will fail with “No route” or “Connection refused.”
  • Testing: If you run into issues, always check wg show (on both client and server), ip route (client), sudo netstat -tlnp | grep nginx (server), and the sudo journalctl -u wg-quick@wg0 / /var/log/nginx/error.log logs for details.

7. Conclusion

By following these steps, you achieve:

  • A secure WireGuard VPN where only 10.0.0.0/24 flows through the tunnel, ensuring normal Internet traffic remains direct.
  • An NGINX-based proxy that can forward Redis and Postgres connections from both 165.**.***.*** (public) and 10.0.0.1 (VPN) to the appropriate internal DO database instances.
  • A consistent environment that is simple for team members to replicate, given they have the correct keys, IPs, and whitelisted addresses.

End of Manual.