How to manage the files of several Incus containers from a separate Incus container

Incus is a manager for virtual machines and system containers.

A system container is an instance of an operating system that also runs on a computer, along with the main operating system. A system container uses, instead, security primitives of the Linux kernel for the separation from the main operating system. You can think of system containers as software virtual machines.

In this post we are going to see how to conveniently manage the files of several Incus containers from a separate Incus container. The common use-case is that you have several Incus containers that each one of them is a Website and you want your Web developer to have access to the files from a central location with either FTP or SFTP. Ideally, that central location should be an Incus container as well.

Therefore, we are looking on how to share storage between containers. The other case that we are not looking here, is how to share storage between the host and the containers.

The setup

We are creating several Incus containers and each one of them is a separate web server. Each web server expects to find the Web content files in the /var/www/ directory. Then, we want to create a separate container for the Web developer in order to give access to those /var/www/ directories from some central location. The Web developer will get access to that specific container and only that container. As Incus admins we are supposed to provide access to the Web developer to that specific container through SSH or FTP.

In this setup, the Incus container for the web server is webserver1 and the Web developer’s container is called webdev.

We will be creating storage volumes for each web server from the Incus storage pool, then incus attach those volumes to both the corresponding web server container and the Web developer’s container.

Setting up the Incus container for webserver1

First we create the web server container, webcontainer1, and install the web server package. By default, the nginx web server creates a directory html into /var/www/ for our default Web server. In there we will be attaching in the next+3 step the storage volume to store the files for this web server .

$ incus launch images:debian/12/cloud webserver1
Launching webserver1
$ incus exec webserver1 -- su --login debian
debian@webserver1:~$ sudo apt update
...
debian@webserver1:~$ sudo apt install -y nginx
...
debian@webserver1:~$ cd /var/www/
debian@webserver1:/var/www$ ls -l
total 1
drwxr-xr-x 2 root root 3 Mar 14 08:34 html
debian@webserver1:/var/www$ ls -l html/
total 1
-rw-r--r-- 1 root root 615 Mar 14 08:34 index.nginx-debian.html
debian@webserver1:/var/www$ 

Setting up the Incus container for webdev

Then, we create the Incus container for the Web developer. Ideally, you should provide access to this container to your Web developer through SSH/SFTP. Use incus config device add to create a proxy device in order to give access to your Web developer. Here, we create a WEBDEV directory in the home directory of the default debian user account of this container. In there, in the next step, we will be attaching the separate storage volumes of each web server.

$ incus launch images:debian/12/cloud webdev
Launching webdev
$ incus exec webdev -- su --login debian
debian@webdev:~$ pwd
/home/debian
debian@webdev:~$ mkdir WEBDEV
debian@webdev:~$ ls -l 
total 1
drwxr-xr-x 2 debian debian 2 Mar 14 09:28 WEBDEV
debian@webdev:~$ 

Setting up the storage volume for each web server

When you launch an Incus container, you get automatically a single storage volume for the files of that container. We are treating ourselves and we create an extra storage volume for the web data. But let’s learn a bit about storage, storage pools and storage volumes.

We run incus storage list to get a list of storage pools for our installation. In this case, the storage pool is called default(name), we are using ZFS for storage (driver), and the ZFS pool (source) is called default as well. For the last part, you can run zpool list to verify the ZFS pool details. For the USED BYnumber of 89 in this example, you can verify it from the output of zfs list.

$ incus storage list
+---------+--------+---------+-------------+---------+---------+
|  NAME   | DRIVER | SOURCE  | DESCRIPTION | USED BY |  STATE  |
+---------+--------+---------+-------------+---------+---------+
| default | zfs    | default |             | 89      | CREATED |
+---------+--------+---------+-------------+---------+---------+
$ zpool list
NAME      SIZE  ALLOC     FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
default   512G  136.9G  375.1G        -         -     8%    18%  1.00x    ONLINE  -
$ 

We run incus storage volume list to get a list of the storage volumes in Incus. I am not show the output here because it’s big. The first column is the type of the storage volume, either

  1. container, one per system container,
  2. image, for each cache image from a remote like images.linuxcontainers.org,
  3. virtual-machine, for each virtual machine, or
  4. custom, for those created by ourselves as we are going to do in a moment.

The fourth column is the content-type of a storage volume, and this can be either filesystem or block. The default when creating storage volumes is filesystem and we will be creating filesystem in a bit.

