split LXD post in two, explainer and crash course
This commit is contained in:
		
							parent
							
								
									169418efbd
								
							
						
					
					
						commit
						f25cb39b50
					
				| 
						 | 
					@ -0,0 +1,161 @@
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					title: "Crash Course to LXD"
 | 
				
			||||||
 | 
					subtitle: "Quick instructions for installing LXD and setting up your first application."
 | 
				
			||||||
 | 
					date: 2023-09-18T22:30:07-04:00
 | 
				
			||||||
 | 
					categories:
 | 
				
			||||||
 | 
					  - Technology
 | 
				
			||||||
 | 
					tags:
 | 
				
			||||||
 | 
					  - Sysadmin
 | 
				
			||||||
 | 
					  - Containers
 | 
				
			||||||
 | 
					  - VMs
 | 
				
			||||||
 | 
					  - Docker
 | 
				
			||||||
 | 
					  - LXD
 | 
				
			||||||
 | 
					draft: true
 | 
				
			||||||
 | 
					toc: true
 | 
				
			||||||
 | 
					rss_only: false
 | 
				
			||||||
 | 
					cover: ./cover.png
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you're wondering _why_ I like system containers, see the previous post, _[LXD: Containers for
 | 
				
			||||||
 | 
					Human Beings.][lxd]_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[lxd]: {{< ref "lxd-containers-for-human-beings" >}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{< adm type="note" >}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Note:** the instructions below say to install LXD using [Snap.][snap] I
 | 
				
			||||||
 | 
					personally dislike Snap, but LXD is a Canonical product and they're doing their
 | 
				
			||||||
 | 
					best to promote it as much as possible. [Incus] is a fork of LXD by the primary
 | 
				
			||||||
 | 
					creators and maintainers and one of the first things they did was [rip out Snap
 | 
				
			||||||
 | 
					support,][rsnap] so it will eventually be installable as a proper native
 | 
				
			||||||
 | 
					package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[snap]: https://en.wikipedia.org/wiki/Snap_(software)
 | 
				
			||||||
 | 
					[Incus]: https://github.com/lxc/incus
 | 
				
			||||||
 | 
					[rsnap]: https://github.com/lxc/incus/compare/9579f65cd0f215ecd847e8c1cea2ebe96c56be4a...3f64077a80e028bb92b491d42037124e9734d4c7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{< /adm >}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. Install snap following [Canonical's tutorial](https://earl.run/ZvUK)
 | 
				
			||||||
 | 
					   - LXD is natively packaged for Arch and Alpine, but configuration can be a
 | 
				
			||||||
 | 
					     massive headache.
 | 
				
			||||||
 | 
					2. `sudo snap install lxd`
 | 
				
			||||||
 | 
					3. `lxd init`
 | 
				
			||||||
 | 
					   - Defaults are fine for the most part; you may want to increase the size of
 | 
				
			||||||
 | 
					     the storage pool.
 | 
				
			||||||
 | 
					4. `lxc launch images:debian/12 container-name`
 | 
				
			||||||
 | 
					5. `lxc shell container-name`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As an example of how to use LXD in a real situation, we'll set up [my URL
 | 
				
			||||||
 | 
					shortener.][earl] You'll need a VPS with LXD installed and a (sub)domain pointed
 | 
				
			||||||
 | 
					to the VPS.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Run `lxc launch images:debian/12 earl` followed by `lxc shell earl` and `apt
 | 
				
			||||||
 | 
					install curl`. Also `apt install` a text editor, like `vim` or `nano` depending
 | 
				
			||||||
 | 
					on what you're comfortable with. Head to the **Installation** section of [earl's
 | 
				
			||||||
 | 
					SourceHut page][earl] and expand the **List of latest binaries**. Copy the link
 | 
				
			||||||
 | 
					to the binary appropriate for your platform, head back to your terminal, type
 | 
				
			||||||
 | 
					`curl -LO`, and paste the link you copied. This will download the binary to your
 | 
				
			||||||
 | 
					system. Run `mv <filename> earl` to rename it, `chmod +x earl` to make it
 | 
				
			||||||
 | 
					executable, then `./earl` to execute it. It will create a file called
 | 
				
			||||||
 | 
					`config.yaml` that you need to edit before proceeding. Change the `accessToken`
 | 
				
			||||||
 | 
					to something else and replace the `listen` value, `127.0.0.1`, with `0.0.0.0`.
 | 
				
			||||||
 | 
					This exposes the application to the host system so we can reverse proxy it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[earl]: https://earl.run/source
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The next step is daemonising it so it runs as soon as the system boots. Edit the
 | 
				
			||||||
 | 
					file located at `/etc/systemd/system/earl.service` and paste the following code
 | 
				
			||||||
 | 
					snippet into it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```ini
 | 
				
			||||||
 | 
					[Unit]
 | 
				
			||||||
 | 
					Description=personal link shortener
 | 
				
			||||||
 | 
					After=network.target
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Service]
 | 
				
			||||||
 | 
					User=root
 | 
				
			||||||
 | 
					Group=root
 | 
				
			||||||
 | 
					WorkingDirectory=/root/
 | 
				
			||||||
 | 
					ExecStart=/root/earl -c config.yaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Install]
 | 
				
			||||||
 | 
					WantedBy=multi-user.target
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Save, then run `systemctl daemon-reload` followed by `systemctl enable --now
 | 
				
			||||||
 | 
					earl`. You should be able to `curl localhost:8275` and see some HTML.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Now we need a reverse proxy on the host. Exit the container with `exit` or
 | 
				
			||||||
 | 
					`Ctrl+D`, and if you have a preferred webserver, install it. If you don't have a
 | 
				
			||||||
 | 
					preferred webserver yet, I recommend [installing Caddy.][caddy] All that's left
 | 
				
			||||||
 | 
					is running `lxc list`, making note of the `earl` container's `IPv4` address, and
 | 
				
			||||||
 | 
					reverse proxying it. If you're using Caddy, edit `/etc/caddy/Caddyfile` and
 | 
				
			||||||
 | 
					replace everything that's there with the following.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[caddy]: https://caddyserver.com/docs/install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```text
 | 
				
			||||||
 | 
					<(sub)domain> {
 | 
				
			||||||
 | 
						encode zstd gzip
 | 
				
			||||||
 | 
						reverse_proxy <container IP address>:1313
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Run `systemctl restart caddy` and head to whatever domain or subdomain you
 | 
				
			||||||
 | 
					entered. You should see the home page with just the text `earl` on it. If you go
 | 
				
			||||||
 | 
					to `/login`, you'll be able to enter whatever access token you set earlier and
 | 
				
			||||||
 | 
					log in.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Further tips
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					One of the things you might want to do post-installation is mess around with
 | 
				
			||||||
 | 
					profiles. There's a `default` profile in LXD that you can show with `lxc profile
 | 
				
			||||||
 | 
					show default`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``` text
 | 
				
			||||||
 | 
					$ lxc profile show default
 | 
				
			||||||
 | 
					config: {}
 | 
				
			||||||
 | 
					description: Default LXD profile
 | 
				
			||||||
 | 
					devices:
 | 
				
			||||||
 | 
					  eth0:
 | 
				
			||||||
 | 
					    name: eth0
 | 
				
			||||||
 | 
					    network: lxdbr0
 | 
				
			||||||
 | 
					    type: nic
 | 
				
			||||||
 | 
					  root:
 | 
				
			||||||
 | 
					    path: /
 | 
				
			||||||
 | 
					    pool: default
 | 
				
			||||||
 | 
					    type: disk
 | 
				
			||||||
 | 
					name: default
 | 
				
			||||||
 | 
					used_by: []
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Not all config options are listed here though; you'll need to read [the
 | 
				
			||||||
 | 
					documentation] for a full enumeration.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[the documentation]: https://documentation.ubuntu.com/lxd/en/latest/config-options/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I've seen some people say that executing a fork bomb from inside a container is
 | 
				
			||||||
 | 
					equivalent to executing it on the host. The fork bomb will blow up the whole
 | 
				
			||||||
 | 
					system and render every application and container you're running inoperable.
 | 
				
			||||||
 | 
					That's partially true because LXD _by default_ doesn't put a limit on how many
 | 
				
			||||||
 | 
					processes a particular container can spawn. You can limit that number yourself
 | 
				
			||||||
 | 
					by running
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```text
 | 
				
			||||||
 | 
					lxc profile set default limits.processes <num-processes>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Any container you create under the `default` profile will have a total process
 | 
				
			||||||
 | 
					limit of `<num-processes>`. I can't tell you what a good process limit is
 | 
				
			||||||
 | 
					though; you'll need to do some testing and experimentation on your own.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As stated in [the containers section][pp] of the previous post, this doesn't
 | 
				
			||||||
 | 
					_save_ you from fork bombs. It just helps prevent a fork bomb from affecting the
 | 
				
			||||||
 | 
					host OS or other containers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[pp]: {{< ref "lxd-containers-for-human-beings#containers" >}}
 | 
				
			||||||
| 
						 | 
					@ -275,145 +275,6 @@ ZFS for your LXD storage pool, maybe go with [syncoid and sanoid.][ss]
 | 
				
			||||||
My point is that using system containers doesn't mean throwing out the last few
 | 
					My point is that using system containers doesn't mean throwing out the last few
 | 
				
			||||||
decades of systems knowledge and wisdom.
 | 
					decades of systems knowledge and wisdom.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Crash course to LXD
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Quick instructions for installing LXD and setting up your first application.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Installation
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{{< adm type="note" >}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
**Note:** the instructions below say to install LXD using [Snap.][snap] I
 | 
					 | 
				
			||||||
personally dislike Snap, but LXD is a Canonical product and they're doing their
 | 
					 | 
				
			||||||
best to promote it as much as possible. One of the first things the Incus
 | 
					 | 
				
			||||||
project did was [rip out Snap support,][rsnap] so it will eventually be
 | 
					 | 
				
			||||||
installable as a proper native package.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[snap]: https://en.wikipedia.org/wiki/Snap_(software)
 | 
					 | 
				
			||||||
[rsnap]: https://github.com/lxc/incus/compare/9579f65cd0f215ecd847e8c1cea2ebe96c56be4a...3f64077a80e028bb92b491d42037124e9734d4c7
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{{< /adm >}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
1. Install snap following [Canonical's tutorial](https://earl.run/ZvUK)
 | 
					 | 
				
			||||||
   - LXD is natively packaged for Arch and Alpine, but configuration can be a
 | 
					 | 
				
			||||||
     massive headache.
 | 
					 | 
				
			||||||
2. `sudo snap install lxd`
 | 
					 | 
				
			||||||
3. `lxd init`
 | 
					 | 
				
			||||||
   - Defaults are fine for the most part; you may want to increase the size of
 | 
					 | 
				
			||||||
     the storage pool.
 | 
					 | 
				
			||||||
4. `lxc launch images:debian/12 container-name`
 | 
					 | 
				
			||||||
5. `lxc shell container-name`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Usage
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
As an example of how to use LXD in a real situation, we'll set up [my URL
 | 
					 | 
				
			||||||
shortener.][earl] You'll need a VPS with LXD installed and a (sub)domain pointed
 | 
					 | 
				
			||||||
to the VPS.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Run `lxc launch images:debian/12 earl` followed by `lxc shell earl` and `apt
 | 
					 | 
				
			||||||
