Sysadmin hook breaks network interface when using cloud-init network management

Running FreePBX 17 / sysadmin 17.0.3.7 on Debian 12 (Vultr cloud image, cloud-init 23.4.4, ifupdown). Hitting a reproducible issue where the server loses its IPv4 address and can only be recovered from console.

Cloud-init writes the network config to /etc/network/interfaces.d/50-cloud-init, covering both interfaces (public NIC via DHCP, VPC NIC static).

The sysadmin module’s hooks/rename-interface renames that file to a per-interface name — on my box, enp1s0. The content is unchanged; it’s a straight rename, confirmed by matching inode content and ctime.

At the next boot, cloud-init recreates 50-cloud-init. Since /etc/network/interfaces sources interfaces.d/*, ifup now reads two files describing the same interfaces. The second pass fails:

ifup[780]: RTNETLINK answers: File exists
ifup[620]: ifup: failed to bring up enp8s0
networking.service: Main process exited, code=exited, status=1/FAILURE

Because networking.service is a oneshot and dhclient is forked inside its cgroup, the failure takes dhclient down with it. No DHCP client remains running, so the lease on enp1s0 is never renewed, and the address disappears at expiry — typically ~24h after boot. sshd is still listening and the console looks normal, but SYNs arrive with no local address to match, so connections time out silently.

The hook fires during any sysadmin-module activity, not just installation. In my case it ran when I opened asterisk-version-switch and quit without changing anything:

sysadmin-hook[100835]: sysadmin hook started - ["sysadmin_manager","sysadmin.rename-interface"]
sysadmin-hook[100835]: Running '.../sysadmin/hooks/rename-interface' via pcntl_exec

The file’s ctime is one second later.

modules/firewall/Network.class.php has:

php

public function getInterfaceConfig($int) {
    // TODO: Portable-ize this.
    return $this->getRedhatInterfaceConfig($int);
}

public function getRedhatInterfaceConfig($int) {
    ...
    if (is_readable("/etc/network/interfaces.d/$int")) {

So the modules expect RHEL-style per-interface config files, mapped onto Debian paths. That works on an appliance install where nothing else manages the directory, but is colliding with cloud-init on Vultr image of Debian 12.

My questions are:

  1. Is there a supported way to tell sysadmin not to manage network config on cloud instances?
  2. Would it be reasonable for rename-interface to skip the rename when a cloud-init-managed config is present, or to detect the datasource?
  3. Is anyone else running FreePBX 17 on Debian 12 cloud images seeing this? It seems like it would affect any cloud-init deployment, not just Vultr.

Right now, I’ve worked around the issue by creating a guard script that runs at boot (ordered before networking.service) and every 5 minutes via cron, moving any non-50-cloud-init file out of interfaces.d/. It works, but it’s fighting the module rather than configuring it, so I’d rather do this properly if there’s a supported path.

Not a fix, but I run netplan instead so freepbx doesn’t touch it.

That sounds like a real conflict between FreePBX’s interface handling and cloud-init rather than a simple DHCP problem. The duplicated config in explains why networking fails after reboot, so I’d be interested to know if there’s a supported way to disable the sysadmin interface rename on cloud-init systems.

FreePBX is designed as an appliance OS/application. It wants control over everything on the system from network management to package management. You have literally chosen to use something that will fight with FreePBX over said management.

This is like installing a NAS appliance and being upset because it wants to manage the disks but you want to use something else to manage the disks.

This isn’t some third-party tool that I added. cloud-init comes by default with Debian 12. Anyone installing FreePBX 17 on a cloud VM will experience similar issues.

I’m not bringing this up for Sangoma to add support for cloud-init. There are other ways to very easily resolve this:

  1. rename-interface skips the rename when /var/lib/cloud/instance exists
  2. sysadmin writes its own config only when no cloud-init-managed file is present
  3. the installer warns at install time when cloud-init is managing the network

An appliance that intends to own the network is reasonable, but failing silently a day later when a DHCP lease tries to renew is an issue.

I understand what you are saying - this is the maintenance cost of running FreePBX. So that means I should just accept everything as is? No. We should be trying to improve it, not leave it alone because that’s just how it is.

Yes, it’s available by default. It’s not installed by default.

Not a single one of the Debian 12/13 systems I’ve spun up at Vultr have cloud-init because you literally have to enable it when deploying a server. Also, just because cloud-init is there and/or being used doesn’t automatically mean it’s managing the network. That is a choice that is made and executed by the user.

So people will experience similar issues when they not only enable cloud-init but configure cloud-init to specifically manage the network.

This is literally adding support for cloud-init. All of those suggestions require FreePBX to be aware and look for cloud-init and then act accordingly. Thus adding support for cloud-init.

This is what happens when conflicting things are installed. You may not immediately see an issue until the conflicting things start to actual fight over it.

No I’m not saying that. I’m saying perhaps one should consider what they are doing first and make sure they are compensating for it properly. Such as “FreePBX with SysAdmin module will expect to manage the network interfaces and if I do it via cloud-init…it will cause conflicts. I should outline what those are so I can deal with it” or use an option that will avoid conflicts.

Here’s the thing, I’d be behind adding cloud-init support within SysAdmin but since it’s commercial only Sangoma can do it. Until then, using cloud-init to manage the network with commercial versions of FreePBX will problematic. Could use OSS only FreePBX, that won’t have conflicts as there’s nothing trying to manage the network in FreePBX. Could not use cloud-init to manage the network with commercial FreePBX.

Leaving it off and it still uses cloud-init to configure the network. Here are the settings I use when spinning these up


Cloud-Init is off, but still being deployed.

Cool, call it cloud-init support. My point is that the scope is small: a check for /var/lib/cloud/instance before the rename, or a warning at install time. That’s different from managing cloud-init’s config.

I found an issue, and am trying to resolve it. Can we work towards that?

I have to use Sysadmin because many of my machines use commercial modules - I don’t even use the paid version. To be fair, this was not an issue on previous versions of the distro - only on machines that are deployed using a cloud image of Debian 12. Which makes sense because the previous distros were a fully encapsulated OS instead of a script that installs everything on top of vanilla Debian. The sysadmin module’s assumptions carried over from the appliance model, but the deployment model changed underneath. That’s where I’m trying to figure out if I’m wrong or if sysadmin should be improved based on the deployment.

Again, cloud-init can exist but not really control the network. Just because you don’t enable the user data for cloud-init doesn’t mean it doesn’t exist. I’ve been running this system since Jan 2025, it has network metadata in cloud-init and yea, it tries to bring up the interface, that’s it. But because /etc/network/interfaces always runs first and that is where the network is managed. The most cloud-init does it try to bring up an interface after it was already brought up.

I rebooted the system Jul 27th. I haven’t had a single network issue or losing any IPs from DHCP from Vultr. I have not experienced this issue even with cloud-init metadata being used.

last_update: Mon, 27 Jul 2026 05:17:56 +0000
errors: []
recoverable_errors:
WARNING:
        - Running ['ifup', 'enp1s0'] resulted in stderr output: ifup: interface enp1s0 already configured

I provided the ways it can be resolved. Don’t use Sysadmin, Don’t use could-init for this or Sangoma is going to have to update SysAdmin to work with/check for not only cloud-init but if it’s what is holding the interface data and managing the network (bringing an interface up/down isn’t management).

You want to dig into more? Provide some details and logs. Let’s see the output of cloud-init status --long and that should have the errors and warnings for when it tried to control the network last.

However, everything I’ve seen in my systems shows /etc/network/interfaces always runs first and then cloud-init runs after. So by the time cloud-init even just attempts to bring the interface up, it’s already up and configured. Are you seeing different behavior or the same?

Network interface configuration doesn’t belong in a FreePBX module. Should be torn out altogether. 2.5 cents

(post deleted by author)

At least not the way it’s implemented now. Part of a bigger problem of trying to wrap sysadmin module around the spine of the firewall module. Feels very kludgey and fragile and causes all sorts of problems imo.

Not sure if this will help you, but I used netplan one time in order to disable the 2nd network interface. Netplan is designed to be a complementary tool to cloud-init and is probably the best way to override those settings.

netplan set --origin-hint disable-eth1 ethernets.eth1.activation-mode=off

netplan apply

This particular command will create a new disable-eth1.yaml file in /etc/netplan