Skip to content

Many Snaps on LXC

Lauri Ojansivu edited this page Dec 6, 2022 · 33 revisions

NEW WAY: Parallel Snap Installs

Note: This presumes that your laptop runs newest Ubuntu or Kubuntu, and that server is Ubuntu.

  1. Install Caddy2 https://github.com/wekan/wekan/wiki/Caddy-Webserver-Config

  2. Optional, recommended: Encrypted VM. Idea: Bare Metal Caddy => Proxy to encrypted VM ports => Each customer separate Snap WeKan port. Snap sandbox files at /common, snap code can not access files outside of it's /common directories.

2.1) If your server has additional harddrives, format them:

ls /dev
mkfs.ext4 /dev/nvme0n1

2.2) Look at that above command text output, what is created disk UUID. Add those to /etc/fstab:

UUID=12345-678-90	/data	ext4	errors=remount-ro	0	1

2.3) Create directories for mounting disk, and mount all drives:

sudo su
cd /
mkdir /data
mount -a

2.4) Install to your laptop and bare metal server packages for using remote desktop with KVM:

sudo apt install virt-manager qemu-system

2.5) Check that you can ssh to server with ssh public key as root. For that, create ssh key on your laptop, press enter many times until it's done:

ssh-keygen

2.6) copy laptop .ssh/id_rsa.pub content to server /root/.ssh/authorized_keys .

2.7) At server disable password login at /etc/ssh/sshd_config , password login enabled false. And sudo systemctl restart ssh

2.8) At your laptop edit .ssh/config , there add your server IP address etc. This server here is named x1.

Host x1
  Hostname 123.123.123.123
  User root
  IdentityFile ~/.ssh/id_rsa

2.9) Check that you can ssh from laptop to server as root without prompts.

2.10) Start virt-manager GUI at your laptop:

  • File / Add connection
  • Hypervisor: QEMU/KVM
  • Connect to remote host via SSH
  • Username: root
  • Machine name: x1
  • Connect automatically: [X]
  • Click [Connect]

2.11) AT SERVER: Create harddrive image: qemu-img create -f qcow2 web.qcow2 700G

2.12) Download newest Kubuntu desktop iso with wget.

2.13) Install kubuntu with full disk encryption. Modify amount of RAM (here 32 GB), file locations etc. Do not select to allocate encrypted disk image immediately, let image size grow.

2.14) Create growing disk with max size:

qemu-img create -f qcow2 web.qcow2 700G

2.15) Start install from .iso image. Here RAM -r 32 GB, name web, change disk and iso locations below, vcpu 20 (check your server with nproc, should be less that all):

sudo virt-install -r 32000 -n web --os-type=linux --os-variant=ubuntu16.04 \
--disk /data/VMs/web.qcow2,device=disk,format=qcow2 \
-c /data/VMs/iso/kubuntu-22.10-desktop-amd64.iso \
--vcpus=20 --vnc --noautoconsole

It will appear to your laptop virt-manager GUI.

If you have shutdown KVM VM, you can start it from virt-manager, or this way without .iso image:

sudo virt-install -r 32000 -n web --boot hd --video=vga --os-type=linux --os-variant=ubuntu16.04 \
--disk /data/VMs/web.qcow2,device=disk,format=qcow2 \
--vcpus=20 --vnc --noautoconsole
  1. Use Parallel Snap installs https://snapcraft.io/docs/parallel-installs

For example:

sudo snap set system experimental.parallel-instances=true
  1. With newest WeKan Candidate like https://github.com/wekan/wekan-snap/wiki/CentOS8 . Note: Each user has different wekan port and mongodb port.
sudo snap install wekan --channel=latest/candidate
sudo snap install wekan wekan_customer1 --channel=latest/candidate
sudo snap disable wekan
sudo snap set wekan_customer1 caddy-enabled='false'
  1. Add some settings, for example Google login and AWS SES email sending:
