LXC

How to fix lxc launch Failed getting root disk: No root device could be found

Problem:

While trying to launch a lxc container using a command like

lxc launch ubuntu:22.04 mycontainer

you see the following error message:

Creating mycontainer
Error: Failed instance creation: Failed creating instance record: Failed initialising instance: Failed getting root disk: No root device could be found

Solution:

You didn’t initialize your LXD storage properly. Run

lxd init

in order to configure the storage for lxd. For most setups except performance-critical production setups, I recommend to use the dir storage backend because it does not require any further configuration. You can leave all other options at their default values.

Name of the storage backend to use (zfs, btrfs, ceph, cephobject, dir, lvm) [default=zfs]: dir
Posted by Uli Köhler in Container, LXC

Move LXC container to new VM

Create snapshot on your current VM

lxc snapshot container_name snapshot_name

Validate created snapshot by checking the snapshots list displayed with:

lxc info container_name 

In case you have not named your snapshot, look for the most recent creation date. It might have a default name like snap1.

Create an image from the snapshot

lxc publish container_name/snapshot_name --alias="image_alias" description="image_description"

Verify your created image by checking the image list displayed with:

lxc image info image_alias

Export the created image to an archive in your current path

lxc image export image_alias image_archive_name

Send the file to your new VM

Make sure, that you can establish an SSH connection to your new VM from your old VM, e.g. by a VPN or Wireguard connection. Use scp to copy the image like so:

scp ./image_archive_name.tar.gz usera@host:/home/user

Import image and launch new container on your new VM

Make sure lxc and lxd are installed on your new VM and then import the image like so:

lxc image import image_archive_name.tar.gz --alias image_alias_on_new_vm

Make sure the imported image appears in the list on your new VM.

lxc image list

Then launch a new container from the image with:

lxc launch image_alias_on_new_vm container_name
Posted by Joshua Simon in Container, LXC

LXC delete image

1. List your lxc images

lxc image list

2. Delete image

lxc image delete [image alias]
Posted by Joshua Simon in Container, LXC

LXC create container from snapshot

1. Create a snapshot

lxc snapshot [mycontainer] [snapshot name]

2. Create local image from snapshot

lxc publish [mycontainer]/[snapshot name] --alias [image alias]

3. List your images

lxc image list

4. Create container from iamge

lxc launch [image alias] [mynewcontainer]
Posted by Joshua Simon in Container, LXC

How to copy an LXC container

You can copy a running lxc container like this

lxc copy [name of container to be copied] [new container]

for example

lxc copy mycontainer mycontainerCopy
Posted by Joshua Simon in LXC

How to open a shell in an LXC container

You can run a shell in your LXC container using

lxc exec [name of container] /bin/bash

for example

lxc exec mycontainer /bin/bash
Posted by Uli Köhler in LXC

How to fix LXC ‘Error: The remote isn’t a private LXD server’

Problem:

You are trying to launch a LXC container using a command like

lxc launch mycontainer ubuntu:18.04

but you see this error message:

Solution:

Your command line arguments are in the wrong order. You need to run lxc launch [image] [name of container], not lxc launch [name of container] [image] ! The correct command looks like this:

lxc launch ubuntu:18.04 mycontainer

 

Posted by Uli Köhler in LXC

How to fix LXC file push ‘Error: Path already exists as a directory: File too large’

Problem:

You are trying to copy a file to a LXC container using lxc file push, but you see this error message:

Error: Path already exists as a directory: File too large

Solution:

Add a slash (/) at the end of your path, for example:

mycontainer/root => mycontainer/root/

Working example:

lxc file push myfile.zip mycontainer/root/

Also see our previous post How to copy files to a LXC container

Posted by Uli Köhler in LXC

How to copy files to a LXC container

Once you’ve created a LXC container using a command like

lxc launch ubuntu:18.04 mycontainer

you can push files to the container using

lxc file push myfile.zip mycontainer/root/

This will copy the local file myfile.zip to /root/myfile.zip on the container. Ensure that your path ends with /, since lxc file push myfile.zip mycontainer/root  will show this error message:

Error: Path already exists as a directory: File too large

In that case, add a slash (/) to the end of your destination path (e.g. mycontainer/root => mycontainer/root/).

Posted by Uli Köhler in Container, LXC

How to create a LXC Ubuntu container in 15 seconds

Run this:

lxc launch ubuntu:22.04 mycontainer

In case you see this error message

