diff --git a/knowledge base/apt-file.md b/knowledge base/apt-file.md
new file mode 100644
index 0000000..48090d8
--- /dev/null
+++ b/knowledge base/apt-file.md
@@ -0,0 +1,34 @@
+# apt-file
+
+## Table of contents
+
+1. [TL:DR](#tldr)
+1. [Further readings](#further-readings)
+1. [Sources](#sources)
+
+## TL:DR
+
+```sh
+apt-file update
+apt-file list 'cfengine3'
+apt-file search '/path/to/file'
+```
+
+## Further readings
+
+- [`apt`][apt]
+
+## Sources
+
+All the references in the [further readings] section, plus the following:
+
+- [List of files installed from apt package]
+
+
+
+
+[apt]: apt.md
+[further readings]: #further-readings
+
+
+[list of files installed from apt package]: https://serverfault.com/questions/96964/list-of-files-installed-from-apt-package#96965
diff --git a/knowledge base/apt.md b/knowledge base/apt.md
index 6f52c19..c542ba4 100644
--- a/knowledge base/apt.md
+++ b/knowledge base/apt.md
@@ -90,15 +90,23 @@ sudo apt update
- [Apt configuration]
- [Configuring Apt sources]
- [Unattended Upgrades]
-- [cheat.sh]
+- [`dpkg`][dpkg]
+- [`apt-file`][apt-file]
## Sources
+- [cheat.sh]
- [Fix a "Problem with MergeList" or "status file could not be parsed" error]
-
+
[apt configuration]: https://wiki.debian.org/AptConfiguration
[configuring apt sources]: https://wiki.debian.org/SourcesList
[unattended upgrades]: https://wiki.debian.org/UnattendedUpgrades
+
+
+[apt-file]: apt-file.md
+[dpkg]: dpkg.md
+
+
[cheat.sh]: https://cheat.sh/apt
[fix a "problem with mergelist" or "status file could not be parsed" error]: https://askubuntu.com/questions/30072/how-do-i-fix-a-problem-with-mergelist-or-status-file-could-not-be-parsed-err#30199
diff --git a/knowledge base/cfengine3.md b/knowledge base/cfengine3.md
new file mode 100644
index 0000000..581bd08
--- /dev/null
+++ b/knowledge base/cfengine3.md
@@ -0,0 +1,79 @@
+# CFEngine
+
+## Table of contents
+
+1. [TL:DR](#tldr)
+1. [Installation](#installation)
+1. [Further readings](#further-readings)
+1. [Sources](#sources)
+
+## TL:DR
+
+| Command | Configuration |
+| ----------- | ------------------------ |
+| `cf-remote` | `~/.cfengine/cf-remote/` |
+
+```sh
+# List packages available for download.
+cf-remote list
+
+# Add hosts to groups.
+# Will allow to use groups in other commands.
+cf-remote save -H 'root@cfengine.lan' --role 'hub' --name 'hubs-group-name'
+cf-remote save -H 'user@client.lan' --role 'client' --name 'clients-group-name'
+
+# Show hosts spawned by `cf-remote` or added to it.
+cf-remote show
+cf-remote show --ansible-inventory
+
+# Get info about hosts.
+cf-remote info -H 'host-alias'
+
+# Bootstrap remote hosts.
+cf-remote install -B 'hub'
+cf-remote --log-level 'INFO' install -B 'hub'
+
+# Install a specific edition on remote hosts.
+cf-remote install -E 'community' -c 'client'
+cf-remote install -E 'enterprise' --hub 'hub'
+
+# Reset `cf-remote` settings.
+rm -r "${HOME}/.cfengine/cf-remote"
+
+# Print the contents of DB files.
+cf-check dump
+
+# Assess the health of one or more DB files.
+cf-check diagnose
+
+# Diagnose databases, then backup and delete any one found corrupted.
+cf-check repair
+```
+
+## Installation
+
+On the development machine:
+
+```sh
+pip3 install 'cfbs' 'cf-remote'
+cf-remote save -H 'root@cfengine.lan' --role 'hub' --name 'hub'
+cf-remote install --hub 'hub' --bootstrap 'hub'
+```
+
+## Further readings
+
+- [Website]
+- [Documentation]
+
+## Sources
+
+All the references in the [further readings] section, plus the following:
+
+
+[documentation]: https://docs.cfengine.com/docs/master/
+[website]: https://cfengine.com/
+
+
+[further readings]: #further-readings
+
+
diff --git a/knowledge base/dpkg.md b/knowledge base/dpkg.md
index d27d38f..d809d39 100644
--- a/knowledge base/dpkg.md
+++ b/knowledge base/dpkg.md
@@ -3,28 +3,52 @@
## TL;DR
```sh
-# Reconfigure a package.
-dpkg-reconfigure --priority low unattended-upgrades
+# Reconfigure packages.
+dpkg-reconfigure --priority 'low' 'unattended-upgrades'
-# add an extra architecture
-dpkg --add-architecture i386
+# Find which package provides a file already present on a system.
+dpkg -S '/path/to/file'
-# list extra architectures
-dpkg --print-foreign-architectures
+# Find which files were installed by a package.
+dpkg -L 'cfengine3'
-# list available extra architectures
+# Find which files would be installed by a local package.
+dpkg --contents 'cfengine3.deb'
+
+# List available extra architectures.
dpkg-architecture --list-known
-#list all installed packages of the i386 architecture
-dpkg --get-selections | grep i386 | awk '{print $1}'
+# Add extra architectures.
+dpkg --add-architecture 'i386'
-# remove the i386 architecture
-apt-get purge $(dpkg --get-selections | grep --color=never i386 | awk '{print $1}')
-dpkg --remove-architecture i386
+# List added extra architectures.
+dpkg --print-foreign-architectures
+
+# List all installed packages of the i386 architecture.
+dpkg --get-selections | grep 'i386' | awk '{print $1}'
+
+# Remove all traces of the i386 architecture.
+apt-get purge \
+ "$(dpkg --get-selections | grep --color=never 'i386' | awk '{print $1}')" \
+&& dpkg --remove-architecture 'i386'
```
+## Further readings
+
+- [`apt`][apt]
+
## Sources
-- [How to check if dpkg-architecture --list has all the architectures?]
+All the references in the [further readings] section, plus the following:
+- [How to check if dpkg-architecture --list has all the architectures?]
+- [List of files installed from apt package]
+
+
+
+
+[apt]: apt.md
+
+
[how to check if dpkg-architecture --list has all the architectures?]: https://askubuntu.com/questions/852115/how-to-check-if-dpkg-architecture-list-has-all-the-architectures#852120
+[list of files installed from apt package]: https://serverfault.com/questions/96964/list-of-files-installed-from-apt-package#96965
diff --git a/knowledge base/lxc.md b/knowledge base/lxc.md
index 698a0f4..89467be 100644
--- a/knowledge base/lxc.md
+++ b/knowledge base/lxc.md
@@ -51,8 +51,18 @@ echo "vagrant veth lxcbr0 10" | sudo tee -a /etc/lxc/lxc-usernet
## Further readings
-- LXC's [website]
-- LXC's [getting started] guide
+- [Website]
+- [Getting started guide][getting started]
-[website]: https://linuxcontainers.org/
+## Sources
+
+All the references in the [further readings] section, plus the following:
+
+
[getting started]: https://linuxcontainers.org/lxc/getting-started/
+[website]: https://linuxcontainers.org/
+
+
+[further readings]: #further-readings
+
+
diff --git a/knowledge base/pi-hole.md b/knowledge base/pi-hole.md
index eea56fe..9da6094 100644
--- a/knowledge base/pi-hole.md
+++ b/knowledge base/pi-hole.md
@@ -15,12 +15,14 @@ stat /etc/pihole/gravity.db
## Further readings
-- Pi-hole's [repository]
+- [Website]
+- [Github]
- The [pihole] command
- [Run Pi-hole as a container with Podman on openSUSE]
-[repository]: https://github.com/pi-hole/pi-hole
+[github]: https://github.com/pi-hole/pi-hole
+[website]: https://pi-hole.net/
[pihole]: pihole.md
diff --git a/knowledge base/turris os.md b/knowledge base/turris os.md
index 007f720..bc4e0c2 100644
--- a/knowledge base/turris os.md
+++ b/knowledge base/turris os.md
@@ -10,9 +10,16 @@ Linux distribution based on top of OpenWrt. Check the [website] for more informa
1. [Local DNS resolution](#local-dns-resolution)
1. [Static DHCP leases and hostnames](#static-dhcp-leases-and-hostnames)
1. [Containers](#containers)
- 1. [Git server](#git-server)
- 1. [Pi-hole](#pi-hole)
-1. [Hardening ideas](#hardening-ideas)
+ 1. [Create new containers](#create-new-containers)
+ 1. [Assign containers a static IP address](#assign-containers-a-static-ip-address)
+ 1. [Start containers](#start-containers)
+ 1. [Execute a shell into containers](#execute-a-shell-into-containers)
+ 1. [Start containers at boot](#start-containers-at-boot)
+ 1. [Examples](#examples)
+ 1. [CFEngine hub](#cfengine-hub)
+ 1. [Git server](#git-server)
+ 1. [Pi-hole](#pi-hole)
+1. [Hardening](#hardening)
1. [The SFP+ caged module](#the-sfp-caged-module)
1. [Use the SFP module as a LAN port](#use-the-sfp-module-as-a-lan-port)
1. [Further readings](#further-readings)
@@ -141,78 +148,146 @@ luci-reload
## Containers
-Some packages are not available in `opkg`'s repository, but containers can be used to provide them.
+Some packages are not available in `opkg`'s repository, but containers can replace them.
+This is particularly useful to run services off the system which are not officially supported (like [Pi-hole]).
+At the time of writing [LXC] is the only container runtime supported in Turris OS, and this guide will assume one is using it.
This requires the `lxc` package to be installed.
-> Suggested the use of an [expansion disk](#hardware-upgrades).
+> It is highly suggested to use an [expansion disk](#hardware-upgrades) to store any container, but specially any one I/O heavy.
-The usual steps are the following, and should be executed in Turris OS:
-
-1. Create a container for the service:
-
- ```sh
- # Default source is 'repo.turris.cz/lxc'.
- lxc-create --name 'test' --template 'download'
- lxc-create -n 'pi-hole' -t 'download' -- --dist 'debian' --release 'bullseye' --arch 'armhf' --server 'images.linuxcontainers.org'
- ```
-
-1. Assign it a static IP address:
-
- ```sh
- uci add dhcp host
- uci set dhcp.@host[-1].name='pi-hole'
- uci set dhcp.@host[-1].mac="$(grep 'hwaddr' '/srv/lxc/pi-hole/config' | sed 's/.*= //')"
- uci set dhcp.@host[-1].ip='192.168.111.2'
- uci commit 'dhcp'
- reload_config
- luci-reload
- ```
-
-1. Start the container:
-
- ```sh
- lxc-start --name 'pi-hole'
-
- # Check it's running correctly.
- lxc-info --name 'pi-hole'
- ```
-
-1. Execute a shell into it:
-
- ```sh
- lxc-attach --name 'pi-hole'
- ```
-
-1. Set up the container.
-
- > See examples of specific instructions in the subsections below.
+The procedure to have a working container is as follows:
+1. [Create a new container](#create-new-containers).
+1. Optionally, [assign it a static IP address](#assign-containers-a-static-ip-address).
+ This is particularly suggested in case of services.
+1. [Start the container](#start-containers).
+1. [Execute a shell](#execute-a-shell-into-containers) to enter it and set it all up.
+ See the configuration [examples](#examples) below.
1. Check all is working as expected.
-1. If you changed the hostname inside the container, restart it for good measure.
-1. Start the container at boot if required:
+1. If you changed the container's hostname from inside if, restart it for good measure.
+1. Set the container to [start at boot](#start-containers-at-boot) if required.
- ```sh
- vim '/etc/config/lxc-auto'
- ```
+Details for all actions are explained in the next sections.
+Unless otherwise specified:
- ```txt
- config container
- option name pi-hole
- option timeout 60
- ```
+- All shell commands need to be executed from Turris OS.
+- All WebUI actions need to be taken from LuCI.
+ At the time of writing reForis does not have a way to manage containers.
-### Git server
+### Create new containers
-> This procedure assumes you are using a LXC container based upon Debian Bullseye.
-
-Follow the usual procedure above and, as the _set up the container_ step, install and configure git from *+inside** the container:
+In shell:
```sh
-# Set the correct hostname, if different from what is expected.
+# Default source is 'repo.turris.cz/lxc'.
+lxc-create --name 'test' --template 'download'
+lxc-create -n 'pi-hole' -t 'download' -- --dist 'debian' --release 'bullseye' --arch 'armhf' --server 'images.linuxcontainers.org'
+```
+
+Using the WebUI:
+
+1. Navigate to the _Services_ > _LXC Containers_ page.
+1. In the _Create New Container_ section, give it a name and choose its template.
+1. Click the _Create_ button under _Actions_.
+
+### Assign containers a static IP address
+
+In shell:
+
+```sh
+uci add dhcp host
+uci set dhcp.@host[-1].name='pi-hole'
+uci set dhcp.@host[-1].mac="$(grep 'hwaddr' '/srv/lxc/pi-hole/config' | sed 's/.*= //')"
+uci set dhcp.@host[-1].ip='192.168.111.2'
+uci commit 'dhcp'
+reload_config
+luci-reload
+```
+
+Using the WebUI:
+
+1. Get the container's MAC address:
+
+ 1. Navigate to the _Services_ > _LXC Containers_ page.
+ 1. In the dropdown menu for the container, choose _configure_.
+ 1. Grab the MAC address from the textbox.
+
+1. Navigate to the _Network_ > _DHCP and DNS_ page.
+1. In the _Static Leases_ tab, assign a new lease to the container's MAC address.
+
+### Start containers
+
+In shell:
+
+```sh
+lxc-start --name 'pi-hole'
+
+# Check it's running correctly.
+lxc-info --name 'pi-hole'
+```
+
+Using the WebUI:
+
+1. Navigate to the _Services_ > _LXC Containers_ page.
+1. In the _Available Containers_ section, click the _Start_ button under _Actions_.
+
+### Execute a shell into containers
+
+In shell:
+
+```sh
+lxc-attach --name 'pi-hole'
+```
+
+### Start containers at boot
+
+```sh
+vim '/etc/config/lxc-auto'
+```
+
+```txt
+config container
+ option name pi-hole
+ option timeout 60
+```
+
+### Examples
+
+#### CFEngine hub
+
+> CFEngine does not seem to support 32bits ARM processors (but it does support arm64) anymore.
+
+
+ Old installation test
+
+ > This procedure assumes an LXC container based upon Debian Bullseye.
+
+ ```sh
+ # Set the correct hostname.
+ hostnamectl set-hostname 'cfengine'
+
+ # Install CFEngine and the SSH server.
+ # Also install `unattended-upgrades` to ease updates management.
+ DEBIAN_FRONTEND='noninteractive' apt-get install --assume-yes 'cfengine3' 'openssh-server' 'unattended-upgrades'
+
+ # Set up passwordless authentication.
+ mkdir "${HOME}/.ssh" && chmod '700' "${HOME}/.ssh"
+ echo 'ssh-…' >> "${HOME}/.ssh/authorized_keys" && chmod '600' "${HOME}/.ssh/authorized_keys"
+ ```
+
+
+
+#### Git server
+
+> This procedure assumes an LXC container based upon Debian Bullseye.
+
+```sh
+# Set the correct hostname.
hostnamectl set-hostname 'git'
-# Install `git`, the SSH server and `unattended-upgrades`.
+# Install Git and the SSH server.
+# Also install `unattended-upgrades` to ease updates management.
DEBIAN_FRONTEND='noninteractive' apt-get install --assume-yes 'git' 'openssh-server' 'unattended-upgrades'
# (Optionally) configure the SSH server.
@@ -241,16 +316,16 @@ chsh 'git' -s "$(which 'git-shell')"
exit
```
-### Pi-hole
+#### Pi-hole
-> This procedure assumes you are using a LXC container based upon Debian Bullseye.
+> This procedure assumes an LXC container based upon Debian Bullseye.
See [Installing pi-hole on Turris Omnia], [Install Pi-hole] and [Pi-Hole on Turris Omnia] for details.
-Choose one of Pi-hole's [supported operating systems][pi-hole supported operating systems], then follow the usual procedure above and, as the _set up the container_ step, install and configure pi-hole from *+inside** the container:
+Install and configure Pi-hole in the container:
```sh
-# Set the correct hostname, if different from what is expected.
+# Set the correct hostname.
hostnamectl set-hostname 'pi-hole'
# Install pi-hole.
@@ -266,7 +341,8 @@ curl -sSL 'https://install.pi-hole.net' | bash
/etc/.pihole/pihole -up
```
-After this, finish the procedure above. Then, in Turris OS:
+Finish setting up the container as explained above.
+Then, in Turris OS:
```sh
# Distribute pi-hole as the primary DNS.
@@ -283,7 +359,9 @@ uci commit 'dhcp' && reload_config && luci-reload
/etc/init.d/dnsmasq restart
```
-## Hardening ideas
+## Hardening
+
+Suggestions:
- [SSH]:
- Change the SSH port from the default `22` value.
@@ -363,9 +441,10 @@ luci-reload
- [How to control LED diodes]
- [Factory reset on Turris Omnia]
- [Supported SFP modules]
-- [opkg]
-- [uci]
+- [`opkg`][opkg]
+- [UCI]
- [Home NAS]
+- [LXC]
## Sources
@@ -386,7 +465,9 @@ All the references in the [further readings] section, plus the following:
[further readings]: #further-readings
+[lxc]: lxc.md
[opkg]: opkg.md
+[pi-hole]: pi-hole.md
[ssh]: ssh.md
[uci]: uci.md