diff --git a/knowledge base/turris os.md b/knowledge base/turris os.md index fa50208..0c9e4a7 100644 --- a/knowledge base/turris os.md +++ b/knowledge base/turris os.md @@ -18,7 +18,7 @@ Linux distribution based on top of OpenWrt. Check the [website] for more informa 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) -1. [Sources](#sources) + 1. [Sources](#sources) ## TL;DR @@ -121,8 +121,8 @@ day, but not to be dazzled by the diodes in the night. Create the cron file in the `/etc/cron.d` directory: -```txt -# File /etc/cron.d/rainbow_night. +```sh +$ cat '/etc/cron.d/rainbow_night' # Set the light intensity to the second lowest degree every day at 11 PM and set # it back to maximum every day at 7 AM. MAILTO="" # avoid automatic logging of the output @@ -134,6 +134,7 @@ MAILTO="" # avoid automatic logging of the output Turris OS can answer DNS queries for local devices. +> [!note] > Requires the _Network Settings_ > _DNS_ > _Enable DHCP clients in DNS_ option to be enabled. ## Static DHCP leases and hostnames @@ -148,7 +149,8 @@ the name the host presents itself with).
Not setting a hostname in an entry will make Turris OS resolve the IP address with the name the host presents itself with. -CLI procedure: +
+ CLI procedure ```sh uci add dhcp host @@ -160,36 +162,48 @@ reload_config luci-reload ``` +
+ ## Containers 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 +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. -> It is highly suggested to use an [expansion disk](turris%20omnia.md#hardware-upgrades) to store any container, but -> specially any one I/O heavy. +> [!tip] +> Use an [expansion disk](turris%20omnia.md#hardware-upgrades) to store containers' data.
+> Especially suggested for any I/O heavy application, to avoid wearing down the device's internal storage. -The procedure to have a working container is as follows: +The _standard_ procedure to have a new 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. \[optionally] [assign it a static IP address](#assign-containers-a-static-ip-address).
+ 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 below. +1. [Execute a shell](#execute-a-shell-into-containers) in the container and set it all up.
+ See the examples below. 1. Check all is working as expected. 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. +1. \[optionally] Set the container to [start at boot](#start-containers-at-boot). Details for all actions are explained in the next sections.
Unless otherwise specified: - 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. + As of 2026-02-23, reForis does not allow to manage containers. + +Gather information about running containers (in shell): + +```sh +lxc-info --name 'gitea' + +# Only the first IP address. +lxc-info --name 'forgejo' --ips --no-humanize | head -n '1' +``` ### Create new containers @@ -281,289 +295,346 @@ config container ### Examples
- baikal + Baikal -> This procedure assumes one is using an LXC container based on the Debian Bullseye image. -> -> ```sh -> lxc-create -n 'baikal' -t 'download' -- -d 'Debian' -r 'Bookworm' -a 'armv7l' -> ``` +> [!tip] +> Refer [baikal] and . -Refer [baikal] and . +1. Create and start the container: -```sh -# Set the correct hostname. -hostnamectl set-hostname 'baikal' -sed -i 's/LXC_NAME/baikal/' '/etc/hosts' + ```sh + lxc-create -n 'baikal' -t 'download' -- -d 'Debian' -r 'Bookworm' -a 'armv7l' + ``` -# Install baikal. -# Also install `unattended-upgrades` to ease updates management. -DEBIAN_FRONTEND='noninteractive' apt-get install --assume-yes --no-install-recommends \ - 'apache2' 'ca-certificates' 'curl' 'php' 'php-sqlite3' 'php-sabre-dav' 'unattended-upgrades' 'unzip' -a2dismod 'mpm_event' -a2enmod 'rewrite' 'php*' 'ssl' -systemctl restart 'apache2' -openssl req -nodes \ - -newkey 'rsa:4096' -keyout '/etc/ssl/private/baikal.key' -out '/etc/ssl/private/baikal.crt' -x509 -days '365' \ - -subj '/C=NL/ST=North Holland/L=Amsterdam/O=Example Org/OU=Infra/CN=baikal.lan' -curl -fsL -o '/var/www/baikal.zip' 'https://github.com/sabre-io/Baikal/releases/download/0.10.1/baikal-0.10.1.zip' -unzip -ud '/var/www/' '/var/www/baikal.zip' && rm '/var/www/baikal.zip' -chown -R 'www-data:www-data' '/var/www/baikal/Specific' '/var/www/baikal/config' -cat < '/etc/apache2/sites-enabled/010-baikal.conf' - +1. Install and configure Baikal in the container: - DocumentRoot /var/www/baikal/html - ServerName baikal.lan + ```sh + # Set the correct hostname. + hostnamectl set-hostname 'baikal' + sed -i 's/LXC_NAME/baikal/' '/etc/hosts' - RewriteEngine on - # Generally already set by global Apache configuration - # RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] - RewriteRule /.well-known/carddav /dav.php [R=308,L] - RewriteRule /.well-known/caldav /dav.php [R=308,L] + # Install baikal. + # Also install `unattended-upgrades` to ease updates management. + DEBIAN_FRONTEND='noninteractive' apt-get install --assume-yes --no-install-recommends \ + 'apache2' 'ca-certificates' 'curl' 'php' 'php-sqlite3' 'php-sabre-dav' 'unattended-upgrades' 'unzip' + a2dismod 'mpm_event' + a2enmod 'rewrite' 'php*' 'ssl' + systemctl restart 'apache2' + openssl req -nodes \ + -newkey 'rsa:4096' -keyout '/etc/ssl/private/baikal.key' -out '/etc/ssl/private/baikal.crt' -x509 -days '365' \ + -subj '/C=NL/ST=North Holland/L=Amsterdam/O=Example Org/OU=Infra/CN=baikal.lan' + curl -fsL -o '/var/www/baikal.zip' 'https://github.com/sabre-io/Baikal/releases/download/0.10.1/baikal-0.10.1.zip' + unzip -ud '/var/www/' '/var/www/baikal.zip' && rm '/var/www/baikal.zip' + chown -R 'www-data:www-data' '/var/www/baikal/Specific' '/var/www/baikal/config' + cat < '/etc/apache2/sites-enabled/010-baikal.conf' + - - Options None - # If you install cloning git repository, you may need the following - # Options +FollowSymlinks - AllowOverride None - # Configuration for apache-2.4: - Require all granted - # Configuration for apache-2.2: - # Order allow,deny - # Allow from all - + DocumentRoot /var/www/baikal/html + ServerName baikal.lan - - ExpiresActive Off - + RewriteEngine on + # Generally already set by global Apache configuration + # RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + RewriteRule /.well-known/carddav /dav.php [R=308,L] + RewriteRule /.well-known/caldav /dav.php [R=308,L] - SSLEngine on - SSLCertificateFile /etc/ssl/private/baikal.crt - SSLCertificateKeyFile /etc/ssl/private/baikal.key + + Options None + # If you install cloning git repository, you may need the following + # Options +FollowSymlinks + AllowOverride None + # Configuration for apache-2.4: + Require all granted + # Configuration for apache-2.2: + # Order allow,deny + # Allow from all + - -EOF -``` + + ExpiresActive Off + -Testing (after installing and creating a user): + SSLEngine on + SSLCertificateFile /etc/ssl/private/baikal.crt + SSLCertificateKeyFile /etc/ssl/private/baikal.key -```sh -curl -svvvko - --digest --user 'mark@baikal.lan:123p' https://baikal.lan/dav.php/calendars/mark@baikal.lan/default/ -``` + + EOF + ``` + +1. Connect to to start the first-time installation wizard. +1. Test the service: + + ```sh + curl -svvvko - --digest --user 'mark@baikal.lan:somePassword123' \ + --url 'https://baikal.lan/dav.php/calendars/mark@baikal.lan/default/' + ``` + +1. \[optionally] Configure Turris OS to [start the container at boot][start containers at boot].
- basic, stripped git server + Basic, stripped git server -> This procedure assumes one is using an LXC container based on the Debian Bullseye image. -> -> ```sh -> lxc-create -n 'git' -t 'download' -- -d 'Debian' -r 'Bullseye' -a 'armv7l' -> ``` +1. Create and start the container. -```sh -# Set the correct hostname. -hostnamectl set-hostname 'git' -sed -i 's/LXC_NAME/git/' '/etc/hosts' + ```sh + lxc-create -n 'git' -t 'download' -- -d 'Debian' -r 'Bullseye' -a 'armv7l' + ``` -# 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' +1. Install and configure the git server in the container: -# (Optionally) configure the SSH server. -vim '/etc/ssh/sshd_config' -systemctl restart 'ssh.service' + ```sh + # Set the correct hostname. + hostnamectl set-hostname 'git' + sed -i 's/LXC_NAME/git/' '/etc/hosts' -# Create the git user. -adduser 'git' + # 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' -# Set up passwordless authentication. -mkdir '/home/git/.ssh' && sudo chmod '700' '/home/git/.ssh' -touch '/home/git/.ssh/authorized_keys' && sudo chmod '600' '/home/git/.ssh/authorized_keys' -echo 'ssh-…' >> '/home/git/.ssh/authorized_keys' + # (Optionally) configure the SSH server. + vim '/etc/ssh/sshd_config' + systemctl restart 'ssh.service' -# (Optionally) create the repositories' root directory. -mkdir '/home/git/repositories' + # Create the git user. + adduser 'git' -# Make sure the 'git' user has the correct permissions on the folders. -chown -R 'git' '/home/git' + # Set up passwordless authentication. + mkdir '/home/git/.ssh' && sudo chmod '700' '/home/git/.ssh' + touch '/home/git/.ssh/authorized_keys' && sudo chmod '600' '/home/git/.ssh/authorized_keys' + echo 'ssh-…' >> '/home/git/.ssh/authorized_keys' -# (Optionally) lock down the git user. -# This will *prevent* clients to set their SSH key using `ssh-copy-id`. -chsh 'git' -s "$(which 'git-shell')" + # (Optionally) create the repositories' root directory. + mkdir '/home/git/repositories' -# All done! -exit -``` + # Make sure the 'git' user has the correct permissions on the folders. + chown -R 'git' '/home/git' + + # (Optionally) lock down the git user. + # This will *prevent* clients to set their SSH key using `ssh-copy-id`. + chsh 'git' -s "$(which 'git-shell')" + + # All done! + exit + ``` + +1. \[optionally] Configure Turris OS to [start the container at boot][start containers at boot].
- cfengine hub + CFEngine hub -> CFEngine does not seem to support 32bits ARM processors anymore (but it does support arm64).
-> Still, I am using a 32bit processor so this is not doable for me. +> [!warning] +> CFEngine does **not** seem to support 32bits ARM processors anymore (but it does support arm64).
+> Still, I am using a 32bit processor so this is **not** doable for me.
Old installation test - > This procedure assumes one is using an LXC container based on the Debian Bullseye image. - > - > ```sh - > lxc-create -n 'baikal' -t 'download' -- -d 'Debian' -r 'Bullseye' -a 'armv7l' - > ``` + 1. Create and start the container. - ```sh - # Set the correct hostname. - hostnamectl set-hostname 'cfengine' + ```sh + lxc-create -n 'cfengine' -t 'download' -- -d 'Debian' -r 'Bullseye' -a 'armv7l' + ``` - # 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' + 1. Install and configure CFEngine in the container: - # Set up passwordless authentication. - mkdir "${HOME}/.ssh" && chmod '700' "${HOME}/.ssh" - echo 'ssh-…' >> "${HOME}/.ssh/authorized_keys" && chmod '600' "${HOME}/.ssh/authorized_keys" - ``` + ```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" + ```
- gitea + Forgejo -> This procedure assumes one is using an LXC container based on LinuxContainers' Alpine 3.20 image: -> -> ```sh -> lxc-create --name 'gitea' --template 'download' -- \ -> --server 'images.linuxcontainers.org' --dist 'alpine' --release '3.20' --arch 'armhf' -> ``` +1. Create and start the container. -```sh -# Set the correct hostname. -# Should be already set correctly. -echo 'gitea' > '/etc/hostname' -hostname -F '/etc/hostname' + ```sh + lxc-create --name 'forgejo' --template 'download' -- \ + --server 'images.linuxcontainers.org' --dist 'alpine' --release '3.23' --arch 'armhf' + lxc-start --name 'forgejo' + ``` -# Install Gitea. -apk add 'gitea' 'gitea-openrc' +1. Install and configure Forgejo in the container: -# Start Gitea. -rc-update add 'gitea' -rc-service 'gitea' start + ```sh + # Set the correct hostname. + # Should be already set correctly. + echo 'forgejo' > '/etc/hostname' + hostname -F '/etc/hostname' -# Connect to 'gitea:3000' to start the first-time installation wizard. -``` + # Install Forgejo. + apk add 'forgejo' 'forgejo-openrc' + + # Start Forgejo. + rc-update add 'forgejo' + rc-service 'forgejo' start + ``` + +1. Connect to to start the first-time installation wizard. +1. \[optionally] Configure Turris OS to [start the container at boot][start containers at boot].
- monitoring + Gitea -> This procedure assumes you are using an LXC container based on the Debian Bullseye image. -> -> ```sh -> lxc-create -n 'baikal' -t 'download' -- -d 'Debian' -r 'Bullseye' -a 'armv7l' -> ``` +1. Create and start the container. -```sh -# Set the correct hostname. -hostnamectl set-hostname 'monitoring' + ```sh + lxc-create --name 'gitea' --template 'download' -- \ + --server 'images.linuxcontainers.org' --dist 'alpine' --release '3.20' --arch 'armhf' + ``` -# Install the requirements -DEBIAN_FRONTEND='noninteractive' apt-get install --assume-yes 'unattended-upgrades' 'wget' +1. Install and configure Gitea in the container: -# Stop installing recommended and suggested packages. -cat > /etc/apt/apt.conf.d/99norecommend << EOF -APT::Install-Recommends "0"; -APT::Install-Suggests "0"; -EOF + ```sh + # Set the correct hostname. + # Should be already set correctly. + echo 'gitea' > '/etc/hostname' + hostname -F '/etc/hostname' -# Add Grafana's repository with its key. -wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key -echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" | tee -a /etc/apt/sources.list.d/grafana.list + # Install Gitea. + apk add 'gitea' 'gitea-openrc' -# Install Prometheus and Grafana. -apt update -DEBIAN_FRONTEND='noninteractive' apt-get install --assume-yes 'grafana-enterprise' 'prometheus' + # Start Gitea. + rc-update add 'gitea' + rc-service 'gitea' start + ``` -# Configure Prometheus and Grafana. -# See the '/docker/monitoring' example. - -# Enable the services. -systemctl enable 'grafana-server.service' -systemctl enable 'prometheus.service' - -# All done! -exit -``` +1. Connect to to start the first-time installation wizard. +1. \[optionally] Configure Turris OS to [start the container at boot][start containers at boot].
- pi-hole + Monitoring -> This procedure assumes you are using an LXC container based on the Debian Bullseye image. -> -> ```sh -> lxc-create -n 'baikal' -t 'download' -- -d 'Debian' -r 'Bullseye' -a 'armv7l' -> ``` +> [!warning] +> The stack used in this container could _**easily**_ overload the device.
+> Keep CPU and memory usage under control. -See [Installing pi-hole on Turris Omnia], [Install Pi-hole] and [Pi-Hole on Turris Omnia] for details. +1. Create and start the container. -Install and configure Pi-hole in the container: + ```sh + lxc-create -n 'monitoring' -t 'download' -- -d 'Debian' -r 'Bullseye' -a 'armv7l' + ``` -```sh -# Set the correct hostname. -hostnamectl set-hostname 'pi-hole' +1. Install and configure the services in the container: -# Install pi-hole. -DEBIAN_FRONTEND='noninteractive' apt-get install --assume-yes 'ca-certificates' 'curl' 'unattended-upgrades' -curl -sSL 'https://install.pi-hole.net' | bash + ```sh + # Set the correct hostname. + hostnamectl set-hostname 'monitoring' -# Follow the guided procedure. + # Install the requirements + DEBIAN_FRONTEND='noninteractive' apt-get install --assume-yes 'unattended-upgrades' 'wget' -# Change the Web interface password, if needed. -/etc/.pihole/pihole -a -p + # Stop installing recommended and suggested packages. + cat > /etc/apt/apt.conf.d/99norecommend << EOF + APT::Install-Recommends "0"; + APT::Install-Suggests "0"; + EOF -# Update pi-hole as a whole, if needed. -/etc/.pihole/pihole updatePihole -/etc/.pihole/pihole -up + # Add Grafana's repository with its key. + wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key + echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" | tee -a /etc/apt/sources.list.d/grafana.list -# Set the router as the primary DNS server. -sed -E -i'.bak' 's|^#?\s*DNS\s*=\s*.*$|DNS=192.168.1.1|' '/etc/systemd/resolved.conf' + # Install Prometheus and Grafana. + apt update + DEBIAN_FRONTEND='noninteractive' apt-get install --assume-yes 'grafana-enterprise' 'prometheus' -# Set Cloudflare as the fallback DNS server. -# Optional. -sed -E -i'.bak' 's|^#?\s*FallbackDNS\s*=\s*.*$|FallbackDNS=1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001 # Cloudflare|' '/etc/systemd/resolved.conf' + # Configure Prometheus and Grafana. + # See the '/docker/monitoring' example. -# Set the interface to ignore DNS lists given by the DHCP server. -cp '/etc/systemd/network/eth0.network' '/etc/systemd/network/eth0.network.bak' -cat >> '/etc/systemd/network/eth0.network' < -Then, in Turris OS: + # All done! + exit + ``` -```sh -# Distribute pi-hole as the primary DNS. -# Keep the router as secondary. -uci set dhcp.lan.dhcp_option='6,192.168.111.2,192.168.111.1' +
-# The DNS server address in the IPv6 RA should be the container's ULA address -# since the global routable IPv6 address tend to change daily. -uci add_list dhcp.lan.dns="$(lxc-info --name pi-hole | grep -E 'IP.* f[cd]' | sed 's/IP: *//')" +
+ Pi-hole -# Apply the new configuration. -uci commit 'dhcp' && reload_config && luci-reload -/etc/init.d/odhcpd restart -/etc/init.d/dnsmasq restart -``` +> [!tip] +> See [Installing pi-hole on Turris Omnia], [Install Pi-hole] and [Pi-Hole on Turris Omnia] for details. + +1. Create and start the container: + + ```sh + lxc-create -n 'pi-hole' -t 'download' -- -d 'Debian' -r 'Bullseye' -a 'armv7l' + ``` + +1. Install and configure Pi-hole in the container: + + ```sh + # Set the correct hostname. + hostnamectl set-hostname 'pi-hole' + + # Install pi-hole. + DEBIAN_FRONTEND='noninteractive' apt-get install --assume-yes 'ca-certificates' 'curl' 'unattended-upgrades' + curl -sSL 'https://install.pi-hole.net' | bash + + # Follow the guided procedure. + + # Change the Web interface password, if needed. + /etc/.pihole/pihole -a -p + + # Update pi-hole as a whole, if needed. + /etc/.pihole/pihole updatePihole + /etc/.pihole/pihole -up + + # Set the router as the primary DNS server. + sed -E -i'.bak' 's|^#?\s*DNS\s*=\s*.*$|DNS=192.168.1.1|' '/etc/systemd/resolved.conf' + + # Set Cloudflare as the fallback DNS server. + # Optional. + sed -E -i'.bak' 's|^#?\s*FallbackDNS\s*=\s*.*$|FallbackDNS=1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001 # Cloudflare|' '/etc/systemd/resolved.conf' + + # Set the interface to ignore DNS lists given by the DHCP server. + cp '/etc/systemd/network/eth0.network' '/etc/systemd/network/eth0.network.bak' + cat >> '/etc/systemd/network/eth0.network' < to start the first-time installation wizard. +1. Configure Turris OS to [start the container at boot][start containers at boot]. +1. Configure Turris OS to use Pi-hole as DNS server: + + ```sh + # Distribute pi-hole as the primary DNS. + # Keep the router as secondary. + uci set dhcp.lan.dhcp_option='6,192.168.111.2,192.168.111.1' + + # The DNS server address in the IPv6 RA should be the container's ULA address + # since the global routable IPv6 address tend to change daily. + uci add_list dhcp.lan.dns="$(lxc-info --name pi-hole | grep -E 'IP.* f[cd]' | sed 's/IP: *//')" + + # Apply the new configuration. + uci commit 'dhcp' && reload_config && luci-reload + /etc/init.d/odhcpd restart + /etc/init.d/dnsmasq restart + ```
@@ -577,6 +648,7 @@ See: List of [supported SFP modules]. +> [!important] > The physical WAN port and the SFP module cage are wired to a single controller; when a SFP module is inserted, the > physical WAN **port** **will be disabled**, and the virtual WAN interface will automatically be switched to the SFP > module. @@ -657,9 +729,7 @@ luci-reload - [UCI] - [LXC] -## Sources - -All the references in the [further readings] section, plus the following: +### Sources - [Install Pi-hole] - [Pi-Hole on Turris Omnia] @@ -672,7 +742,7 @@ All the references in the [further readings] section, plus the following: --> -[further readings]: #further-readings +[Start containers at boot]: #start-containers-at-boot [baikal]: baikal.md