Error: Failed container creation: No storage pool found. Please create a new storage pool

see How to fix lxd ‘Failed container creation: No storage pool found. Please create a new storage pool.’

Now you can connect to your container using

lxc exec mycontainer /bin/bash

 

Posted by Uli Köhler in Container, Linux, LXC

How to download a file or directory from a LXC container

To download files, use

lxc file pull <container name>/<path>/<filename> <target directory>

To download directories, use

lxc file pull --recursive <container name>/<path>/<filename> <target directory>

Examples:

Download /root/myfile.txt from mycontainer to the current directory (.):

lxc file pull mycontainer/root/myfile.txt .

Download /root/mydirectory from mycontainer to the current directory (.):

lxc file pull -r mycontainer/root/mydirectory .

 

Posted by Uli Köhler in Container, Linux, LXC, Virtualization

Launching Debian containers using LXC on Ubuntu

Problem:

You know you can launch an Ubuntu LXC container using

lxc launch ubuntu:18.04 myvm

Now you want to launch a Debian VM using

lxc launch debian:jessie myvm

but you only get this error message:

Error: The remote "debian" doesn't exist

Solution:

The debian images are (by default) available from the images remote, not the debian remote, so you need to use this:

lxc launch images:debian/jessie myvm

 

Posted by Uli Köhler in Container, Linux, LXC, Virtualization

How to find the size of a lxc container

In order to determine the size of a LXC container, first run lxc storage list to list your storage pools:

uli@myserver:~$ lxc storage list
+---------+-------------+--------+------------------------------------+---------+
|  NAME   | DESCRIPTION | DRIVER |               SOURCE               | USED BY |
+---------+-------------+--------+------------------------------------+---------+
| default |             | dir    | /var/lib/lxd/storage-pools/default | 2       |
+---------+-------------+--------+------------------------------------+---------+

If the driver is not dir, you are using a COW-type storage backend. Using this technology it is not possible to easily determine the storage size of a container. The following instructions apply only for the dir driver.

Now open a root shell and cd to the directory listed in the SOURCE column and cd to its containers subdirectory:

root@myserver ~ # cd /var/lib/lxd/storage-pools/default
root@myserver /var/lib/lxd/storage-pools/default # cd containers/
root@myserver /var/lib/lxd/storage-pools/default/containers # 

This directory contains the storage directory for all containers. Run du -sh * in order to find the size of each container:

root@myserver /var/lib/lxd/storage-pools/default/containers # du -sh *
2.0G    my-container

In this example, the container my-container occupies 2.0 Gibibytes of disk space.

Posted by Uli Köhler in Container, Linux, LXC

Routing public IPv6 addresses to your lxc/lxd containers

The enormous amount of IPv6 addresses available to most commercially hosted VPS / root servers with a public IPv6 prefix allows you to route a public IPv6 address to every container that is running on your server. This tutorial shows you how to do that, even if you have no prior experience with routing,

Step 0: Create your LXC container

We assume you have already done this – just for reference, here’s how you can create a container:

lxc launch ubuntu:18.04 my-container

Step 1: Which IP address do you want to assign to your container?

First you need to find out what prefix is routed to your host. Usually you can do that by checking in your provider’s control panel. You’re looking for something like 2a01:4f9:c010:278::1/64. Another option would be to run sudo ifconfig

and look for a inet6 line in the section of your primary network interface (this only works if you have configured your server to have an IPv6 address). Note that addresses that start with fe80:: and addresses starting with fd, among others, are not public IPv6 addresses.

Then you can define a new IPv6 address to your container. Which one you choose – as long as it’s within the prefix – is entirely your decision.

Often, <prefix>::1 is used for the host itself, therefore you could, for example, choose <prefix>::2. Note that some providers use some IP addresses for other purposes. Check your provider’s documentation for details.

If you don’t want to make it easy to find your container’s public IPv6, don’t choose <prefix>::1<prefix>::2<prefix>::3 etc but something more random like <prefix>:af15:99b1:0b05:1, for example2a01:4f9:c010:278:af15:99b1:0b05:0001. Ensure your IPv6 address has 8 groups of 4 hex digits each!

For this example, we choose the IPv6 address 2a01:4f9:c010:278::8.

Step 2: Find out the ULA of your container

We need to find the ULA (unique local address – similar to a private IPv4 address which is not routed on the internet) of the container. Using lxc, this is quite easy:

