Back to All Posts

Why Your Ubuntu LXC Container Has a Hidden SSH User (and Might Be Mining Bitcoins for Script Kiddies in China)

TL;DR: Ubuntu vanilla LXC container template comes with ubuntu sudoer with an empty password and ssh allowed. You need to take care of that 😀

Ok, relatively recently I've realized (in a HARD way) that when LXC containers create an ubuntu user with sudoer privileges and an EMPTY password. And uhm,they're also allowed to accept SSH connections (kudos Ubuntu team!)

I think the Ubuntu Gremlins came up with this brilliant idea for AWS and Azure, but they definitely didn't have you in mind.

So, if you're a solopreneur or a small company "IT section" that doesn't have a whole DevOps team full of people smarter than you - and you like to fiddle with Linux Containers (for fun and profit) - you should probably read further, unless you enjoy mining bitcoins for script kiddies in China. If you do - you do you, I'm not judging. (Okay, maybe I'm judging a little, try finding better hobbies, I would recommend hiking.)

Run this inside the container, after you finish whatever you wanted to do, of course:

# Disable SSH password authentication entirely
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#\?PermitEmptyPasswords.*/PermitEmptyPasswords no/' /etc/ssh/sshd_config
systemctl restart ssh

# And delete the default ubuntu user for good measure
deluser --remove-home ubuntu 2>/dev/null || true

That closes the door for password logins entirely, including the creepy invisible guest account named ubuntu.


But if you want a permanent fix, and not something you'll forget until the next container launch, you can nuke the default user creation at the source, cloud-init.

Here's the sequence of commands to make your LXC template behave like a proper adult.

Run this inside your base container (for example, name it something like ubuntu-base, pinky-piggletoon to keep it with the Ubuntu-naming):

lxc exec ubuntu-base -- bash

mkdir -p /etc/cloud/cloud.cfg.d
tee /etc/cloud/cloud.cfg.d/99-disable-ubuntu.cfg >/dev/null <<'EOF'
# Disable default ubuntu user creation
users:
  - default
disable_root: true
ssh_pwauth: false
system_info:
  default_user:
    name: root
    lock_passwd: true
EOF

touch /etc/cloud/cloud-init.disabled
systemctl disable cloud-init
systemctl stop cloud-init
deluser --remove-home ubuntu 2>/dev/null || true
exit

That's it. Now every new container cloned from ubuntu-base will start without the ubuntu user, and SSH password login will be disabled by default.

You can even check:

lxc exec test-clean -- bash -c "grep ubuntu /etc/shadow || echo '✅ clean clone, no ubuntu user created'"