How to Install LXD Container & HA-Proxy with SSL for Ubuntu 20.x

DigitalOcean Referral Badge

What is LXD

LXD is a next generation system container and virtual machine manager. It offers a unified user experience around full Linux systems running inside containers or virtual machines.

LXD is image based and provides images for a wide number of Linux distributions. It provides flexibility and scalability for various use cases, with support for different storage backends and network types and the option to install on hardware ranging from an individual laptop or cloud instance to a full server rack.

I am not discussing the disadvantages , not worth my time 🙂

The main benefits of using LXD Container are:

– LXD containers are much lighter and faster to start than other virtualization technologies such as KVM or Xen.

– You can run multiple containers on a single host and each container can have its own IP address, making it easy to run microservices architectures.

– LXD containers provide better security isolation than other virtualization technologies since each container has its own set of users and permissions.

– LXD containers can be easily moved between different hosts thanks to their built-in live migration feature.

– You can use LXD containers to easily create development and test environments that are identical to your production environment.

I am assuming you’ve Ubuntu 20.x installed let’s begin :-

Before you do anything, let’s make sure Ubuntu is up2date, let’s run the following commands

sudo apt-get update && apt-get upgrade -y

The recommended storage backend for LXD when you run it on Ubuntu is the ZFS filesystem. To enable ZFS support in LXD install the zfsutils-linux:

sudo apt install -y zfsutils-linux

Finally let’s initialize LXD

sudo lxd init

You will get the following, I am using zfs so here’s my output

Do you want to configure a new storage pool? (yes/no) [default=yes]: yes
Name of the new storage pool [default=default]: default
Name of the storage backend to use (btrfs, dir, lvm, zfs) [default=zfs]: zfs
Create a new ZFS pool? (yes/no) [default=yes]: yes
Would you like to use an existing block device? (yes/no) [default=no]: yes
Path to the existing block device: /dev/sdb

You can always use default but pay close attention to storage backend and and block size

Now let’s create some profile and give them specific permissions, I am using C2 instance from google & my instance are as follows

8CPU and 32GB memory and 40 GB SSD Drive

lxc profile copy default vhosts

What I did above is I copy the default profile and named it vhosts, You can make as many profile as you like but I am just making one at this time.

Now let’s set some limit based on our server configuration

lxc profile set vhosts limits.memory "16GB"
lxc profile set vhosts limits.cpu 4
lxc profile set vhosts boot.autostart "true"

I just gave my profile 16gb ram, 4 CPU and I also set my profile to auto start , in the event , I do decide to restart my server so my container will auto start.

As we now setup our profile and set limits, let’s launch this container

lxc launch ubuntu:20.04 container1 --profile vhosts

What’s happening here is , we are launching container1 and telling lxc to use profile vhosts

Now let’s setup disk space for that container

lxc config device add container1 root disk pool=default path=/
lxc config device set container1 root size 35GB

I am just leaving 5GB for the server, you can play with that however you like but this is how I did it.

if you run the following command it will give you the list of container and IP_ ADDRESS

lxc list
+-----------+---------+------------------------------------+
|   NAME    |  STATE  |        IPV4                        |
+-----------+---------+------------------------------------+
|container1 | RUNNING | 10.10.10.2 (eth0)                  |
+-----------+---------+------------------------------------+

Now let’s go inside that container and install just nginx

lxc shell container1
root@container1# apt-get update && apt-get upgrade -y && apt-get install nginx -y

I am not going into detail how to setup nginx, you can click here and read more about my nginx configuration generator

Let’s assume you’ve successfully installed nginx and setup ssl certificates in your container1 web server, now it’s time to deploy proxy container

We will repeat the same step, but change the name

lxc profile copy default proxy
lxc profile set proxy limits.memory "16GB"
lxc profile set proxy limits.cpu 4
lxc profile set proxy boot.autostart "true"

Let’s setup proxy container

lxc launch ubuntu:20.04 proxy --profile proxy

Let’s Install HA Proxy

Go inside proxy container

lxc shell proxy

root@proxy# apt-get update && apt-get upgrade -y && apt-get install ha-proxy -y

copy the following configuration file & I will explain what it is

nano /etc/haproxy/haproxy.cfg
global
        log /dev/log    local0
        log /dev/log    local1 notice
        chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
        stats timeout 30s
        user haproxy
        group haproxy
        daemon
        maxconn    4000

        # Default SSL material locations
        ca-base /etc/ssl/certs
        crt-base /etc/ssl/private


        # See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
        ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-P
OLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
        ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
        ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        timeout connect 10s
        timeout client  60s
        timeout server  60s
        errorfile 400 /etc/haproxy/errors/400.http
        errorfile 403 /etc/haproxy/errors/403.http
        errorfile 408 /etc/haproxy/errors/408.http
        errorfile 500 /etc/haproxy/errors/500.http
        errorfile 502 /etc/haproxy/errors/502.http
        errorfile 503 /etc/haproxy/errors/503.http
        errorfile 504 /etc/haproxy/errors/504.http

frontend www
        mode http
        option forwardfor
        option httplog
                log-format "%ci:%cp [%t] $H $HM $HP $HQ $HU $HV %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq"
        bind :80

        acl acl_sohaib.com hdr(host) -i sohaib.com www.sohaib.com
        use_backend container1 if acl_sohaib.com


backend container1
        mode http
        option httpchk
        option forwardfor
        server web1 10.10.10.2:80 check


frontend www_secure
        mode tcp
        option tcplog
                log-format "%ci:%cp [%t] $H $HM $HP $HQ $HU $HV %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq"
        bind :443

        acl tls req.ssl_hello_type 1
        tcp-request inspect-delay 5s
        tcp-request content accept if tls
        acl acl_sohaib.com_secure req.ssl_sni -i sohaib.com www.sohaib.com
        use_backend container1_secure if acl_sohaib.com_secure



backend container1_secure
        mode tcp
        option ssl-hello-chk
        server web1 10.10.10.2:443 check

Lastly, We’ve to forward the port in main server so exit out everything by typing

exit

In your server outside of containers type the following

sudo lxc config device add proxy port80 proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80

sudo lxc config device add proxy port443 proxy listen=tcp:0.0.0.0:443 connect=tcp:127.0.0.1:443

Now check your domain , I’ve used sohaib.com as an example you can add many backend and acl in ha proxy , I will later post the full configuration showing how to connect 2 containers and 2 backend, or you can post your comment and let me know and I will be more than happy to share that configuration with you.

List of LXC Commands

Leave a Reply

Your email address will not be published. Required fields are marked *