EDU Container
The memory of the VPS is almost full now, after installing several applications. Let's rescale it from 2 VCPUs and 4 GB RAM to 4 VCPU and 8 GB RAM. We can keep the disk size the same (40 GB).
Rescaling can be done from web interface of Hetzner. First we turn the
power off, then select the new size, then click the button Rescale. It
will take a few minutes. We can check with free -h
the new size of
the memory.
1. Introduction
We have installed already many docker-scripts apps, and the directory
/var/ds/
has started to look a bit crowded. We can create an Incus
container, install Docker and docker-scripts in it, and migrate some
of these apps from the host to this container. For example let's move
all the applications related to education (Moodle, VCLab, LinuxMint,
RaspberryPi, etc.).
After this reorganization, the deployment diagram should look like this:
So, we are going to:
-
Create an Incus container named
edu
. -
Give it a fixed IP and make some improvements (set a better prompt, etc.)
-
Install Docker and docker-scripts. Install
revproxy
andmariadb
. -
Migrate to it containers for Moodle, Guacamole, LinuxMint, RaspberryPi, etc.
-
Change the configuration of
sniproxy
to forward to the IP of the Incus container the domainsedu.user1.fs.al
(Moodle) andvclab.user1.fs.al
(Guacamole).
2. Create an Incus container
2.1 Create the container
Let's create a Debian container, named edu
:
incus launch images:debian/12 edu \
-c security.nesting=true \
-c security.syscalls.intercept.mknod=true \
-c security.syscalls.intercept.setxattr=true
incus list
incus info edu
incus config show edu
The configuration -c security.nesting=true
is needed in order to run
docker inside the container. However, since the container is
unprivileged, it does not really have any security implications.
Similarly, the other two configuration options are needed so that docker can handle its images efficiently.
2.2 Setup the container
Let's make a few small improvements inside the container:
# get a shell in the container
incus shell edu
# install some tools
apt install --yes nano curl wget
# uncomment some aliases
sed -i ~/.bashrc \
-e 's/# export LS_OPTIONS=/export LS_OPTIONS=/' \
-e 's/# alias ls=/alias ls=/' \
-e 's/# alias ll=/alias ll=/' \
-e 's/# alias l=/alias l=/'
cat ~/.bashrc
# set a better prompt
echo 'source ~/.bashrc_custom' >> ~/.bashrc
cat <<'EOF' > ~/.bashrc_custom
# set a better prompt
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u\[\033[01;33m\]@\[\033[01;36m\]\h \[\033[01;33m\]\w \[\033[01;35m\]\$ \[\033[00m\]'
EOF
source ~/.bashrc_custom
# install and enable bash-completion
apt install --yes bash-completion
cat <<'EOF' >> ~/.bashrc_custom
# enable programmable completion features
if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
source /etc/bash_completion
fi
EOF
nano ~/.bashrc_custom
source ~/.bashrc_custom
# enable automatic security updates
apt install --yes unattended-upgrades
# in case of using vim, uncomment its dark background setting
sed -i /etc/vim/vimrc \
-e 's/^"set background=dark/set background=dark/'
2.3 Set a fixed IP
We have to set a fixed IP to this container, so that sniproxy
can
forward HTTPS connections to it. If the IP is a dynamic random one,
then the configuration of sniproxy
has to be changed whenever the IP
of the container changes, which is not convenient.
Remember that when we installed Incus, we limited the DHCP
range of the containers to
10.31.96.2-10.31.96.200
. So, we can used fixed IPs from
10.31.96.201
and above. Let's use 10.31.96.201
for this container.
ls /etc/systemd/network/
nano /etc/systemd/network/eth0.network
ip addr
IP=10.31.96.201/24
GW=10.31.96.1
cat <<EOF > /etc/systemd/network/eth0.network
[Match]
Name=eth0
[Address]
Address=$IP
[Route]
Gateway=$GW
[Network]
DHCP=no
DNS=8.8.8.8
EOF
nano /etc/systemd/network/eth0.network
systemctl restart systemd-networkd
ip addr
ip ro
ping google.com
exit
incus ls
incus restart edu
incus ls
3. Install Docker etc
3.1 Install Docker
-
Get Docker’s official GPG key:
wget https://download.docker.com/linux/ubuntu/gpg \
-O /etc/apt/keyrings/docker.asc
ls -l /etc/apt/keyrings/docker.asc -
Add the Docker sources to the apt list:
cat <<EOF > /etc/apt/sources.list.d/docker.sources
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: bookworm
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
cat /etc/apt/sources.list.d/docker.sources -
Install it:
apt update
apt install --yes \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
3.2 Install docker-scripts
apt install git make m4 highlight tree
git clone \
https://gitlab.com/docker-scripts/ds \
/opt/docker-scripts/ds
cd /opt/docker-scripts/ds/
make install
3.3 Install revproxy
ds pull revproxy
ds init revproxy @revproxy
cd /var/ds/revproxy/
nano settings.sh
ds make
On settings.sh
, before running ds make
:
- Set your email address to
SSL_CERT_EMAIL
. - Uncomment
ENABLE_PROXY_PROTOCOL=true
.
3.4 Install mariadb
ds pull mariadb
ds init mariadb @mariadb
cd /var/ds/mariadb/
nano settings.sh
ds make
3.5 Logwatch and notifications
Let's make sure that we get logwatch notifications from the edu
container:
-
Install and setup
msmtp
:apt install \
msmtp msmtp-mta bsd-mailxcat << _EOF_ > /etc/msmtprc
account smtp
maildomain user1.fs.al
host smtp.user1.fs.al
from edu@user1.fs.al
tls_starttls on
set_from_header on
account default : smtp
aliases /etc/aliases.msmtp
syslog LOG_MAIL
_EOF_
nano /etc/msmtprccat << _EOF_ > /etc/aliases.msmtp
default: dashohoxha@gmail.com
_EOF_
nano /etc/aliases.msmtpmail --help
mail -s Test1 -- root <<< "Test 1" -
Install and setup logwatch:
apt install --yes logwatch libdate-manip-perl
cat << _EOF_ > /etc/logwatch/conf/logwatch.conf
Range = between -7 days and -1 days
_EOF_mkdir -p /etc/cron.weekly/
mv /etc/cron.daily/00logwatch /etc/cron.weekly/nano /etc/cron.weekly/00logwatch
/etc/cron.weekly/00logwatch
Now let's enable logwatch for the containers that we will install with
docker-scripts inside edu
:
cat << _EOF_ >> ~/.ds/global_settings.sh
SMTP_SERVER="smtp.user1.fs.al"
SMTP_DOMAIN="user1.fs.al"
#SMTP_PORT=25
LOGWATCH_EMAIL=dashohoxha@gmail.com
_EOF_
nano ~/.ds/global_settings.sh
4. Migrate containers
4.1 Setup sniproxy
Go to /var/ds/sniproxy/
, edit etc/sniproxy.conf
and modify the
table so that it looks like this:
table {
# incus container: edu
edu.user1.fs.al 10.31.96.201 proxy_protocol
vclab.user1.fs.al 10.31.96.201 proxy_protocol
# docker container: revproxy
.* revproxy proxy_protocol
}
cd /var/ds/sniproxy/
nano etc/sniproxy.conf
ds restart
The requests for the domains edu.user1.fs.al
and vclab.user1.fs.al
are being forwarded to the IP of the incus container edu
. The rest
are forwarded to the docker container revproxy
, as usual.
4.2 Migrate Moodle
-
On the host, make a backup and stop the container:
cd /var/ds/edu.user1.fs.al/
ds backup
ds stop -
Transfer the scripts and the directory of the container:
incus file --help
incus file push --help
incus file push -p -r \
/opt/docker-scripts/moodle/ \
edu/opt/docker-scripts/
incus file push -p -r \
/var/ds/edu.user1.fs.al \
edu/var/ds/ -
Inside the incus container, build the Moodle container and restore the backup:
incus shell edu
cd /var/ds/edu.user1.fs.al/
ds make
ds restore backup-*.tgz -
Open https://edu.user1.fs.al in browser and login as admin. Go to the Notifications page and make sure that the database is updated.
-
On the host, clean up the Moodle container etc.
ds /var/ds/edu.user1.fs.al/
ds stop
ds remove
ds mariadb drop
ds revproxy rm
cd ..
rm -rf edu.user1.fs.al/
rm -rf /opt/docker-scripts/moodle/
cd revproxy/
ls domains/
ls letsencrypt/live/
ds del-ssl-cert edu.user1.fs.al
4.3 Migrate Guacamole
-
On the host, make a backup and stop the container:
cd /var/ds/vclab.user1.fs.al/
ds backup
ds stop -
Transfer the scripts and the directory of the container:
incus file push -pr \
/opt/docker-scripts/guacamole/ \
edu/opt/docker-scripts/
incus file push -pr \
/var/ds/vclab.user1.fs.al \
edu/var/ds/ -
Inside the incus container, build the Guacamole container and restore the backup:
incus shell edu
cd /var/ds/vclab.user1.fs.al/
ds make
ds restore backup-*.tgz -
Open https://vclab.user1.fs.al in browser.
-
On the host, clean up the Guacamole container etc.
ds /var/ds/vclab.user1.fs.al/
ds stop
ds remove
ds mariadb drop
ds revproxy rm
cd ..
rm -rf vclab.user1.fs.al/
rm -rf /opt/docker-scripts/guacamole/
cd revproxy/
ls domains/
ls letsencrypt/live/
ds del-ssl-cert vclab.user1.fs.al
4.4 LinuxMint and RaspberryPi
-
On the host, make a backup:
cd /var/ds/mate1/
ds users backup
ds stop
cd /var/ds/raspi1/
ds users backup
ds stop -
Transfer the scripts and the directory of the containers:
incus file push -pr \
/opt/docker-scripts/linuxmint/ \
edu/opt/docker-scripts/
incus file push -pr \
/var/ds/mate1 \
edu/var/ds/
incus file push -pr \
/opt/docker-scripts/raspberrypi/ \
edu/opt/docker-scripts/
incus file push -pr \
/var/ds/raspi1 \
edu/var/ds/ -
Inside
edu
, build the containers and restore the backups:incus shell edu
cd /var/ds/mate1/
ds make
ds users restore backup/users-*.tgz
cd /var/ds/raspi1/
ds make
ds users restore backup/users-*.tgz -
Clean up:
ds @mate1 remove
ds @raspi1 remove
rm -rf /var/ds/mate1/
rm -rf /var/ds/raspi1/
rm -rf /opt/docker-scripts/linuxmint/
rm -rf /opt/docker-scripts/raspberrypi/
docker system prune