utils/lxc.sh

With the use of Linux Containers (LXC) we can scale our tasks over a stack of containers, what we call the: lxc suite. The searx suite (lxc-searx.env) is loaded by default, every time you start the lxc.sh script (you do not need to care about).

Before you can start with containers, you need to install and initiate LXD once:

$ snap install lxd
$ lxd init --auto

To make use of the containers from the searx suite, you have to build the LXC suite containers initial. But be warned, this might take some time:

$ sudo -H ./utils/lxc.sh build

A cup of coffee later, your LXC suite is build up and you can run whatever task you want / in a selected or even in all LXC suite containers. If you do not want to build all containers, you can build just one:

$ sudo -H ./utils/lxc.sh build searx-ubu1804

Good to know …

Each container shares the root folder of the repository and the command utils/lxc.sh cmd handles relative path names transparent, compare output of:

$ sudo -H ./utils/lxc.sh cmd -- ls -la Makefile
...

In the containers, you can run what ever you want, e.g. to start a bash use:

$ sudo -H ./utils/lxc.sh cmd searx-ubu1804 bash
INFO:  [searx-ubu1804] bash
root@searx-ubu1804:/share/searx#

If there comes the time you want to get rid off all the containers and clean up local images just type:

$ sudo -H ./utils/lxc.sh remove
$ sudo -H ./utils/lxc.sh remove images

Install suite

To install the complete searx suite (includes searx, morty & filtron) into all LXC use:

$ sudo -H ./utils/lxc.sh install suite

The command above installs a searx suite (see Installation scripts). To get the IP (URL) of the filtron service in the containers use show suite command. To test instances from containers just open the URLs in your WEB-Browser:

$ sudo ./utils/lxc.sh show suite | grep filtron
[searx-ubu1604]  INFO:  (eth0) filtron:    http://n.n.n.246:4004/ http://n.n.n.246/searx
[searx-ubu1804]  INFO:  (eth0) filtron:    http://n.n.n.147:4004/ http://n.n.n.147/searx
[searx-ubu1910]  INFO:  (eth0) filtron:    http://n.n.n.140:4004/ http://n.n.n.140/searx
[searx-ubu2004]  INFO:  (eth0) filtron:    http://n.n.n.18:4004/ http://n.n.n.18/searx
[searx-fedora31]  INFO:  (eth0) filtron:    http://n.n.n.46:4004/ http://n.n.n.46/searx
[searx-archlinux]  INFO:  (eth0) filtron:    http://n.n.n.32:4004/ http://n.n.n.32/searx

To install a nginx reverse proxy for filtron and morty use (or alternatively use apache):

sudo -H ./utils/lxc.sh cmd -- FORCE_TIMEOUT=0 ./utils/filtron.sh nginx install
sudo -H ./utils/lxc.sh cmd -- FORCE_TIMEOUT=0 ./utils/morty.sh nginx install

Running commands

