VPS Tutorials
VPS Multi-IP Configuration Tutorial: Add a Secondary IP, Specify Outbound Source Address, Nginx Binding (2026)
Multi-IP is not just "write the address down and you're done." You first need to figure out whether the provider gave you a single additional IP or a whole /29 route; then correctly add the secondary IP to the network interface and make it persistent; finally, if you want "a certain service to use a certain IP for outbound," you need binding or policy routing. This article gives you a practical workflow from zero to working, with commands.

The reason you buy a multi-IP VPS is usually quite simple:
- Run multiple sites on the same machine, hoping "site A / site B" each get their own independent IP
- Run a mail server, needing a clean IP + the ability to configure PTR (reverse DNS)
- Run crawlers/API requests, wanting to spread outbound IPs
- You don't want to explain every time that "these businesses are actually on the same VPS"
But the most annoying parts of multi-IP are also very consistent:
- The secondary IP is added, but it still can't be pinged from outside
- Outbound always goes through the primary IP (even though you clearly want to use the secondary IP)
- Nginx only listens on one IPv4 address, and the other IP times out
This article is written with the goal of "being actionable": follow along and you can get the secondary IP working, make it persistent, and control the outbound source address.
Providers usually give multi-IP in two forms:
- A single additional IPv4 (/32)
- You get: one extra IPv4 + instructions to "add it to eth0"
- A whole subnet (/29, /28) routed to you
- You get: a public subnet + gateway/routing instructions
These two configuration methods share common points, but "choosing the outbound source IP" and "routing table" handling will differ.
You can first print out your current network state:
ip -4 addr
ip -4 route
Focus on two things:
- How the primary IP is configured (DHCP or static)
- What the default route's gateway is
1) Don't rush to persist yet: temporarily add a secondary IP with the ip command (fastest verification)
Assume the secondary IP you got is 203.0.113.10/32 and the network interface is eth0.
sudo ip addr add 203.0.113.10/32 dev eth0
ip -4 addr show dev eth0
This step only "attaches the IP to the network interface" and won't change your default route.
Verify outbound from the VPS itself:
curl -4 -s https://api.ipify.org && echo
Then verify "outbound with a specified source address" (this step is key):
curl -4 --interface 203.0.113.10 -s https://api.ipify.org && echo
- If the second one also returns
203.0.113.10: it means your secondary IP can at least do outbound - If it errors (e.g.
Cannot assign requested address/ timeout): it means the secondary IP isn't truly usable yet, so don't rush to write config files
Many providers' IPs are "routed to you," and whether inbound works also depends on your local firewall/service listening. Get outbound working first, and you'll feel much more at ease.
Which category your system falls into is usually determined by these three commands:
ls -l /etc/netplan/ 2>/dev/null || true
ls -l /etc/network/interfaces 2>/dev/null || true
nmcli -v 2>/dev/null || true
Open the existing config (the filename may differ):
sudo ls -l /etc/netplan/
sudo cat /etc/netplan/*.yaml
Add the secondary IP in addresses: (example):
network:
version: 2
ethernets:
eth0:
dhcp4: true
addresses:
- 203.0.113.10/32
Apply:
sudo netplan apply
You can use the most stable post-up approach (avoid changing how your primary IP is set):
auto eth0
iface eth0 inet dhcp
# add extra IPv4
post-up ip addr add 203.0.113.10/32 dev eth0 || true
pre-down ip addr del 203.0.113.10/32 dev eth0 || true
Restart networking:
sudo systemctl restart networking
# 先找到连接名
nmcli con show
# 假设连接名是 "System eth0"
sudo nmcli con mod "System eth0" +ipv4.addresses "203.0.113.10/32"
sudo nmcli con up "System eth0"
For example, in Nginx you only wrote:
listen 80;
Then it may only listen on 0.0.0.0:80 (usually fine), but if you wrote a specific IP, make sure you write both.
Example: make the site accessible on both the primary IP + secondary IP:
server {
listen 203.0.113.1:80;
listen 203.0.113.10:80;
server_name example.com;
location / { return 200 "ok\n"; }
}
Reload:
sudo nginx -t
sudo systemctl reload nginx
The simplest self-check:
sudo ss -lntp | head
Confirm the service is listening, then check the firewall rules.
If you haven't done basic hardening yet, it's recommended to go through this article first (don't turn multi-IP into "multiple entry points getting scanned"):
This is "the most real pitfall of multi-IP."
There are two levels of solutions:
- Simple and direct: let the program bind the source address itself (solves 80% of needs)
- More general: use policy routing so that traffic "going out from a certain IP" uses a separate routing table
The next two sections cover each.
Many services/tools support binding a source address.
curl -4 --interface 203.0.113.10 -s https://api.ipify.org && echo
ssh -b 203.0.113.10 user@target-host
- Nginx can bind a source IP when reverse-proxying to upstreams
- Your program (Go/Node/Python) can also bind a local address when making requests
As long as you can bind at the application layer, you basically don't need to touch policy routing.
Applicable scenario: you don't want to manually bind every program, or you want to use a certain IP as a "dedicated outbound IP."
Assume:
- Primary IP:
203.0.113.1 - Secondary IP:
203.0.113.10 - Default gateway:
203.0.113.254 - Network interface:
eth0
ip -4 route show dev eth0 scope link
You'll see something like:
203.0.113.0/24 dev eth0 proto kernel scope link src 203.0.113.1
Remember this subnet (e.g. 203.0.113.0/24).
# 1) 新建路由表
sudo bash -lc 'echo "100 out-ip2" >> /etc/iproute2/rt_tables'
# 2) 给新表加直连网段(让它能到网关)
sudo ip route add 203.0.113.0/24 dev eth0 scope link table out-ip2
# 3) 新表默认路由,指定 src
sudo ip route add default via 203.0.113.254 dev eth0 src 203.0.113.10 table out-ip2
# 4) 规则:从 203.0.113.10 发出的流量走 out-ip2 表
sudo ip rule add from 203.0.113.10/32 table out-ip2
# 查看
ip rule
ip route show table out-ip2
Verify:
curl -4 --interface 203.0.113.10 -s https://api.ipify.org && echo
Note: different providers' gateways/subnets may not look like the above. As long as you follow the idea of "also writing the scope link entry into the new table," it will basically work.
This varies a lot across distributions.
- You can first persist it with a "startup script + systemd service" approach (least likely to be overwritten by netplan/cloud-init)
- Or write the rules into a network hook per distribution
If your main goal is "usable for beginners," it's recommended to get 5.2 working first, then decide how to persist it.
Many people ultimately want multi-IP for mail.
But the biggest blockers for self-hosted mail services are often not Postfix, but:
- Port 25
- IP reputation
- PTR/reverse DNS
If you're going for mail specifically, it's strongly recommended to go through this article as a "pitfall checklist":
- VPS Security Hardening Guide: SSH + Firewall + Fail2Ban
- Can't connect to your VPS? SSH login troubleshooting solutions
- How to troubleshoot slow VPS network: from speed tests to packet loss localization
- VPS website won't open? Common problem diagnosis and fixes
- Building a Mail Server on a VPS (Docker Mailserver)