sudo snap set wekan_wekanteam mail-from='Wekan Team Boards <[email protected]>'
sudo snap set wekan_wekanteam mail-url='smtp://username:[email protected]:587?tls={ciphers:"SSLv3"}&secureConnection=false'
sudo snap set wekan_wekanteam mongodb-port='27025'
sudo snap set wekan_wekanteam oauth2-auth-endpoint='https://accounts.google.com/o/oauth2/v2/auth'
sudo snap set wekan_wekanteam oauth2-client-id='YOUR-GOOGLE-LOGIN-CLIENT_ID.apps.googleusercontent.com'
sudo snap set wekan_wekanteam oauth2-secret='YOUR-GOOGLE-LOGIN-SECRET'
sudo snap set wekan_wekanteam oauth2-email-map='email'
sudo snap set wekan_wekanteam oauth2-enabled='true'
sudo snap set wekan_wekanteam oauth2-fullname-map='name'
sudo snap set wekan_wekanteam oauth2-id-map='sub'
sudo snap set wekan_wekanteam oauth2-request-permissions='openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email'
sudo snap set wekan_wekanteam oauth2-token-endpoint='https://oauth2.googleapis.com/token'
sudo snap set wekan_wekanteam oauth2-userinfo-endpoint='https://openidconnect.googleapis.com/v1/userinfo'
sudo snap set wekan_wekanteam oauth2-username-map='nickname'
sudo snap set wekan_wekanteam port='3025'
sudo snap set wekan_wekanteam root-url='https://boards.wekan.team'
  1. Example backup script, that backups MongoDB databases. Although, maybe files directories needed to be added too.

Note: Here customer1 likes to get backup copy of backups, so this copies customer1 backup to separate directory that is synced only to that customer with Syncthing. Via email was asked customer syncthing ID, and added sync.

Set it as executeable:

chmod +x backup.sh

To run it:

sudo su
cd backup
./backup.sh

Here is backup.sh:

#!/bin/bash

# Backup all MongoDB databases from different ports.
# Note: You may need to check also is there files directory,
#       and also backup that, like /var/snap/wekan/common/files etc

function backup {
  cd /home/wekan/backup
  # >> /home/wekan/backup/backup-log.txt
  mkdir -p /home/wekan/backup/new/$1
  cd /home/wekan/backup/new/$1
  mongodump --port $2
  sudo snap get wekan_$1 > snap-settings.txt
  cd ..
  7z a $(date -u +$1-wekan-backup-%Y-%m-%d_%H.%M_UTC.7z) $1
  mkdir /home/wekan/$3
  chown wekan:wekan *.7z
  mv *.7z /home/wekan/$3/
  rm -rf $1
  cd /home/wekan/backup
}

function backupchat {
  cd /home/wekan/backup >> /home/wekan/backup/backup-log.txt
  mkdir -p /home/wekan/backup/new/$1 >> /home/wekan/backup/backup-log.txt
  cd /home/wekan/backup/new/$1 >> /home/wekan/backup/backup-log.txt
  mongodump >> /home/wekan/backup/backup-log.txt
  cd ..
  7z a $(date -u +$1-backup-%Y-%m-%d_%H.%M_UTC.7z) $1
  mkdir /home/wekan/$3
  chown wekan:wekan *.7z
  mv *.7z /home/wekan/$3/
  rm -rf $1
  cd /home/wekan/backup
}

# Syntax:
# backup companyname port backupdir

function websync {
  # Backup WeKan Kanban Snaps to different Syncthing sync directories
  backup "company1" "27022" "backup-wekan-company1"
  backup "company1" "27022" "websync"
  backup "company2" "27021" "websync"
  backup "company3" "27023" "websync"
  backup "company4" "27024" "websync"
  backup "wekanteam" "27025" "websync"
  # Backup RocketChat Snap
  backupchat "chat" "27027" "websync"
  cd ~/websync
  ## backup the backup scripts
  # 7z a $(date -u +wekan-backup-scripts-%Y-%m-%d_%H.%M_UTC.7z) ~/backup
}