install curl`. Also `apt install` a text editor, like `vim` or `nano` depending
 | 
					 | 
				
			||||||
on what you're comfortable with. Head to the **Installation** section of [earl's
 | 
					 | 
				
			||||||
SourceHut page][earl] and expand the **List of latest binaries**. Copy the link
 | 
					 | 
				
			||||||
to the binary appropriate for your platform, head back to your terminal, type
 | 
					 | 
				
			||||||
`curl -LO`, and paste the link you copied. This will download the binary to your
 | 
					 | 
				
			||||||
system. Run `mv <filename> earl` to rename it, `chmod +x earl` to make it
 | 
					 | 
				
			||||||
executable, then `./earl` to execute it. It will create a file called
 | 
					 | 
				
			||||||
`config.yaml` that you need to edit before proceeding. Change the `accessToken`
 | 
					 | 
				
			||||||
to something else and replace the `listen` value, `127.0.0.1`, with `0.0.0.0`.
 | 
					 | 
				
			||||||
This exposes the application to the host system so we can reverse proxy it.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[earl]: https://earl.run/source
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The next step is daemonising it so it runs as soon as the system boots. Edit the
 | 
					 | 
				
			||||||
file located at `/etc/systemd/system/earl.service` and paste the following code
 | 
					 | 
				
			||||||
snippet into it.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```ini
 | 
					 | 
				
			||||||