uli@myserver:~$ lxc list
+--------------+---------+-----------------------+-----------------------------------------------+
|     NAME     |  STATE  |         IPV4          |                     IPV6                      |
+--------------+---------+-----------------------+-----------------------------------------------+
| my-container | RUNNING | 10.144.118.232 (eth0) | fd42:830b:36dc:3691:216:3eff:fed1:9058 (eth0) |
+--------------+---------+-----------------------+-----------------------------------------------+

You need to look in the IPv6 column and copy the address listed there. In this example, the address is fd42:830b:36dc:3691:216:3eff:fed1:9058.

Step 3: Setup IPv6 routing

Now we can tell the host Linux to route your chosen public IPv6 to the container’s private IPv6. This is quite easy:

sudo ip6tables -t nat -A PREROUTING -d <public IPv6> -j DNAT --to-destination <container private IPv6>

In our example, this would be

sudo ip6tables -t nat -A PREROUTING -d 2a01:4f9:c010:278::8 -j DNAT --to-destination fd42:830b:36dc:3691:216:3eff:fed1:9058

First, test the command by running it in a shell. If it works (i.e. if it doesn’t print any error message), you can permanently store it e.g. by adding it to /etc/rc.local (after #!/bin/bash, before exit 0). Advanced users should prefer to add it to /etc/network/interfaces.

Step 4: Connect to your container using SSH on your public IPv6 (optional)

Note: This step requires that you have working IPv6 connectivity at your local computer. If you are unsure, check at ipv6-test.com

First, open a shell on your container:

lxc exec my-container bash

After running this, you should see a root shell prompt inside your container:

root@my-container:~#

The following commands should be entered in the container shell, not the host!

Now we can create a user to login to (in this example, we create the uli user):

root@my-container:~# adduser uli
Adding user `uli' ...
Adding new group `uli' (1001) ...
Adding new user `uli' (1001) with group `uli' ...
Creating home directory `/home/uli' ...
Copying files from `/etc/skel' ...
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
Changing the user information for uli
Enter the new value, or press ENTER for the default
        Full Name []: 
        Room Number []: 
        Work Phone []: 
        Home Phone []: 
        Other []: 
Is the information correct? [Y/n]

You only need to enter a password (you won’t see anything on screen when entering it) twice, for all other lines you can just press enter.

The ubuntu:18.04 lxc image used in this example does not allow SSH password authentication in its default configuration. In order to fix this, change PasswordAuthentication no to PasswordAuthentication yes in /etc/ssh/sshd_config and restart the SSH server by running service sshd restart. Be sure you understand the security implications before you do that!

Now, logout of your container shell by pressing Ctrl+D. The following commands can be entered on your desktop or any other server with IPv6 connectivity.

Now login to your server:

ssh <username>@<public IPv6 address>

in this example:

ssh uli@2a01:4f9:c010:278::8

If you configured everything correctly, you’ll see the shell prompt for your container:

uli@my-container:~$

Note: Don’t forget to configure a firewall for your container, e.g. ufw! Your container’s IPv6 is exposed to the internet and just assuming noone will guess it is not good security practice.

Posted by Uli Köhler in Cloud, Container, Linux, LXC, Networking

How to fix lxc ‘Error: The remote isn’t a private LXD server’

Problem:

You want to launch a lxc container using lxc launch, but you get this error message instead:

Error: The remote isn't a private LXD server

Solution:

You are using a command like this:

lxc launch mycontainer ubuntu:18.04

You’ve swapped the container name and image arguments! The correct command looks like this:

lxc launch ubuntu:18.04 mycontainer
Posted by Uli Köhler in Container, Linux, LXC

How to fix lxd ‘Failed container creation: No storage pool found. Please create a new storage pool.’

Problem:

You want to launch some lxd container using lxc launch […] but instead you get the following error message:

Failed container creation: No storage pool found. Please create a new storage pool.

Solution:

You need to initialize lxd before using it:

lxd init

When it asks you about the backend

Name of the storage backend to use (btrfs, dir, lvm) [default=btrfs]:

choosing the default option (btrfs) means that you’ll have to use a dedicated block device (or a dedicated preallocated file image) for storage. While this is more efficient if you run many containers at a time, I recommend to choose the dir backend for the default storage pool, because that option will be easiest to configure and will not occupy as much space on your hard drive.

See Storage management in lxd for more more details, including different options for storage pools in case you need a more advanced setup.

Posted by Uli Köhler in Linux, LXC, Virtualization