Inside containers, you can use make or run scripts from the Tooling box utils/*. By example: to setup a Buildhosts and run the Makefile target test in the archlinux container:

sudo -H ./utils/lxc.sh cmd searx-archlinux ./utils/searx.sh install buildhost
sudo -H ./utils/lxc.sh cmd searx-archlinux make test

Setup searx buildhost

You can install the searx buildhost environment into one or all containers. The installation procedure to set up a build host takes its time. Installation in all containers will take more time (time for another cup of coffee).:

sudo -H ./utils/lxc.sh cmd -- ./utils/searx.sh install buildhost

To build (live) documentation inside a archlinux container:

sudo -H ./utils/lxc.sh cmd searx-archlinux make docs-clean docs-live
...
[I 200331 15:00:42 server:296] Serving on http://0.0.0.0:8080

To get IP of the container and the port number live docs is listening:

$ sudo ./utils/lxc.sh show suite | grep docs-live
...
[searx-archlinux]  INFO:  (eth0) docs-live:  http://n.n.n.12:8080/

Overview

The --help output of the script is largely self-explanatory:

usage::
  lxc.sh build        [containers|<name>]
  lxc.sh copy         [images]
  lxc.sh remove       [containers|<name>|images]
  lxc.sh [start|stop] [containers|<name>]
  lxc.sh show         [images|suite|info|config [<name>]]
  lxc.sh cmd          [--|<name>] '...'
  lxc.sh install      [suite|base [<name>]]

build
  :containers:   build, launch all containers and 'install base' packages
  :<name>:       build, launch container <name>  and 'install base' packages
copy:
  :images:       copy remote images of the suite into local storage
remove
  :containers:   delete all 'containers' or only <container-name>
  :images:       delete local images of the suite
start/stop
  :containers:   start/stop all 'containers' from the suite
  :<name>:       start/stop container <name> from suite
show
  :info:         show info of all (or <name>) containers from LXC suite
  :config:       show config of all (or <name>) containers from the LXC suite
  :suite:        show services of all (or <name>) containers from the LXC suite
  :images:       show information of local images
cmd
  use single qoutes to evaluate in container's bash, e.g.: 'echo $(hostname)'
  --             run command '...' in all containers of the LXC suite
  :<name>:       run command '...' in container <name>
install
  :base:         prepare LXC; install basic packages
  :suite:        install LXC searx suite into all (or <name>) containers

LXC suite: searx --> http://fv-az150-355/searx
  suite includes searx, morty & filtron
suite images:
  ubu1604 ubu1804 ubu2004 ubu2010 fedora31 archlinux centos7
suite containers:
  searx-ubu1604 searx-ubu1804 searx-ubu2004 searx-ubu2010 searx-fedora31
  searx-archlinux searx-centos7

searx suite

# -*- coding: utf-8; mode: sh indent-tabs-mode: nil -*-
# SPDX-License-Identifier: AGPL-3.0-or-later
# shellcheck shell=bash

# This file is a setup of a LXC suite.  It is sourced from different context, do
# not manipulate the environment directly, implement functions and manipulate
# environment only is subshells!

# ----------------------------------------------------------------------------
# config
# ----------------------------------------------------------------------------

# shellcheck disable=SC2034
LXC_SUITE_NAME="searx"
lxc_set_suite_env() {
    # name of https://images.linuxcontainers.org
    export LINUXCONTAINERS_ORG_NAME="${LINUXCONTAINERS_ORG_NAME:-images}"
    export LXC_HOST_PREFIX="${LXC_SUITE_NAME:-searx}"
    export LXC_SUITE=(

        # to disable containers, comment out lines ..

        # end of standard support see https://wiki.ubuntu.com/Releases
        "$LINUXCONTAINERS_ORG_NAME:ubuntu/16.04"  "ubu1604" # April 2021
        "$LINUXCONTAINERS_ORG_NAME:ubuntu/18.04"  "ubu1804" # April 2023
        "$LINUXCONTAINERS_ORG_NAME:ubuntu/20.04"  "ubu2004" # April 2025
        "$LINUXCONTAINERS_ORG_NAME:ubuntu/20.10"  "ubu2010" # July 2021

        # EOL see https://fedoraproject.org/wiki/Releases
        "$LINUXCONTAINERS_ORG_NAME:fedora/31"     "fedora31"

        # rolling releases see https://www.archlinux.org/releng/releases/
        "$LINUXCONTAINERS_ORG_NAME:archlinux"     "archlinux"

        # EOL 30 June 2024
        "$LINUXCONTAINERS_ORG_NAME:centos/7"      "centos7"
    )

    PUBLIC_URL="${PUBLIC_URL:-http://$(uname -n)/searx}"
    if in_container; then
        # container hostnames do not have a DNS entry: use primary IP!
        PUBLIC_URL="http://$(primary_ip)/searx"

        # make GUEST's services public to the HOST
        FILTRON_API="0.0.0.0:4005"
        FILTRON_LISTEN="0.0.0.0:4004"
        MORTY_LISTEN="0.0.0.0:3000"

        # export LXC specific environment
        export PUBLIC_URL FILTRON_API FILTRON_LISTEN MORTY_LISTEN
    fi
}

lxc_suite_install_info() {
    (
        lxc_set_suite_env
        cat <<EOF
LXC suite: ${LXC_SUITE_NAME} --> ${PUBLIC_URL}
  suite includes searx, morty & filtron
suite images:
$(echo "  ${LOCAL_IMAGES[*]}" | $FMT)
suite containers:
$(echo "  ${CONTAINERS[*]}" | $FMT)
EOF
    )
    }

lxc_suite_install() {
    (
        lxc_set_suite_env
        FORCE_TIMEOUT=0
        export FORCE_TIMEOUT
        "${LXC_REPO_ROOT}/utils/searx.sh"   install all
        "${LXC_REPO_ROOT}/utils/morty.sh"   install all
        "${LXC_REPO_ROOT}/utils/filtron.sh" install all

        rst_title "suite installation finished ($(hostname))" part
        lxc_suite_info
        echo
    )
}

lxc_suite_info() {
    (
        lxc_set_suite_env
        for ip in $(global_IPs) ; do
            if [[ $ip =~ .*:.* ]]; then
                info_msg "(${ip%|*}) IPv6:       http://[${ip#*|}]"
            else
                # IPv4:
                # shellcheck disable=SC2034,SC2031
                info_msg "(${ip%|*}) filtron:    http://${ip#*|}:4004/ $PUBLIC_URL"
                info_msg "(${ip%|*}) morty:      http://${ip#*|}:3000/ $PUBLIC_URL_MORTY"
                info_msg "(${ip%|*}) docs-live:  http://${ip#*|}:8080/"
            fi
        done
    )
}