Ansible shows status as changed even though the LXC has been created

  • When I run my playbook on my Proxmox instance to create an LXC, it successfully creates the LXC and shows status as ok=2 changed=1

  • However, when I run the playbook again, even though nothing inside the LXC changes, the play shows status as ok=2 changed=1

  • The proxmox tasks, show no rerun either, however, I believe the play should not display changed=1 in Play Recap either.

  • Is this the expected behaviour? I am new to Ansible so please guide me in case my understanding is wrong.

  • Version(s) of the relevant software tools, libraries, collections etc
    – ansible [core 2.20.5]
    – proxmoxer [2.2.0]
    – community.proxmox [1.6.0]

  • Logs from running the play with -vvv flag

changed: [192.168.1.50] => {
    "changed": true,
    "invocation": {
        "module_args": {
            "api_host": "192.168.1.50",
            "api_password": null,
            "api_port": null,
            "api_timeout": 5,
            "api_token_id": "ansible",
            "api_token_secret": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "api_user": "root@pam",
            "ca_path": null,
            "clone": null,
            "clone_type": "opportunistic",
            "cores": 4,
            "cpus": null,
            "cpuunits": null,
            "delete": null,
            "description": "Copyparty LXC",
            "disk": null,
            "disk_volume": {
                "host_path": null,
                "options": null,
                "size": 200,
                "storage": "local-lvm",
                "volume": null
            },
            "features": [
                "nesting=1"
            ],
            "force": false,
            "hookscript": null,
            "hostname": "copyparty-ct",
            "ip_address": null,
            "memory": 4096,
            "mount_volumes": null,
            "mounts": null,
            "nameserver": null,
            "netif": {
                "net0": "name=eth0,bridge=vmbr0,firewall=1,ip=dhcp,ip6=dhcp,type=veth"
            },
            "node": "msi",
            "onboot": true,
            "ostemplate": "local:vztmpl/alpine-3.23-default_20260116_amd64.tar.xz",
            "ostype": "alpine",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "pool": null,
            "purge": false,
            "searchdomain": null,
            "startup": null,
            "state": "present",
            "storage": "local",
            "swap": 512,
            "tags": [
                "copyparty",
                "alpine"
            ],
            "timeout": 30,
            "timezone": "host",
            "unprivileged": true,
            "update": true,
            "validate_certs": false,
            "vmid": 408
        }
    },
    "msg": "VM copyparty-ct (408) has been updated.",
    "vmid": 408
}

Hi there, first of all, welcome to the forum.

To get a better understanding of what exactly is happening, we’d need to see the actual task(s) within the playbook that happen, but I’ll try to explain what could possibly be the reason.

Depending on how the task is performed, it might be that the task will always be performed, no matter whether it’s necessary. Let’s say i have a task that writes “1” into “file.conf”, that task will always be performed, and thus will show up as changed.
Same goes for changing the owner:group of a file, even if the value is already correct, it will always show up as changed. Some modules are rather simple, and just perform what you ask it to do, even when the values are already set.

I’m sure there’s others on this forum that can give you a way more descriptive explanation, but above should answer your question, whether it might be partially.

1 Like

That seems like a plausible explanation, anyways here is the task in question

---
- hosts: all
  tasks:
    - name: Create a new container for copyparty.
      community.proxmox.proxmox:
        api_host: "192.168.1.50"
        api_token_id: API_TOKEN_ID
        api_token_secret: API_TOKEN_SECRET
        api_user: API_USER
        cores: 4
        description: Copyparty LXC
        disk_volume:
          storage: 'local-lvm'
          size: 200
        features:
          - nesting=1
        hostname: copyparty-ct
        memory: 4096
        netif:
          net0: "name=eth0,bridge=vmbr0,firewall=1,ip=dhcp,ip6=dhcp,type=veth"
        node: NODE_NAME
        onboot: true
        ostemplate: 'local:vztmpl/alpine-3.23-default_20260116_amd64.tar.xz'
        ostype: 'alpine'
        password: 'PASSWORD'
        pubkey: 'ssh-ed25519 PUBKEY'
        state: present
        swap: 512
        tags: ['copyparty', 'alpine']
        timezone: host
        vmid: 408

Thanks for sharing the task. I don’t have personal experience with the proxmox module, but my assumption remains the same as shared earlier.The API call/ Ansible task writes a few values, and probably sees them as changed, even though they remain the same.

That is a major drawback of proxmox_kvm and proxmox - they have historically grown and are not fully idempotent. So until someone does the heavy lifting and refactors those two modules, they will not be idempotent.

Most likely it is caused by the network interface configuration, since the MAC changes whenever the interface is changed. This probably happenened to your container as well.

1 Like

Ah yes the MAC address is dynamic. Let me try fixing it and see how it works. If it does not work out then that’s what I will make do with.

You may use the dedicated nic module to set the mac address, this will make it idempotent. :slight_smile: