User Tools

Site Tools


Turris OS compilation from source codes

Turris is an OpenWrt-based system with various tweaks and additional software that for example automatically updates the system or analyzes network traffic. The complete source codes for Turris OS are available from the git repository and binary versions of it can be compiled practically on any machine. Turris OS can be compiled on any PC. In production, the system is compiled automatically on Ubuntu and the following steps are verified for that system, but the compilation process should be similar on any other compatible system. The first step is to clone the Turris OS repository. That can be done via one of the following commands (the second command is for cloning from a mirror GitHub server):

git clone https://gitlab.labs.nic.cz/turris/openwrt.git
git clone https://github.com/CZ-NIC/turris-os.git

Preparing the development environment

The best way to guarantee a smooth compilation process is to use an identical environment to the one used in production. Best is to have a container with this environment, which will enable the separation of the main system from the system for compilation. There are two supported ways of doing this, either by using a tool called Vagrant or using Docker.

Vagrant

Vagrant is a tool for easy management of development environments. Scripts are available in the Turris OS repository, which allow the creation of this environment with just few commands. At the same time it ensures synchronization between the host system and development environment, so it is possible to work with sets of programs installed on the host system in terms of repository (for example with the favorite text editor) and all changes are immediately propagated to the otherwise isolated environment, which only shares a directory with the cloned repository and in which the system compilation is started.

First we install the Vagrant application. This can be done using a package manager (for example APT on Ubuntu/Debian), however, in some distributions only older versions are available, which miss various required functionalities so problems may occur. In such cases it is advisable to download the newest version from the official website.

While installing Vagrant, installation of the the plugin vagrant-lxc, which allows the use of LXC containers, is also required. The container make separation of the compilation environment from the host system easier without significantly compiling speed decrease. This plugin of course also requires support of LXC in the host system. Installation of this plugin and its dependencies can be done with these two commands (assuming that Vagrant is already installed):

sudo apt-get install lxc
vagrant plugin install vagrant-lxc

In the last step, you should create a symbolic link (or copy) to a file with a development environment definition and put it into the root directory with the cloned Turris OS repository:

ln -s vagrant/Vagrantfile

It is now possible to run an instance of the development environment. This can be done using the command vagrant up --provider=lxc (the option --provider=lxc is required for the first initialization only). This command comes in useful every time the installation is terminated (using vagrant halt or after the host system reboot). In those cases, where the development environment needs to be reinstalled or it needs to be completely removed, the command vagrant destroy can be used.

To access the development system the command vagrant ssh can be run in Turris repository directory. This opens up an SSH connection to the container with the development environment and it can now be used as normal system. The directory synchronized with the Turris OS repository is accessible through the path /openwrt.

Docker

Docker is in comparison with the Vagrant tool more widespread, and thus it is possible that it is already installed and configured on your system. The files needed to create Docker containers are located in the cloned Turris OS repository in the directory 'Docker'. The necessary files are the scripts: build-all and run and especially files describing Docker containers. The first step is to create containers. The script build-all contains five lines calling docker, which create five containers. Their names and meaning are the following:

  • base – basic system containing all the dependencies needed to build Turris OS. Source codes are cloned in the directory '/ home / build / openwrt' in the latest version of the 'test' branch (a branch which is now being developed).
  • omnia-toolchain – requires the base and builds on it. It is the place where the configuration for Turris Omnia is and it contains the compiled toolchain. Packages, however, are not compiled. This can be useful, if you need to adjust a single package only, not the whole system.
  • omnia – requires and is based on the omnia-toolchain. The container accommodates the basic system and the system for Turris Omnia. This container, however, not all of the packages are compiled (this would require a large amount of time).
  • turris-toolchain - requires and builds on the base. It has configurations for Turris 1.x and the compiled toolchain. The packages, however, are not compiled. This can be useful if you need to compile only one package, not the whole system.
  • turris - requires and builds on turris-toolchain. The container is designed for the basic system of Turris 1.x and so compilation should be quick. But even in this case, not all packages are compiled (that would require a large amount of time).

To save time and space you can remove the lines for the platform, which is not relevant to you. Then run the script build-all. This process may take hours, depending on the performance of the hardware on which the compilation runs and on which you are creating the containers.

After the containers are created, it is possible to access them using the Run script. This script requires the name of the container (e.g. './run Omnia') as the first argument. If no arguments are passed, it will attempt to attach to the container omnia-toolchain.

Beware! As far as the Docker is concerned, after the end of the container all changes are discarded if not set otherwise. Also unlike the Vagrant tools, Docker does not work with your original cloned repository.

In the following sections distinguish which container you chose to use. In case of base, you have to perform the procedure as described. For other Docker containers you do not need to update feeds and configuration settings, you can move straight to the compilation. In that case it is also not recommended to use compile_fw script because that first cleans the repository.

Installation without Vagrant environment

If you don't want to or can't use Vagrant on your system, then it is possible to install compilation dependencies directly onto the system. These dependencies can be found in the initialization script vagrant/vagrant_bootstrap.sh, which is run during the initial run of the Vagrant environment. In systems based on Debian the commands can mostly be used without change. In other systems, corresponding packages have to be installed. Table on OpenWrt wiki can be useful when searching for appropriate packages. The previously mentioned script also edits the URL for package download and optionally allows installation of additional arguments for the command make in the buildroot using the extension openwrt-bash-completion.

The last resort option is the use of a virtual system. This method is more demanding on resources (CPU and memory), but it is possible to apply in on a wide variety of systems, including Windows. Virtualization can be done using for example a freely distributed application VirtualBox. In that case, it is advisable to choose Ubuntu as the installed system, because then it is enough to clone the Turris OS repository and run the previously mentioned script and the development environment is ready.

Compiling Turris OS

Buildroot (a compilation tool) Turris OS, or OpenWRT, consist of a big amount of scripts, that cross compile (compile for the target platform) software using the tool GNU Make. The primary command used in buildroot is therefore make. In addition to the key system components contained in the repository openwrt (turris-os) additional packages are compiled, which are managed from the repository turris-os-packages and other third party repositories. Their inclusion in the system is handled by the script which also manages feeds. So let's look at commands, which can be useful when using buildroot. All commands should be run in the root directory of the repository (folder / openwrt in the Vagrant environment). They are listed in the order in which they should be run after initialization of the clean development environment:

  • ./scripts/feeds update -a – Updates all feeds from their location. This step also downloads content from other repositories like turris-os-packages into separate folders.
  • ./scripts/feeds install -a – Installs packages from all feeds into buildroot. This creates symbolic links to the definition of packages in the package/ and it is possible to select and compile packages.
  • cp configs/omnia .config– Copies the configuration file for Turris Omnia (alternatively configs/Turris for Turris 1.x)
  • make menuconfig - Displays the configuration menu. Within it you can control what kinds of packages should be be compiled and possibly other parameters of the compiled system can be adjusted. After saving, information on the current configuration is also generated (which can as well be achieved by running the command make defconfig).

After you run these commands, you can start compiling all the tools and the system itself. Because if done by single strain, this operation would last very long, the example shows the use of the symptom -j NUMBER where NUMBER represents the number of jobs that can run simultaneously. It is recommended to select the number that corresponds to the number of CPU kernels or one unit higher. Parameters LOGFILE=1 BUILD_LOG=1 IS_TTY=1 ensure that the output of the compilation is recorded in the file and the console displays only basic information about the compilation:

make -j 4 LOGFILE=1 BUILD_LOG=1 IS_TTY=1

Sometimes the operation ends with an error. In that case, use either the parameters form the examples, and then look for the error in the file logs/build.log or add the parameter V=s to the command to receive an extended output on the console.

Sometimes it is desirable to compile only one package. If you already have the compiled toolchain (For example, you ran the command make as in the example above), fetch source codes using the following command. This will also start their compilation for the target system and the creation of the .ipk package installation on the router. In addition, it is sometime necessary to first assemble dependency packages for the required package.

make package/package-name/install

As package name you should enter the name of the folder, in which the file Makefile for the given package is located, not the package name specified in the variable PKG_NAME. If the file Makefile contains more packages, all of the packages will be created, which have been selected in the configuration.

Compiled packages (and any additional output compilations, such as SDK, and other files) can be found in the bin/. Created .ipk files can then be copied onto the router and installed.

To facilitate the compilation there are shell scripts compile_turris_fw and compile_omnia_fw in the repository, which when run delete old files, initialize feeds and run compilation of the system. It is appropriate to run them with the parameter USE_CCACHE = 1 and in a number of tasks (for instance USE_CCACHE=1 ./compile_turris_fw -j4) it is necessary to install the package ccache onto the system, which runs compilation. You can also use the parameter BUILD_ALL – this runs the installation of completely all packages that are included in the Turris OS. This operation takes considerably longer (in terms of hours). To start compiling the complete Turris OS, with the use of cache during compilation and with four roles and error output being recorded in the file, run the following:

USE_CCACHE=1 BUILD_ALL=1 ./compile_turris_fw -j 4 LOGFILE=1 BUILD_LOG=1 IS_TTY=1

Troubleshooting

Insufficient space when creating the Docker container

Docker containers usually take up tens of gigabytes. If their creation failed because of insufficient space, then you should check, if you really have run out of space and clear it. If you however have enough space, then you might need to adjust the configuration of the Docker daemon with the use of these options --storage-opt dm.basesize=40G --storage-opt dm.loopmetadatasize=10G.

The resulting configuration should look something like this:

dockerd -H fd:// --storage-opt dm.basesize=40G --storage-opt dm.loopmetadatasize=10G

After this adjustment it is necessary to restart the Docker daemon and remove all generated files for the change to apply. The exact path of the files depends on your system, but it is usually /var/lib/docker.