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.
- The public IP (
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
-
SSH into your Droplet:
ssh root@165.**.***.***
-
Update the system:
sudo apt update && sudo apt upgrade -y
-
Install WireGuard:
sudo apt install wireguard -y
2.2 Generate Server Keys
- Create private and public keys:
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
-
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
- Create the
/etc/wireguard/wg0.conf
file:
sudo nano /etc/wireguard/wg0.conf
- 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>
-
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
-
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
-
Check WireGuard status:
sudo wg show
You should seewg0
with IP10.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
-
wg genkey | tee ~/client_privatekey | wg pubkey > ~/client_publickey
-
Note these keys:
cat ~/client_privatekey
cat ~/client_publickey
3.3 Add the Laptop as a Peer on the Droplet
- SSH back into the droplet:
ssh root@165.**.***.***
- 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
- Restart WireGuard on the droplet:
sudo systemctl restart wg-quick@wg0
3.4 Create the Client Configuration on Your Laptop
-
sudo nano /etc/wireguard/wg0.conf
- 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
-
Secure the file and bring up the interface:
sudo chmod 600 /etc/wireguard/wg0.conf
sudo wg-quick up wg0
-
Verify:
wg show
ping 10.0.0.1
You should see successful pings to10.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
-
Link or copy the file into/etc/nginx/streams-enabled/
or ensureinclude /etc/nginx/streams-available/default;
is in your main/etc/nginx/nginx.conf
.
-
Test the config:
sudo nginx -t
-
Reload/Restart NGINX:
sudo service nginx restart
-
Verify that NGINX is listening on both IPs:
sudo netstat -tlnp | grep 6501
sudo netstat -tlnp | grep 8501
You should see references to both165.**.***.***
and10.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 routing8.8.8.8
or using NAT, DNS might break. Simply removeDNS=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 thesudo 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) and10.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.