[Unit]
 | 
					 | 
				
			||||||
Description=personal link shortener
 | 
					 | 
				
			||||||
After=network.target
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Service]
 | 
					 | 
				
			||||||
User=root
 | 
					 | 
				
			||||||
Group=root
 | 
					 | 
				
			||||||
WorkingDirectory=/root/
 | 
					 | 
				
			||||||
ExecStart=/root/earl -c config.yaml
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Install]
 | 
					 | 
				
			||||||
WantedBy=multi-user.target
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Save, then run `systemctl daemon-reload` followed by `systemctl enable --now
 | 
					 | 
				
			||||||
earl`. You should be able to `curl localhost:8275` and see some HTML.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Now we need a reverse proxy on the host. Exit the container with `exit` or
 | 
					 | 
				
			||||||
`Ctrl+D`, and if you have a preferred webserver, install it. If you don't have a
 | 
					 | 
				
			||||||
preferred webserver yet, I recommend [installing Caddy.][caddy] All that's left
 | 
					 | 
				
			||||||
is running `lxc list`, making note of the `earl` container's `IPv4` address, and
 | 
					 | 
				
			||||||
reverse proxying it. If you're using Caddy, edit `/etc/caddy/Caddyfile` and
 | 
					 | 
				
			||||||
replace everything that's there with the following.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[caddy]: https://caddyserver.com/docs/install
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```text
 | 
					 | 
				
			||||||
<(sub)domain> {
 | 
					 | 
				
			||||||
	encode zstd gzip
 | 
					 | 
				
			||||||
	reverse_proxy <container IP address>:1313
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Run `systemctl restart caddy` and head to whatever domain or subdomain you
 | 
					 | 
				
			||||||
entered. You should see the home page with just the text `earl` on it. If you go
 | 
					 | 
				
			||||||
to `/login`, you'll be able to enter whatever access token you set earlier and
 | 
					 | 
				
			||||||
log in.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Further tips
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
One of the things you might want to do post-installation is mess around with
 | 
					 | 
				
			||||||
profiles. There's a `default` profile in LXD that you can show with `lxc profile
 | 
					 | 
				
			||||||
