Automatic Public IP Change on multiple domains

SYSTEM INFORMATION
OS type and version Ubuntu 20.04
Webmin version 2.101
Virtualmin version 7.8.2

Hello. I know the first thing you’re going to tell me is that Virtualmin should be run on a server with a fixed public IP, but I’ve been using this server like this for years and haven’t had any problems so far.

Up until now, I’ve been using DNS through a tool that updates them every time my connection’s IP changes. I’ve been using this one:

https://dondominio.dev/es/dondns/

which is quite similar to this other tool (you’ve probably heard of it):

Now, I wanted to take it a step further and let Virtualmin itself be the DNS server for my domain. I’ve pointed the DNS to the ones provided by Virtualmin, and everything seems to be working fine… as long as my IP doesn’t change, of course.

I wanted to solve this problem (I’m sure there are more people with the same issue), so I started to create a script. Here are the steps the script takes:

  1. It checks the public IP that’s in the records of one of the domains (any one because in all of them, it should be the same in my case). It compares this to the real public IP of the Virtualmin server.

  2. It checks the real public IP of the Virtualmin server.

  3. I create a function to validate if a line of text is or isn’t an IP address.

  4. Using that function, I validate if what I get in step 2 is correct. If it’s not (if the server that validates that IP is down or something like that), the script stops for security reasons. If everything is correct, the script continues.

  5. If the public IP of that domain and the real one are the same, the script stops.

  6. If both are different, it changes the IP for all domains in Virtualmin and sends me an email to notify me of the change.

That’s what I’ve done.

#!/bin/bash

# Obtener la IP pública del servidor Virtualmin
virtualmin_ip=$(sudo virtualmin list-domains --domain mydomain.com --multiline | grep "External IP address" | awk '{print $NF}')

# Obtener la IP pública de la máquina
opendns_ip=$(dig +short myip.opendns.com @resolver1.opendns.com)

# Función para validar una dirección IP
is_valid_ip() {
    local ip="$1"
    if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
        return 0 # Es una IP válida
    else
        return 1 # No es una IP válida
    fi
}

# Verificar si la IP de OpenDNS es válida
if ! is_valid_ip "$opendns_ip"; then
    exit 1
fi

# Comprobar si las IP son idénticas
if [ "$virtualmin_ip" == "$opendns_ip" ]; then
    exit 0
else
    # Cambiar la IP en todos los dominios en Virtualmin
    for domain in $(sudo virtualmin list-domains --multiline --name-only); do
        sudo virtualmin modify-domain --domain "$domain" --ip "$opendns_ip"
    done

    # Enviar un correo electrónico de notificación
    echo "La IP de tus dominios se han cambiado a $opendns_ip" | mutt -s "Cambio de IP en tus dominios" tu@email.com
fi

But it doesn’t seem like the last step is working correctly. Can anyone help me? My goal is to set this up as a cron task to run every 10 minutes. Any idea about how to solve it?

Isn’t this inbuilt in Virtualmin?

That part could be a solution, but I’m not entirely sure it’s the ideal solution for several reasons:

  1. I don’t use the “dyndns” dynamic DNS service. The dropdown menu allows you to choose the option “I don’t use any service,” so I suppose I should choose this option.
  2. It asks for the “Full hostname to update.” If I leave that part blank, it won’t let me continue. What should I put here? After all, I have more than one domain hosted on Virtualmin. In all of them, the dynamic address is updated with its external tool, but I want when the IP is updated, everything related to DNS is updated in all domains (A records, SPF, etc.), not just in one of them.

Maybe if you can tell me how to configure this page, it might work for me, but I’m not entirely sure it’s what I need.

Not sure sorry, I’ve always used fixed IP’s so I have not much knowledge on this.

uhmmm, I’m conducting tests, and it indeed works for one domain. Every 5 minutes, it checks for changes and applies them to that domain. But how can I make it apply them to all domains? Let’s see if someone can provide me with an answer.

I see some sudo commands are you running the command as root or a user ? If running as a user try running as root. To debug the script, in your last loop why not echo the domain name you are trying to edit, to make sure the loop is working correctly

OK. I changed the script. So now it looks like this:

#!/bin/bash

# Obtener la IP pública del servidor Virtualmin
virtualmin_ip=$(virtualmin list-domains --domain mydomain.com --multiline | grep "External IP address" | awk '{print $NF}')

# Obtener la IP pública de la máquina
opendns_ip=$(dig +short myip.opendns.com @resolver1.opendns.com)

# Función para validar una dirección IP
is_valid_ip() {
    local ip="$1"
    if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
        return 0 # Es una IP válida
    else
        return 1 # No es una IP válida
    fi
}

# Verificar si la IP de OpenDNS es válida
if ! is_valid_ip "$opendns_ip"; then
    exit 1
fi

# Comprobar si las IP son idénticas
if [ "$virtualmin_ip" == "$opendns_ip" ]; then
    exit 0
else
    # Cambiar la IP en todos los dominios en Virtualmin
    for domain in $(virtualmin list-domains --name-only --toplevel --php-mode fpm); do
        virtualmin modify-domain --domain "$domain" --dns-ip "$opendns_ip"
    done

    # Enviar un correo electrónico de notificación
    echo "La IP de mydomain.com se ha cambiado a $opendns_ip" | mutt -s "Cambio de IP en mydomain.com" tu@email.com
fi

It runs better, but when the scripts ends, i obtain the following errors.

All done
Agregando interfaz IP virtual para 111.11.11.11 ...
Error: RTNETLINK answers: File exists
 <sup class="ui_help" data-container="body" data-placement="auto right" data-title="virtual-server/feature-virt.pl (line 50)" data-toggle="tooltip"><i class="fa fa-0_80x fa-question-circle cursor-help"></i></sup>
Error
-----
RTNETLINK answers: File exists
 <sup class="ui_help" data-container="body" data-placement="auto right" data-title="virtual-server/feature-virt.pl (line 50)" data-toggle="tooltip"><i class="fa fa-0_80x fa-question-circle cursor-help"></i></sup>

Note that i try with a random ip address (111.11.11.11 is not my public ip. Perhaps is this the cause of the error?). Why this command is adding a virtual interface for this ip? I want to add a public ip, not a private ip.

I think that i’m on the right way, but i have to use the command “Virtualmin modify-domain” better.

I think that i got it. The right code is the following:

#!/bin/bash

# Obtener la IP pública del servidor Virtualmin
virtualmin_ip=$(sudo virtualmin list-domains --domain mydomain.com --multiline | grep "External IP address" | awk '{print $NF}')

# Obtener la IP pública de la máquina
opendns_ip=$(dig +short myip.opendns.com @resolver1.opendns.com)

# Función para validar una dirección IP
is_valid_ip() {
    local ip="$1"
    if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
        return 0 # Es una IP válida
    else
        return 1 # No es una IP válida
    fi
}

# Verificar si la IP de OpenDNS es válida
if ! is_valid_ip "$opendns_ip"; then
    exit 1
fi

# Comprobar si las IP son idénticas
if [ "$virtualmin_ip" == "$opendns_ip" ]; then
    exit 0
else
    # Cambiar la IP en todos los dominios en Virtualmin
    virtualmin modify-all-ips --old-ip "$virtualmin_ip" --new-ip "$opendns_ip"
    
    # Enviar un correo electrónico de notificación
    mensaje="Las IP son diferentes. Se ha cambiado la IP en Virtualmin."
    echo "$mensaje" | mail -s "Cambio de IP en Virtualmin" my@mailaddress.com
fi

you may wish to search the forums as this sounds like another post in the last few months — I did not have time to search for that post myself :smile:

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.