Creating the webdata1 storage volume

Now we are ready to create the webdata1 storage volume. In the functionality of the incus storage volume, we use the create command to create on the default storage pool the webdata1 storage volume, which is of type filesystem.

$ incus storage volume create default webdata1 --type=filesystem
Storage volume webdata1 created
$ 

Attaching the webdata1storage volume to the web server container

Now we can attach the webdata storage volume to the webserver1 container. In the functionality of the incus storage volume, we use the attach command to attach from the default storage pool the webdata1 storage volume to the webserver1 container, and mount it over the /var/www/html/ path.

$ incus storage volume attach default webdata1 webserver1 /var/www/html/
$ 

Attaching the webdata1storage volume to the webdev container

Now we can attach the webdata storage volume to the webdev container. In the functionality of the incus storage volume, we use the attach command to attach from the default storage pool the webdata1 storage volume to the webdev container, and mount it over the /home/debian/WEBDEV/ path.

$ incus storage volume attach default webdata1 webdev /home/debian/WEBDEV/webserver1
$ 

Preparing the storage volume for webserver1

We have attached the storage volume into both the web server container and the web development container. Let’s setup the initial permissions and setup some simple hello world HTML file. We get a shell into the web development container webdev, and observe that the storage volume has been mounted. The default permissions are drwxr-xr-x and we replace them into drwxr-xr-x. That is, we can list the contents of the directory. Then, we changed the owner:group into debian:debianin order to allow all access to the Web developer when they edit the files.

$ incus exec webdev -- su --login debian
debian@webdev:~$ ls -l
total 1
drwxr-xr-x 3 debian debian 3 Mar 14 10:33 WEBDEV
debian@webdev:~$ cd WEBDEV/
debian@webdev:~/WEBDEV$ ls -l
total 1
drwx--x--x 2 root root 2 Mar 14 09:59 webserver1
debian@webdev:~/WEBDEV$ sudo chmod 755 webserver1/
debian@webdev:~/WEBDEV$ sudo chown debian:debian webserver1/
debian@webdev:~/WEBDEV$ ls -l
total 1
drwxr-xr-x 2 debian debian 2 Mar 14 09:59 webserver1
debian@webdev:~/WEBDEV$ 

Creating an initial HelloWorld HTML file

Still in the webdev container, we create an initial HTML file. Note that once you paste the HTML code, you press Ctrl+d to save the index.html file.

debian@webdev:~/WEBDEV$ cd webserver1
debian@webdev:~/WEBDEV/webserver1$ cat > index.html
<!DOCTYPE HTML>
<html>
  <head>
    <title>Welcome to Incus</title>
    <meta charset="utf-8"  />
  </head>
  <style>
    body {
      background: rgb(2,0,36);
      background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 35%, rgba(0,212,255,1) 100%);
    }
    h1,p {
      color: white;
      text-align: center;
    }
  </style>
  <body>
    <h1>Welcome to Incus</h1>
    <p>The web development data of this web server are stored in an Incus storage volume. </p>
    <p>This storage volume is attached to both the web server container and a web development container. </p>
  </body>
</html>
Ctrl+d
debian@webdev:~/WEBDEV/webserver1$ ls -l
total 1
-rw-r--r-- 1 debian debian 608 Mar 14 11:05 index.html
debian@webdev:~/WEBDEV/webserver1$ logout
$ 

Testing the result

We visit the web server using our browser. The IP address of the web server is obtained as follows.

$ incus list webserver1 -c n4
+------------+--------------------+
|    NAME    |        IPV4        |
+------------+--------------------+
| webserver1 | 10.10.10.88 (eth0) |
+------------+--------------------+
$ 

This is the HTML page we created.

Conclusion

We showed how to use a storage volume to separate the web server data files from the web server container. Those files are stored in the Incus storage pool. We attached the same storage volume to a separate container for the Web developer so that they get access to the files and only the files from a central location, the webdev container.

An additional task would be to setup git in the webdev container so that any changes to the web files are tracked.

You can also detach storage volumes (no shown here).

You would use incus config device to create a proxy device to give external access to the Web developer. Preferably over SSH/SFTP, instead of just plain FTP. In fact in terms of usability it does not make a difference between the two. Yeah, please use SFTP. All web development tools should support SFTP.

Permanent link to this article: https://blog.simos.info/how-to-manage-the-files-of-several-incus-containers-from-a-separate-incus-container/

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.