show default`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
``` text
 | 
					 | 
				
			||||||
$ lxc profile show default
 | 
					 | 
				
			||||||
config: {}
 | 
					 | 
				
			||||||
description: Default LXD profile
 | 
					 | 
				
			||||||
devices:
 | 
					 | 
				
			||||||
  eth0:
 | 
					 | 
				
			||||||
    name: eth0
 | 
					 | 
				
			||||||
    network: lxdbr0
 | 
					 | 
				
			||||||
    type: nic
 | 
					 | 
				
			||||||
  root:
 | 
					 | 
				
			||||||
    path: /
 | 
					 | 
				
			||||||
    pool: default
 | 
					 | 
				
			||||||
    type: disk
 | 
					 | 
				
			||||||
name: default
 | 
					 | 
				
			||||||
used_by: []
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Not all config options are listed here though; you'll need to read [the
 | 
					 | 
				
			||||||
documentation] for a full enumeration.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[the documentation]: https://documentation.ubuntu.com/lxd/en/latest/config-options/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
I've seen some people say that executing a fork bomb from inside a container is
 | 
					 | 
				
			||||||
equivalent to executing it on the host. The fork bomb will blow up the whole
 | 
					 | 
				
			||||||
system and render every application and container you're running inoperable.
 | 
					 | 
				
			||||||
That's partially true because LXD _by default_ doesn't put a limit on how many
 | 
					 | 
				
			||||||
processes a particular container can spawn. You can limit that number yourself
 | 
					 | 
				
			||||||
by running
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```text
 | 
					 | 
				
			||||||
lxc profile set default limits.processes <num-processes>
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Any container you create under the `default` profile will have a total process
 | 
					 | 
				
			||||||
limit of `<num-processes>`. I can't tell you what a good process limit is
 | 
					 | 
				
			||||||
though; you'll need to do some testing and experimentation on your own.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
As stated in [the containers section,](#containers) this doesn't _save_ you from
 | 
					 | 
				
			||||||
fork bombs. It just helps prevent a fork bomb from affecting the host OS or
 | 
					 | 
				
			||||||
other containers.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[^1]:
 | 
					[^1]:
 | 
				
			||||||
    There's a [technical
 | 
					    There's a [technical
 | 
				
			||||||
    publication](https://dl.acm.org/doi/10.1145/3132747.3132763) indicating that
 | 
					    publication](https://dl.acm.org/doi/10.1145/3132747.3132763) indicating that
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue