\documentclass{article}
\usepackage[margin=2cm]{geometry}

\usepackage{graphicx} % Add the graphicx package for \reflectbox

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[polish]{babel}

\usepackage{hyperref}

\usepackage[
    sortcites,
    backend=biber,
    hyperref=true,
    firstinits=true,
    maxbibnames=99,
    ]{biblatex}
\addbibresource{references.bib}


\title{OpenWRT incus/LXD Container Setup}

\author{
    % mp\raisebox{-1.5ex}{\reflectbox{\rotatebox[origin=c]{180}{A}}}b\raisebox{-1.5ex}{\reflectbox{\rotatebox[origin=c]{180}{I}}}
    M. Pabiszczak
}

\date{\today} % Date inserted at compile time

\begin{document}


\maketitle


\section*{Comparison between incus and LXD}
Linux Containers (incus) and LXD are both significant technologies in the realm of containerization and virtualization. incus is a pioneering technology that offers operating-system level virtualization through lightweight containers. It allows for running multiple isolated Linux systems (containers) on a single control host. LXD, on the other hand, is an extension of incus, providing a more user-friendly and scalable approach to container management. LXD enhances the capabilities of incus with features like easy storage management, network management, and a REST API for remote control. While LXD builds upon incus, each has its unique use cases and advantages. Below is a comparative analysis of incus and LXD across various features:

\vspace{5mm}

\begin{tabular}{ |p{3cm}|p{6cm}|p{6cm}| }
 \hline
 \textbf{Feature} & \textbf{incus (Linux Containers)} & \textbf{LXD} \\
 \hline
 Architecture & Built on Linux kernel features like cgroups and namespaces, offering process and resource isolation. Shares the host's kernel but runs in isolated user spaces. & Built on top of incus, providing a more user-friendly and scalable system with a daemon-based architecture. Adds extra features like a REST API for remote management. \\
 \hline
 Ease of Use & Known for its simplicity and flexibility in configuration with command-line tools. Requires understanding of Linux namespaces and cgroups. & Provides an easier and more intuitive command-line interface and REST API, making it simpler to use, especially for managing large numbers of containers. \\
 \hline
 Networking and Storage & Versatile networking options and storage managed using standard Linux filesystems. Containers have their own file system layout. & Inherits incus's capabilities and extends them with improved storage options like ZFS, BTRFS, and LVM, and easier network management. \\
 \hline
 Security Features & Offers various security features like AppArmor and SELinux support, but not inherently sandboxed. & Enhances security by offering container snapshots, easier transfer of containers with security profiles, and integration with AppArmor and SELinux. \\
 \hline
 Community and Ecosystem & Strong community and ecosystem with active development. Integrates well with various tools for development and production. & Expands on incus’s ecosystem, with support from Canonical (the company behind Ubuntu), ensuring more frequent updates and feature additions. \\
 \hline
 Use Cases & Suitable for environments where full OS virtualization is unnecessary. Used in CI/CD, development environments, and lightweight application isolation. & Ideal for more extensive container deployments, offering an easier and more scalable container management system. Suitable for both on-premises and cloud environments. \\
 \hline
\end{tabular}
\newpage


\section{Finding and Using the Latest OpenWRT Snapshot in LXD}

\subsection{Creating and Configuring a Network Bridge}

\begin{enumerate}

        \item \textbf{Creating a New Network Bridge}:\\
        To create a new network bridge named \texttt{incusbr0} in LXD, execute the following command:
        \begin{verbatim}
            sudo incus network create incusbr0
        \end{verbatim}
        This command creates the network bridge \texttt{incusbr0}. After its creation, you can use this bridge for various networking purposes in LXD.
    
        To delete the network bridge named \texttt{incusbr0} that you have created, use the following command:
        \begin{verbatim}
            sudo incus network delete incusbr0
        \end{verbatim}
        This command will remove the network bridge \texttt{incusbr0} from LXD.

        \item \textbf{Displaying Information About the Created Network}:\\
        To display detailed information about the created network \texttt{incusbr0}, use the following command:
        \begin{verbatim}
            sudo incus network show incusbr0
        \end{verbatim}
        This command will provide details about the \texttt{incusbr0} network configuration.
        
    \item \textbf{Attaching and Detaching a Container from a Network Bridge}:\\
    To attach a container named \texttt{owrt0} to a network bridge \texttt{incusbr0} and then detach it, use the following commands:
    \begin{verbatim}
        sudo incus network attach incusbr0 owrt0 eth0 eth0
        sudo incus network detach incusbr0 owrt0 eth0
    \end{verbatim}
    The first command attaches the container \texttt{owrt0} to the network bridge \texttt{incusbr0}, while the second command detaches it from the bridge.
    To display the network device configuration of a specific container such as \texttt{owrt0}, use:
    \begin{verbatim}
        sudo incus config device show owrt0
    \end{verbatim}
    The output will show the network devices and their configurations for the \texttt{owrt0} container. For example:
    \begin{verbatim}
    eth0:
      name: eth0
      network: incusbr0
      type: nic
    \end{verbatim}
    \item \textbf{Adding the New Network Bridge to the Default Profile}:\\
    After creating \texttt{incusbr0}, you can add it as a network interface to the default profile using this command:
    \begin{verbatim}
        sudo incus profile device add default eth0 nic nictype=bridged parent=incusbr0
    \end{verbatim}
    This adds the bridge \texttt{incusbr0} to the default profile. LXD containers that use the default profile will by default be connected to the newly created bridge \texttt{incusbr0}.

    To remove the network interface \texttt{eth0}, which is associated with the \texttt{incusbr0} network bridge, from the default profile, use this command:
    \begin{verbatim}
        sudo incus profile device remove default eth0
    \end{verbatim}
    This command removes the network interface \texttt{eth0} from the default profile, disconnecting it from the \texttt{incusbr0} bridge.

    \item \textbf{Displaying Information About the Default Profile}:\\
    To display detailed information about the default profile in LXD, use the following command:
    \begin{verbatim}
        sudo incus profile show default
    \end{verbatim}
    This command will provide details about the \texttt{default} profile configurations.
    

\end{enumerate}

\subsection{Listing Available Images}
You can view all images in your local LXD store to verify the import. The command below displays a list of images with details like size, upload date, and aliases.
\begin{verbatim}
sudo incus image list
\end{verbatim}

\subsection{Deleting an Image}
If needed, you can remove an image from your local LXD store. Use the following command with either the image's alias or its fingerprint. Remember, this action is irreversible, so make sure to delete the correct image.
\begin{verbatim}
sudo incus image delete [alias_or_fingerprint]
\end{verbatim}

\subsection{Listing OpenWRT Images}
Use the command below to list all available OpenWRT images in the default LXD image repository. This helps you find the desired architecture and version, like `amd64` and the latest release date.
\begin{verbatim}
sudo incus image list images: openwrt
\end{verbatim}

\subsection{Importing the Snapshot Image}
For using a specific OpenWRT snapshot, such as `Openwrt snapshot amd64`, import it into your local LXD image store. This can be done with the following command, which assigns an easy-to-remember alias to the imported image.
\begin{verbatim}
sudo incus image copy images:openwrt/snapshot/amd64 local: --alias openwrt-latest
\end{verbatim}

\subsection{Launching an OpenWRT Container}
Finally, to create and start a new container using the imported OpenWRT image, use this command. It creates a container named \texttt{owrt0} with the OpenWRT image you imported.
\begin{verbatim}
sudo incus launch openwrt-latest owrt0
\end{verbatim}

To list all the currently available LXD containers, including the newly created \texttt{owrt0} container, use the following command:
\begin{verbatim}
sudo incus ls
\end{verbatim}

\subsection{Recreating the OpenWRT Container}

To recreate the OpenWRT container named "owrt0", first stop and destroy the existing container, then recreate it using the same snapshot version. The commands to execute are as follows:

\begin{verbatim}
sudo incus stop owrt0
sudo incus delete owrt0
sudo incus launch openwrt-latest owrt0
\end{verbatim}

\subsection{Attaching a Console to the Container}

To access the interactive console of an LXD container, you can use the \texttt{incus exec} command. This command allows you to run commands inside the container or to access its interactive shell. 

\paragraph{Starting an Interactive Console Session:}
To start an interactive console session in an LXD container, use the \texttt{incus exec} command followed by the container's name, then \texttt{--}, and \texttt{bash} or \texttt{ash}, depending on what is available in the container. For example:

\begin{verbatim}
sudo incus exec owrt0 -- ash
\end{verbatim}

This command will start an interactive bash session in the container named \texttt{owrt0}.

\paragraph{Executing a Single Command:}
You can also use \texttt{incus exec} to execute a single command inside the container. For instance, to check the system version inside the container, you can use:

\begin{verbatim}
sudo incus exec owrt0 -- uname -a
\end{verbatim}

This command executes \texttt{uname -a} inside the \texttt{owrt0} container and displays the output.

\section{Configuring Proxy Devices in LXD Containers}

Proxy devices in LXD allow network connections to be forwarded between the host and the containers. This can be particularly useful for exposing services running within a container to the outside network or redirecting traffic from the host to the container.

\subsection{Adding a Proxy Device}

To add a proxy device to an LXD container, you can use the \texttt{incus config device add} command. For example, to forward traffic from port 1234 on the host to port 80 in the container named \texttt{owrt0}, the command would be:

\begin{verbatim}
incus config device add owrt0 owrt-proxy proxy listen=tcp:0.0.0.0:1234 \
    connect=tcp:127.0.0.1:80
\end{verbatim}

In this command:
\begin{itemize}
    \item \texttt{owrt0} is the name of the container to which the proxy device is being added.
    \item \texttt{owrt-proxy} is the arbitrary name given to the new proxy device.
    \item The \texttt{listen} parameter specifies the host's IP address and port to listen on. Here, \texttt{0.0.0.0:1234} means all IPv4 addresses on the host on port 1234.
    \item The \texttt{connect} parameter specifies the container's IP address and port to connect to. Here, \texttt{127.0.0.1:80} directs the traffic to port 80 on the container.
\end{itemize}

\subsection{Listing Proxy Devices for a Container}

To list all configured devices, including proxy devices for a specific container, you can use the \texttt{incus config device show} command followed by the container name. For the container \texttt{owrt0}, the command is:

\begin{verbatim}
incus config device show owrt0
\end{verbatim}

This command will display a list of all devices attached to the container \texttt{owrt0}, including details about the proxy device(s) configured.

\subsection{Summary}

Proxy devices are a powerful feature of LXD, allowing for flexible network configurations and exposing container services to the host network. By following the commands outlined above, you can easily set up port forwarding for your LXD containers.


% \section{Network Bridge Configuration with dnsmasq}

% To configure a network bridge `mybridge` in LXD using `dnsmasq` for DHCP and NAT, follow these steps:

% \subsection{dnsmasq Installation}

% \begin{verbatim}
% sudo apt-get install dnsmasq
% \end{verbatim}

% \subsection{dnsmasq Configuration}

% Edit the dnsmasq configuration file, usually located at \texttt{/etc/dnsmasq.conf}. 
% Add the following configuration:

% \begin{verbatim}
% interface=mybridge
% bind-interfaces
% dhcp-range=192.168.1.10,192.168.1.100,24h
% \end{verbatim}

% This sets up a DHCP server on the `mybridge` with an address pool from 192.168.1.10 to 192.168.1.100, and a lease time of 24 hours.

% \subsection{NAT Configuration}

% Configuring NAT (Network Address Translation) is necessary for containers to communicate with the Internet. Execute the following commands to set up NAT for the `mybridge`:

% \begin{verbatim}
% sudo iptables -t nat -A POSTROUTING -o <your-external-interface> -j MASQUERADE
% sudo iptables -A FORWARD -i mybridge -o <your-external-interface> -j ACCEPT
% sudo iptables -A FORWARD -i <your-external-interface> -o mybridge -m state --state RELATED,ESTABLISHED \
%               -j ACCEPT
% \end{verbatim}

% Replace \texttt{<your-external-interface>} with the name of your server's external network interface.


\section*{Configuring the OpenWRT}

After creating the container, configure the network and DHCP settings using UCI commands as follows:

\begin{verbatim}
uci add network device
uci set network.@device[-1].name="br-lan"
uci set network.@device[-1].type="bridge"
uci set network.@device[-1].bridge_empty="1"

uci set network.lan=interface
uci set network.lan.device=br-lan
uci set network.lan.proto=static
uci set network.lan.ipaddr=192.168.100.1
uci set network.lan.netmask=255.255.255.0

uci set dhcp.lan=dhcp
uci set dhcp.lan.start=100
uci set dhcp.lan.limit=150
uci set dhcp.lan.leasetime=2h
uci set dhcp.lan.interface=lan

uci commit network
uci commit firewall
uci commit dhcp

/etc/init.d/network restart
/etc/init.d/firewall restart
/etc/init.d/dnsmasq restart



uci delete network.lan
uci delete network.@device[0]

uci delete network.wan
uci delete network.wan6

uci commit network

uci show network


network.wan=interface
network.wan.ifname='eth0'
network.wan.proto='dhcp'


\end{verbatim}


% \bibliographystyle{plain}
\printbibliography

\end{document}

incus network create incusbr0
incus profile device add default eth0 nic nictype=bridged parent=incusbr0

sudo incus stop owrt0
sudo incus delete owrt0
sudo incus launch openwrt-latest owrt0


bridge -d link show master br-lan
bridge vlan show dev web1A

sudo incus launch ubuntu:22.04 lxd-u1


sudo incus network attach incusbr0 owrt0 eth0 eth0
sudo incus config device show owrt0

eth0:
  name: eth0
  network: incusbr0
  type: nic


sudo incus network detach incusbr0 owrt0 eth0

while true; do clear; diff network network.old; sleep 1; done


incus profile create net
incus profile edit net

config:
  user.user-data: |
    #net-config
    package_upgrade: true

    packages:
      - aptitude
      - tmux
      - vim-nox
      - nano
      - mc
      - git
      - curl
      - termshark
      - procps
      - sudo
      - iproute2
      - iputils-ping
      - bridge-utils
      - ifupdown
      - udev
      - make
      - build-essential
      - libssl-dev
      - zlib1g-dev
      - libbz2-dev
      - libreadline-dev
      - libsqlite3-dev
      - wget
      - llvm
      - libncurses5-dev
      - libncursesw5-dev
      - xz-utils
      - libffi-dev
      - liblzma-dev
      - python3-ipython

    runcmd:
      - echo "user:pass" | chpasswd
      - useradd -ms /bin/bash user
      - adduser user sudo

description: Custom Ubuntu profile for network tools and utilities
name: net
used_by: []

sudo incus launch ubuntu:22.04 lxd-u1 --profile default --profile net