(websync) >> /home/wekan/backup/backup-log.txt 2>&1
  1. At bare metal server is installed Caddy2.

Each customer has set in their nameserver to WeKan hosting server IP address:

A 123.123.123.123  

After that, when ping wekan.company1.com shows 123.123.123.123 correctly, it's possible to get automatic Let's Encrypt SSL/TLS cert with Caddy2.

At encrypted KVM VM type ip address, it shows what is KVM VM internal IP address.

Caddy2 proxies with Let's Encrypt TLS HTTPS to encrypted VM HTTP IP address and port where WeKan (Node.js) is running.

/etc/caddy/Caddyfile . Examples when in /etc/caddy directory as root: caddy start, caddy stop, caddy validate, caddy --help

(redirect) {
        @http {
                protocol http
        }
        redir @http https://{host}{uri}
}

kanban.customer1.com {
        tls {
                alpn http/1.1
        }

        reverse_proxy 192.168.123.23:3024
}

kanban.customer2.com {
        tls {
                alpn http/1.1
        }

        reverse_proxy 192.168.123.23:3025
}

Other non-kanban examples:

# Static website that uses free CloudFlare TLS certificates
company.com {
        tls {
                load /data/websites/certificates/company
                alpn http/1.1
        }
        root * /data/websites/company.com
        file_server
}

# RocketChat
chat.company.com {
        tls {
                alpn http/1.1
        }

        reverse_proxy 192.168.123.23:3000
}

# Browseable files listing static website
files.company.com {
        tls {
                alpn http/1.1
        }
        root * /data/websites/files.company.com
        file_server browse
}

OLD WAY: Many Snaps on LXC

1) Main Snap on bare metal

Install Wekan Snap to newest Ubuntu bare metal server. Snaps have automatic updates.

For example:

sudo apt-get install snapd
reboot
sudo snap install wekan

For Let's Encrypt SSL, like this to /var/snap/wekan/common/Caddyfile. We will be proxying to inside LXD container:

boards.example.com {
	tls {
	    alpn http/1.1
	}

	proxy / 10.10.10.231:3001 {
	  websocket
	  transparent
	}
}

For CloudFlare SSL, like this to /var/snap/wekan/common/Caddyfile:

http://boards.example.com https://boards.example.com {
	tls {
	    load /var/snap/wekan/common/certificates
	    alpn http/1.1
	}

	proxy / 10.10.10.231:3001 {
	  websocket
	  transparent
	}
}

2) New LXC container

So when I start new lxc container:

lxc launch images:ubuntu/20.04 lxccontainername

3) Snapd and Wekan

Then I go inside container and install snapd:

lxc exec lxccontainername -- /bin/bash
apt -y install snapd
reboot
lxc exec lxccontainername -- /bin/bash
snap install wekan
snap set wekan root-url='https://boards.example.com'
sudo snap set wekan port='3001'
sudo snap set wekan mail-from='Wekan Team Boards <[email protected]>'
sudo snap set wekan mail-url='smtps://username:[email protected]:587'
ip address
exit

That ip address command does show current IP address of container, that you can then add to bare metal /var/snap/wekan/common/Caddyfile.

You can also add more lxc containers to different subdomains and proxy to them in main Caddyfile.

4) Some LXC commands

New Ubuntu container

lxc launch images:ubuntu/20.04 lxccontainername

Inside LXC container

lxc exec lxccontainername -- /bin/bash

Running command in LXC

lxc exec lxccontainername -- apt install p7zip-full

Limit RAM available to LXC

lxc config set lxccontainername limits.memory 4GB

New Debian container

lxc launch images:debian/buster mydebiancontainername

New CentOS 7 container

lxc launch images:centos/7/amd64 centos

List containers

lxc list -cns

Result:

+---------------+---------+
|     NAME      |  STATE  |
+---------------+---------+
| mycontainer   | RUNNING |
+---------------+---------+

Stop and delete container

lxc stop mycontainer
lxc delete mycontainer
Clone this wiki locally