Hi!
Sorry for the delay.
The gist of the issue is that when you lxc start a container, the command returns quickly, but the container may not have actually finished booting. The reason is that LXD gives the instruction to the container to boot and the container is now on its own. It might get ready straight away, or it may take a few moments.
How can you be sure when to start running lxc exec on a container that you have just lxc start-ed?
You could put some delay for a few seconds, with lxc exec test -- sleep 5.
But the elegant way is to make use of cloud-init. The ubuntu: repository containers, and also the /cloud containers from the images: repository support cloud-init. cloud-init is a service that runs at the very end of the startup process. If you run the following, it will wait (will print dots while waiting) until cloud-init finishes.
lxc exec test -- cloud-init status --wait
Then, if you lxc exec test -- passwd -d ubuntu will work as expected.
But do you need to wait for the container to boot up before you can run commands?
The answer is no. If the command is lxc exec test -- touch /i_was_here, then it runs successfully even as soon as you run lxc start test.
Let’s avoid using passwd -d to reset the password of an account, but rather run the following. This is a shell command, does not invoke the passwd command, and directly edits the /etc/shadow file to remove the password lock.
lxc exec mytest -- sed -i '/^ubuntu\:/{s/\!//g}' /etc/shadow
We run it and let’s see how does the /etc/shadow line for ubuntu looks like. That’s weird. Now there are two characters. We are supposed to have removed ! and now we see that character and then an asterisk!
ubuntu:!*:18713:0:99999:7:::
When you copy a LXD container, the copied container apparently runs cloud-init as soon as it is started for the first time. And per /var/log/cloud-init.log, the ubuntu: container images create a non-root account and then lock it. Here is the relevant fragment of /var/log/cloud-init.log,
2021-03-27 20:14:11,966 - __init__.py[DEBUG]: Adding user ubuntu
2021-03-27 20:14:11,966 - subp.py[DEBUG]: Running hidden command to protect sensitive input/output logstring: ['useradd', 'ubuntu', '--comment', 'Ubuntu', '--groups', 'adm,audio,cdrom,dialout,dip,floppy,lxd,netdev,plugdev,sudo,video', '--shell', '/bin/bash', '-m']
2021-03-27 20:14:12,001 - subp.py[DEBUG]: Running command ['passwd', '-l', 'ubuntu'] with allowed return codes [0] (shell=False, capture=True)
I’ll stop here. The importance of this whole exercise is that the user account files should be considered not ready when a container is starting up. If you want to edit those file, you would need to wait until cloud-init does its own work, and then you can proceed and make changes.