Building off what Joe said, here is the procedure that took me about four hours and worked first time out to Change a Debian 12 Virtualmin Server to a New Static IP Address:
This procedure assumes Debian 12 uses a static IPv4 address in /etc/network/interfaces. It also assumes the new IP address and gateway have already been tested and are working.
Gather the Current Network Information
Before changing anything, determine exactly how Debian currently handles networking.
Run:
echo "===== HOSTNAME ====="
hostname
hostname -f
echo
echo "===== IP ADDRESSES ====="
ip -br addr
echo
echo "===== ROUTES ====="
ip route
echo
echo "===== /etc/network/interfaces ====="
cat /etc/network/interfaces
echo
echo "===== NETWORK SERVICES ====="
systemctl is-active networking
systemctl is-active systemd-networkd
systemctl is-active NetworkManager
echo
echo "===== DNS CONFIGURATION ====="
cat /etc/resolv.conf
echo
echo "===== HOSTS FILE ====="
cat /etc/hosts
A typical minimal Debian Virtualmin installation may use the traditional /etc/network/interfaces configuration. However, verify this rather than assuming it.
If NetworkManager or systemd-networkd manages the interface, this procedure will need adjustment.
Identify the Network Values
Before continuing, write down these values:
- Current server IPv4 address
- Current CIDR prefix, such as
/24, /26, or /29
- Current gateway
- New server IPv4 address
- New CIDR prefix
- New gateway
- Physical network interface, such as
eno1
Do not confuse the gateway with the network address.
For example, a /29 contains eight addresses. One is the network address, one is the broadcast address, and the others fall within the usable range. The Internet provider may reserve one usable address as its gateway.
Determine What Virtualmin Uses
Find the virtual servers using the old address:
virtualmin list-domains --ip OLD_IP --multiline
Replace OLD_IP with the server’s existing IPv4 address.
Next, find references to that address in Virtualmin and Apache:
grep -RFn 'OLD_IP' /etc/webmin/virtual-server 2>/dev/null
grep -RFn 'OLD_IP' /etc/apache2 2>/dev/null
Apache installations managed by Virtualmin often have <VirtualHost> entries containing the actual server IP address. Do not manually edit all of those files. Virtualmin can update them later.
Look for Other Hard-Coded References
Check other important services before the move:
grep -RFn 'OLD_IP' \
/etc/network \
/etc/hosts \
/etc/postfix \
/etc/dovecot \
/etc/firewalld \
/etc/fail2ban \
/etc/nftables.conf \
2>/dev/null
Also see whether any running services bind specifically to the old IP:
ss -lntup | grep 'OLD_IP'
Services such as BIND or Network Time Protocol may appear here simply because they listen on every configured interface.
If necessary, inspect their configuration to determine whether the address is actually hard-coded.
Check Fail2Ban
If the server uses Fail2Ban, check its trusted-address settings:
grep -RniE 'ignoreip' /etc/fail2ban 2>/dev/null
An existing administrator network may appear in an ignoreip line.
If the new management network should also be trusted, add it before the migration. Keeping both the old and new management networks temporarily can make the transition safer.
Check FirewallD
If FirewallD is installed, inspect it:
systemctl is-active firewalld
firewall-cmd --get-default-zone
firewall-cmd --get-active-zones
firewall-cmd --get-zone-of-interface=eno1
ZONE=$(firewall-cmd --get-default-zone)
firewall-cmd --zone="$ZONE" --list-all
Replace eno1 if the server uses another interface.
Make sure SSH, Webmin, HTTP, HTTPS, and any other required services will remain reachable from the new network.
Test the New Network First
When possible, test the new IP address on another computer before moving the Virtualmin server.
Configure the test computer with:
IP address: NEW_IP
Subnet/CIDR: NEW_PREFIX
Default gateway: NEW_GATEWAY
DNS servers: desired resolvers
Verify that it can reach:
- The new gateway
- A known Internet IP address
- A hostname through DNS
This eliminates many router, switch, provider, and cabling questions before touching the production server.
Back Up Debian’s Network Configuration
Before editing anything, save the existing files:
cp -a /etc/network/interfaces /etc/network/interfaces.before-ip-change
cp -a /etc/hosts /etc/hosts.before-ip-change
These copies provide a simple rollback if something goes wrong.
Change the Debian Network Configuration
Edit:
/etc/network/interfaces
A static configuration will generally contain lines similar to:
allow-hotplug eno1
iface eno1 inet static
address OLD_IP/OLD_PREFIX
gateway OLD_GATEWAY
dns-nameservers DNS_SERVER_1 DNS_SERVER_2
dns-domain example.com
Change only the address and gateway information:
allow-hotplug eno1
iface eno1 inet static
address NEW_IP/NEW_PREFIX
gateway NEW_GATEWAY
dns-nameservers DNS_SERVER_1 DNS_SERVER_2
dns-domain example.com
Do not restart networking yet if the server is still physically attached to the old network.
Update /etc/hosts
If /etc/hosts contains the old server address, update it as well.
For example:
OLD_IP server.example.com server
becomes:
NEW_IP server.example.com server
Verify both files carefully before proceeding:
cat /etc/network/interfaces
cat /etc/hosts
Shut Down and Move the Server
If a reboot is acceptable, a clean shutdown provides a straightforward cutover.
Run:
shutdown -h now
After the machine powers off:
- Disconnect it from the old network.
- Connect it to the new network.
- Power it back on.
The server should now boot directly with its permanent new configuration.
Verify Debian Networking
Connect to the server using its new IP address.
Then run:
ip -br addr
ip route
Verify that the expected new address appears and that the default route uses the new gateway.
Test the gateway:
ping -c 4 NEW_GATEWAY
Test Internet connectivity:
ping -c 4 8.8.8.8
Test DNS resolution:
getent hosts google.com
Do not proceed until basic networking works correctly.
Back Up the Virtualmin Configuration
Before asking Virtualmin to update its configuration, create another backup:
tar -czf /root/before-virtualmin-ip-change-$(date +%Y%m%d-%H%M%S).tgz \
/etc/webmin/virtual-server \
/etc/apache2 \
/etc/bind
Messages from tar about removing leading / characters are normal.
Tell Virtualmin About the New IP Address
Now let Virtualmin update all virtual servers using the old address:
virtualmin modify-all-ips --old-ip OLD_IP --new-ip NEW_IP
Virtualmin should report each virtual server it updates.
The operation may also apply the webserver configuration and reload or restart services managed by Virtualmin.
Do not manually replace the addresses inside Apache virtual-host files when Virtualmin can handle them.
Verify the Virtualmin Changes
Look for remaining references to the old address:
grep -RFn 'OLD_IP' /etc/webmin/virtual-server 2>/dev/null
Then check Apache:
grep -RFn 'OLD_IP' /etc/apache2 2>/dev/null
Test Apache’s configuration:
apachectl configtest
The expected result is:
Syntax OK
List the domains Virtualmin now associates with the new address:
virtualmin list-domains --ip NEW_IP --name-only
The expected virtual servers should appear.
Run Virtualmin’s Configuration Check
Run:
virtualmin check-config
Pay particular attention to lines reporting:
Default IPv4 address for virtual servers
Detected external IPv4 address
Both should show the new address.
Check Virtualmin’s cached address afterward:
grep -nE 'external_ip_cache|old_defip' \
/etc/webmin/virtual-server/config
These values should also reflect the new address.
Test Websites Before Changing DNS
It is possible to test each website on the new IP while public DNS still points elsewhere.
For HTTP:
curl -I --max-time 10 \
--resolve example.com:80:NEW_IP \
http://example.com/
For HTTPS:
curl -I --max-time 10 \
--resolve example.com:443:NEW_IP \
https://example.com/
The --resolve option forces curl to contact the new IP while still sending the proper hostname.
This is particularly useful for testing Apache virtual hosts and SSL certificates before changing public DNS.
Repeat the test for each important hosted domain.
Change Public DNS
Once the server and websites work correctly on the new address, update public DNS.
Change A records that point to the old server IP so they point to the new server IP.
Remember to check more than just the primary domain names. Other records may include:
www
mail
webmail
admin
- Server hostname
- FTP hostnames
- Other custom hostnames
CNAME records that point to an apex hostname normally require no IP change because they follow that hostname automatically.
Do not perform a global replacement of an old IP if that address also hosts unrelated domains elsewhere.
Allow DNS Time to Propagate
Existing recursive DNS servers may continue returning the old address until their cached records expire.
The amount of time depends primarily on the DNS record’s Time to Live value.
Keep the old service available during this period when practical.
Check Automatic Jobs After the Move
A successful website migration does not necessarily prove that scheduled jobs will work.
Check the next scheduled run of:
- Remote backups
- Rsync jobs
- Secure Shell transfers
- Monitoring
- Cron jobs
- External database connections
- Offsite storage jobs
Jobs that connect using the server hostname should normally follow the DNS change.
However, remote firewalls, Fail2Ban installations, or access-control lists may explicitly trust the old IP address. Those systems may need the new address added.
Watch for IPv6
The new network may automatically provide a public IPv6 address even when the migration concerns only IPv4.
Check:
ip -br addr
Also review the output from:
virtualmin check-config
If a public IPv6 address appears unexpectedly, decide separately whether the server should use IPv6 publicly. Do not assume that an IPv4 migration automatically requires publishing IPv6 DNS records.
Keep the Backups Until Everything Is Proven
Do not immediately remove the backup copies made during the migration.
Keep:
/etc/network/interfaces.before-ip-change
/etc/hosts.before-ip-change
/root/before-virtualmin-ip-change-*.tgz
until websites, certificates, scheduled backups, mail-related services, and remote connections have operated normally.
The Important Division of Responsibility
The safest way to think about the process is simple.
Debian controls the server’s network interface, IP address, subnet, gateway, and local hostname mapping.
Virtualmin controls the hosted virtual servers and the service configurations it manages.
Public DNS controls where the rest of the Internet finds the server.
Changing all three deliberately, in that order, makes an IP-address migration considerably less mysterious—and much easier to troubleshoot if something goes wrong.