<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mi blog lah!</title>
	<atom:link href="https://blog.simos.info/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.simos.info</link>
	<description>Το ιστολόγιό μου</description>
	<lastBuildDate>Sun, 08 Mar 2026 21:49:26 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>

<image>
	<url>https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/02/cropped-android-chrome-512x512-1.png?fit=32%2C32&#038;ssl=1</url>
	<title>Mi blog lah!</title>
	<link>https://blog.simos.info</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">5555344</site>	<item>
		<title>How to run Firecracker microVMs with vmsan on Incus</title>
		<link>https://blog.simos.info/how-to-run-firecracker-microvms-with-vmsan-on-incus/</link>
					<comments>https://blog.simos.info/how-to-run-firecracker-microvms-with-vmsan-on-incus/#respond</comments>
		
		<dc:creator><![CDATA[Simos Xenitellis]]></dc:creator>
		<pubDate>Sun, 08 Mar 2026 21:48:08 +0000</pubDate>
				<category><![CDATA[general]]></category>
		<category><![CDATA[incus]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[Planet Ubuntu]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[Ubuntu-gr]]></category>
		<category><![CDATA[cloudflare]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[curlpipe]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[vm]]></category>
		<category><![CDATA[vmsan]]></category>
		<guid isPermaLink="false">https://blog.simos.info/?p=54078</guid>

					<description><![CDATA[Incus is a manager for virtual machines and system containers. A virtual machine (VM) is an instance of an operating system that runs on a computer, along with the main operating system. A virtual machine uses hardware virtualization features for the separation from the main operating system. With virtual machines, a complete operating system boots &#8230; </p><p><a class="more-link btn" href="https://blog.simos.info/how-to-run-firecracker-microvms-with-vmsan-on-incus/">Continue reading</a>]]></description>
										<content:encoded><![CDATA[
<p><a href="https://linuxcontainers.org/incus/">Incus</a> is a manager for virtual machines and system containers.</p>



<p>A <strong>virtual machine</strong> (VM) is an instance of an operating system that runs on a computer, along with the main operating system. A virtual machine uses hardware virtualization features for the separation from the main operating system. With virtual machines, a complete operating system boots up in them. </p>



<p>Incus, to run VMs, uses KVM as <a href="https://aws.amazon.com/compare/the-difference-between-type-1-and-type-2-hypervisors/">a Type 1 hypervisor</a>, and QEMU as a Type 2 hypervisor <em>and</em> emulator.</p>



<p>On the other hand, <a href="https://github.com/angelorc/vmsan"><strong><em>vmsan</em></strong></a> only uses KVM as a Type 1 hypervisor. This means that it has far less features, but it is very lightweight. </p>



<p>In this post we have a look at <strong><em>vmsan</em></strong> by running it in an Incus virtual machine. </p>


<h2 class="simpletoc-title">Table of Contents</h2>
<ul class="simpletoc-list">
<li><a href="#prerequisites">Prerequisites</a>

</li>
<li><a href="#setting-up-vmsan">Setting up vmsan</a>

</li>
<li><a href="#using-vmsan">Using vmsan</a>


<ul><li>
<a href="#vmsan-create-to-create-a-microvm">vmsan create to create a microVM</a>

</li>
<li><a href="#vmsan-list-to-list-the-microvms">vmsan list to list the microVMs</a>

</li>
</ul>
<li><a href="#vmsan-connect-to-get-a-shell-into-a-microvm">vmsan connect to get a shell into a microVM</a>

</li>
<li><a href="#running-nginx-in-a-microvm">Running nginx in a microVM</a>

</li>
<li><a href="#conclusion">Conclusion</a>
</li></ul>

<h2 class="wp-block-heading" id="prerequisites">Prerequisites</h2>


<p>You need to </p>



<ol class="wp-block-list">
<li>have Incus installed and initialized</li>



<li>have configured Incus to run virtual machines</li>



<li>have configured your system for <strong><em>nested virtualization</em></strong></li>
</ol>



<p>For the last two points, check out this post, </p>



<figure class="wp-block-embed is-type-wp-embed is-provider-mi-blog-lah wp-block-embed-mi-blog-lah"><div class="wp-block-embed__wrapper">
<blockquote class="wp-embedded-content" data-secret="im1lVQejYh"><a href="https://blog.simos.info/how-to-run-an-incus-vm-inside-an-incus-vm-nested-virtualization/">How to run an Incus VM inside an Incus VM (nested virtualization)</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;How to run an Incus VM inside an Incus VM (nested virtualization)&#8221; &#8212; Mi blog lah!" src="https://blog.simos.info/how-to-run-an-incus-vm-inside-an-incus-vm-nested-virtualization/embed/#?secret=ruv2HvNvBn#?secret=im1lVQejYh" data-secret="im1lVQejYh" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</div></figure>


<h2 class="wp-block-heading" id="setting-up-vmsan">Setting up <code>vmsan</code></h2>


<p>We launch an Incus VM and in there we install <strong><em>vmsan</em></strong>. By default, the Incus VM will have 1GiB RAM and 10GiB disk space. When you run <code>incus shell</code>, the instance should have finished the start-up. Otherwise, you get an error as shown below. Just try again and until you get the command succeeds.</p>



<pre class="wp-block-code"><code>$ <kbd>incus launch --vm images:ubuntu/24.04/cloud microvm</kbd>
$ <kbd>incus shell microvm</kbd>
Error while executing alias expansion: incus exec microvm -- su -l
Error: VM agent isn't currently running  // it just means the VM did not finish yet booting.
$ <kbd>incus shell microvm</kbd>
root@microvm:~# </code></pre>



<p>Then, we follow the instructions at <a href="https://vmsan.dev/getting-started/installation">https://vmsan.dev/getting-started/installation</a> to install <strong><em>vmsan</em></strong>. First we install <code>curl</code> because the installation script is a <code>curl pipe</code> script. And we also install <code>iptables</code> because currently it&#8217;s not installed automatically by the installation script. This may change in the future. Note that <code>unzip</code> and <code>squashfs-tools</code> are both installed by the installation script, as shown below. We are also prompted to setup an optional Cloudflare tunnel which we do not do in this tutorial for simplicity. </p>



<pre class="wp-block-code"><code>root@microvm:~# <kbd>apt install -y curl iptables</kbd>
...
root@microvm:~# <kbd>curl -fsSL https://vmsan.dev/install | bash</kbd>

  vmsan installer
  Firecracker microVM sandbox toolkit
  https:&#47;&#47;github.com/angelorc/vmsan

&#91;info]  <mark style="background-color:#7bdcb5" class="has-inline-color">Installing prerequisites: unzip squashfs-tools</mark>...
&#91;ok]    Prerequisites installed
&#91;info]  <mark style="background-color:#7bdcb5" class="has-inline-color">Node.js not found — installing Node.js 22 via NodeSource</mark>...
...
2026-03-04 18:15:18 - Repository configured successfully.
2026-03-04 18:15:18 - To install Node.js, run: apt install nodejs -y
2026-03-04 18:15:18 - You can use N|solid Runtime as a node.js alternative
2026-03-04 18:15:18 - To install N|solid Runtime, run: apt install nsolid -y 

&#91;ok]    Node.js v22.22.0 installed
&#91;info]  Setting up /root/.vmsan...
&#91;ok]    Directories created
&#91;info]  Fetching latest Firecracker version...
&#91;info]  Downloading firecracker.tgz...
&#91;ok]    <mark style="background-color:#7bdcb5" class="has-inline-color has-black-color">Firecracker v1.14.2 installed</mark>
&#91;info]  Downloading vmlinux-6.1...
&#91;ok]    <mark style="background-color:#7bdcb5" class="has-inline-color">Kernel installed (vmlinux-6.1)</mark>
&#91;info]  Downloading ubuntu-24.04.squashfs...
&#91;info]  Converting squashfs to ext4 (this may take a minute)...
&#91;ok]    Rootfs installed (ubuntu-24.04.ext4, 1024 MB)
&#91;info]  Fetching latest release tag...
&#91;ok]    Latest release: v0.1.0-alpha.24
&#91;info]  Installing vmsan CLI via npm...
npm warn deprecated node-domexception@1.0.0: Use your platform's native DOMException instead

added 62 packages in 27s

8 packages are looking for funding
  run `npm fund` for details
npm notice
npm notice New major version of npm available! 10.9.4 -&gt; 11.11.0
npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.11.0
npm notice <mark style="background-color:#0693e3" class="has-inline-color has-black-color">To update run: npm install -g npm@11.11.0</mark>
npm notice
&#91;ok]    vmsan CLI installed (0.1.0-alpha.24)
&#91;info]  Downloading vmsan-agent...
&#91;ok]    vmsan-agent v0.1.0-alpha.24 installed
&#91;info]  Downloading cloudflared...
&#91;ok]    cloudflared 2026.2.0 installed

  ┌─────────────────────────────────────────────────────────────┐
  │  Cloudflare Tunnel (optional)                              │
  │                                                            │
  │  vmsan can expose VMs via Cloudflare Tunnels.              │
  │  You need a Cloudflare API token and a domain managed      │
  │  by Cloudflare.                                            │
  └─────────────────────────────────────────────────────────────┘

  <mark style="background-color:#fcb900" class="has-inline-color">Configure Cloudflare now?</mark> &#91;y/N] <kbd>N</kbd>
&#91;info]  Skipping Cloudflare configuration

&#91;ok]    <mark style="background-color:#8ed1fc" class="has-inline-color">vmsan environment ready at /root/.vmsan</mark>

  Firecracker  /root/.vmsan/bin/firecracker
  Jailer       /root/.vmsan/bin/jailer
  Kernel       /root/.vmsan/kernels/vmlinux-6.1
  Rootfs       /root/.vmsan/rootfs/ubuntu-24.04.ext4
  Agent        /root/.vmsan/bin/vmsan-agent
  cloudflared  /root/.vmsan/bin/cloudflared (not configured)
  CLI          /usr/bin/vmsan

  To configure Cloudflare later, re-run this installer.

root@microvm:~# </code></pre>



<p>Finally, we launch a microVM. We use the parameter <code>--connect</code> that gives as a non-root shell into the newly created microVM. The microVM has by default 128MiB RAM and a disk space of 10GiB. The Incus VM is also at 10GiB, which may not good. The default memory size is too little to even run <code>apt get</code> and the default disk space is too much. Don&#8217;t worry, we will remove this microVM and create a new one in the next section. What&#8217;s important, is that we got a shell into the microVM. It works!</p>



<pre class="wp-block-code"><code>root@microvm:~# <kbd>vmsan create --connect</kbd>
◐ Creating VM vm-918c59dc...                                                              
◐ Setting up networking...                                                                
&#x2714; Network: TAP fhvm0, Host 172.16.0.1, Guest 172.16.0.2                                   
◐ Preparing chroot...                                                                     
◐ Spawning Firecracker via jailer...                                                      
◐ Waiting for API socket...                                                               
&#x2714; API socket ready                                                                        
◐ Starting VM...                                                                          
&#x2714; VM vm-918c59dc is running (PID: 2116)                                                   

 ╭───────────────────────────────────────────────────────────────────────────────────────╮
 │                                                                                       │
 │  <mark style="background-color:#7bdcb5" class="has-inline-color">VM Created</mark>: vm-918c59dc                                                              │
 │                                                                                       │
 │    <mark style="background-color:#00d084" class="has-inline-color">Status</mark>:   <mark style="background-color:#8ed1fc" class="has-inline-color">running</mark>                                                                  │
 │    PID:      2116                                                                     │
 │    vCPUs:    1                                                                        │
 │    Memory:   128 MiB                                                                  │
 │    Runtime:  base                                                                     │
 │    Disk:     10 GB                                                                    │
 │                                                                                       │
 │    <mark style="background-color:#00d084" class="has-inline-color">Network</mark>:                                                                           │
 │      TAP:    fhvm0                                                                    │
 │      Host:   172.16.0.1                                                               │
 │      Guest:  172.16.0.2                                                               │
 │      MAC:    AA:FC:00:00:00:01                                                        │
 │      Policy: allow-all                                                                │
 │                                                                                       │
 │    Kernel:   /root/.vmsan/kernels/vmlinux-6.1                                         │
 │    Rootfs:   /root/.vmsan/rootfs/ubuntu-24.04.ext4                                    │
 │                                                                                       │
 │    Socket:   /root/.vmsan/jailer/firecracker/vm-918c59dc/root/run/firecracker.socket  │
 │    Chroot:   /root/.vmsan/jailer/firecracker/vm-918c59dc                              │
 │    State:    /root/.vmsan/vms/vm-918c59dc.json                                        │
 │                                                                                       │
 ╰───────────────────────────────────────────────────────────────────────────────────────╯

◐ Waiting for agent to become ready...                                                    
&#x2714; <mark style="background-color:#7bdcb5" class="has-inline-color">Agent is ready</mark>. Connecting via PTY shell...                                             
<mark style="background-color:#f78da7" class="has-inline-color">ubuntu@ubuntu-fc-uvm</mark>:~$ </code></pre>



<p>The microVM gets an IP address from the 176.16.x.y private address range. The hostname of the microVM is <em>ubuntu-fc-uvm</em>, and the name is derived from <em>Ubuntu FireCracker microVirtualMachine</em>.</p>



<p>Let&#8217;s list the available microVMs and then remove &#8217;em. In the next section we examine a bit more about these commands.</p>



<pre class="wp-block-code"><code>root@microvm:~# <kbd>vmsan list</kbd>
ID            STATUS    CREATED         MEMORY    VCPUS  RUNTIME   TIMEOUT TUNNEL SNAPSHOT                                                                              
<mark style="background-color:#fcb900" class="has-inline-color">vm-918c59dc</mark>   running   5 minutes ago   128 MiB   1      base      -       -      -       
root@microvm:~# <kbd>vmsan remove vm-63eade04</kbd>

 ERROR  Cannot remove running VM(s): vm-63eade04. Stop them first or use --force (-f).

root@microvm:~# <kbd>vmsan remove vm-63eade04 --force</kbd>
◐ Removing vm-63eade04...
&#x2714; Removed vm-63eade04
root@microvm:~# <kbd>vmsan list</kbd>
No VMs found.    
root@microvm:~#</code></pre>


<h2 class="wp-block-heading" id="using-vmsan">Using <code>vmsan</code></h2>


<p>Here are the available commands for <code>vmsan</code>. We can <mark style="background-color:#7bdcb5" class="has-inline-color">create</mark> microVMs and we can <mark style="background-color:#7bdcb5" class="has-inline-color">list</mark> them. By listing them, we can see the name that was given to them so that we can <mark style="background-color:#7bdcb5" class="has-inline-color">start</mark>, <mark style="background-color:#7bdcb5" class="has-inline-color">stop</mark> and <mark style="background-color:#7bdcb5" class="has-inline-color has-black-color">remove</mark> them. We can get a shell or run commands in a microVM with <mark style="background-color:#7bdcb5" class="has-inline-color">connect</mark> and <mark style="background-color:#7bdcb5" class="has-inline-color">exec</mark>. We transfer files with <mark style="background-color:#7bdcb5" class="has-inline-color">upload</mark> and <mark style="background-color:#7bdcb5" class="has-inline-color">download</mark>. Finally, with <mark style="background-color:#7bdcb5" class="has-inline-color">network</mark> we change the network policy.</p>



<pre class="wp-block-code"><code>root@microvm:~# <kbd>vmsan</kbd> 
Firecracker microVM sandbox toolkit (vmsan v0.1.0-alpha.24)

USAGE vmsan &#91;OPTIONS] create|list|ls|start|stop|remove|rm|connect|upload|download|exec|network

OPTIONS

     --json    Output structured JSON (one event per command) 
  --verbose    Show detailed debug output with wide event tree

COMMANDS

    create    Create and start a Firecracker microVM                 
      list    List all VMs                                           
        ls    List all VMs                                           
     start    Start a previously stopped VM                          
      stop    Stop one or more running VMs                           
    remove    Remove one or more VMs (stops if running, then deletes)
        rm    Remove one or more VMs (stops if running, then deletes)
   connect    Connect to a running VM                                
    upload    Upload local files to a running VM                     
  download    Download a file from a running VM                      
      exec    Execute a command inside a running VM                  
   network    Update network policy on a running VM                  

Use vmsan &lt;command&gt; --help for more information about a command.

No command specified.
root@microvm:~# </code></pre>


<h3 class="wp-block-heading" id="vmsan-create-to-create-a-microvm"><code>vmsan create</code> to create a microVM</h3>


<p>Here are the parameters. Note that if you run without any parameters (like <code>--help</code>), it will plough ahead create a microVM with the default parameters.</p>



<p>By default, a microVM has 1 vCPU, 128MiB memory (you specify here the number only), disk space of <code>10gb</code> (you specify here the number with <code>gb</code>). If you use the <code>--connect</code> parameter, you get a non-root shell once the microVM is created. The default image is <code>base</code>, which is currently an Ubuntu 24.04.3. Once you launch a microVM, the <code>base</code> image uses 388MB of disk space. In addition, the microVM from the <code>base</code> image occupies about 34MiB of memory.</p>



<pre class="wp-block-code"><code>root@microvm:~# <kbd>vmsan create --help</kbd>
Create and start a Firecracker microVM (vmsan create v0.1.0-alpha.24)

USAGE vmsan create &#91;OPTIONS] 

OPTIONS

                   --vcpus="1"    Number of vCPUs (default: 1)                                                                                                                 
                --memory="128"    Memory in MiB (default: 128)                                                                                                                 
                      --kernel    Path to kernel image. Auto-detected from kernels/ if not specified.                                                                          
                      --rootfs    Path to rootfs image. Auto-detected from rootfs/ if not specified.                                                                           
                  --from-image    Build rootfs from a Docker/OCI image (e.g. ubuntu:latest).                                                                                   
              --runtime="base"    Runtime label (e.g. python3.13, node22, node22-demo). node22-demo auto-selects node:22 image and serves a branded welcome page. Default: base
                     --project    Project label for grouping VMs                                                                                                               
                 --disk="10gb"    Root disk size in GB (default: 10gb)                                                                                                         
                     --timeout    Auto-shutdown timeout (e.g. 1h, 30m, 2h30m)                                                                                                  
                --publish-port    Ports to forward to the VM (comma-separated, e.g. 8080,3000)                                                                                 
                    --snapshot    Snapshot ID to restore from                                                                                                                  
  --network-policy="allow-all"    Base network mode: allow-all (default), deny-all, or custom. Auto-promoted to custom when domains or CIDRs are provided.                     
              --allowed-domain    Domains/patterns to allow (comma-separated). Wildcard * for subdomains.                                                                      
                --allowed-cidr    Address ranges to allow (comma-separated CIDR, e.g. 10.0.0.0/8)                                                                              
                 --denied-cidr    Address ranges to deny (comma-separated CIDR). Takes precedence over all allows.                                                             
                  --no-seccomp    Disable seccomp-bpf filter for the Firecracker process.                                                                                      
                   --no-pid-ns    Disable PID namespace isolation for the jailer.                                                                                              
                   --no-cgroup    Disable cgroup resource limits for CPU and memory.                                                                                           
                    --no-netns    Disable per-VM network namespace isolation.                                                                                                  
                   --bandwidth    Max bandwidth per VM (e.g., 50mbit, 100mbit). Default: unlimited.                                                                            
                     --connect    Automatically connect to the VM shell after creation.                                                                                        
                      --silent    Suppress all output                                                                                                                          


root@microvm:~# </code></pre>



<p>We are creating microVM with the following defaults. </p>



<pre class="wp-block-code"><code>root@microvm:~# <kbd>vmsan create --disk="1gb" --memory="512" --connect</kbd>
◐ Creating VM vm-4373c955...
◐ Setting up networking...
&#x2714; Network: TAP fhvm0, Host 172.16.0.1, Guest 172.16.0.2 
◐ Preparing chroot...
◐ Spawning Firecracker via jailer... 
◐ Waiting for API socket...
&#x2714; API socket ready 
◐ Starting VM...   
&#x2714; VM vm-4373c955 is running (PID: 3987) 
 ╭───────────────────────────────────────────────────────────────────────────────────────╮
 │                                                                                       │
 │  VM Created: vm-4373c955                                                              │
 │                                                                                       │
 │    Status:   running                                                                  │
 │    PID:      3987                                                                     │
 │    vCPUs:    1                                                                        │
 │    Memory:   512 MiB                                                                  │
 │    Runtime:  base                                                                     │
 │    Disk:     1 GB                                                                     │
 │                                                                                       │
 │    Network:                                                                           │
 │      TAP:    fhvm0                                                                    │
 │      Host:   172.16.0.1                                                               │
 │      Guest:  172.16.0.2                                                               │
 │      MAC:    AA:FC:00:00:00:01                                                        │
 │      Policy: allow-all                                                                │
 │                                                                                       │
 │    Kernel:   /root/.vmsan/kernels/vmlinux-6.1                                         │
 │    Rootfs:   /root/.vmsan/rootfs/ubuntu-24.04.ext4                                    │
 │                                                                                       │
 │    Socket:   /root/.vmsan/jailer/firecracker/vm-4373c955/root/run/firecracker.socket  │
 │    Chroot:   /root/.vmsan/jailer/firecracker/vm-4373c955                              │
 │    State:    /root/.vmsan/vms/vm-4373c955.json                                        │
 │                                                                                       │
 ╰───────────────────────────────────────────────────────────────────────────────────────╯

◐ Waiting for agent to become ready...
&#x2714; Agent is ready. Connecting via PTY shell...
ubuntu@ubuntu-fc-uvm:~$ <kbd>cat /etc/lsb-release </kbd>
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=24.04
DISTRIB_CODENAME=noble
DISTRIB_DESCRIPTION="Ubuntu 24.04.3 LTS"
ubuntu@ubuntu-fc-uvm:~$ <kbd>df -h .</kbd>
Filesystem      Size  Used Avail Use% Mounted on
/dev/root       974M  388M  570M  41% /
ubuntu@ubuntu-fc-uvm:~$ <kbd>free -h</kbd>
               total        used        free      shared  buff/cache   available
Mem:           104Mi        34Mi        28Mi       1.7Mi        52Mi        70Mi
Swap:             0B          0B          0B
ubuntu@ubuntu-fc-uvm:~$ <kbd>su</kbd>
root@ubuntu-fc-uvm:/home/ubuntu# <kbd>cd</kbd>
root@ubuntu-fc-uvm:~# <kbd>pwd</kbd>
/root
root@ubuntu-fc-uvm:~# <kbd>exit</kbd>
exit
ubuntu@ubuntu-fc-uvm:~$ <kbd>exit</kbd>
root@microvm:~# </code></pre>


<h3 class="wp-block-heading" id="vmsan-list-to-list-the-microvms"><code>vmsan list</code> to list the microVMs</h3>


<p>We run <code>vmsan list</code> to list the available microVMs.</p>



<pre class="wp-block-code"><code>root@microvm:~# <kbd>vmsan list</kbd>
ID            STATUS    CREATED         MEMORY    VCPUS   RUNTIME TIMEOUT TUNNEL SNAPSHOT
vm-4373c955   running   7 minutes ago   512 MiB   1       base    -       -      -       
root@microvm:~# </code></pre>


<h2 class="wp-block-heading" id="vmsan-connect-to-get-a-shell-into-a-microvm"><code>vmsan connect</code> to get a shell into a microVM</h2>


<p>We run <code>vmsan connect</code> to get a shell into a microVM. We need the ID of the microVM, and we get it by running <code>vmsan list</code>. We can get root by running <code>su</code>. The <code>root</code> account does not have a password, therefore you are not asked for a password for the <code>su</code> command. <code>sudo</code> is not enabled in this image as it is not needed. I am running <code>su --login</code> in order to get a login shell for root. </p>



<pre class="wp-block-code"><code>root@microvm:~# <kbd>vmsan connect vm-4373c955</kbd>
ubuntu@ubuntu-fc-uvm:~$ <kbd>su --login</kbd>
root@ubuntu-fc-uvm:~# </code></pre>


<h2 class="wp-block-heading" id="running-nginx-in-a-microvm">Running nginx in a microVM</h2>


<p>Let&#8217;s do something useful. We are going to run <code>nginx</code> in a microVM and we will access it from the host. We are going to start from scratch, creating a new microVM.</p>



<pre class="wp-block-code"><code>root@microvm:~# <kbd>vmsan create <kbd>--disk="1gb" --memory="512"</kbd> --publish-port 80 --connect</kbd>
◐ Creating VM <mark style="background-color:#0693e3" class="has-inline-color">vm-2f796b98</mark>...                                                              
◐ Setting up networking...                                                                
&#x2714; Network: TAP fhvm0, Host 198.19.0.1, Guest 198.19.0.2                                   
◐ Preparing chroot...                                                                     
◐ Spawning Firecracker via jailer...                                                      
◐ Waiting for API socket...                                                               
&#x2714; API socket ready                                                                        
◐ Starting VM...                                                                          
&#x2714; VM vm-2f796b98 is running (PID: 6942)                                                   

 ╭───────────────────────────────────────────────────────────────────────────────────────╮
 │                                                                                       │
 │  VM Created: <mark style="background-color:#7bdcb5" class="has-inline-color">vm-2f796b98</mark>                                                              │
 │                                                                                       │
 │    Status:   running                                                                  │
 │    PID:      6942                                                                     │
 │    vCPUs:    1                                                                        │
 │    Memory:   512 MiB                                                                  │
 │    Runtime:  base                                                                     │
 │    Disk:     1 GB                                                                    │
 │                                                                                       │
 │    Network:                                                                           │
 │      TAP:    fhvm0                                                                    │
 │      Host:   198.19.0.1                                                               │
 │      Guest:  198.19.0.2                                                               │
 │      MAC:    AA:FC:00:00:00:01                                                        │
 │      Policy: allow-all                                                                │
 │      <mark style="background-color:#7bdcb5" class="has-inline-color">Ports</mark>:  80                                                                       │
 │                                                                                       │
 │    Kernel:   /root/.vmsan/kernels/vmlinux-6.1                                         │
 │    Rootfs:   /root/.vmsan/rootfs/ubuntu-24.04.ext4                                    │
 │                                                                                       │
 │    Socket:   /root/.vmsan/jailer/firecracker/vm-2f796b98/root/run/firecracker.socket  │
 │    Chroot:   /root/.vmsan/jailer/firecracker/vm-2f796b98                              │
 │    State:    /root/.vmsan/vms/vm-2f796b98.json                                        │
 │                                                                                       │
 ╰───────────────────────────────────────────────────────────────────────────────────────╯

◐ Waiting for agent to become ready...                                                    
&#x2714; Agent is ready. Connecting via PTY shell...                                             
ubuntu@vm-2f796b98:~$ </code></pre>



<p>Note that if we try to run <code>apt install</code>, it will fail because it cannot find the packages. The reason is that this VM has not updated automatically the package list, and we have to perform this manually. <code>lsof -i</code> shows that the Web server has not started yet. We <strong><em>enable</em></strong> and then <strong><em>start</em></strong> the <em>nginx</em> service.  We then verify that <em>nginx</em> is now running. Finally, we change the default <code>index.html</code> file to reflect that we are running the Web server in a microVM and all that in an Incus VM.</p>



<pre class="wp-block-code"><code>ubuntu@vm-2f796b98:~$ su -l
root@ubuntu-fc-uvm:~# 
root@ubuntu-fc-uvm:~# <kbd>apt install nginx lsof</kbd>
Reading package lists... Done
Building dependency tree... Done
E: Unable to locate package nginx
E: Unable to locate package lsof
root@ubuntu-fc-uvm:~# <kbd>apt update</kbd>
...
root@ubuntu-fc-uvm:~# <kbd>apt install -y nginx lsof</kbd>
...
root@ubuntu-fc-uvm:~# <kbd>lsof -i</kbd>
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
systemd     1 root   64u  IPv4   1507      0t0  TCP *:ssh (LISTEN)
systemd     1 root   65u  IPv6   1511      0t0  TCP *:ssh (LISTEN)
vmsan-age 582 root    3u  IPv6   1630      0t0  TCP *:9119 (LISTEN)
vmsan-age 582 root    8u  IPv6   1953      0t0  TCP 172.16.0.2:9119->10.200.0.1:39920 (ESTABLISHED)
root@vm-f1d2f963:~# <kbd>systemctl enable nginx</kbd>
Synchronizing state of nginx.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable nginx
root@ubuntu-fc-uvm:~# <kbd>systemctl start nginx</kbd>
root@ubuntu-fc-uvm:~# <kbd>lsof -i</kbd>
COMMAND    PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
systemd      1     root   64u  IPv4   1507      0t0  TCP *:ssh (LISTEN)
systemd      1     root   65u  IPv6   1511      0t0  TCP *:ssh (LISTEN)
vmsan-age  582     root    3u  IPv6   1630      0t0  TCP *:9119 (LISTEN)
vmsan-age  582     root    8u  IPv6   1953      0t0  TCP 172.16.0.2:9119->10.200.0.1:39920 (ESTABLISHED)
nginx     6342     root    5u  IPv4  11303      0t0  TCP *:http (LISTEN)
nginx     6342     root    6u  IPv6  11304      0t0  TCP *:http (LISTEN)
nginx     6343 www-data    5u  IPv4  11303      0t0  TCP *:http (LISTEN)
nginx     6343 www-data    6u  IPv6  11304      0t0  TCP *:http (LISTEN)
root@vm-f1d2f963:~# sed -i "s/Welcome to nginx/Welcome to nginx running in a vmsan microMV, which runs in an Incus VM/g"  /var/www/html/index.nginx-debian.html 
root@ubuntu-fc-uvm:~# </code></pre>



<p>We exit to the host and create <em>the Incus proxy device</em>. While exiting, we have a look at the firewall rule that performed the publishing of port 80 (http) to the Incus virtual machine. </p>



<pre class="wp-block-code"><code>root@ubuntu-fc-uvm:~# <kbd>exit</kbd>
exit
ubuntu@ubuntu-fc-uvm:~$ <kbd>exit</kbd>
exit
root@microvm:~# <kbd>iptables-nft</kbd> 
...
Chain FORWARD (policy DROP)
ACCEPT     tcp  --  anywhere             198.19.0.2           tcp dpt:<mark style="background-color:#00d084" class="has-inline-color">http</mark>
...
root@microvm:~# <kbd>exit</kbd>
logout
$ </code></pre>



<p>Here is a screenshot of the the website, when accessed from the host. We use the IP address of the Incus VM <strong><em>microvm</em></strong>.</p>



<figure class="wp-block-image size-full"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2026/03/image-2.png?ssl=1"><img data-recalc-dims="1" fetchpriority="high" decoding="async" width="750" height="438" data-attachment-id="54100" data-permalink="https://blog.simos.info/how-to-run-firecracker-microvms-with-vmsan-on-incus/image-17/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2026/03/image-2.png?fit=765%2C447&amp;ssl=1" data-orig-size="765,447" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2026/03/image-2.png?fit=300%2C175&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2026/03/image-2.png?fit=750%2C438&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2026/03/image-2.png?resize=750%2C438&#038;ssl=1" alt="" class="wp-image-54100" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2026/03/image-2.png?w=765&amp;ssl=1 765w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2026/03/image-2.png?resize=300%2C175&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2026/03/image-2.png?resize=750%2C438&amp;ssl=1 750w" sizes="(max-width: 750px) 100vw, 750px" /></a></figure>


<h2 class="wp-block-heading" id="conclusion">Conclusion</h2>


<p>We had a quick look into <a href="https://github.com/angelorc/vmsan">vmsan</a>, a project that manages micro virtual machines that are based on Firecracker. vmsan is a new project and the maintainer is <a href="https://github.com/angelorc">Angelo RC</a>.</p>



<p>vmsan also added support for Cloudflare tunnels. This means that you can expose your microVMs to the Internet using those Cloudflare tunnels. If you own a domain and you have configured it to be managed by Cloudflare, then vmsan allows you to publish your site automatically without needing to enable port forwarding. You would need to create an API key for this on Cloudflare and then feed that API key to vmsan. </p>



<p>At the moment vmsan comes with four images. </p>



<ol class="wp-block-list">
<li>Ubuntu 24.04</li>



<li>Ubuntu 24.04 with Python 3.13</li>



<li>Ubuntu 24.04 with Node.js 22 LTS</li>



<li>Ubuntu 24.04 with Node.js 24 LTS</li>
</ol>



<p>I would expect that the project will add support for smaller images, such as Alpine. Considering that Firecracker is not QEMU and has fewer requirements for resources (and features!), it would make sense to have tiny VMs.</p>



<p>vmsan itself is a Node.js application. </p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.simos.info/how-to-run-firecracker-microvms-with-vmsan-on-incus/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">54078</post-id>	</item>
		<item>
		<title>How to run a Linux Desktop virtual machine on Incus</title>
		<link>https://blog.simos.info/how-to-run-a-linux-desktop-virtual-machine-on-incus/</link>
					<comments>https://blog.simos.info/how-to-run-a-linux-desktop-virtual-machine-on-incus/#comments</comments>
		
		<dc:creator><![CDATA[Simos Xenitellis]]></dc:creator>
		<pubDate>Thu, 01 May 2025 22:51:53 +0000</pubDate>
				<category><![CDATA[incus]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[Planet Ubuntu]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[Ubuntu-gr]]></category>
		<guid isPermaLink="false">https://blog.simos.info/?p=51377</guid>

					<description><![CDATA[Incus is a manager for virtual machines and system containers. A virtual machine (VM) is an instance of an operating system that runs on a computer, along with the main operating system. A virtual machine uses hardware virtualization features for the separation from the main operating system. With virtual machines, the full operating system boots &#8230; </p><p><a class="more-link btn" href="https://blog.simos.info/how-to-run-a-linux-desktop-virtual-machine-on-incus/">Continue reading</a>]]></description>
										<content:encoded><![CDATA[
<p><a href="https://linuxcontainers.org/incus/">Incus</a> is a manager for virtual machines and system containers.</p>



<p>A <strong>virtual machine</strong> (VM) is an instance of an operating system that runs on a computer, along with the main operating system. A virtual machine uses hardware virtualization features for the separation from the main operating system. With virtual machines, the full operating system boots up in them. While in most cases you would run Linux on a VM without a desktop environment, you can also run Linux with a desktop environment (like in VirtualBox and VMWare).</p>



<p>In <a href="https://blog.simos.info/how-to-run-a-windows-virtual-machine-on-incus-on-linux/">How to run a Windows virtual machine on Incus on Linux</a> we saw how to run a run a Windows VM on Incus. In this post we see how to run a Linux Desktop virtual machine on Incus. </p>


<h2 class="simpletoc-title">Table of Contents</h2>
<ul class="simpletoc-list">
<li><a href="#updates">Updates</a>

</li>
<li><a href="#prerequisites">Prerequisites</a>

</li>
<li><a href="#cheat-sheet">Cheat sheet</a>

</li>
<li><a href="#availability-of-images">Availability of images</a>

</li>
<li><a href="#booting-a-desktop-linux-vm-on-incus">Booting a desktop Linux VM on Incus</a>


<ul><li>
<a href="#booting-the-ubuntu-desktop-image-on-incus">Booting the Ubuntu desktop image on Incus</a>

</li>
<li><a href="#booting-the-archlinux-desktop-image-on-incus">Booting the ArchLinux desktop image on Incus</a>

</li>
<li><a href="#booting-the-opensuse-desktop-image-on-incus">Booting the OpenSUSE desktop image on Incus</a>

</li>
</ul>
<li><a href="#troubleshooting">Troubleshooting</a>


<ul><li>

<ul><li>
<a href="#i-closed-the-desktop-window-but-the-vm-is-running-how-do-i-get-it-back-up">I closed the desktop window but the VM is running. How do I get it back up?</a>

</li>
<li><a href="#error-this-console-is-already-connected-force-is-required-to-take-it-over">Error: This console is already connected. Force is required to take it over.</a>

</li>
<li><a href="#error-instance-is-not-running">Error: Instance is not running</a>

</li>
<li><a href="#i-get-no-audio-from-the-desktop-vm-how-do-i-get-sound-in-the-desktop-vm">I get no audio from the desktop VM! How do I get sound in the desktop VM?</a>

</li>
<li><a href="#how-do-i-shutdown-the-desktop-vm">How do I shutdown the desktop VM?</a>

</li>
<li><a href="#error-failed-instance-creation-the-image-used-by-this-instance-is-incompatible-with-secureboot-please-set-securitysecurebootfalse-on-the-instance">Error: Failed instance creation: The image used by this instance is incompatible with secureboot. Please set security.secureboot=false on the instance</a>

</li>
<li><a href="#error-failed-instance-creation-failed-creating-instance-record-add-instance-info-to-the-database-failed-to-create-instances-entry-unique-constraint-failed-instancesprojectid-instancesname">Error: Failed instance creation: Failed creating instance record: Add instance info to the database: Failed to create &#8220;instances&#8221; entry: UNIQUE constraint failed: instances.project_id, instances.name</a>
</li>
</ul>
</li>
</ul>
</li></ul>

<h2 class="wp-block-heading" id="updates">Updates</h2>


<p>No updates yet.</p>


<h2 class="wp-block-heading" id="prerequisites">Prerequisites</h2>


<ol class="wp-block-list">
<li>You should have <a href="https://linuxcontainers.org/incus/docs/main/tutorial/first_steps/">a system that runs Incus</a>. </li>



<li>A system with support for hardware virtualization so that it can run virtual machines.</li>



<li>A virtual machine image of your preferred Linux desktop distribution.</li>
</ol>


<h2 class="wp-block-heading" id="cheat-sheet">Cheat sheet</h2>


<p>You should specify how much RAM memory you are giving to the VM. The default is only 1GiB of RAM, which is not enough for desktop VMs. The <code>--console=vga</code> launches for you the Remote Viewer GUI application to allow you to use the desktop in a window.</p>



<pre class="wp-block-code"><code>$ <mark style="background-color:#7bdcb5" class="has-inline-color">incus image list images:desktop</mark>       # List all available desktop images
$ <mark style="background-color:#7bdcb5" class="has-inline-color">incus launch --vm images:ubuntu/jammy/desktop mydesktop -c limits.memory=3GiB --console=vga</mark>
$ <mark style="background-color:#7bdcb5" class="has-inline-color">incus console mydesktop --type=vga</mark>    # Reconnect to already running instance
$ <mark style="background-color:#7bdcb5" class="has-inline-color">incus start mydesktop --console=vga</mark>   # Start an existing desktop VM</code></pre>


<h2 class="wp-block-heading" id="availability-of-images">Availability of images</h2>


<p>Currently, Incus provides you with the following VM images of Linux desktop distributions. The architecture is <code>x86_64</code>.</p>



<p>Run the following command to list all available Linux desktop images. <code>incus image</code> is the section of Incus that deals with the management of images. The <code>list</code> command lists the available images of a <em>remote</em>/repository, the default being <code>images:</code> (run <code>incus remote list</code> for the full list of <em>remotes</em>). After the colon (<code>:</code>), you type <em>filter</em> keywords, and in this case we typed <code>desktop</code> to show images that have the word <code>desktop</code> in them (to show only Desktop images). We are interested in a few columns only, therefore <code>-c ldt</code> only shows the columns for the <em>Alias</em>, the <em>Description</em> and the <em>Type</em>.</p>



<pre class="wp-block-code"><code>$ <mark style="background-color:#00d084" class="has-inline-color">incus image list images:desktop -c ldt</mark>
+------------------------------------------+---------------------------+-----------------+
|                  ALIAS                   |      DESCRIPTION          |      TYPE       |
+------------------------------------------+---------------------------+-----------------+
| archlinux/desktop-gnome (3 more)         | <mark style="background-color:#8ed1fc" class="has-inline-color">Archlinux</mark> current amd64   | VIRTUAL-MACHINE |
+------------------------------------------+---------------------------+-----------------+
| opensuse/15.5/desktop-kde (1 more)       | <mark style="background-color:#00d084" class="has-inline-color has-black-color">Opensuse</mark> 15.5 amd64       | VIRTUAL-MACHINE |
+------------------------------------------+---------------------------+-----------------+
| opensuse/15.6/desktop-kde (1 more)       | <mark style="background-color:#00d084" class="has-inline-color">Opensuse</mark> 15.6 amd64       | VIRTUAL-MACHINE |
+------------------------------------------+---------------------------+-----------------+
| opensuse/tumbleweed/desktop-kde (1 more) | <mark style="background-color:#00d084" class="has-inline-color">Opensuse</mark> tumbleweed amd64 | VIRTUAL-MACHINE |
+------------------------------------------+---------------------------+-----------------+
| ubuntu/24.10/desktop (3 more)            | <mark style="background-color:#ff6900" class="has-inline-color">Ubuntu</mark> oracular amd64     | VIRTUAL-MACHINE |
+------------------------------------------+---------------------------+-----------------+
| ubuntu/focal/desktop (3 more)            | <mark style="background-color:#ff6900" class="has-inline-color">Ubuntu</mark> focal amd64        | VIRTUAL-MACHINE |
+------------------------------------------+---------------------------+-----------------+
| ubuntu/jammy/desktop (3 more)            | <mark style="background-color:#ff6900" class="has-inline-color">Ubuntu</mark> jammy amd64        | VIRTUAL-MACHINE |
+------------------------------------------+---------------------------+-----------------+
| ubuntu/noble/desktop (3 more)            | <mark style="background-color:#ff6900" class="has-inline-color">Ubuntu</mark> noble amd64        | VIRTUAL-MACHINE |
+------------------------------------------+---------------------------+-----------------+
| ubuntu/plucky/desktop (1 more)           | <mark style="background-color:#ff6900" class="has-inline-color">Ubuntu</mark> plucky amd64       | VIRTUAL-MACHINE |
+------------------------------------------+---------------------------+-----------------+
$ </code></pre>



<p>These images have been generated with the utility <code>distrobuilder</code>, <a href="https://github.com/lxc/distrobuilder">https://github.com/lxc/distrobuilder</a> The purpose of the utility is to prepare the images so that when we launch them, we get immediately the desktop environment and do not perform any manual configuration. The configuration files for distrobuilder to create these images can be found at <a href="https://github.com/lxc/lxc-ci/tree/main/images">https://github.com/lxc/lxc-ci/tree/main/images</a> For example, the <code>archlinux.yaml</code> configuration file has a section to create the desktop image, along with the container and other virtual machine images. </p>



<p>The full list of Incus images are also available on the Web, through the website <a href="https://images.linuxcontainers.org/">https://images.linuxcontainers.org/</a> It is possible to generate more such desktop images by following the steps of the existing configuration files. Perhaps a Kali Linux desktop image would be very useful. In the <a href="https://images.linuxcontainers.org/">https://images.linuxcontainers.org/</a> website you can also view the build logs that were generated while building the images, and figure out what parameters are needed for <code>distrobuilder</code> to build them (along with the actual configuration file). For example, here are the logs for the ArchLinux desktop image, <a href="https://images.linuxcontainers.org/images/archlinux/current/amd64/desktop-gnome/">https://images.linuxcontainers.org/images/archlinux/current/amd64/desktop-gnome/</a></p>



<p>Up to this point we got a list of the available virtual machine images that are provided by Incus. We are ready to boot them.</p>


<h2 class="wp-block-heading" id="booting-a-desktop-linux-vm-on-incus">Booting a desktop Linux VM on Incus</h2>


<p>When launching a VM, Incus provides by default 1GiB RAM and 10GiB of disk space. The disk space is generally OK, but the RAM is too little for a desktop image (it&#8217;s OK for non-desktop images). For example, for an Ubuntu desktop image, the instance requires about 1.2GB of memory to start up and obviously more to run other programs. Therefore, if we do not specify more RAM, then the VM would struggle to make do of the mere 1GiB of RAM.</p>


<h3 class="wp-block-heading" id="booting-the-ubuntu-desktop-image-on-incus">Booting the Ubuntu desktop image on Incus</h3>


<p>Here is the command to launch a desktop image. We use <code>incus launch</code> to launch the image. It&#8217;s a VM, hence <code>--vm</code>. We are using the image from the <code>images:</code> remote, the one called <code>ubuntu/plucky/desktop</code> (it&#8217;s the last from the list of the previous section). We <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-luminous-vivid-orange-color">c</mark>onfigure a new limit for the memory usage, <code>-c limits.memory=3GiB</code>, so that the instance will be able to run successfully. Finally, the console is not textual but graphical. We specify that with <code>--console=vga</code> which means that Incus will launch the remote desktop utility for us. </p>



<pre class="wp-block-code"><code>$ <mark style="background-color:#7bdcb5" class="has-inline-color">incus launch --vm images:ubuntu/plucky/desktop mydesktop -c limits.memory=3GiB --console=vga</mark>
Launching mydesktop
</code></pre>



<p>Here is a screenshot of the new window with the running desktop virtual machine. </p>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-01-23-03-37.png?ssl=1"><img data-recalc-dims="1" decoding="async" width="750" height="508" data-attachment-id="51379" data-permalink="https://blog.simos.info/how-to-run-a-linux-desktop-virtual-machine-on-incus/screenshot-from-2025-05-01-23-03-37/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-01-23-03-37.png?fit=1300%2C880&amp;ssl=1" data-orig-size="1300,880" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Screenshot from 2025-05-01 23-03-37" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-01-23-03-37.png?fit=300%2C203&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-01-23-03-37.png?fit=750%2C508&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-01-23-03-37.png?resize=750%2C508&#038;ssl=1" alt="" class="wp-image-51379" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-01-23-03-37.png?resize=1024%2C693&amp;ssl=1 1024w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-01-23-03-37.png?resize=300%2C203&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-01-23-03-37.png?resize=768%2C520&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-01-23-03-37.png?resize=750%2C508&amp;ssl=1 750w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-01-23-03-37.png?w=1300&amp;ssl=1 1300w" sizes="(max-width: 750px) 100vw, 750px" /></a><figcaption class="wp-element-caption">Screenshot of images:ubuntu/plucky/desktop</figcaption></figure>



<p>Now we closed the wizard.</p>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/image.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="508" data-attachment-id="51380" data-permalink="https://blog.simos.info/how-to-run-a-linux-desktop-virtual-machine-on-incus/image-13/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/image.png?fit=1300%2C880&amp;ssl=1" data-orig-size="1300,880" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/image.png?fit=300%2C203&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/image.png?fit=750%2C508&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/image.png?resize=750%2C508&#038;ssl=1" alt="" class="wp-image-51380" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/image.png?resize=1024%2C693&amp;ssl=1 1024w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/image.png?resize=300%2C203&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/image.png?resize=768%2C520&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/image.png?resize=750%2C508&amp;ssl=1 750w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/image.png?w=1300&amp;ssl=1 1300w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a><figcaption class="wp-element-caption">Screenshot of images:ubuntu/plucky/desktop after we close the wizard.</figcaption></figure>


<h3 class="wp-block-heading" id="booting-the-archlinux-desktop-image-on-incus">Booting the ArchLinux desktop image on Incus</h3>


<p>I cannot get this image to show the desktop. If someone can make this work, please post in a comment.</p>



<pre class="wp-block-code"><code>$ <mark style="background-color:#7bdcb5" class="has-inline-color">incus launch --vm images:archlinux/desktop-gnome mydesktop -c limits.memory=3GiB --console=vga -c security.secureboot=false</mark>
Launching mydesktop
</code></pre>


<h3 class="wp-block-heading" id="booting-the-opensuse-desktop-image-on-incus">Booting the OpenSUSE desktop image on Incus</h3>


<pre class="wp-block-code"><code>$ <mark style="background-color:#7bdcb5" class="has-inline-color">incus launch --vm images:opensuse/15.5/desktop-kde mydesktop -c limits.memory=3GiB --console=vga</mark>
Launching mydesktop
</code></pre>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-02-01-41-39.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="508" data-attachment-id="51382" data-permalink="https://blog.simos.info/how-to-run-a-linux-desktop-virtual-machine-on-incus/screenshot-from-2025-05-02-01-41-39/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-02-01-41-39.png?fit=1300%2C880&amp;ssl=1" data-orig-size="1300,880" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Screenshot from 2025-05-02 01-41-39" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-02-01-41-39.png?fit=300%2C203&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-02-01-41-39.png?fit=750%2C508&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-02-01-41-39.png?resize=750%2C508&#038;ssl=1" alt="" class="wp-image-51382" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-02-01-41-39.png?resize=1024%2C693&amp;ssl=1 1024w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-02-01-41-39.png?resize=300%2C203&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-02-01-41-39.png?resize=768%2C520&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-02-01-41-39.png?resize=750%2C508&amp;ssl=1 750w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2025/05/Screenshot-from-2025-05-02-01-41-39.png?w=1300&amp;ssl=1 1300w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a></figure>


<h2 class="wp-block-heading" id="troubleshooting">Troubleshooting</h2>

<h4 class="wp-block-heading" id="i-closed-the-desktop-window-but-the-vm-is-running-how-do-i-get-it-back-up">I closed the desktop window but the VM is running. How do I get it back up?</h4>


<p>If you closed the Remote Viewer window, you can get Incus to start it again with the following command. By doing so, you are actually reconnecting back to the VM and continue working from where you left off.</p>



<p>We are using the <code>incus console</code> action to connect to the running <em>mydesktop</em> instance and request access through the Remote Viewer (rather than a text console).</p>



<pre class="wp-block-code"><code>$ <mark style="background-color:#7bdcb5" class="has-inline-color">incus console mydesktop --type=vga</mark>
</code></pre>


<h4 class="wp-block-heading" id="error-this-console-is-already-connected-force-is-required-to-take-it-over">Error: This console is already connected. Force is required to take it over.</h4>


<p>You are already connected to the desktop VM with the Remote Viewer and you are trying to connect again. Either go to the existing Remote Viewer window, or add the parameter <code>--force</code> to close the existing Remote Viewer window and open a new one. </p>


<h4 class="wp-block-heading" id="error-instance-is-not-running">Error: Instance is not running</h4>


<p>You are trying to connect to a desktop VM with the Remote Viewer but the instance (which already exists) is not running. Use the action <code>incus start</code> to start the virtual machine, along with the <code>--type=vga</code> parameter to get Incus to launch the Remote Viewer for you.</p>



<pre class="wp-block-code"><code>$ <mark style="background-color:#7bdcb5" class="has-inline-color">incus start mydesktop --console=vga</mark></code></pre>


<h4 class="wp-block-heading" id="i-get-no-audio-from-the-desktop-vm-how-do-i-get-sound-in-the-desktop-vm">I get no audio from the desktop VM! How do I get sound in the desktop VM?</h4>


<p>This requires extra steps which I do not show yet. There are three options. The first is to use the QEMU device emulation to emulate a sound device in the VM. The second is to somehow push an audio device into the VM so that this audio device is used exclusively in the VM (have not tried this but I think it&#8217;s possible). The third and perhaps best option is to use network audio with PulseAudio/Pipewire. You enable network audio on your desktop and then configure the VM instance to connect to that network audio server. I have tried that and it worked well for me. The downside is that the Firefox snap package in the VM could not figure out that there is network audio there and I could not get audio in that application. </p>


<h4 class="wp-block-heading" id="how-do-i-shutdown-the-desktop-vm">How do I shutdown the desktop VM?</h4>


<p>Use the desktop UI to perform the shutdown. The VM will shut down cleanly.</p>


<h4 class="wp-block-heading" id="error-failed-instance-creation-the-image-used-by-this-instance-is-incompatible-with-secureboot-please-set-securitysecurebootfalse-on-the-instance">Error: Failed instance creation: The image used by this instance is incompatible with secureboot. Please set security.secureboot=false on the instance</h4>


<p>You tried to launch a virtual machine with SecureBoot enabled but the image does not support SecureBoot. You need to disable SecureBoot when you launch this image. The instance has been created but is unable to run unless you disable SecureBoot. You can either disable SecureBoot through an Incus configuration for this image, or just delete the instance, and try again with the parameter <code>-c security.secureboot=false</code>. </p>



<p>Here is how to disable SecureBoot, then try to <code>incus start</code> that instance. </p>



<pre class="wp-block-code"><code>$ <mark style="background-color:#7bdcb5" class="has-inline-color">incus config set mydesktop security.secureboot=true</mark></code></pre>



<p>Here is how you would enable that flag when you launch such a VM.</p>



<pre class="wp-block-code"><code>incus launch --vm images:archlinux/desktop-gnome mydesktop -c limits.memory=3GiB --console=vga <mark style="background-color:#fcb900" class="has-inline-color">-c security.secureboot=false</mark></code></pre>



<p>Note that official Ubuntu images can work with SecureBoot enabled, most others don&#8217;t. It has to do with the Linux kernel being digitally signed by some certification authority.</p>


<h4 class="wp-block-heading" id="error-failed-instance-creation-failed-creating-instance-record-add-instance-info-to-the-database-failed-to-create-instances-entry-unique-constraint-failed-instancesprojectid-instancesname">Error: Failed instance creation: Failed creating instance record: Add instance info to the database: Failed to create &#8220;instances&#8221; entry: UNIQUE constraint failed: instances.project_id, instances.name</h4>


<p>This error message is a bit cryptic. It just means that you are trying to create or launch an instance while the instance already exists. Read as <em><strong>Error: The instance name already exists</strong></em>.</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.simos.info/how-to-run-a-linux-desktop-virtual-machine-on-incus/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">51377</post-id>	</item>
		<item>
		<title>A networking guide for Incus</title>
		<link>https://blog.simos.info/useful-networking-tips-with-incus/</link>
					<comments>https://blog.simos.info/useful-networking-tips-with-incus/#comments</comments>
		
		<dc:creator><![CDATA[Simos Xenitellis]]></dc:creator>
		<pubDate>Sun, 29 Sep 2024 14:12:22 +0000</pubDate>
				<category><![CDATA[general]]></category>
		<category><![CDATA[incus]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[Planet Ubuntu]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[Ubuntu-gr]]></category>
		<category><![CDATA[bridge]]></category>
		<category><![CDATA[incusbr0]]></category>
		<category><![CDATA[lxd]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[profile]]></category>
		<category><![CDATA[tutorial]]></category>
		<guid isPermaLink="false">https://blog.simos.info/?p=45684</guid>

					<description><![CDATA[Incus is a hypervisor/manager for virtual machines and application/system containers. Get community support here. A virtual machine (VM) is an instance of an operating system that runs on a computer, along with the main operating system. A virtual machine uses hardware virtualization features for the separation from the main operating system. A system container is &#8230; </p><p><a class="more-link btn" href="https://blog.simos.info/useful-networking-tips-with-incus/">Continue reading</a>]]></description>
										<content:encoded><![CDATA[
<p><a href="https://linuxcontainers.org/incus/">Incus</a> is a hypervisor/manager for <em>virtual machines</em> and <em>application/system containers</em>. <a href="https://discuss.linuxcontainers.org/">Get community support here</a>. </p>



<p>A <strong>virtual machine</strong> (VM) is an instance of an operating system that runs on a computer, along with the main operating system. A virtual machine uses hardware virtualization features for the separation from the main operating system.</p>



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



<p>An <strong><em>application container</em></strong> is a container that has an application or service. It follows the lifecycle of the application instead of a system. That is, here you start and stop the application instead of booting and shutting down a system. Incus supports <a href="https://opencontainers.org/">Open Container Initiative (OCI)</a> images such as Docker images. When Incus launches an OCI image, it uses its own runtime, not Docker&#8217;s. That is, Incus consumes images from any OCI image repositories.</p>



<p>In virtual machines and system/application containers we can attach <strong><em>virtual</em></strong> <strong><em>networking devices</em></strong>, either</p>



<ul class="wp-block-list">
<li>none, (i.e. an instance without networking)</li>



<li>one or, (i.e. most common and simple case)</li>



<li>more than one.</li>
</ul>



<p>In addition to the virtual networking devices, <strong>we can also attach real hardware networking devices</strong>. Those devices can be taken away from the host and get pushed into a virtual machine or system container.</p>



<p>You may use a combination of those networking devices in the same instance. It is left as an exercise to the reader to explore that road. In these tutorials we are look at one at most networking device per instance. </p>



<p>There will be attempts to generalize and explain in practical terms. If I get something wrong, please correct me in the comments so that it gets fixed and we all learn something new. Note that I will be editing this content along the way, adding material, troubleshooting cases, etc. </p>



<p><strong>In this post</strong> we are listing tutorials of <a href="https://linuxcontainers.org/incus/docs/main/reference/devices_nic/">the different Incus devices of type <strong><em>nic</em></strong></a> (network interface controller). Whatever we write in this post and the linked tutorials, are covered in that documentation URL!</p>



<p>The list of tutorials per networking:</p>



<ol class="wp-block-list">
<li><code>bridge</code> (the default, <em>the local network bridge</em>), <strong><em>it&#8217;s in this post below</em></strong>.</li>



<li><code>bridged</code>, (<em>pending</em>)</li>



<li><code>macvlan</code>, (<em>pending</em>)</li>



<li>none,</li>



<li><code>physical</code>, </li>



<li><code>ipvlan</code>,</li>



<li><code>routed</code>, </li>
</ol>


<h2 class="wp-block-heading" id="the-setup">The setup</h2>


<p>When demonstrating these network configurations, we will be using an Incus VM. When learning, try there in your Incus VM before applying on your host or your server.</p>



<p>We <strong><em>launch</em></strong> an Incus VM, called <em>tutorial</em>, with Ubuntu 24.04 LTS, then get a shell with the default non-root account <strong><em>ubuntu</em></strong>. I am impatient and I am typing repeatedly the <code>incus exec</code> command to get a shell. The VM takes a few moments to boot up, and I get interested error messages until the VM is actually running. Not really relevant to this tutorial but you will get educated at every opportunity.</p>



<pre class="wp-block-code"><code>$ <kbd>incus launch images:ubuntu/24.04/cloud tutorial --vm</kbd>
Launching tutorial
$ <kbd>incus exec tutorial -- su -l ubuntu</kbd>
Error: VM agent isn't currently running
$ <kbd>incus exec tutorial -- su -l ubuntu</kbd>
su: user ubuntu does not exist or the user entry does not contain all the required fields
$ <kbd>incus exec tutorial -- su -l ubuntu</kbd>
To run a command as administrator (user "root"), use "sudo &lt;command&gt;".
See "man sudo_root" for details.

ubuntu@tutorial:~$ </code></pre>



<p>We got a shell in the VM. Then, install Incus which is available in the default repositories of Ubuntu 24.04 LTS. Also, we install <code>zfsutils-linux</code>, which are the client utilities to use ZFS in Incus. We are advised to add our non-root account to the <code>incus-admin</code> group in order to have access to Incus. Without that, we would have to use <code>sudo</code> all the time. When you add a user to a group, you need to logout then log in again for the change to take effect. And this is what we do (unless you know about <code>newgrp</code>).</p>



<pre class="wp-block-code"><code>ubuntu@tutorial:~$ <kbd>sudo apt install -y incus zfsutils-linux</kbd>
...
Creating group 'incus' with GID 989.
Creating group 'incus-admin' with GID 988.
Created symlink /etc/systemd/system/multi-user.target.wants/incus-startup.service → /usr/lib/systemd/system/incus-startup.service.
Created symlink /etc/systemd/system/sockets.target.wants/incus-user.socket → /usr/lib/systemd/system/incus-user.socket.
Created symlink /etc/systemd/system/sockets.target.wants/incus.socket → /usr/lib/systemd/system/incus.socket.
incus.service is a disabled or a static unit, not starting it.
incus-user.service is a disabled or a static unit, not starting it.

<mark style="background-color:#8ed1fc" class="has-inline-color">Incus has been installed. You must run `sudo incus admin init` to
perform the initial configuration of Incus.</mark>
<mark style="background-color:#7bdcb5" class="has-inline-color">Be sure to add user(s) to either the 'incus-admin' group for full
administrative access or the 'incus' group for restricted access,
then have them logout and back in to properly setup their access.</mark>

...
ubuntu@tutorial:~$ <kbd>sudo usermod -a -G incus-admin ubuntu</kbd>
ubuntu@tutorial:~$ <kbd>logout</kbd>
$ <kbd>incus exec tutorial -- su -l ubuntu</kbd>
ubuntu@tutorial:~$ </code></pre>



<p>Now we initialize Incus with <code>sudo incus admin init</code>.</p>


<h2 class="wp-block-heading" id="default-incus-networking">Default Incus networking</h2>


<p>When you install and setup Incus with <code>incus admin init</code>, you are prompted whether you want to create <em>a local network bridge</em>. We press Enter to all prompts, which means that we accept all the defaults that are presented to us. The last question is whether to show the initialization configuration. If you missed it, you can get it after the fact by running <code>incus admin init --dump</code> (dumps the configuration).</p>



<pre class="wp-block-code"><code>ubuntu@tutorial:~$ <kbd>incus admin init</kbd>
Would you like to use clustering? (yes/no) &#91;default=no]: 
Do you want to configure a new storage pool? (yes/no) &#91;default=yes]: 
Name of the new storage pool &#91;default=default]: 
Name of the storage backend to use (zfs, dir) &#91;default=zfs]: 
Create a new ZFS pool? (yes/no) &#91;default=yes]: 
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) &#91;default=no]: 
Size in GiB of the new loop device (1GiB minimum) &#91;default=5GiB]: 
<mark style="background-color:#00d084" class="has-inline-color">Would you like to create a new local network bridge? (yes/no) &#91;default=yes]: 
What should the new bridge be called? &#91;default=incusbr0]: 
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) &#91;default=auto]: 
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) &#91;default=auto]: </mark>
Would you like the server to be available over the network? (yes/no) &#91;default=no]: 
Would you like stale cached images to be updated automatically? (yes/no) &#91;default=yes]: 
Would you like a YAML "init" preseed to be printed? (yes/no) &#91;default=no]: <kbd>yes</kbd>
config: {}
<mark style="background-color:#8ed1fc" class="has-inline-color">networks</mark>:
- config:
    ipv4.address: auto
    ipv6.address: auto
  description: ""
  name: incusbr0
  type: ""
  project: default
<mark style="background-color:#8ed1fc" class="has-inline-color">storage_pools</mark>:
- config:
    size: 5GiB
  description: ""
  name: default
  driver: zfs
<mark style="background-color:#8ed1fc" class="has-inline-color">profiles</mark>:
- config: {}
  description: ""
  <mark style="background-color:#0693e3" class="has-inline-color">devices</mark>:
    eth0:
      name: eth0
      network: incusbr0
      type: nic
    root:
      path: /
      pool: default
      type: disk
  name: default
<mark style="background-color:#8ed1fc" class="has-inline-color">projects</mark>: &#91;]
<mark style="background-color:#8ed1fc" class="has-inline-color">cluster</mark>: null

ubuntu@tutorial:~$</code></pre>



<p>If you accept the defaults (i.e. press Enter in each) or type them explicitly, you get a local bridge named <code>incusbr0</code> that is managed by Incus, and gives private IPv4 and IPv6 IP addresses to your newly created instances. </p>



<p>Let&#8217;s see them in practice in your Incus installation. You have configured Incus and Incus created a default <em>profile</em>, called <strong>default</strong>, for you. This profile is applied by default to all newly created instances and has the networking configuration in there. In that profile there are two devices, and one of them is the networking device. In Incus the device is called <code>eth0</code> (in pink color), and in the instance it will be shown as <code>eth0</code> (green color). On the host, the bridge will appear with the name <code>incusbr0</code>. It&#8217;s a networking type, hence of type <code>nic</code>.</p>



<pre class="wp-block-code"><code>ubuntu@tutorial:~$ <kbd>incus profile list</kbd>
+---------+-----------------------+---------+
|  NAME   |      DESCRIPTION      | USED BY |
+---------+-----------------------+---------+
| <mark style="background-color:#8ed1fc" class="has-inline-color">default</mark> | Default Incus profile | 0       |
+---------+-----------------------+---------+
ubuntu@tutorial:~$ <kbd>incus profile show default</kbd>
config: {}
description: Default Incus profile
<mark style="background-color:#fcb900" class="has-inline-color">devices</mark>:
  <mark style="background-color:#f78da7" class="has-inline-color">eth0</mark>:
    name: <mark style="background-color:#7bdcb5" class="has-inline-color has-black-color">eth0</mark>
    network: <mark style="background-color:#0693e3" class="has-inline-color">incusbr0</mark>
    type: <mark style="background-color:#abb8c3" class="has-inline-color">nic</mark>
  root:
    path: /
    pool: default
    type: disk
name: <mark style="background-color:#8ed1fc" class="has-inline-color">default</mark>
used_by: &#91;]
ubuntu@tutorial:~$ 
</code></pre>



<p><code>incusbr0</code> was created by Incus. Let&#8217;s see details through the <code>incus network</code> commands. We first <strong><em>list</em></strong> the network interfaces and then we <strong><em>show</em></strong> the <code>incusbr0</code> network interface. <code>incusbr0</code> is a <strong><em>managed</em></strong> network interface (in pink below), and it&#8217;s managed by Incus. Incus takes care of the networking and provides DHCP services, and access to the upstream network (i.e. the Internet). <code>incusbr0</code> is a network bridge (in blue). An instance that requires network configuration from <code>incusbr0</code>, will get an IP address from the range <code>10.180.234.1-254</code> (in orange). Network Address Translation (NAT) is enabled (also in orange), which means there is access to the upstream network, and likely the Internet. </p>



<pre class="wp-block-code"><code>ubuntu@tutorial:~$ <kbd>incus network list</kbd>
+----------+----------+---------+-----------------+---------+---------+
|   NAME   |   TYPE   | MANAGED |      IPV4       | USED BY |  STATE  |    
+----------+----------+---------+-----------------+---------+---------+
| enp5s0   | physical | NO      |                 | 0       |         |    
+----------+----------+---------+-----------------+---------+---------+
| <mark style="background-color:#00d084" class="has-inline-color">incusbr0</mark> | bridge   | <mark style="background-color:#f78da7" class="has-inline-color">YES</mark>     | 10.180.234.1/24 | 1       | CREATED |
+----------+----------+---------+-----------------+---------+---------+
ubuntu@tutorial:~$ <kbd>incus network show incusbr0</kbd>
config:
  <mark style="background-color:#fcb900" class="has-inline-color">ipv4.address</mark>: 10.180.234.1/24
  <mark style="background-color:#fcb900" class="has-inline-color has-black-color">ipv4.nat</mark>: "true"
  ipv6.address: fd42:7:7dfe:75cf::1/64
  ipv6.nat: "true"
description: ""
name: <mark style="background-color:#00d084" class="has-inline-color">incusbr0</mark>
type: <mark style="background-color:#8ed1fc" class="has-inline-color">bridge</mark>
used_by:
- /1.0/profiles/default
managed: <mark style="background-color:#f78da7" class="has-inline-color">true</mark>
status: Created
locations:
- none
ubuntu@tutorial:~$ </code></pre>



<p>Let&#8217;s launch a container and test these out. The instance got an IP address (in orange) that is within the range of the network bridge above. </p>



<pre class="wp-block-code"><code>ubuntu@tutorial:~$ <kbd>incus launch images:alpine/edge/cloud myalpine</kbd>
Launching myalpine
ubuntu@tutorial:~$ <kbd>incus list -c ns4t</kbd>     
+----------+---------+----------------------+-----------+
|   NAME   |  STATE  |         IPV4         |   TYPE    |
+----------+---------+----------------------+-----------+
| myalpine | RUNNING | <mark style="background-color:#fcb900" class="has-inline-color">10.180.234.24 (eth0)</mark> | CONTAINER |
+----------+---------+----------------------+-----------+
ubuntu@tutorial:~$ </code></pre>



<p>The IP address is OK but could it look better? It&#8217;s private anyway, and we can select anything from the range <code>10.x.y.z</code>. Let&#8217;s change it so that it uses instead <code>10.10.10.1-254</code>. We set the configuration of <code>incusbr0</code> for <code>ipv4.address</code> (see earlier) to a new value, <code>10.10.10.1/24</code>. Each number separated by commas is 8 bits in length, and <code>/24</code> means that the first 3 * 8 = 24 bits should stay the same. We make the change, but the instance still has the old IP address. We restart the instance, and it automatically gets the new IP address  from the new range. </p>



<pre class="wp-block-code"><code>ubuntu@tutorial:~$ <kbd>incus network set incusbr0 ipv4.address=10.10.10.1/24</kbd>
ubuntu@tutorial:~$ <kbd>incus list -c ns4t</kbd>
+----------+---------+----------------------+-----------+
|   NAME   |  STATE  |         IPV4         |   TYPE    |
+----------+---------+----------------------+-----------+
| myalpine | RUNNING | <mark style="background-color:#fcb900" class="has-inline-color">10.180.234.24</mark> (eth0) | CONTAINER |
+----------+---------+----------------------+-----------+
ubuntu@tutorial:~$ <kbd>incus restart myalpine</kbd>
ubuntu@tutorial:~$ <kbd>incus list -c ns4t</kbd>
+----------+---------+--------------------+-----------+
|   NAME   |  STATE  |        IPV4        |   TYPE    |
+----------+---------+--------------------+-----------+
| myalpine | RUNNING | <mark style="background-color:#00d084" class="has-inline-color">10.10.10.24</mark> (eth0) | CONTAINER |
+----------+---------+--------------------+-----------+
ubuntu@tutorial:~$ </code></pre>



<p>We have created <code>incusbr0</code>. Are we allowed to create another private bridge? Sure we are. We will call it <code>incusbr1</code>, and also we disable IPv6 networking. IPv6 addresses are too wide and mess up the formatting on my blog. If you notice earlier, there were no IPv6 addresses although IPv6 was configured on <code>incusbr0</code>. I cheated and removed the IPv6 addresses in some command outputs.</p>



<pre class="wp-block-code"><code>ubuntu@tutorial:~$ <kbd>incus network create incusbr1 ipv4.address=10.10.20.1/24 ipv6.address=none</kbd>
Network <mark style="background-color:#8ed1fc" class="has-inline-color">incusbr1</mark> created
ubuntu@tutorial:~$ <kbd>incus network show incusbr1</kbd>
config:
  ipv4.address: <mark style="background-color:#00d084" class="has-inline-color">10.10.20.1/24</mark>
  ipv6.address: <mark style="background-color:#fcb900" class="has-inline-color">none</mark>
description: ""
name: <mark style="background-color:#8ed1fc" class="has-inline-color">incusbr1</mark>
type: bridge
used_by: &#91;]
managed: true
status: Created
locations:
- none
ubuntu@tutorial:~$ </code></pre>



<p>We have created <code>incusbr1</code>. Can we now launch an instance onto that private bridge? We launch the instance called <em>myalpine1</em> and we used the <code>incus launch</code> parameter <code>--network incusbr1</code> to specify a different network than the default network in the <em>default</em> Incus profile. We verify below that <em>myalpine1</em> is served by <em>incusbr1</em> (in green).</p>



<pre class="wp-block-code"><code>ubuntu@tutorial:~$ <kbd>incus launch images:alpine/edge/cloud myalpine1 --network incusbr1</kbd>
Launching myalpine1
ubuntu@tutorial:~$ <kbd>incus list -c ns4t</kbd>
+-----------+---------+--------------------+-----------+
|   NAME    |  STATE  |        IPV4        |   TYPE    |
+-----------+---------+--------------------+-----------+
| myalpine  | RUNNING | 10.10.10.24 (eth0) | CONTAINER |
+-----------+---------+--------------------+-----------+
| myalpine1 | RUNNING | <mark style="background-color:#8ed1fc" class="has-inline-color">10.10.20.85</mark> (eth0) | CONTAINER |
+-----------+---------+--------------------+-----------+
ubuntu@tutorial:~$ <kbd>incus network show incusbr1</kbd>
config:
  ipv4.address: <mark style="background-color:#8ed1fc" class="has-inline-color">10.10.20.1/24</mark>
  ipv6.address: none
description: ""
name: incusbr1
type: bridge
<mark style="background-color:#00d084" class="has-inline-color">used_by</mark>:
- /1.0/instances/myalpine1
managed: true
status: Created
locations:
- none
ubuntu@tutorial:~$ </code></pre>


<h2 class="wp-block-heading" id="technical-details">Technical details</h2>


<p>The instances that use the Incus private bridge have access to the Internet. How is this achieved? It&#8217;s achieve with either <code>iptables</code> or <code>nftables</code> rules. In recent versions of Linux distributions, you would be using <code>nftables</code> by default (command: <code>nft</code>, no relation to NFTs). To view <em>the firewall ruleset</em> that were created by Incus, run <code>sudo nft list ruleset</code>. Here is my ruleset and should be similar to yours. There is one table for Incus and four <strong><em>chains</em></strong>. A <em>persistent</em>, a <em>forward</em>, an <em>in</em> and an <em>out</em>. More at <a href="https://wiki.nftables.org/wiki-nftables/index.php/Main_Page">the documentation site at nftables</a>.</p>



<pre class="wp-block-code"><code>ubuntu@tutorial:~$ <kbd>sudo nft list ruleset</kbd>
<mark style="background-color:#8ed1fc" class="has-inline-color">table inet</mark> incus {
	<mark style="background-color:#8ed1fc" class="has-inline-color">chain</mark> <mark style="background-color:#00d084" class="has-inline-color">pstrt</mark>.incusbr0 {
		type nat hook postrouting priority srcnat; policy accept;
		ip saddr 10.57.39.0/24 ip daddr != 10.57.39.0/24 masquerade
		ip6 saddr fd42:e7b:739c:7117::/64 ip6 daddr != fd42:e7b:739c:7117::/64 masquerade
	}

	<mark style="background-color:#8ed1fc" class="has-inline-color">chain</mark> <mark style="background-color:#00d084" class="has-inline-color">fwd</mark>.incusbr0 {
		type filter hook forward priority filter; policy accept;
		ip version 4 oifname "incusbr0" accept
		ip version 4 iifname "incusbr0" accept
		ip6 version 6 oifname "incusbr0" accept
		ip6 version 6 iifname "incusbr0" accept
	}

	<mark style="background-color:#8ed1fc" class="has-inline-color">chain</mark> <mark style="background-color:#00d084" class="has-inline-color">in</mark>.incusbr0 {
		type filter hook input priority filter; policy accept;
		iifname "incusbr0" tcp dport 53 accept
		iifname "incusbr0" udp dport 53 accept
		iifname "incusbr0" icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
		iifname "incusbr0" udp dport 67 accept
		iifname "incusbr0" icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, nd-router-solicit, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } accept
		iifname "incusbr0" udp dport 547 accept
	}

	<mark style="background-color:#8ed1fc" class="has-inline-color">chain</mark> <mark style="background-color:#00d084" class="has-inline-color">out</mark>.incusbr0 {
		type filter hook output priority filter; policy accept;
		oifname "incusbr0" tcp sport 53 accept
		oifname "incusbr0" udp sport 53 accept
		oifname "incusbr0" icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
		oifname "incusbr0" udp sport 67 accept
		oifname "incusbr0" icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } accept
		oifname "incusbr0" udp sport 547 accept
	}
}
ubuntu@tutorial:~$ </code></pre>


<h2 class="wp-block-heading" id="future-considerations">Future considerations</h2>


<ol class="wp-block-list">
<li><a href="https://discuss.linuxcontainers.org/t/network-isolation-by-project-on-single-server-incus-host/19843/4">Network isolation</a>.</li>
</ol>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.simos.info/useful-networking-tips-with-incus/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">45684</post-id>	</item>
		<item>
		<title>How to recover or reconnect an Incus storage pool</title>
		<link>https://blog.simos.info/how-to-recover-or-reconnect-an-incus-storage-pool/</link>
					<comments>https://blog.simos.info/how-to-recover-or-reconnect-an-incus-storage-pool/#respond</comments>
		
		<dc:creator><![CDATA[Simos Xenitellis]]></dc:creator>
		<pubDate>Wed, 11 Sep 2024 14:05:17 +0000</pubDate>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[Planet Ubuntu]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[Ubuntu-gr]]></category>
		<category><![CDATA[incus]]></category>
		<category><![CDATA[lxd]]></category>
		<category><![CDATA[pool]]></category>
		<category><![CDATA[recovery]]></category>
		<category><![CDATA[storage pool]]></category>
		<category><![CDATA[volume]]></category>
		<category><![CDATA[zfs]]></category>
		<guid isPermaLink="false">https://blog.simos.info/?p=49069</guid>

					<description><![CDATA[Incus is a manager for virtual machines, system containers and application containers. Get Incus support here. When you initially setup Incus, you create a storage pool where Incus will put in there everything. There are several options for storage pools, in this post we focus on ZFS storage pools, and those specifically that are stored &#8230; </p><p><a class="more-link btn" href="https://blog.simos.info/how-to-recover-or-reconnect-an-incus-storage-pool/">Continue reading</a>]]></description>
										<content:encoded><![CDATA[
<p><a href="https://linuxcontainers.org/incus/">Incus</a> is a manager for <em>virtual machines</em>, <em>system containers</em> and <em>application containers</em>. <a href="https://discuss.linuxcontainers.org/">Get Incus support here</a>. </p>



<p>When you initially setup Incus, you create a storage pool where Incus will put in there everything. There are several options for storage pools, in this post we focus on ZFS storage pools, and those specifically that are stored on a separate block device (like <code>/dev/sdb</code>).</p>



<p>We are dealing with two cases. One, your installation of Incus has been somehow removed but the storage pool is somewhere there intact and you want to recover by installing again Incus. Two, you want to move the disk with storage pool from one computer to another, like reconnecting the storage pool on a new server. </p>



<p>This type of task is quite risky if you have a lot of important data on your system. Obviously, prior to you actually doing this on an actual system, you should take backups with <code>incus export</code> of your most important instances. And then, you should perform this tutorial several times so that you get the gist of recovering Incus installations. This tutorial shows you how to do a dry run of creating an Incus installation, killing it off, and then miraculously recovering it.</p>


<h2 class="wp-block-heading" id="prerequisites">Prerequisites</h2>


<p>You should have <a href="https://linuxcontainers.org/incus/docs/main/installing/">a running Incus installation</a>.</p>


<h2 class="wp-block-heading" id="setting-up-incus-using-a-block-storage-volume"> Setting up Incus, using a block storage volume</h2>


<p>We launch an Incus virtual machine (VM) that will act as our Incus server. We then (on the host) create a storage volume of type <strong><em>block</em></strong>. Next, we attach that block storage volume to the VM. In the VM it can be found as <code>/dev/sdb</code>. Subsequently, we <code>incus admin init</code> to initialize Incus, and configure Incus to use the block device <code>/dev/sdb</code> when creating the storage pool. When we run <code>incus admin init</code>, we press Enter when we want to accept the default value.</p>



<pre class="wp-block-code"><code>$ <kbd>incus launch images:ubuntu/24.04/cloud --vm incusserver</kbd>
Launching incusserver
$ <kbd>incus storage volume create default IncusStorage --type=block size=6GiB</kbd>
Storage volume IncusStorage created
$ <kbd>incus storage volume attach default IncusStorage incusserver</kbd>
$ <kbd>incus shell incusserver</kbd>
root@incusserver:~# <kbd>fdisk -l /dev/sdb</kbd>
<mark style="background-color:#00d084" class="has-inline-color">Disk /dev/sdb: 6 GiB</mark>, 6442450944 bytes, 12582912 sectors
Disk model: QEMU HARDDISK   
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
root@incusserver:~# <kbd>sudo apt install -y incus zfsutils-linux</kbd>
...
root@incusserver:~# <kbd>incus admin init</kbd>
Would you like to use clustering? (yes/no) &#91;default=no]: 
Do you want to configure a new storage pool? (yes/no) &#91;default=yes]: 
Name of the new storage pool &#91;default=default]: 
Name of the storage backend to use (dir, zfs) &#91;default=zfs]: 
Create a new ZFS pool? (yes/no) &#91;default=yes]: 
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) &#91;default=no]: <kbd>yes</kbd>
Path to the existing block device: <kbd>/dev/sdb</kbd>
Would you like to create a new local network bridge? (yes/no) &#91;default=yes]: 
What should the new bridge be called? &#91;default=incusbr0]: 
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) &#91;default=auto]: 
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) &#91;default=auto]: 
Would you like the server to be available over the network? (yes/no) &#91;default=no]: 
Would you like stale cached images to be updated automatically? (yes/no) &#91;default=yes]: 
Would you like a YAML "init" preseed to be printed? (yes/no) &#91;default=no]: <kbd>yes</kbd>
config: {}
networks:
- config:
    ipv4.address: auto
    ipv6.address: auto
  description: ""
  name: incusbr0
  type: ""
  project: default
<mark style="background-color:#7bdcb5" class="has-inline-color">storage_pools</mark>:
- config:
    <mark style="background-color:#f78da7" class="has-inline-color">source: /dev/sdb</mark>
  description: ""
  name: <mark style="background-color:#8ed1fc" class="has-inline-color">default</mark>
  driver: zfs
profiles:
- config: {}
  description: ""
  devices:
    eth0:
      name: eth0
      network: incusbr0
      type: nic
    root:
      path: /
      pool: default
      type: disk
  name: default
projects: &#91;]
cluster: null

root@incusserver:~#</code></pre>



<p>Next we populate the Incus installation with a few alpines. We do this because we want to see these containers again after we recover the storage pool.</p>



<pre class="wp-block-code"><code>root@incusserver:~# <kbd>incus launch images:alpine/edge alpine1</kbd>
Launching alpine1
root@incusserver:~# <kbd>incus launch images:alpine/edge alpine2</kbd>
Launching alpine2
root@incusserver:~# <kbd>incus launch images:alpine/edge alpine3</kbd>
Launching alpine3
root@incusserver:~#</code></pre>



<p>This is where the interesting stuff start. We now want to shutdown the Incus server and remove it. However, the block storage volume will still be there and in good condition, as the server has been shutdown cleanly. Note that the <strong><em>block</em></strong> storage volumes should only be attached to one system at a time.</p>



<pre class="wp-block-code"><code>root@incusserver:~# <kbd>shutdown -h now</kbd>
root@incusserver:~# Error: websocket: close 1006 (abnormal closure): unexpected EOF
$ <kbd>incus storage volume show default IncusStorage</kbd>
config:
  size: 6GiB
description: ""
name: IncusStorage
type: custom
used_by:
- /1.0/instances/incusserver
location: none
content_type: block
project: default
created_at: ...
$ <kbd>incus delete incusserver</kbd>
$ <kbd>incus storage volume show default IncusStorage</kbd>
config:
  size: 6GiB
description: ""
name: IncusStorage
type: custom
used_by: &#91;]
location: none
content_type: block
project: default
created_at: ...
$</code></pre>



<p>Next, we launch a new VM that will be used as a new Incus server, then attach back the block storage volume with <code>incus storage volume attach</code> and install Incus along with the necessary ZFS client utils.</p>



<pre class="wp-block-code"><code>$ <kbd>incus launch images:ubuntu/24.04/cloud --vm incusserver</kbd>
Launching incusserver
$ <kbd>incus storage volume attach default IncusStorage incusserver</kbd>
$ <kbd>incus shell incusserver</kbd>
Error: Instance is not running
$ <kbd>incus shell incusserver</kbd>
Error: VM agent isn't currently running
$ <kbd>incus shell incusserver</kbd>
Error: VM agent isn't currently running
$ <kbd>incus shell incusserver</kbd>
Error: VM agent isn't currently running
$ <kbd>incus shell incusserver</kbd>
Error: VM agent isn't currently running
$ <kbd>incus shell incusserver</kbd>
Error: VM agent isn't currently running
$ <kbd>incus shell incusserver</kbd>
Error: VM agent isn't currently running
$ <kbd>incus shell incusserver</kbd>
root@incusserver:~# <kbd>apt install -y zfsutils-linux incus</kbd>
...
root@incusserver:~#</code></pre>



<p>Finally, we bring back the old installation data with those three alpines. We run <code>zpool import</code>, which is a ZFS command that will look for potential ZFS pools and list them by name. The command <code>zpool import default</code> is the one that does the actual import. The ZFS pool name <em>default</em> was the name that was given by Incus before, when we were initializing Incus. Subsequently, we run <code>incus admin recover</code> to recover the ZFS pool and reconnect it with this new installation of Incus.</p>



<pre class="wp-block-code"><code>root@incusserver:~# <kbd>zfs list</kbd>
no datasets available
root@incusserver:~# <kbd>zpool list</kbd>
no pools available
root@incusserver:~# <kbd>zpool import</kbd>
   pool: default
     id: 8311839500301555365
  state: ONLINE
 action: The pool can be imported using its name or numeric identifier.
 config:

	default     ONLINE
	  sdb       ONLINE
root@incusserver:~# <kbd>zpool import default</kbd>
root@incusserver:~# <kbd>zpool list</kbd>
NAME      SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
default  5.50G  6.80M  5.49G        -         -     0%     0%  1.00x    ONLINE  -
root@incusserver:~# 
root@incusserver:~# <kbd>incus admin recover</kbd>
This server currently has the following storage pools:
Would you like to recover another storage pool? (yes/no) &#91;default=no]: <kbd>yes</kbd>
Name of the storage pool: <kbd>default</kbd>
Name of the storage backend (zfs, dir): <kbd>zfs</kbd>
Source of the storage pool (block device, volume group, dataset, path, ... as applicable): <kbd>/dev/sdb</kbd>
Additional storage pool configuration property (KEY=VALUE, empty when done): 
Would you like to recover another storage pool? (yes/no) &#91;default=no]: 
The recovery process will be scanning the following storage pools:
 - NEW: "default" (backend="zfs", source="/dev/sdb")
Would you like to continue with scanning for lost volumes? (yes/no) &#91;default=yes]: 
Scanning for unknown volumes...
The following unknown storage pools have been found:
 - Storage pool "default" of type "zfs"
The following unknown volumes have been found:
 - Container "alpine2" on pool "default" in project "default" (includes 0 snapshots)
 - Container "alpine3" on pool "default" in project "default" (includes 0 snapshots)
 - Container "alpine1" on pool "default" in project "default" (includes 0 snapshots)
Would you like those to be recovered? (yes/no) &#91;default=no]: <kbd>yes</kbd>
Starting recovery...
root@incusserver:~# <kbd>incus list</kbd>
+---------+---------+------+------+-----------+-----------+
|  NAME   |  STATE  | IPV4 | IPV6 |   TYPE    | SNAPSHOTS |
+---------+---------+------+------+-----------+-----------+
| alpine1 | STOPPED |      |      | CONTAINER | 0         |
+---------+---------+------+------+-----------+-----------+
| alpine2 | STOPPED |      |      | CONTAINER | 0         |
+---------+---------+------+------+-----------+-----------+
| alpine3 | STOPPED |      |      | CONTAINER | 0         |
+---------+---------+------+------+-----------+-----------+
root@incusserver:~#</code></pre>



<p>Those alpines are in a <strong><em>STOPPED</em></strong> state. Will they <em>start</em>? Sure they will.</p>



<pre class="wp-block-code"><code>root@incusserver:~# <kbd>incus start alpine1 alpine2 alpine3</kbd>
root@incusserver:~# <kbd>incus list -c ns4t</kbd>
+---------+---------+----------------------+-----------+
|  NAME   |  STATE  |         IPV4         |   TYPE    |
+---------+---------+----------------------+-----------+
| alpine1 | RUNNING | 10.36.146.69 (eth0)  | CONTAINER |
+---------+---------+----------------------+-----------+
| alpine2 | RUNNING | 10.36.146.101 (eth0) | CONTAINER |
+---------+---------+----------------------+-----------+
| alpine3 | RUNNING | 10.36.146.248 (eth0) | CONTAINER |
+---------+---------+----------------------+-----------+
root@incusserver:~#</code></pre>



<p>In this tutorial we saw how to recover an Incus installation, while the storage pool is intact. We covered the case that the storage pool is ZFS on a block device. </p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.simos.info/how-to-recover-or-reconnect-an-incus-storage-pool/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">49069</post-id>	</item>
		<item>
		<title>How to use your Android phone with ADB in an Incus container</title>
		<link>https://blog.simos.info/how-to-use-your-android-phone-with-adb-in-an-incus-container/</link>
					<comments>https://blog.simos.info/how-to-use-your-android-phone-with-adb-in-an-incus-container/#comments</comments>
		
		<dc:creator><![CDATA[Simos Xenitellis]]></dc:creator>
		<pubDate>Thu, 22 Aug 2024 15:35:15 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[Planet Ubuntu]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[Ubuntu-gr]]></category>
		<category><![CDATA[adb]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[incus]]></category>
		<category><![CDATA[lxd]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[usb]]></category>
		<guid isPermaLink="false">https://blog.simos.info/?p=48861</guid>

					<description><![CDATA[Incus is a manager for virtual machines and system containers. A system container (therein 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 &#8230; </p><p><a class="more-link btn" href="https://blog.simos.info/how-to-use-your-android-phone-with-adb-in-an-incus-container/">Continue reading</a>]]></description>
										<content:encoded><![CDATA[
<p><a href="https://linuxcontainers.org/incus/">Incus</a> is a manager for <em>virtual machines</em> and <em>system containers</em>.</p>



<p>A <strong>system container</strong> (therein <em>container</em>) 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 <em>software virtual machines</em>.</p>



<p>In this post we are going to see <strong><em>how to conveniently let an Incus container to have access to the Android USB debugging (ADB) of our Android mobile phone</em></strong>. Normally, you would run <code>adb</code> commands on the host. But in this case, we are launching a container and give it access to ADB. We set it up so that only the container can access the phone with ADB.</p>



<p>The reason why I am writing this post is that there are several pitfalls along the way. Let&#8217;s figure out how it all works. </p>


<h2 class="wp-block-heading" id="setting-up-the-android-phone-for-usb-debugging">Setting up the Android phone for USB Debugging</h2>


<p>To enable USB debugging on your Android phone, there&#8217;s a hidden list of steps that involves going into your phone settings, tapping seven times on the appropriate place of the About page, and then your phone shows the message <strong><em>You are now a developer</em></strong>. You will need to search for the exact steps for your device, as the place where you need to tap seven times may be different among manufacturers. </p>



<p>Still on the phone, you then need to visit another location in the phone Settings, one that is called <strong><em>Developer options</em></strong>. In there, you need to scroll a bit until you see the option <strong><em>USB debugging</em></strong>. You will need to enable that. When you click to enable, you will be presented with a warning dialog box about the ramifications of having enabled the USB debugging. Read that carefully, and enable <em><strong>USB debugging</strong></em>. Note that after this exercise, and if you do not need to use ADB for a long period, you should disable the <strong><em>Developer options</em></strong>. The risk with the enabled <strong><em>USB debugging</em></strong> is that if you connect your phone with a (data) USB cable to some malicious computer or even a malicious USB charger, they may take over your device in a very bad way.</p>



<p>In the first screenshot it shows the warning when you try to enable <strong><em>USB debugging</em></strong>. The second screenshot shows that the <strong><em>USB debugging</em></strong> has been enabled successfully.</p>



<figure data-carousel-extra='{&quot;blog_id&quot;:1,&quot;permalink&quot;:&quot;https://blog.simos.info/how-to-use-your-android-phone-with-adb-in-an-incus-container/&quot;}'  class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image alignwide size-large wp-duotone-grayscale"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enable-developer-options.jpg?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="347" height="1024" data-attachment-id="48862" data-permalink="https://blog.simos.info/how-to-use-your-android-phone-with-adb-in-an-incus-container/android-enable-developer-options/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enable-developer-options.jpg?fit=542%2C1601&amp;ssl=1" data-orig-size="542,1601" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="android-enable-developer-options" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enable-developer-options.jpg?fit=102%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enable-developer-options.jpg?fit=347%2C1024&amp;ssl=1" data-id="48862" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enable-developer-options.jpg?resize=347%2C1024&#038;ssl=1" alt="" class="wp-image-48862" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enable-developer-options.jpg?resize=347%2C1024&amp;ssl=1 347w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enable-developer-options.jpg?resize=102%2C300&amp;ssl=1 102w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enable-developer-options.jpg?resize=520%2C1536&amp;ssl=1 520w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enable-developer-options.jpg?w=542&amp;ssl=1 542w" sizes="auto, (max-width: 347px) 100vw, 347px" /></a></figure>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enabled-developer-options.jpg?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="461" height="1024" data-attachment-id="48863" data-permalink="https://blog.simos.info/how-to-use-your-android-phone-with-adb-in-an-incus-container/android-enabled-developer-options/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enabled-developer-options.jpg?fit=720%2C1600&amp;ssl=1" data-orig-size="720,1600" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="android-enabled-developer-options" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enabled-developer-options.jpg?fit=135%2C300&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enabled-developer-options.jpg?fit=461%2C1024&amp;ssl=1" data-id="48863" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enabled-developer-options.jpg?resize=461%2C1024&#038;ssl=1" alt="" class="wp-image-48863" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enabled-developer-options.jpg?resize=461%2C1024&amp;ssl=1 461w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enabled-developer-options.jpg?resize=135%2C300&amp;ssl=1 135w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enabled-developer-options.jpg?resize=691%2C1536&amp;ssl=1 691w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/08/android-enabled-developer-options.jpg?w=720&amp;ssl=1 720w" sizes="auto, (max-width: 461px) 100vw, 461px" /></a></figure>
</figure>



<p>There&#8217;s an option in the second screenshot to <strong><em>Revoke USB debugging authorizations</em></strong>. I recommend to do that, especially if you have already connected your phone to your computer. By doing so, we can make sure that the host is not able to connect successfully to the device, and only the container can do so. Note that when you try to connect to the device with <code>adb</code>, you get a dialog box on the phone on whether to authorize this new connection.</p>



<p>When you connect your Android phone to your Linux host, the device should appear in the output of <code>lsusb</code> (list USB devices) as follows. I think the USB Vendor and Product IDs should be the same, 0x18d1 and 0x4ee7 respectively. And it should say at the end &#8220;<strong><em>(charging + debug)</em></strong>&#8220;. If you get something else, then you fell for the Android notification that says <strong><em>Use USB for [File Transfer / Android Auto]</em></strong>. That&#8217;s not good for us that we need USB debugging. The proper setting is <strong><em>Use USB for [No data transfer]</em></strong>. Yeah, a bit counter-intuitive. </p>



<pre class="wp-block-code"><code>$ <kbd>lsusb</kbd>
...
Bus 005 Device 005: ID <mark style="background-color:#00d084" class="has-inline-color">18d1:4ee7</mark> Google Inc. Nexus/Pixel Device <mark style="background-color:#8ed1fc" class="has-inline-color">(charging + debug)</mark>
...
$ </code></pre>


<h2 class="wp-block-heading" id="setting-up-the-host">Setting up the host</h2>


<p>In order to let the container have access to the phone, we need to make sure that there is no <code>adb</code> command on the host that is running. We can make sure that this is the case, if we run the following. If the ADB server is running on the host, then the container does not have access to the device. Interestingly, if you setup the container properly and ADB is running on the host, then as soon as you <code>adb kill-server</code> on the host, the container immediately has access to the device.</p>



<pre class="wp-block-code"><code><kbd>sudo adb kill-server</kbd></code></pre>


<h2 class="wp-block-heading" id="creating-the-container">Creating the container</h2>


<p>We are creating the container, we will called it <em>adb</em>, and it has access to USB debugging on the Android phone. The way we work with Incus is that we create a container with the task of accessing the phone, and then keep that container whenever we need to access the phone. In the <code>incus config device</code> command, we <code>add</code> to the <code>adb</code> container a device called <code>adb</code>(can use any name here), which is of type <code>usb</code>, and has the vendor and product IDs shown below. Finally, we restart the container. </p>



<pre class="wp-block-code"><code>$ <kbd>incus launch images:debian/12/cloud adb</kbd>
Launching adb
$ <kbd>incus config device add adb adb usb vendorid=18d1 productid=4ee7</kbd>
Device adb added to adb
user@user-desktop:~$ incus exec adb -- apt install -y adb
...
$ <kbd>incus restart adb</kbd>
$ </code></pre>


<h2 class="wp-block-heading" id="using-adb-in-the-incus-container">Using adb in the Incus container</h2>


<p>Let&#8217;s run <code>adb devices</code> in the container. You will most likely get <strong><em>unauthorized</em></strong>. When you run this command, your phone will prompt you whether you want to authorize this access. You should select to authorize the access.</p>



<pre class="wp-block-code"><code>$ <kbd>incus exec adb -- adb devices</kbd>
* daemon not running; starting now at tcp:5037
* daemon started successfully
List of devices attached
42282370	unauthorized
$ </code></pre>



<p>Now, run again the command.</p>



<pre class="wp-block-code"><code>$ <kbd>incus exec adb -- adb devices</kbd>
List of devices attached
42282370	device
$ </code></pre>



<p>And that&#8217;s it. </p>


<h2 class="wp-block-heading" id="stress-testing-adb-in-the-incus-container">Stress testing adb in the Incus container</h2>


<p>You would like to make this setup as robust as possible. One step is to remove the <code>adb</code> binary from the host.</p>



<p>Another test is to restart the container, and then check whether it still has access to the device.</p>



<pre class="wp-block-code"><code>$ <kbd>incus restart adb</kbd>
$ <kbd>incus exec adb -- adb devices</kbd>
* daemon not running; starting now at tcp:5037
* daemon started successfully
List of devices attached
42282370	device

$ <kbd>incus restart adb</kbd>
$ <kbd>incus exec adb -- adb devices</kbd>
* daemon not running; starting now at tcp:5037
* daemon started successfully
List of devices attached
42282370	device
$ </code></pre>



<p>Obviously, when you want to perform more work with <code>adb</code>, you can just get a shell into the container. </p>



<pre class="wp-block-code"><code>$ <kbd>incus exec adb -- sudo --login --user debian</kbd>
debian@adb:~$ <kbd>adb devices</kbd>
List of devices attached
42285120	device

debian@adb:~$ <kbd>adb shell</kbd>
komodo:/ $ <kbd>exit</kbd>
debian@adb:~$ <kbd>logout</kbd>
$ </code></pre>


<h2 class="wp-block-heading" id="conclusion">Conclusion</h2>


<p>If you setup your system so that only a designated container can have access to your Android phone with USB debugging, then you get a bit better setup in terms of security. </p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.simos.info/how-to-use-your-android-phone-with-adb-in-an-incus-container/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">48861</post-id>	</item>
		<item>
		<title>How to share a folder between a host and a container in Incus</title>
		<link>https://blog.simos.info/how-to-share-a-folder-between-a-host-and-a-container-in-incus/</link>
					<comments>https://blog.simos.info/how-to-share-a-folder-between-a-host-and-a-container-in-incus/#comments</comments>
		
		<dc:creator><![CDATA[Simos Xenitellis]]></dc:creator>
		<pubDate>Thu, 22 Aug 2024 13:08:33 +0000</pubDate>
				<category><![CDATA[general]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[Planet Ubuntu]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[Ubuntu-gr]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[GID]]></category>
		<category><![CDATA[incus]]></category>
		<category><![CDATA[lxd]]></category>
		<category><![CDATA[UID]]></category>
		<guid isPermaLink="false">https://blog.simos.info/?p=46660</guid>

					<description><![CDATA[Incus is a manager for virtual machines and system containers. A system container (therein 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 &#8230; </p><p><a class="more-link btn" href="https://blog.simos.info/how-to-share-a-folder-between-a-host-and-a-container-in-incus/">Continue reading</a>]]></description>
										<content:encoded><![CDATA[
<p><a href="https://linuxcontainers.org/incus/">Incus</a> is a manager for <em>virtual machines</em> and <em>system containers</em>. </p>



<p>A <strong>system container</strong> (therein <em>container</em>) 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 <em>software virtual machines</em>.</p>



<p>In this post we are going to see <strong><em>how to conveniently share a folder between the host and an Incus container</em></strong>. The common use-case is that you want to share directly files between the host and a container and you want the file ownership to be handled well. Note that in a container the UID and GID do not correspond to the same values as on the host.</p>



<p>Therefore, we are looking on <strong><em>how to share storage between the host and one or more Incus containers</em></strong>. The other case that we look into earlier, is to <a href="https://blog.simos.info/how-to-manage-the-files-of-several-incus-containers-from-a-separate-incus-container/">share storage between containers that has been allocated on the Incus storage pool</a>.</p>


<h2 class="wp-block-heading" id="quick-answer">Quick answer</h2>


<pre class="wp-block-code"><code><kbd>incus config device add mycontainer mysharedfolder disk source=/home/myusername/SHARED path=/SHARED <mark style="background-color:#00d084" class="has-inline-color">shift=true</mark></kbd></code></pre>


<h2 class="simpletoc-title">Table of Contents</h2>
<ul class="simpletoc-list">
<li><a href="#quick-answer">Quick answer</a>

</li>
<li><a href="#background">Background</a>

</li>
<li><a href="#somewhat-sharing-folders-between-the-host-and-incus-containers">Somewhat sharing folders between the host and Incus containers</a>

</li>
<li><a href="#how-to-properly-share-a-folder-between-a-host-and-a-container-in-incus">How to properly share a folder between a host and a container in Incus</a>

</li>
<li><a href="#incus-config-device-commads">Incus config device commads</a>

</li>
<li><a href="#conclusion">Conclusion</a>
</li></ul>

<h2 class="wp-block-heading" id="background">Background</h2>


<p><a href="https://systemd.io/UIDS-GIDS/">On a Linux system the User ID (UID) and Group ID (GID) values</a> are generally in the range of 0 (for <code>root</code>) to 65534 (for <code>nobody</code>). You can verify this by having a look at your <code>/etc/passwd</code> file on your system. In this file, each line is a different account; either a system account or a user account. Such a sample line is the following. There are several fields, separated by a colon character (<code>:</code>). The first field is the user name (here, <code>root</code>). The third field is the numeric user ID (UID) with the value of <code>0</code>. The fourth field is the numeric group ID (GID) with the value of <code>0</code> as well. This is the root account.</p>



<pre class="wp-block-code"><code><mark style="background-color:#7bdcb5" class="has-inline-color">root</mark>:x:<mark style="background-color:#f78da7" class="has-inline-color">0</mark>:<mark style="background-color:#8ed1fc" class="has-inline-color">0</mark>:root:/root:/bin/bash</code></pre>



<p>Let&#8217;s do another one. The default user account in Debian and Debian-derived Linux distributions. The username in this Linux installation is <code>myusername</code>, the UID is <code>1000</code> and the GID is <code>1000</code> as well. This value of 1000 is quite common between Linux distributions.</p>



<pre class="wp-block-code"><code><mark style="background-color:#7bdcb5" class="has-inline-color">myusername</mark>:x:<mark style="background-color:#f78da7" class="has-inline-color">1000</mark>:<mark style="background-color:#8ed1fc" class="has-inline-color">1000</mark>:User,,,:/home/user:/bin/bash</code></pre>



<p>And now this one is the last one we will do. This is a special account with username <code>nobody</code>, and UID/GID at 65534. The purpose of this account is to be used for resources that somehow do not have a valid ID, or for processes and services that are expected to have the least privileges. In an Incus container you will see <code>nobody</code> and <code>nogroup</code> if you shared a folder and the translation of the IDs between the host and the container did not work well or did not happen at all.</p>



<pre class="wp-block-code"><code><mark style="background-color:#7bdcb5" class="has-inline-color">nobody</mark>:x:<mark style="background-color:#f78da7" class="has-inline-color">65534</mark>:<mark style="background-color:#8ed1fc" class="has-inline-color">65534</mark>:nobody:/nonexistent:/usr/sbin/nologin</code></pre>


<h2 class="wp-block-heading" id="somewhat-sharing-folders-between-the-host-and-incus-containers">Somewhat sharing folders between the host and Incus containers</h2>


<p>To share a directory from the host to your Incus container(s), you <code>add</code> a <code>disk</code> device using <code>incus config device</code>. Here, <em>mycontainer</em> is the name of the container. And <em>mysharedfolder</em> is the name of the share which is only visible in Incus. You specify the <code>source</code> (an <strong><em>existing</em></strong> folder on the  host) and the <code>path</code> (a folder in the container). However, there&#8217;s one big issue here. There&#8217;s no translation between the UID and GID of the files and directories in that folder. </p>



<pre class="wp-block-code"><code><kbd>incus config device add mycontainer mysharedfolder disk source=/home/myusername/SHARED path=/SHARED</kbd></code></pre>



<p>Here&#8217;s on the host and in the container and then again on the host. In the last command it shows an empty folder. I think it&#8217;s possible to view the contents of <em>SHARED</em> in the container from the viewpoint of the host. It would require a smart use of the <code>nsenter</code> command to enter the proper <em>namespace</em> which I am not sure yet how to do for ZFS storage pools. If it worked, it would show that UID of <em>myusername</em> in the container from the viewpoint of the host, it would be something like 1001000 (Base ID 100000 plus 1000 for the first non-root account). That is, if the container has files with UID/GID outside of its range of 100000 &#8211; 165535, those files are not accessible from within the container.</p>



<pre class="wp-block-code"><code>$ <kbd>ls -l SHARED/</kbd>
total 0
-rw-rw-r-- 1 myusername myusername 0 Ιουλ 30 19:26 one
-rw-rw-r-- 1 myusername myusername 0 Ιουλ 30 19:26 two
-rw-rw-r-- 1 myusername myusername 0 Ιουλ 30 19:26 three
$ <kbd>incus exec mycontainer -- ls -l /SHARED/</kbd>
total 0
-rw-rw-r-- 1 <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">nobody</mark> <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">nogroup</mark> 0 Jul 30 16:26 one
-rw-rw-r-- 1 <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">nobody</mark> <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">nogroup</mark> 0 Jul 30 16:26 three
-rw-rw-r-- 1 <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">nobody</mark> <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-red-color">nogroup</mark> 0 Jul 30 16:26 two
$ <kbd>sudo ls -l /var/lib/incus/containers/mycontainer/rootfs/SHARED</kbd>
total 0
$ </code></pre>



<p>This was a good exercise to show the common mistake in sharing a folder from the host to the container. You can now <em>remove</em> the <code>disk</code> device and do it again properly.</p>



<pre class="wp-block-code"><code>$ <kbd>incus config device remove mycontainer mysharedfolder</kbd>
Device mysharedfolder removed from mycontainer
$ </code></pre>


<h2 class="wp-block-heading" id="how-to-properly-share-a-folder-between-a-host-and-a-container-in-incus">How to properly share a folder between a host and a container in Incus</h2>


<p>The shared folder requires some sort of automated UID/GID shifting so that from the point of view of the container, it has valid (within range) values for the UID/GID. This is achieved with the parameter <code>shift=true</code> when we create the Incus <em>disk</em> device. </p>



<p>Let&#8217;s see a full example. We create a container and then create a folder on the host, which we call <em>SHARED</em>. Then, in that folder we create three empty files using the <code>touch</code> command. We are being fancy here. Then, we create the Incus <code>disk</code> device to share the folder into the container, and enable <code>shift=true</code>.</p>



<pre class="wp-block-code"><code>$ <kbd>incus launch images:ubuntu/24.04/cloud mycontainer</kbd>
Launching mycontainer
$ <kbd>mkdir SHARED</kbd>
$ <kbd>touch SHARED/one SHARED/two SHARED/there</kbd>
$ <kbd>incus config device add mycontainer mysharedfolder disk source=/home/myusername/SHARED path=/SHARED shift=true</kbd>
Device mysharedfolder added to mycontainer
$ </code></pre>



<p>where</p>



<ul class="wp-block-list">
<li><code>incus config device</code>, the Incus command to configure devices. </li>



<li><code>add</code>, we add a device.</li>



<li><em>mycontainer</em>, the name of the container.</li>



<li><em>mysharedfolder</em>, the name of the shared folder. This is only visible from the host, and it&#8217;s just any name. We need a name so that we can specify the device when we want to perform further management.</li>



<li><code>disk</code>, this is a disk device. Currently, <a href="https://linuxcontainers.org/incus/docs/main/reference/devices/">Incus supports 12 types of devices</a>.</li>



<li><em><code>source=</code>/home/myusername/SHARED</em>, the absolute path to the source folder. We type <code>source=</code> and then source folder, no spaces in between. The source folder (which is on the host) must already exist.</li>



<li><em><code>path=</code>/SHARED</em>, the absolute path to the folder in the container. </li>



<li><code>shift=true</code>, the setting that automagically performs the necessary UID/GID translation.</li>
</ul>



<p>In some cases, for example when your Linux kernel on the Incus host is old, the <code>shift=true</code> setting may not work. Or, some filesystems may not support it. I leave it to you to report back any cases where this did not work. In the comments below.</p>



<p>Let&#8217;s verify that everything work OK. First we see the files on the host. In my case, both the user <em>myusername</em> and group <em>myusername</em> have UID and GID 1000. In the container (which was <em>images:ubuntu/24.04/cloud</em>) they also have the same UID/GID of 1000, but for this Ubuntu runtime the default username with UID 1000 is <em>ubuntu</em>, and the default group with GID 1000 is <em>lxd</em>. These are just names and are not important. If you are still unsure, then use <code>ls</code> with the added parameter <code>--numeric-uid-gid</code> to show the numeric IDs. In both cases below, the UID and GID are 1000.</p>



<pre class="wp-block-code"><code>$ <kbd>ls -l SHARED/</kbd>
total 0
-rw-rw-r-- 1 myusername myusername 0 Ιουλ 30 19:26 one
-rw-rw-r-- 1 myusername myusername 0 Ιουλ 30 19:26 two
-rw-rw-r-- 1 myusername myusername 0 Ιουλ 30 19:26 three
$ <kbd>incus exec mycontainer -- ls -l /SHARED/</kbd>
total 0
-rw-rw-r-- 1 ubuntu lxd 0 Jul 30 16:26 one
-rw-rw-r-- 1 ubuntu lxd 0 Jul 30 16:26 two
-rw-rw-r-- 1 ubuntu lxd 0 Jul 30 16:26 three
$ </code></pre>



<p>If we had created an <code>images:debian/12/cloud</code> container, here is how the files would look like. The username with UID 1000 is <code>debian</code>, and the group with GID 1000 is <code>netdev</code>.</p>



<pre class="wp-block-code"><code>$ <kbd>incus exec mycontainer -- ls -l /SHARED/</kbd>
total 0
-rw-rw-r-- 1 debian netdev 0 Jul 30 16:26 one
-rw-rw-r-- 1 debian netdev 0 Jul 30 16:26 three
-rw-rw-r-- 1 debian netdev 0 Jul 30 16:26 two
$ </code></pre>



<p>You can create files and subfolders in the shared folder, either on the host or in the container. You can also share it between more containers. </p>


<h2 class="wp-block-heading" id="incus-config-device-commads">Incus config device commads</h2>


<p>Let&#8217;s have a look at the <code>incus config device</code> commands.</p>



<pre class="wp-block-code"><code>$ <kbd>incus config device </kbd>
Usage:
  incus config device &#91;flags]
  incus config device &#91;command]

Available Commands:
  <mark style="background-color:#00d084" class="has-inline-color">add</mark>         Add instance devices
  <mark style="background-color:#fcb900" class="has-inline-color">get</mark>         Get values for device configuration keys
  <mark style="background-color:#0693e3" class="has-inline-color">list</mark>        List instance devices
  <mark style="background-color:#abb8c3" class="has-inline-color">override</mark>    Copy profile inherited devices and override configuration keys
  <mark style="background-color:#cf2e2e" class="has-inline-color">remove</mark>      Remove instance devices
  set         Set device configuration keys
  <mark style="background-color:#9b51e0" class="has-inline-color">show</mark>        Show full device configuration
  unset       Unset device configuration keys

Global Flags:
      --debug          Show all debug messages
      --force-local    Force using the local unix socket
  -h, --help           Print help
      --project        Override the source project
  -q, --quiet          Don't show progress information
      --sub-commands   Use with help or --help to view sub-commands
  -v, --verbose        Show all information messages
      --version        Print version number

Use "incus config device &#91;command] --help" for more information about a command.
$ </code></pre>



<p>We are going to use some of those commands. First, we <mark style="background-color:#8ed1fc" class="has-inline-color">list</mark> the disk devices. There&#8217;s currently only one disk device, <em>mysharedfolder</em>. We then <mark style="background-color:#9b51e0" class="has-inline-color">show</mark> the disk device. We get the list of parameters, which we can get individually and even set them to different values. We then <mark style="background-color:#fcb900" class="has-inline-color">get</mark> the value of the <code>path</code> parameter. Finally, we <mark style="background-color:#cf2e2e" class="has-inline-color">remove</mark> the disk device. We have not shown how to <em>override</em>, <em>set</em> and <em>unset</em>.</p>



<pre class="wp-block-code"><code>$ <kbd>incus config device <mark style="background-color:#8ed1fc" class="has-inline-color">list</mark> mycontainer</kbd>
mysharedfolder
$ <kbd>incus config device <mark style="background-color:#9b51e0" class="has-inline-color">show</mark> mycontainer</kbd>
mysharedfolder:
  path: /SHARED
  shift: "true"
  source: /home/myusername/SHARED
  type: disk
$ <kbd>incus config device <mark style="background-color:#fcb900" class="has-inline-color">get</mark> mycontainer mysharedfolder path</kbd>
/SHARED
$ <kbd>incus config device <mark style="background-color:#cf2e2e" class="has-inline-color">remove</mark> mycontainer mysharedfolder </kbd>
Device mysharedfolder removed from mycontainer
$ 
</code></pre>


<h2 class="wp-block-heading" id="conclusion">Conclusion</h2>


<p>We have seen how to create disk devices on Incus containers in order to share a folder from the host to one or more containers. Using <code>shift=true</code> we can take care of the translation of the UIDs and GIDs. I am interested in corner cases where these do not work. It would help me fix this post, and eventually move it to the official documentation of Incus.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.simos.info/how-to-share-a-folder-between-a-host-and-a-container-in-incus/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">46660</post-id>	</item>
		<item>
		<title>Running OCI images (i.e. Docker) directly in Incus</title>
		<link>https://blog.simos.info/running-oci-images-i-e-docker-directly-in-incus/</link>
					<comments>https://blog.simos.info/running-oci-images-i-e-docker-directly-in-incus/#comments</comments>
		
		<dc:creator><![CDATA[Simos Xenitellis]]></dc:creator>
		<pubDate>Fri, 12 Jul 2024 16:50:21 +0000</pubDate>
				<category><![CDATA[general]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[Planet Ubuntu]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[Ubuntu-gr]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[docker.io]]></category>
		<category><![CDATA[incus]]></category>
		<category><![CDATA[lxc]]></category>
		<category><![CDATA[lxd]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[remote]]></category>
		<guid isPermaLink="false">https://blog.simos.info/?p=48282</guid>

					<description><![CDATA[One of the cool new features in Incus 6.3 is the ability to run OCI images (such as those for Docker) directly in Incus. You can certainly install the Docker packages in an Incus instance but that would put you in a situation of running a container in a container. Why not let Docker be &#8230; </p><p><a class="more-link btn" href="https://blog.simos.info/running-oci-images-i-e-docker-directly-in-incus/">Continue reading</a>]]></description>
										<content:encoded><![CDATA[
<p>One of <a href="https://discuss.linuxcontainers.org/t/incus-6-3-has-been-released/21019">the cool new features in Incus 6.3 is the ability to run OCI images (such as those for Docker) directly in Incus</a>. </p>



<p>You can certainly install the Docker packages in an Incus instance but that would put you in a situation of running a container in a container. Why not let Docker be a first-class citizen in the Incus ecosystem?</p>



<p class="has-text-align-center"><strong><mark style="background-color:#7bdcb5" class="has-inline-color">Note that this feature is new to Incus, which means that if you encounter issues, please discuss and report them.</mark></strong></p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/07/image.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="436" data-attachment-id="48284" data-permalink="https://blog.simos.info/running-oci-images-i-e-docker-directly-in-incus/image-11/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/07/image.png?fit=751%2C437&amp;ssl=1" data-orig-size="751,437" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/07/image.png?fit=300%2C175&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/07/image.png?fit=750%2C436&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/07/image.png?resize=750%2C436&#038;ssl=1" alt="" class="wp-image-48284" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/07/image.png?w=751&amp;ssl=1 751w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/07/image.png?resize=300%2C175&amp;ssl=1 300w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a><figcaption class="wp-element-caption">Launching the docker.io <code>nginx</code> OCI container image in Incus.</figcaption></figure>
</div>

<h2 class="simpletoc-title">Table of Contents</h2>
<ul class="simpletoc-list">
<li><a href="#background">Background</a>

</li>
<li><a href="#prerequisites">Prerequisites</a>

</li>
<li><a href="#adding-the-docker-repository-to-incus">Adding the Docker repository to Incus</a>

</li>
<li><a href="#launching-a-docker-image-in-incus">Launching a Docker image in Incus</a>

</li>
<li><a href="#discussion">Discussion</a>


<ul><li>
<a href="#how-long-is-the-lifecycle-time-of-a-minimal-docker-container">How long is the lifecycle time of a minimal Docker container?</a>

</li>
<li><a href="#how-long-does-it-take-to-repeatedly-run-a-minimal-docker-container">How long does it take to repeatedly run a minimal Docker container?</a>

</li>
<li><a href="#are-the-container-images-cached">Are the container images cached?</a>

</li>
</ul>
<li><a href="#troubleshooting">Troubleshooting</a>


<ul><li>
<a href="#error-cant-list-images-from-oci-registry">Error: Can&#8217;t list images from OCI registry</a>

</li>
<li><a href="#error-stat-proc1-no-such-file-or-directory">Error: stat /proc/-1: no such file or directory</a>

</li>
<li><a href="#failed-getting-remote-image-info-image-not-found">Failed getting remote image info: Image not found</a>
</li>
</ul>
</li></ul>

<h2 class="wp-block-heading" id="background">Background</h2>


<p>In Incus you typically run <em><strong>system containers</strong></em>, which are containers that have been setup to resemble a virtual machine (VM). That is, you launch a system container in Incus, and this system container keeps running until you stop it. Just like with VMs.</p>



<p>In contrast, with Docker you are running <em><strong>application containers</strong></em>. You launch the Docker container with some configuration to perform a task, the task is performed, and the container stops. The task might also be something long-lived, like a Web server. In that case, the application container will have a longer lifetime. With application containers you are thinking primarily about tasks. You stop the task and the container is gone. </p>


<h2 class="wp-block-heading" id="prerequisites">Prerequisites</h2>


<p>You need to <a href="https://linuxcontainers.org/incus/docs/main/installing/">install Incus 6.3</a>. If you are using Debian or Ubuntu, you would select <a href="https://github.com/zabbly/incus">the <strong><em>stable</em></strong> repository of Incus</a>.</p>



<pre class="wp-block-preformatted">$ <strong><kbd>incus version</kbd></strong><br>Client version: 6.3<br>Server version: 6.3<br>$ </pre>


<h2 class="wp-block-heading" id="adding-the-docker-repository-to-incus">Adding the Docker repository to Incus</h2>


<p>The container images from Docker follow the Open Container Image (OCI) format. There is also a special way to access those images through the Docker Hub Container Image Repository, which is distinctive from the other ways supported by Incus. </p>



<p>We will be adding (once only) a <strong><em>remote</em></strong> for the Docker repository. A <strong><em>remote</em></strong> is a configuration to access images from a particular repository of such images. Let&#8217;s see what we already have. We run <code>incus remote list</code> which invokes the <code>list</code> command for the functionality about remotes (<code>incus remote</code>). There are two remotes, the <code>images</code> which is <a href="https://images.linuxcontainers.org/">the standard repository for container images and virtual machine images for Incus</a>. And then there is <code>local</code>, which is the <em>remote</em> of the local installation of Incus. Every installation of Incus has such a default <em>remote</em>. </p>



<pre class="wp-block-code"><code>$ <kbd>incus remote list</kbd>
+-----------------+------------------------------------+---------------+-------------+--------+--------+--------+
|      NAME       |                URL                 |   PROTOCOL    |  AUTH TYPE  | PUBLIC | STATIC | GLOBAL |
+-----------------+------------------------------------+---------------+-------------+--------+--------+--------+
| <mark style="background-color:#7bdcb5" class="has-inline-color">images</mark>          | https://images.linuxcontainers.org | simplestreams | none        | YES    | NO     | NO     |
+-----------------+------------------------------------+---------------+-------------+--------+--------+--------+
| <mark style="background-color:#7bdcb5" class="has-inline-color">local (current)</mark> | unix://                            | incus         | file access | NO     | YES    | NO     |
+-----------------+------------------------------------+---------------+-------------+--------+--------+--------+
$ </code></pre>



<p>The Docker repository has the URL <code>https://docker.io</code> and it is accessed through a different protocol. It is called <code>oci</code>.</p>



<p>Therefore, to add the Docker repository, we need to run <code>incus remote add</code> with the appropriate parameters. The URL is <code>https://docker.io</code> and the <code>--protocol</code> is <code>oci</code>.</p>



<pre class="wp-block-code"><code>$ <kbd>incus remote add docker https://docker.io --protocol=oci</kbd>
$</code></pre>



<p>Let&#8217;s list again the available Incus remotes. The <code>docker</code> remote has been added successfully.</p>



<pre class="wp-block-code"><code>$ <kbd>incus remote list</kbd>
+-----------------+------------------------------------+---------------+-------------+--------+--------+--------+
|      NAME       |                URL                 |   PROTOCOL    |  AUTH TYPE  | PUBLIC | STATIC | GLOBAL |
+-----------------+------------------------------------+---------------+-------------+--------+--------+--------+
| <mark style="background-color:#00d084" class="has-inline-color">docker</mark>          | https://docker.io                  | oci           | none        | YES    | NO     | NO     |
+-----------------+------------------------------------+---------------+-------------+--------+--------+--------+
| images          | https://images.linuxcontainers.org | simplestreams | none        | YES    | NO     | NO     |
+-----------------+------------------------------------+---------------+-------------+--------+--------+--------+
| local (current) | unix://                            | incus         | file access | NO     | YES    | NO     |
+-----------------+------------------------------------+---------------+-------------+--------+--------+--------+
$ </code></pre>



<p>If we ever want to remove a remote called <code>myremote</code>, we would <code>incus remote remove myremote</code>.</p>


<h2 class="wp-block-heading" id="launching-a-docker-image-in-incus">Launching a Docker image in Incus</h2>


<p>When you launch (install and run) a container in Incus, you use <code>incus launch</code> with the appropriate parameters. In this first example, we launched <a href="https://hub.docker.com/_/hello-world">the image <code>hello-world</code></a>, which is <a href="https://hub.docker.com/search?q=&amp;image_filter=official">one of the Docker official images</a>. As an image, it runs, printing some text and then it stops. In this case we used the parameter <code>--console</code> in order to see the text output. Finally, we use the <code>--ephemeral</code> parameter that would automatically delete the container image as soon as it stops. Ephemeral (εφήμερο) is a Greek word, meaning that it lasts only a brief time. Both these two additional parameters are not essential but are helpful in this specific case. </p>



<pre class="wp-block-code"><code>$ <kbd>incus launch docker:hello-world --console --ephemeral</kbd>
Launching the instance
Instance name is: best-feature                       

<mark style="background-color:#7bdcb5" class="has-inline-color">Hello from Docker!</mark>
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https:&#47;&#47;hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

$ </code></pre>



<p>Note that we did not specify a name for the container. Astonishingly, Incus randomly selected the name <code>best-feature</code> with some editorial help. Since this is an ephemeral container and the specific image <code>hello-world</code> is short-lived, it is gone in a flash. Indeed, if you then run <code>incus list</code>, the Docker container is not found because it has been auto-deleted. </p>



<p>Let&#8217;s try another Docker image, <a href="https://hub.docker.com/_/nginx">the official <code>nginx</code> Docker image</a>. It launches the <code>nginx</code> image which serves an empty nginx Web server. We need to run <code>incus list</code> and search for the IP address that was given to the container. Then, we can view the default page of the Web server in our Web browser. </p>



<pre class="wp-block-code"><code>$ <kbd>incus launch docker:nginx --console --ephemeral</kbd>
Launching the instance
Instance name is: best-feature                               
To detach from the console, press: &lt;ctrl&gt;+a q
2024/07/12 16:31:59 &#91;notice] 21#21: using the "epoll" event method
2024/07/12 16:31:59 &#91;notice] 21#21: nginx/1.27.0
2024/07/12 16:31:59 &#91;notice] 21#21: built by gcc 12.2.0 (Debian 12.2.0-14) 
2024/07/12 16:31:59 &#91;notice] 21#21: OS: Linux 6.5.0-41-generic
2024/07/12 16:31:59 &#91;notice] 21#21: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2024/07/12 16:31:59 &#91;notice] 21#21: start worker processes
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 45
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 46
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 47
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 48
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 49
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 50
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 51
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 52
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 53
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 54
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 55
2024/07/12 16:31:59 &#91;notice] 21#21: start worker process 56
10.10.10.1 - - &#91;12/Jul/2024:16:33:29 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" "-"
...
<mark style="background-color:#f78da7" class="has-inline-color">^C</mark>
...
2024/07/12 16:39:10 &#91;notice] 21#21: signal 29 (SIGIO) received
2024/07/12 16:39:10 &#91;notice] 21#21: signal 17 (SIGCHLD) received from 55
2024/07/12 16:39:10 &#91;notice] 21#21: worker process 55 exited with code 0
2024/07/12 16:39:10 &#91;notice] 21#21: exit
<mark style="background-color:#ffffff" class="has-inline-color has-cyan-bluish-gray-color">Error: stat /proc/-1: no such file or directory</mark>
$ </code></pre>


<h2 class="wp-block-heading" id="discussion">Discussion</h2>

<h3 class="wp-block-heading" id="how-long-is-the-lifecycle-time-of-a-minimal-docker-container">How long is the lifecycle time of a minimal Docker container?</h3>


<p>How long does it take to launch the <code>docker:hello-world</code> container? I prepend <code>time</code> to the command, and check the stats at the end of the execution. It takes about four seconds to launch and run a simple Docker container. On my system <s>and my Internet connection</s> (it&#8217;s cached).</p>



<pre class="wp-block-code"><code>$ <kbd>time incus launch docker:hello-world --console --ephemeral</kbd>
...
real	<mark style="background-color:#7bdcb5" class="has-inline-color has-black-color">0m3,956s</mark>
user	0m0,016s
sys	0m0,016s
$ </code></pre>


<h3 class="wp-block-heading" id="how-long-does-it-take-to-repeatedly-run-a-minimal-docker-container">How long does it take to repeatedly run a minimal Docker container?</h3>


<p>We are removing the <code>--ephemeral</code> option. We launch the container and we give some relevant name, <code>mydocker</code>. This container remains after execution. We can see that after launching it, the container stays in a STOPPED state. We then <code>incus start</code> the container with the command <code>time incus start mydocker --console</code>, and we can see that it takes a bit more than half a second to complete the execution.</p>



<pre class="wp-block-code"><code>$ <kbd>incus launch docker:hello-world mydocker --console</kbd>
Launching mydocker

Hello from Docker!
...
$ <kbd>incus list mydocker</kbd>
+----------+---------+------+------+-----------------+-----------+
|   NAME   |  STATE  | IPV4 | IPV6 |      TYPE       | SNAPSHOTS |
+----------+---------+------+------+-----------------+-----------+
| mydocker | STOPPED |      |      | CONTAINER (APP) | 0         |
+----------+---------+------+------+-----------------+-----------+
$ <kbd>time incus start mydocker --console</kbd>

Hello from Docker!
...

Hello from Docker!
...
real	<mark style="background-color:#7bdcb5" class="has-inline-color">0m0,638s</mark>
user	0m0,003s
sys	0m0,013s
$ </code></pre>


<h3 class="wp-block-heading" id="are-the-container-images-cached">Are the container images cached?</h3>


<p>Yes, they are cached. When you launch a container for the first time, you can visibly the downloading of the image components. Also, if you run <code>incus image list</code>, you can see the cached Docker.io images in the output.</p>


<h2 class="wp-block-heading" id="troubleshooting">Troubleshooting</h2>

<h3 class="wp-block-heading" id="error-cant-list-images-from-oci-registry">Error: Can&#8217;t list images from OCI registry</h3>


<p>You tried to <strong><em>list</em></strong> the images of the Docker Hub repository. Currently this is not supported. Technically it could be supported though the repository has more than ten thousand images. Using <code>incus list</code> without parameters may not make sense as the output would require to download the full list of images from the repository. Searching for images does make sense, but if you can search, you should be able to list as well. I am not sure what&#8217;s the maintainer&#8217;s view on this. </p>



<pre class="wp-block-code"><code>$ <kbd>incus image list docker:</kbd>
Error: Can't list images from OCI registry
$ </code></pre>



<p>As a workaround, you can simply locate the image name from the Website at <a href="https://hub.docker.com/search?q=&amp;image_filter=official">https://hub.docker.com/search?q=&amp;image_filter=official</a></p>


<h3 class="wp-block-heading" id="error-stat-proc1-no-such-file-or-directory">Error: stat /proc/-1: no such file or directory</h3>


<p>I ran many many instances of Docker containers and in a few cases I got the above error. I do not know what it is and I am adding it here in case someone manages to replicate. It feels that it&#8217;s some kind of race condition.</p>


<h3 class="wp-block-heading" id="failed-getting-remote-image-info-image-not-found">Failed getting remote image info: Image not found</h3>


<p>You have configured Incus properly and you definitely have Incus version 6.3 (both the client and the server). But still, Incus cannot find any Docker image, not even <code>hello-world</code>.</p>



<p>This can happen if you are using a packaging of Incus that does not include the <code>skopeo</code> and <code>umoci</code> packages. If you are using the Zabbly distribution of Incus, these programs are included in the Incus packaging. Therefore, if you are using alternative packaging for Incus, you can manually install the versions of those packages as provided by your Linux distribution.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.simos.info/running-oci-images-i-e-docker-directly-in-incus/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">48282</post-id>	</item>
		<item>
		<title>How to install and setup the Incus Web UI</title>
		<link>https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/</link>
					<comments>https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/#comments</comments>
		
		<dc:creator><![CDATA[Simos Xenitellis]]></dc:creator>
		<pubDate>Thu, 28 Mar 2024 22:16:39 +0000</pubDate>
				<category><![CDATA[general]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[Planet Ubuntu]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[Ubuntu-gr]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[certificate]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[incus]]></category>
		<category><![CDATA[key]]></category>
		<category><![CDATA[lxd]]></category>
		<category><![CDATA[openssl]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[ui]]></category>
		<category><![CDATA[web]]></category>
		<guid isPermaLink="false">https://blog.simos.info/?p=46759</guid>

					<description><![CDATA[Incus is a manager for virtual machines (VM) and system containers. There is also an Incus support forum. Typically you would use the incus command-line interface (CLI) client to get access to the Incus manager and perform the tasks for the full life-cycle of the virtual machines and system containers. In this post we see &#8230; </p><p><a class="more-link btn" href="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/">Continue reading</a>]]></description>
										<content:encoded><![CDATA[
<p><a href="https://linuxcontainers.org/incus/">Incus</a> is a manager for <strong><em>virtual machines (VM)</em></strong> and <strong><em>system containers</em></strong>. There is also <a href="https://discuss.linuxcontainers.org/">an Incus support forum</a>.</p>



<p>Typically you would use the <code>incus</code> command-line interface (CLI) client to get access to the Incus manager and perform the tasks for the full life-cycle of the virtual machines and system containers. </p>



<p>In this post we see how to install and setup the Incus Web UI. Just like the <code>incus</code> CLI tool that gets access to the REST API of the Incus manager (through a Unix socket or HTTPS), the Incus Web UI does the same over HTTPS. I assume that you have already installed and setup Incus.</p>


<h2 class="simpletoc-title">Table of Contents</h2>
<ul class="simpletoc-list">
<li><a href="#prerequisites">Prerequisites</a>

</li>
<li><a href="#installing-the-incus-web-ui-package">Installing the Incus Web UI package</a>

</li>
<li><a href="#preparing-incus-to-serve-the-web-ui">Preparing Incus to serve the Web UI</a>

</li>
<li><a href="#getting-the-browser-to-authenticate-to-the-server">Getting the browser to authenticate to the server</a>

</li>
<li><a href="#using-the-incus-ui">Using the Incus UI</a>

</li>
<li><a href="#conclusion">Conclusion</a>

</li>
<li><a href="#tips-and-tricks">Tips and Tricks</a>


<ul><li>
<a href="#how-to-make-the-incus-port-accessible-to-localhost-only">How to make the Incus port accessible to localhost only</a>

</li>
<li><a href="#whats-in-incusuicrt-and-incusuipfx">What&#8217;s in incus-ui.crt and incus-ui.pfx?</a>

</li>
<li><a href="#how-to-configure-incus-about-the-location-of-the-incus-ui-files">How to configure Incus about the location of the Incus UI files?</a>

</li>
</ul>
<li><a href="#troubleshooting">Troubleshooting</a>


<ul><li>
<a href="#error-unable-to-connect">Error: Unable to connect</a>

</li>
<li><a href="#error-client-sent-an-http-request-to-an-https-server">Error: Client sent an HTTP request to an HTTPS server</a>

</li>
<li><a href="#warning-potential-security-risk-ahead">Warning: Potential Security Risk Ahead</a>

</li>
<li><a href="#e-unable-to-locate-package-incusuicanonical">E: Unable to locate package incus-ui-canonical</a>

</li>
<li><a href="#message-typesyncstatussuccessstatuscode200operationerrorcode0errormetadata10">Message {&#8220;type&#8221;:&#8221;sync&#8221;,&#8221;status&#8221;:&#8221;Success&#8221;,&#8221;status_code&#8221;:200,&#8221;operation&#8221;:&#8221;&#8221;,&#8221;error_code&#8221;:0,&#8221;error&#8221;:&#8221;&#8221;,&#8221;metadata&#8221;:[&#8220;/1.0&#8221;]}</a>
</li>
</ul>
</li></ul>

<h2 class="wp-block-heading" id="prerequisites">Prerequisites</h2>


<p>You should already have a installation of Incus. If you do not have yet, see the official documentation on <a href="https://linuxcontainers.org/incus/docs/main/tutorial/first_steps/">Incus installation</a> and <a href="https://linuxcontainers.org/incus/docs/main/howto/server_migrate_lxd/">Incus migration</a>, or my prior posts on <a href="https://blog.simos.info/how-to-install-and-set-up-incus-on-a-cloud-server/">Incus installation</a> and <a href="https://blog.simos.info/migrating-to-incus-from-lxd/">Incus migration</a>.</p>


<h2 class="wp-block-heading" id="installing-the-incus-web-ui-package">Installing the Incus Web UI package</h2>


<p>The Incus Web UI package is <code>incus-ui-canonical</code>. We install it. By installing the package, we can enable Incus to serve the necessary Web pages (from <code>/opt/incus/ui</code>) so that we can connect with our browser and manage Incus itself. Note that currently the <code>incus-ui-canonical</code> package is provided by <a href="https://github.com/zabbly/incus?tab=readme-ov-file#installation">the Zabbly repository</a>.</p>



<pre class="wp-block-code"><code><kbd>sudo apt install -y incus-ui-canonical</kbd></code></pre>


<h2 class="wp-block-heading" id="preparing-incus-to-serve-the-web-ui">Preparing Incus to serve the Web UI</h2>


<p>By default Incus is not <em>listening</em> to a Web port so that we can access directly through the browser. <a href="https://linuxcontainers.org/incus/docs/main/howto/server_expose/">We need to enable first Incus to activate access to the Web browser.</a> By default there is no configuration with <code>incus config show</code>.</p>



<pre class="wp-block-code"><code>debian@myincus:~$ <kbd>incus config show </kbd>
config: {}
debian@myincus:~$ </code></pre>



<p>We activate the Incus Web server, selecting the port number 8443. You are free to select another one, if you need to. We set <code>core.https_address</code> to <code>:8443</code>. This information appears in the <code>incus config</code> output.</p>



<pre class="wp-block-code"><code>debian@myincus:~$ <kbd>incus config set core.https_address :8443</kbd>
debian@myincus:~$ <kbd>incus config show </kbd>
config:
  <mark style="background-color:#8ed1fc" class="has-inline-color">core.https_address: :8443</mark>
debian@myincus:~$ </code></pre>



<p>Let&#8217;s verify that Incus is now listening to port 8443. Yes, it does. On all interfaces (because of the <code>*</code>).</p>



<pre class="wp-block-code"><code>debian@myincus:~$ <kbd>sudo apt install -y lsof</kbd>
...
debian@myincus:~$ <kbd>sudo lsof -i :8443</kbd>
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
<mark style="background-color:#8ed1fc" class="has-inline-color">incusd</mark>  8338 root    8u  IPv6  29751      0t0  TCP <mark style="background-color:#7bdcb5" class="has-inline-color">*:8443 (LISTEN)</mark>
debian@myincus:~$ </code></pre>



<p>This is HTTPS, where are the certificate and the server key (private key)?</p>



<pre class="wp-block-code"><code>debian@myincus:~$ <kbd>sudo ls -l /var/lib/incus/server.key /var/lib/incus/server.crt</kbd>
-rw-r--r-- 1 root root 753 Mar 28 18:54 <mark style="background-color:#8ed1fc" class="has-inline-color">/var/lib/incus/server.crt</mark>
-rw------- 1 root root 288 Mar 28 18:54 <mark style="background-color:#8ed1fc" class="has-inline-color">/var/lib/incus/server.key</mark>
debian@myincus:~$ <kbd>sudo openssl x509 -in /var/lib/incus/server.crt -text -noout</kbd>
<mark style="background-color:#7bdcb5" class="has-inline-color">Certificate</mark>:
    Data:
        Version: 3 (0x2)
        Serial Number:
            22:05:f1:14:f2:82:43:68:44:5e:1c:42:4c:28:5b:5c
        Signature Algorithm: ecdsa-with-SHA384
        <mark style="background-color:#7bdcb5" class="has-inline-color">Issuer: O = Linux Containers</mark>, CN = root@myincus
        Validity
            Not Before: Mar 28 18:54:17 2024 GMT
            Not After : Mar 26 18:54:17 2034 GMT
        Subject: O = Linux Containers, CN = root@myincus
        Subject Public Key Info:
            <mark style="background-color:#7bdcb5" class="has-inline-color">Public Key Algorithm: id-ecPublicKey</mark>
                Public-Key: (<mark style="background-color:#7bdcb5" class="has-inline-color">384 bit</mark>)
                pub:
                    04:fb:cd:b6:b2:25:55:68:a5:33:75:48:4c:b0:7a:
                    2f:e9:c0:16:af:6f:b2:36:f9:19:6e:b0:86:bf:d1:
                    9f:07:16:b1:26:8b:75:36:f2:fc:02:38:c7:fa:25:
                    39:01:6c:bb:48:a9:4f:57:0d:af:e1:0f:a3:cf:b1:
                    7c:a2:d9:46:77:e7:94:c7:00:1a:d0:5f:5f:93:d8:
                    11:39:8d:16:0e:d0:62:98:81:93:da:ec:b8:70:24:
                    f2:c4:da:91:0f:f8:8e
                ASN1 OID: secp384r1
                <mark style="background-color:#7bdcb5" class="has-inline-color">NIST CURVE: P-384</mark>
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Alternative Name: 
                DNS:myincus, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1
    <mark style="background-color:#7bdcb5" class="has-inline-color">Signature Algorithm: ecdsa-with-SHA384</mark>
    Signature Value:
        30:64:02:30:15:f4:fa:7b:d6:52:79:d4:c9:27:b9:d6:6c:90:
        f7:0e:13:83:15:ac:af:cd:c5:f2:48:08:99:7f:7b:94:55:06:
        81:95:80:5f:0a:21:17:82:61:ac:5a:b6:5f:b8:49:b3:02:30:
        62:a3:92:66:da:ce:7c:01:49:7e:38:16:c6:16:b3:cb:aa:3d:
        1d:3f:63:12:93:e8:a1:0b:55:f0:80:99:d5:80:8a:a3:a6:2e:
        3d:68:90:a6:dc:55:29:0b:36:80:36:72

debian@myincus:~$</code></pre>



<p>Note that this is a self-signed certificate. Chrome, Firefox and other browsers will complain; you can still accept to continue but it will show a broken padlock at the address bar. If you wish, you can replace these with proper certificates so that the padlock is intact. To do so, once you replace the server key and the server certificate with actual values, restart Incus. If, however, you are running an Incus cluster, you must use <code>incus cluster update-certificate</code> instead to update them. Note that a common alternative to dealing with Incus certificates, is to use a reverse-proxy; you get the reverse-proxy to use a proper certificate and leave Incus as is.</p>



<p>At this point Incus is configured. We can continue with the next step where we get the client (our browser) to be authenticated to the server. </p>


<h2 class="wp-block-heading" id="getting-the-browser-to-authenticate-to-the-server">Getting the browser to authenticate to the server</h2>


<p>Visit the URL of your Incus server with your browser. At first you will likely confronted with a message that the server certificate is not accepted (<em>Warning: Potential Security Risk Ahead</em>). Click to <em>Accept</em> and continue. Then, you are presented with the following screen that asks you to login. You are authenticated to the Incus server through <em>user certificates</em>. You are prompted here to do just that. Your browser will create </p>



<ol class="wp-block-list">
<li>a user certificate to be installed into Incus (<code>incus-ui.crt</code>)</li>



<li>the same user certificate with a private key that will be setup in your browser(s) (<code>incus-ui.pfx</code>).</li>
</ol>



<p>Click on <strong><em>Create a new certificate</em></strong>.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-1.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="485" data-attachment-id="46763" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/image-1/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-1.png?fit=822%2C532&amp;ssl=1" data-orig-size="822,532" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-1" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-1.png?fit=300%2C194&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-1.png?fit=750%2C485&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-1.png?resize=750%2C485&#038;ssl=1" alt="" class="wp-image-46763" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-1.png?w=822&amp;ssl=1 822w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-1.png?resize=300%2C194&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-1.png?resize=768%2C497&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-1.png?resize=750%2C485&amp;ssl=1 750w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a><figcaption class="wp-element-caption">Creating a new certificate.</figcaption></figure>
</div>


<p>Now click on <strong><em>Generate</em></strong> to get your browser to generate the private key and the certificate. </p>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-2.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="641" data-attachment-id="46766" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/image-2/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-2.png?fit=1115%2C953&amp;ssl=1" data-orig-size="1115,953" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-2" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-2.png?fit=300%2C256&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-2.png?fit=750%2C641&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-2.png?resize=750%2C641&#038;ssl=1" alt="" class="wp-image-46766" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-2.png?resize=1024%2C875&amp;ssl=1 1024w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-2.png?resize=300%2C256&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-2.png?resize=768%2C656&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-2.png?resize=750%2C641&amp;ssl=1 750w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-2.png?w=1115&amp;ssl=1 1115w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a></figure>



<p></p>



<p>You are asked whether you want to protect the certificate with a password. In our case we click on <strong><em>Skip</em></strong> because we do not want to encrypt the private key with a password. By clicking on <strong><em>Skip</em></strong>, the private key is still generated but it is not getting encrypted.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-3.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="626" height="446" data-attachment-id="46767" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/image-3/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-3.png?fit=626%2C446&amp;ssl=1" data-orig-size="626,446" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-3" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-3.png?fit=300%2C214&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-3.png?fit=626%2C446&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-3.png?resize=626%2C446&#038;ssl=1" alt="" class="wp-image-46767" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-3.png?w=626&amp;ssl=1 626w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-3.png?resize=300%2C214&amp;ssl=1 300w" sizes="auto, (max-width: 626px) 100vw, 626px" /></a></figure>
</div>


<p>At this point the browser generated <code>incus-ui.crt</code>, which is the user certificate to install in Incus. In the following we added the user certificate to Incus.</p>



<pre class="wp-block-code"><code>debian@myincus:~$ <kbd>incus config trust list</kbd>
+------+------+-------------+-------------+-------------+
| NAME | TYPE | DESCRIPTION | FINGERPRINT | EXPIRY DATE |
+------+------+-------------+-------------+-------------+
debian@myincus:~$ <kbd>incus config trust add-certificate incus-ui.crt</kbd>
debian@myincus:~$ <kbd>incus config trust list</kbd>
+--------------+--------+-------------+--------------+----------------------+
|     NAME     |  TYPE  | DESCRIPTION | FINGERPRINT  |     EXPIRY DATE      |
+--------------+--------+-------------+--------------+----------------------+
| <mark style="background-color:#8ed1fc" class="has-inline-color">incus-ui.crt</mark> | client |             | <mark style="background-color:#8ed1fc" class="has-inline-color">b89b80eb4c89</mark> | 2026/12/23 21:08 UTC |
+--------------+--------+-------------+--------------+----------------------+
debian@myincus:~$ </code></pre>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-4.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="641" data-attachment-id="46768" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/image-4/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-4.png?fit=1115%2C953&amp;ssl=1" data-orig-size="1115,953" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-4" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-4.png?fit=300%2C256&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-4.png?fit=750%2C641&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-4.png?resize=750%2C641&#038;ssl=1" alt="" class="wp-image-46768" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-4.png?resize=1024%2C875&amp;ssl=1 1024w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-4.png?resize=300%2C256&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-4.png?resize=768%2C656&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-4.png?resize=750%2C641&amp;ssl=1 750w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-4.png?w=1115&amp;ssl=1 1115w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a><figcaption class="wp-element-caption">The two files have been generated. We are adding <code>incus-ui.crt</code> to Incus, and <code>incus-ui.pfx</code> to the Web browser. </figcaption></figure>
</div>


<p>The page above has instructions on how to add the user certificate to Firefox, Chrome, Edge and macOS. For example, for the case of Firefox, type the following to the address bar and press Enter. Alternatively, go to Settings→Privacy &amp; Security→Certificates. There, click on <strong><em>View Certificates&#8230;</em></strong> and select the <strong><em>Your Certificates</em></strong> tab. Finally, click to Import&#8230; the <code>incus-ui.pfx</code> certificate file.</p>



<pre class="wp-block-code"><code>about:preferences#privacy</code></pre>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-5.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="175" data-attachment-id="46769" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/image-5/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-5.png?fit=768%2C179&amp;ssl=1" data-orig-size="768,179" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-5" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-5.png?fit=300%2C70&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-5.png?fit=750%2C175&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-5.png?resize=750%2C175&#038;ssl=1" alt="" class="wp-image-46769" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-5.png?w=768&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-5.png?resize=300%2C70&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-5.png?resize=750%2C175&amp;ssl=1 750w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a><figcaption class="wp-element-caption">This is found in Firefox under <strong><em>Settings</em></strong>→<strong><em>Privacy &amp; Security</em></strong>→<strong><em>Certificates</em></strong>.</figcaption></figure>
</div>


<p>When you add the <code>incus-ui.pfx</code> user certificate in Firefox, it will appear as in the following screenshot.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-6.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="705" height="482" data-attachment-id="46770" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/image-6/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-6.png?fit=705%2C482&amp;ssl=1" data-orig-size="705,482" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-6" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-6.png?fit=300%2C205&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-6.png?fit=705%2C482&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-6.png?resize=705%2C482&#038;ssl=1" alt="" class="wp-image-46770" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-6.png?w=705&amp;ssl=1 705w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-6.png?resize=300%2C205&amp;ssl=1 300w" sizes="auto, (max-width: 705px) 100vw, 705px" /></a><figcaption class="wp-element-caption">The <code>incus-ui.pfx</code> certificate has been added to this instance of Firefox.</figcaption></figure>
</div>


<p>Subsequently, switch back to the Firefox tab with the Incus UI page and you are shown the following prompt to get your browser to send the user certificate to the Incus manager in order to get authenticated, and be able to manage Incus through the Web. Click on <strong><em>OK</em></strong>.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-7.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="311" data-attachment-id="46771" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/image-7/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-7.png?fit=1057%2C439&amp;ssl=1" data-orig-size="1057,439" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-7" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-7.png?fit=300%2C125&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-7.png?fit=750%2C311&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-7.png?resize=750%2C311&#038;ssl=1" alt="" class="wp-image-46771" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-7.png?resize=1024%2C425&amp;ssl=1 1024w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-7.png?resize=300%2C125&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-7.png?resize=768%2C319&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-7.png?resize=750%2C311&amp;ssl=1 750w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-7.png?w=1057&amp;ssl=1 1057w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a><figcaption class="wp-element-caption">You are prompted to identify yourself to Incus UI in order to be able to manage the Incus installation.</figcaption></figure>
</div>


<p>Finally, you are able to manage Incus over the Web with Incus UI. The Web page loads up and you can perform all tasks that you can do with the <code>incus</code> command-line client.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-8.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="584" data-attachment-id="46772" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/image-8/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-8.png?fit=865%2C673&amp;ssl=1" data-orig-size="865,673" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-8" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-8.png?fit=300%2C233&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-8.png?fit=750%2C584&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-8.png?resize=750%2C584&#038;ssl=1" alt="" class="wp-image-46772" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-8.png?w=865&amp;ssl=1 865w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-8.png?resize=300%2C233&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-8.png?resize=768%2C598&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-8.png?resize=750%2C584&amp;ssl=1 750w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a><figcaption class="wp-element-caption">Your browser is now authenticated through your user certificate and you can manage Incus over the Web with Incus UI.</figcaption></figure>
</div>

<h2 class="wp-block-heading" id="using-the-incus-ui">Using the Incus UI</h2>


<p>We click on <strong><em>Create Instance</em></strong> to create a first instance. We select from the list which image to use, then click to <strong><em>Create and start</em></strong>.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-9.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="454" data-attachment-id="46774" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/image-9/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-9.png?fit=1099%2C665&amp;ssl=1" data-orig-size="1099,665" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-9" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-9.png?fit=300%2C182&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-9.png?fit=750%2C454&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-9.png?resize=750%2C454&#038;ssl=1" alt="" class="wp-image-46774" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-9.png?resize=1024%2C620&amp;ssl=1 1024w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-9.png?resize=300%2C182&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-9.png?resize=768%2C465&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-9.png?resize=750%2C454&amp;ssl=1 750w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-9.png?w=1099&amp;ssl=1 1099w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a><figcaption class="wp-element-caption">Creating an instance and starting it.</figcaption></figure>
</div>


<p>While the instance is created, you are updated with the different steps that take place. In the end, the instance is successfully launched.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/Screenshot-2024-03-28-at-23-52-55-10.10.10.98-Incus-UI.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="454" data-attachment-id="46776" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/screenshot-2024-03-28-at-23-52-55-10-10-10-98-incus-ui/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/Screenshot-2024-03-28-at-23-52-55-10.10.10.98-Incus-UI.png?fit=1099%2C665&amp;ssl=1" data-orig-size="1099,665" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Screenshot-2024-03-28-at-23-52-55-10.10.10.98-Incus-UI" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/Screenshot-2024-03-28-at-23-52-55-10.10.10.98-Incus-UI.png?fit=300%2C182&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/Screenshot-2024-03-28-at-23-52-55-10.10.10.98-Incus-UI.png?fit=750%2C454&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/Screenshot-2024-03-28-at-23-52-55-10.10.10.98-Incus-UI.png?resize=750%2C454&#038;ssl=1" alt="" class="wp-image-46776" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/Screenshot-2024-03-28-at-23-52-55-10.10.10.98-Incus-UI.png?resize=1024%2C620&amp;ssl=1 1024w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/Screenshot-2024-03-28-at-23-52-55-10.10.10.98-Incus-UI.png?resize=300%2C182&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/Screenshot-2024-03-28-at-23-52-55-10.10.10.98-Incus-UI.png?resize=768%2C465&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/Screenshot-2024-03-28-at-23-52-55-10.10.10.98-Incus-UI.png?resize=750%2C454&amp;ssl=1 750w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/Screenshot-2024-03-28-at-23-52-55-10.10.10.98-Incus-UI.png?w=1099&amp;ssl=1 1099w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a><figcaption class="wp-element-caption">The instance has been created and is running.</figcaption></figure>
</div>

<h2 class="wp-block-heading" id="conclusion">Conclusion</h2>


<p>With Incus UI you are able to go through all the workflow of managing Incus instances through your Web browser. Incus UI has been implemented as a stateless Web application, which means that no information are stored on the browser. For example, the browser does not maintain a database with the created instances; the state is maintained on Incus.</p>



<p>In this post we saw how to setup Incus UI with SSL/TLS authentication. It&#8217;s also possible to setup Incus UI to use Single Sign-On (SSO). Here is <a href="https://discuss.linuxcontainers.org/t/tutorial-configure-incus-ui-with-sso/19926">a tutorial on how to setup Incus UI with Open-ID Connect (OIDC)</a>.</p>



<p>There are a few more UI Web applications for Incus, including <code><a href="https://github.com/melato/lxops">lxops</a></code>. At some point in the future I expect to cover them as well.</p>


<h2 class="wp-block-heading" id="tips-and-tricks">Tips and Tricks</h2>

<h3 class="wp-block-heading" id="how-to-make-the-incus-port-accessible-to-localhost-only">How to make the Incus port accessible to localhost only</h3>


<p>The address has the format of &lt;<em>ip address</em>&gt;:&lt;<em>port</em>&gt;. You can specify <em>localhost</em> (127.0.0.1) for the part of the IP address. By doing so, Incus will only bind to <em>localhost</em> and listen to local connections only.</p>



<pre class="wp-block-code"><code>debian@myincus:~$ <kbd>incus config show</kbd>
config:
  core.https_address: <mark style="background-color:#7bdcb5" class="has-inline-color">:8443</mark>
debian@myincus:~$ <kbd>incus config set core.https_address 127.0.0.1:8443</kbd>
debian@myincus:~$ <kbd>incus config show</kbd>
config:
  core.https_address: <mark style="background-color:#00d084" class="has-inline-color">127.0.0.1:8443</mark>
debian@myincus:~$ <kbd>sudo lsof -i :8443</kbd>
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
incusd  8338 root    8u  IPv4  30315      0t0  TCP <mark style="background-color:#f78da7" class="has-inline-color">localhost:8443</mark> (LISTEN)
debian@myincus:~$ </code></pre>


<h3 class="wp-block-heading" id="whats-in-incusuicrt-and-incusuipfx">What&#8217;s in <code>incus-ui.crt</code> and <code>incus-ui.pfx</code>?</h3>


<p>You can use <code>openssl</code> to decode both files. This is an RSA 2048-bit certificate using the SHA-1 hash function.</p>



<pre class="wp-block-code"><code>$ <kbd>openssl x509 -in incus-ui.crt -noout -text</kbd>
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            01:12:00:11:07:65:00:03:00:10:00:41:00:04:09:11
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C = AU, ST = Some-State, O = Incus UI 10.10.10.98 (Browser Generated)
        Validity
            Not Before: Mar 28 21:08:58 2024 GMT
            Not After : Dec 23 21:08:58 2026 GMT
        Subject: C = AU, ST = Some-State, O = Incus UI 10.10.10.98 (Browser Generated)
        Subject Public Key Info:
            <mark style="background-color:#8ed1fc" class="has-inline-color">Public Key Algorithm: rsaEncryption</mark>
                Public-Key: (<mark style="background-color:#8ed1fc" class="has-inline-color">2048 bit</mark>)
                Modulus:
                    00:ce:f8:1d:67:e1:a3:f5:1a:16:b6:26:63:8f:32:
                    42:99:0d:af:86:8b:18:49:1a:4b:8e:ab:68:e1:04:
                    ba:24:dd:e6:27:d5:df:7a:13:cf:16:b3:33:28:89:
                    e0:ab:c8:dc:c1:2a:0a:de:ed:26:3a:77:74:dd:42:
                    1c:e2:22:fc:a5:a5:68:c1:c9:3b:4d:12:15:27:ae:
                    c6:50:ec:dc:f1:0a:ba:00:0c:83:d0:0d:0f:81:90:
                    4e:30:43:cb:45:bf:e2:e9:17:39:40:3b:95:8b:8b:
                    18:e9:59:51:fc:9a:7a:80:e4:73:b3:54:bd:ff:1c:
                    7c:81:75:16:e3:6f:3a:56:9b:0f:a3:73:55:45:03:
                    d8:fb:f3:34:4c:60:4f:f2:67:9f:66:ea:29:29:78:
                    6c:66:05:d6:7d:96:cd:0f:2b:4b:9c:71:2c:09:6f:
                    e2:b4:23:d0:5d:d0:fe:b0:6a:b1:58:5e:d7:b5:47:
                    9e:aa:47:34:f8:7d:e1:ed:fe:bf:97:3d:99:49:42:
                    af:e2:e5:b3:c5:1e:58:b1:98:01:db:8f:25:9f:f8:
                    d9:03:02:06:f9:99:0a:3a:a1:70:9d:fe:64:0d:c2:
                    d8:cc:f0:1c:53:e4:31:4c:78:12:c2:fd:72:23:6a:
                    f4:7e:41:f9:d5:df:6b:ad:2c:52:29:d0:7f:eb:65:
                    64:0f
                Exponent: 65537 (0x10001)
    <mark style="background-color:#8ed1fc" class="has-inline-color">Signature Algorithm: sha1WithRSAEncryption</mark>
    Signature Value:
        28:b3:5c:48:64:8c:23:82:dd:e2:05:6a:9d:18:dd:43:f4:07:
        e6:be:1e:80:b7:f9:0c:0f:3d:cd:b8:bd:7b:55:7e:36:6d:74:
        24:d5:69:b2:24:51:3a:2d:c5:95:68:b5:dc:27:d5:83:d9:bc:
        cb:d0:fd:55:24:63:7d:c6:65:9b:f1:b3:9d:f7:b4:4e:ba:83:
        eb:bf:f5:d0:f6:95:2d:7b:90:4e:d3:89:ac:f0:87:e6:fa:9d:
        f6:ea:c2:42:f2:15:17:74:5c:e4:3c:ed:1a:42:3c:e7:04:aa:
        65:42:3e:75:5c:24:8e:52:85:0d:4b:b2:e2:ec:fa:57:4a:68:
        35:4b:8f:3c:13:fc:15:09:80:5a:b1:c8:e0:22:f5:69:25:4b:
        46:8b:e0:b9:e1:3a:f5:0c:40:d2:c3:75:9c:79:9a:aa:68:9b:
        21:36:ed:67:cb:6d:fc:bc:f0:0b:5a:2b:1a:4c:73:67:c5:79:
        b6:27:b9:58:d0:c7:ea:84:21:bf:f4:7c:44:11:d7:88:ab:1d:
        e4:53:c9:10:cd:e6:b8:5a:7a:92:73:a8:1e:fe:1c:2e:dc:e8:
        7e:3d:e9:a2:6d:26:5a:09:40:a1:3e:51:40:8b:da:57:37:9a:
        8d:0e:d8:cf:c1:0a:b1:0b:95:53:05:41:29:39:af:93:9b:aa:
        10:af:a1:6c
$ </code></pre>



<p>For the <code>incus-ui.pfx</code> file, we first convert to the PEM format, then print the contents. The PFX file contains the certificate (the same that was added earlier to Incus) along with the private key.</p>



<pre class="wp-block-code"><code>$ <kbd>openssl pkcs12 -in incus-ui.pfx -out incus-ui.pem -noenc</kbd>
Enter Import Password:
$ <kbd>cat incus-ui.pem </kbd>
Bag Attributes
    localKeyID: 3A 23 25 F7 56 4D 71 B8 FB FD 72 90 2D A1 F3 B8 2F 01 5E 92 
    friendlyName: Incus-UI
subject=C = AU, ST = Some-State, O = Incus UI 10.10.10.98 (Browser Generated)
issuer=C = AU, ST = Some-State, O = Incus UI 10.10.10.98 (Browser Generated)
-----<mark style="background-color:#7bdcb5" class="has-inline-color">BEGIN CERTIFICATE</mark>-----
MIIDMjCCAhqgAwIBAgIQARIAEQdlAAMAEABBAAQJETANBgkqhkiG9w0BAQUFADBV
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTExMC8GA1UEChMoSW5j
dXMgVUkgMTAuMTAuMTAuOTggKEJyb3dzZXIgR2VuZXJhdGVkKTAeFw0yNDAzMjgy
MTA4NThaFw0yNjEyMjMyMTA4NThaMFUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT
b21lLVN0YXRlMTEwLwYDVQQKEyhJbmN1cyBVSSAxMC4xMC4xMC45OCAoQnJvd3Nl
ciBHZW5lcmF0ZWQpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzvgd
Z+Gj9RoWtiZjjzJCmQ2vhosYSRpLjqto4QS6JN3mJ9XfehPPFrMzKIngq8jcwSoK
3u0mOnd03UIc4iL8paVowck7TRIVJ67GUOzc8Qq6AAyD0A0PgZBOMEPLRb/i6Rc5
QDuVi4sY6VlR/Jp6gORzs1S9/xx8gXUW4286VpsPo3NVRQPY+/M0TGBP8mefZuop
KXhsZgXWfZbNDytLnHEsCW/itCPQXdD+sGqxWF7XtUeeqkc0+H3h7f6/lz2ZSUKv
4uWzxR5YsZgB248ln/jZAwIG+ZkKOqFwnf5kDcLYzPAcU+QxTHgSwv1yI2r0fkH5
1d9rrSxSKdB/62VkDwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAos1xIZIwjgt3i
BWqdGN1D9Afmvh6At/kMDz3NuL17VX42bXQk1WmyJFE6LcWVaLXcJ9WD2bzL0P1V
JGN9xmWb8bOd97ROuoPrv/XQ9pUte5BO04ms8Ifm+p326sJC8hUXdFzkPO0aQjzn
BKplQj51XCSOUoUNS7Li7PpXSmg1S488E/wVCYBascjgIvVpJUtGi+C54Tr1DEDS
w3WceZqqaJshNu1ny238vPALWisaTHNnxXm2J7lY0MfqhCG/9HxEEdeIqx3kU8kQ
zea4WnqSc6ge/hwu3Oh+PemibSZaCUChPlFAi9pXN5qNDtjPwQqxC5VTBUEpOa+T
m6oQr6Fs
-----<mark style="background-color:#7bdcb5" class="has-inline-color">END CERTIFICATE</mark>-----
Bag Attributes
    localKeyID: 3A 23 25 F7 56 4D 71 B8 FB FD 72 90 2D A1 F3 B8 2F 01 5E 92 
    friendlyName: Incus-UI
Key Attributes: &lt;No Attributes&gt;
-----<mark style="background-color:#8ed1fc" class="has-inline-color">BEGIN PRIVATE KEY</mark>-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDO+B1n4aP1Gha2
JmOPMkKZDa+GixhJGkuOq2jhBLok3eYn1d96E88WszMoieCryNzBKgre7SY6d3Td
QhziIvylpWjByTtNEhUnrsZQ7NzxCroADIPQDQ+BkE4wQ8tFv+LpFzlAO5WLixjp
WVH8mnqA5HOzVL3/HHyBdRbjbzpWmw+jc1VFA9j78zRMYE/yZ59m6ikpeGxmBdZ9
ls0PK0uccSwJb+K0I9Bd0P6warFYXte1R56qRzT4feHt/r+XPZlJQq/i5bPFHlix
mAHbjyWf+NkDAgb5mQo6oXCd/mQNwtjM8BxT5DFMeBLC/XIjavR+QfnV32utLFIp
0H/rZWQPAgMBAAECggEBAMm1N/tpBgC291F4YmlJg2xk0R8f6oA8V0zpMyKyF7Qc
atWB8/Wm3pnx9bbZgRQKg1LiZYvTtgEfMM7+QuYFURMi/NB4DQpUyDdPd0mhPsbQ
WVH8mnqA5HOzVL3/HHyBdRbjbzpWmw+jc1VFA9j78zRMYE/yZ59m6ikpeGxmBdZ9
+uKyZ4U4/TORu2tadg9frtUl1HhkY1zGAxOyJUbCOVIbZF2iQt5zMZt4XLFhKgwh
jtDklc3dFIDigUZzpMgdLExLWi6CGT++cjJGpseM+QOAubSoCmT6eIs8qi9KpQhk
aZYBerWqBxswkmNGK4Zh+5gFvdW7EmEp128hATgYZGECgYEA7ckh3qL4Jg6FQA8+
UeEoaT2CvDI89HMJfFN2NvU1ZklqP9aDnPvMjui/h/8HtDeb+5FWFZHF1B9laJp3
HnGGt+98/aO9skdFQDiszclDNIHdpSqcD2LWkKz84QTWqTTkRAxJpgnW91oURtyh
WVH8mnqA5HOzVL3/HHyBdRbjbzpWmw+jc1VFA9j78zRMYE/yZ59m6ikpeGxmBdZ9
JSltWZtYemYzPTpZysocyRs5mD8CgYEA3tKviDreIR+TKT3FQoevyicXuwSn6ocH
2RTgJQF+Qyj+1ykQhwRQUD+axZGls5g2JgT+2gFIdUcAR9CN22rxLRbnIj645yGP
Ka4dVhNAZnz/olWgs4onoO0CnOGXAkVdyiBe9H/D1dkj5bqAfY1eov6khPMOyrDF
EXGi0e6uInbddI/sHUAAIIqJ4+knqwJIgxlzA9GFuzzt4oRLGMsoaClLYFCsrekJ
SF/w7DvhoDQo+JIrHuGX4hLgFLWOgp2WMWhbvgZ0P1PWcJukZ/jx7rJmkwKBgGa5
7x75NMtEiU3sInMnpw2ltDUOUnO3SRD1pNiqtZE05zg+wFXe0UAN8sa+/QutUtl4
WVH8mnqA5HOzVL3/HHyBdRbjbzpWmw+jc1VFA9j78zRMYE/yZ59m6ikpeGxmBdZ9
WB4dlVAsKZ7yMVRFG2dUNb7997TnLd9jXDcArSIS4q/uliXvvZFdc2TsQ/hSDolP
HzfNZ3XBo+EXeIFpmYW/rA13GQytLl5oDC28WaEhAoGBAL6acBqMflXUoWWVHZR7
0vNcJjtRTC13SGRoAKR/tT2kUqloz60bgWeVtggkFWTpPGgm6lmSuYvTnPeoHYDf
vLibVFGasTk8Y7Aji0V7rF4O
-----<mark style="background-color:#8ed1fc" class="has-inline-color">END PRIVATE KEY</mark>-----
$ </code></pre>


<h3 class="wp-block-heading" id="how-to-configure-incus-about-the-location-of-the-incus-ui-files">How to configure Incus about the location of the Incus UI files?</h3>


<p>When the Incus service starts running, it uses a hard-coded location for the web files of Incus UI. If that location is not the actual location of your files, then your browser will show the error <code>404</code> (files not found). In that case, you can setup your system so that the <code>incusd</code> service will be able to find<a href="https://linuxcontainers.org/incus/docs/main/environment/"> the proper location by setting the <code>INCUS_UI</code></a><code>=/opt/incus/ui</code> environment variable. You would need to look into your system&#8217;s configuration so that the Incus service will be able to be exposed to the environment variable. One location could be <code>/etc/environment</code> (not tested) or the service script that starts <code>incusd</code>.</p>


<h2 class="wp-block-heading" id="troubleshooting">Troubleshooting</h2>

<h3 class="wp-block-heading" id="error-unable-to-connect">Error: Unable to connect</h3>


<p>You tried to access the IP address of the Incus server as (for example) <code>https://192.168.1.10/</code> while you should have specified the IP address as well.  The URL should look like <code>https://192.168.1.10:8443/</code>.</p>


<h3 class="wp-block-heading" id="error-client-sent-an-http-request-to-an-https-server">Error: Client sent an HTTP request to an HTTPS server</h3>


<p>You tried to connect to the Incus server at an address (for example) <code>http://192.168.1.10:8443/</code> but you omitted the <code>s</code> in <code>https</code>. Use <code>https://192.168.1.10:8443/</code> instead. </p>


<h3 class="wp-block-heading" id="warning-potential-security-risk-ahead">Warning: Potential Security Risk Ahead</h3>


<p>You are accessing the Incus server through the HTTPS address for the first time and the certificate has not been signed by a certification authority. </p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="540" data-attachment-id="46761" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/image/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image.png?fit=755%2C544&amp;ssl=1" data-orig-size="755,544" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image.png?fit=300%2C216&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image.png?fit=750%2C540&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image.png?resize=750%2C540&#038;ssl=1" alt="" class="wp-image-46761" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image.png?w=755&amp;ssl=1 755w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image.png?resize=300%2C216&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image.png?resize=750%2C540&amp;ssl=1 750w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a><figcaption class="wp-element-caption">First attempt to access the Incus server over HTTPS with your browser.</figcaption></figure>
</div>


<p>Click on <em>Advanced</em> and select to <em>Accept the risk and Continue</em>. If you want to avoid this error message, you need to provide a server certificate that is accepted by your browser. </p>


<h3 class="wp-block-heading" id="e-unable-to-locate-package-incusuicanonical">E: Unable to locate package incus-ui-canonical</h3>


<p>You are trying to install <code>incus-ui-canonical</code> and the package is not found. </p>



<p>The package is available from the Zabbly repository (Debian and Ubuntu) and may not exist in the repositories of your Linux distribution. </p>



<p>See <a href="https://github.com/zabbly/incus?tab=readme-ov-file#installation">https://github.com/zabbly/incus?tab=readme-ov-file#installation</a> on how to add the Zabbly repository.</p>


<h3 class="wp-block-heading" id="message-typesyncstatussuccessstatuscode200operationerrorcode0errormetadata10">Message {&#8220;type&#8221;:&#8221;sync&#8221;,&#8221;status&#8221;:&#8221;Success&#8221;,&#8221;status_code&#8221;:200,&#8221;operation&#8221;:&#8221;&#8221;,&#8221;error_code&#8221;:0,&#8221;error&#8221;:&#8221;&#8221;,&#8221;metadata&#8221;:[&#8220;/1.0&#8221;]}</h3>


<p>You have setup both Incus and the Web UI package but when you visit the URL, the page does not load but instead you get output similar to the following. This can happen if there is a mismatch between the version of the Web UI and Incus. </p>



<figure class="wp-block-image size-large"><a href="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-11.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" width="750" height="217" data-attachment-id="51530" data-permalink="https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/image-14/" data-orig-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-11.png?fit=1418%2C410&amp;ssl=1" data-orig-size="1418,410" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-11.png?fit=300%2C87&amp;ssl=1" data-large-file="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-11.png?fit=750%2C217&amp;ssl=1" src="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-11.png?resize=750%2C217&#038;ssl=1" alt="" class="wp-image-51530" srcset="https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-11.png?resize=1024%2C296&amp;ssl=1 1024w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-11.png?resize=300%2C87&amp;ssl=1 300w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-11.png?resize=768%2C222&amp;ssl=1 768w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-11.png?resize=750%2C217&amp;ssl=1 750w, https://i0.wp.com/blog.simos.info/wp-content/uploads/2024/03/image-11.png?w=1418&amp;ssl=1 1418w" sizes="auto, (max-width: 750px) 100vw, 750px" /></a></figure>



<p>In this specific case, the user had enabled the <a href="https://ubuntu.com/security/esm">Ubuntu Expanded Security Maintenance (ESM)</a> and the system enabled a separate version of Incus from the ESM package repository. Packages from that repository take precedence over other repositories. </p>



<p>To verify whether you are affected, run the following command that shows which version of Incus is installed on your system.  If the three asterisks (<code>***</code>) are on the line that starts with <code>6.0.0-1ubuntu0.2+esm1</code>, then the Incus package from the ESM repository is enabled and you are affected. </p>



<pre class="wp-block-code"><code>$ apt policy incus
incus:
  Installed: 1:6.12-ubuntu24.04-202505241744
  Candidate: 1:6.12-ubuntu24.04-202505241744
  Version table:
 *** 1:6.12-ubuntu24.04-202505241744 1001
        500 https://pkgs.zabbly.com/incus/stable noble/main amd64 Packages
        100 /var/lib/dpkg/status
     1:6.12-ubuntu24.04-202505220530 1001
        500 https://pkgs.zabbly.com/incus/stable noble/main amd64 Packages
     1:6.12-ubuntu24.04-202505151658 1001
        500 https://pkgs.zabbly.com/incus/stable noble/main amd64 Packages
     6.0.0-1ubuntu0.2+esm1 510
        510 https://esm.ubuntu.com/apps/ubuntu noble-apps-security/main amd64 Packages
     6.0.0-1ubuntu0.2 500
        500 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 Packages
        500 http://security.ubuntu.com/ubuntu noble-security/universe amd64 Packages
     6.0.0-1 500
        500 http://archive.ubuntu.com/ubuntu noble/universe amd64 Packages
$</code></pre>



<p>A workaround is to reconfigure you Linux distribution so that your system prefers the latest version of Incus from the Zabbly repository. </p>



<pre class="wp-block-code"><code>$ <mark style="background-color:#00d084" class="has-inline-color">sudo nano /etc/apt/preferences.d/incus-zabbly.pref</mark>
...
$ <mark style="background-color:#00d084" class="has-inline-color">cat /etc/apt/preferences.d/incus-zabbly.pref</mark>
<mark style="background-color:#7bdcb5" class="has-inline-color">Package: incus
Pin: origin pkgs.zabbly.com
Pin-Priority: 1001</mark>
$ <mark style="background-color:#00d084" class="has-inline-color">sudo apt update</mark>
$ <mark style="background-color:#00d084" class="has-inline-color">sudo apt install --reinstall incus</mark></code></pre>



<p>Credits for this find to <a href="https://discuss.linuxcontainers.org/t/incus-webui-returns-an-empty-page/23842/1">Yassine Zara at Incus WebUI returns an empty page</a>.</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.simos.info/how-to-install-and-setup-the-incus-web-ui/feed/</wfw:commentRss>
			<slash:comments>16</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">46759</post-id>	</item>
	</channel>
</rss>
