Installing Carbonio CE with Incus
1. Intro
I have a Dedicated Server on hetzner.com and I want to install Carbonio CE. I use Incus on the server, and I want to install Carbonio in a container.
2. Preparing the host
To install and setup the Hetzner server, follow the instructions at: https://docker-scripts.gitlab.io/howto/dedicated-rootserver.html.
3. Create the container
The latest stable version of Carbonio requires ubuntu:20.04
.
incus launch images:ubuntu/20.04 carbonio
incus info carbonio
incus config show carbonio
Let’s also enable bash-completion and set a better prompt in it:
incus exec carbonio -- bash
# make sure that bash-completion is installed
apt install --yes bash-completion
# customize ~/.bashrc
sed -i ~/.bashrc \
-e '/^#\?force_color_prompt=/ c force_color_prompt=yes' \
-e '/bashrc_custom/d'
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\]'
# enable programmable completion features
if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
source /etc/bash_completion
fi
EOF
source ~/.bashrc
The installation of Carbonio CE also requires Python3 and Perl, so let’s make sure that they are installed:
# incus exec carbonio -- bash
apt install --yes python3 perl
4. Networking requirements
We are making a single-server installation of Carbonio, so only the
ports for the external connections are
required
to be open: 25
, 465
, 587
, 80
, 110
, 143
, 443
, 993
,
995
, 5222
, 6071
.
The connection of our container to the network goes through the host, which serves as a gateway. So, the Carbonio server is behind NAT and we need to forward these ports from the host.
Forwarding them is easier if the container has a fixed IP (rather then a dynamic one, obtained from DHCP). So, first of all, let’s change the network configuration inside the container so that it has a fixed IP.
Another requirement before starting to install Carbonio is also to disable IPv6 inside the container.
4.1. Set a fixed IP
Network configuration on ubuntu is managed by netplan
.
incus exec carbonio -- bash
ip address
ip route
rm /etc/netplan/*.yaml
cat <<EOF > /etc/netplan/01-netcfg.yaml
network:
version: 2
ethernets:
eth0:
dhcp4: no
addresses:
- 10.210.64.201/8
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
routes:
- to: default
via: 10.210.64.1
EOF
netplan apply
ip address
ip route
ping 8.8.8.8
4.2. Forward ports
We can use the command incus network forward
to forward these
ports to the internal IP of the Carbonio container:
HOST_IP=10.11.12.13 # the public IP of the host
CONTAINER_IP=10.210.64.201
incus network forward create incusbr0 $HOST_IP
incus network forward list incusbr0
incus network forward port add incusbr0 \
$HOST_IP tcp 25,465,587,110,143,993,995,5222,6071 \
$CONTAINER_IP
incus network forward show incusbr0 $HOST_IP
4.3. Forward the TCP ports 80 and 443
Forwarding these two ports is a bit more complex and cannot be done
with the same method that was used above. This is because these ports
need to be used by other applications as well, beside Carbonio. We
need to forward these ports to different applications or containers,
based on the domain that is being used. We can use sniproxy
for
this:
https://docker-scripts.gitlab.io/howto/install-sniproxy.html
Make sure that the configuration file etc/sniproxy.conf
looks
like this:
table { # . . . . . mail.example.org 10.210.64.201 .*.mail.example.org 10.210.64.201 # . . . . . }
We are using 10.210.64.201, which is the fixed IP of the carbonio container. |
5. Minimal DNS setup
Before starting to install the mail server, let’s make sure that we already have some minimal DNS setup, which should look like this:
mail.example.org. IN A 10.11.12.13
example.org. IN MX 10 mail.example.org.
example.org. IN MX 20 mail.example.org.
example.org. IN TXT "v=spf1 mx -all"
The last line basically tells to the other SMTP servers that only this
server is allowed to send emails on behalf of this domain, and no
other servers. This is done to prevent spammers from faking your email
addresses. If a spammer tries to send a mail as if it is coming from
your domain, the SMTP server that is getting this email will consult
this DNS record and will figure out that the server of the spammer is
not allowed to send emails on behalf of example.org
.
You can use dig
to verify that these DNS records have been activated:
dig MX example.org +short
dig A mail.example.org +short
dig TXT example.org +short
However, keep in mind that DNS changes may take some time to propagate.
6. Installing Carbonio inside the container
We are going to make a single-server installation, following these instructions: https://docs.zextras.com/carbonio-ce/html/single-server-installation.html
6.1. Repository configuration
apt install --yes gnupg2
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 \
--recv-keys 52FD40243E584A21
cat <<EOF > /etc/apt/sources.list.d/zextras.list
deb https://repo.zextras.io/release/ubuntu focal main
EOF
apt update
6.2. Setting hostname
hostnamectl set-hostname mail.example.org
hostname
echo "$(hostname -I) $(hostname -f) mail" >> /etc/hosts
cat /etc/hosts
6.3. Install packages
apt update
apt upgrade --yes
apt install --yes \
service-discover-server \
carbonio-directory-server \
carbonio-proxy \
carbonio-webui \
carbonio-files-ui \
carbonio-mta \
carbonio-appserver \
carbonio-user-management \
carbonio-files-ce \
carbonio-files-db \
carbonio-storages-ce \
carbonio-preview-ce \
carbonio-docs-connector-ce \
carbonio-docs-editor \
carbonio-prometheus \
postgresql-12
Check the status of Carbonio services:
systemctl status carbonio-*
systemctl restart carbonio-prometheus-nginx-exporter.service
6.4. Configuration
carbonio-bootstrap
service-discover setup-wizard
# apt install --yes python3-pip
# pip install requests
apt install --yes python3-requests
pending-setups -a
6.5. DB setup
# create main db role and database
DB_ADM_PWD=Ee5hfaevVo7vieri
su - postgres -c "psql --command=\"CREATE ROLE carbonio_adm WITH LOGIN SUPERUSER encrypted password '$DB_ADM_PWD';\""
su - postgres -c "psql --command=\"CREATE DATABASE carbonio_adm owner carbonio_adm;\""
# bootstrap carbonio files databases
PGPASSWORD=$DB_ADM_PWD carbonio-files-db-bootstrap carbonio_adm 127.0.0.1
# restart the main mailbox process as the zextras user
su - zextras -c 'zmcontrol stop'
su - zextras -c 'zmcontrol start'
7. Setup
7.1. SSL certificate
We are going to use a LetsEncrypt certificate.
-
First, let’s install
certbot
:apt install --yes snapd snap install core snap refresh core snap install --classic certbot ln -s /snap/bin/certbot /usr/bin/certbot
-
Get a certificate:
DOMAIN=mail.example.org EMAIL=user@gmail.com certbot certonly \ --standalone \ --preferred-chain "ISRG Root X1" \ --domains $DOMAIN \ --email $EMAIL \ --agree-tos \ --non-interactive \ --keep-until-expiring \ --dry-run certbot certonly \ --standalone \ --preferred-chain "ISRG Root X1" \ --domains $DOMAIN \ --email $EMAIL \ --agree-tos \ --non-interactive \ --keep-until-expiring
The certificate is saved at
/etc/letsencrypt/live/$DOMAIN/
. -
Copy
privkey.pem
to the Carbonio directory:cp /etc/letsencrypt/live/$DOMAIN/privkey.pem \ /opt/zextras/ssl/carbonio/commercial/commercial.key chown zextras:zextras \ /opt/zextras/ssl/carbonio/commercial/commercial.key
-
Proceed and deploy the SSL certificates:
cp /etc/letsencrypt/live/$DOMAIN/cert.pem /tmp cp /etc/letsencrypt/live/$DOMAIN/chain.pem /tmp
-
Download the ISRG Root X1 chain as below:
apt install --yes wget wget -O /tmp/ISRG-X1.pem \ https://letsencrypt.org/certs/isrgrootx1.pem.txt cat /tmp/ISRG-X1.pem >> /tmp/chain.pem rm /tmp/ISRG-X1.pem
-
Verify the certificate:
su - zextras \ -c 'zmcertmgr verifycrt comm \ /opt/zextras/ssl/carbonio/commercial/commercial.key \ /tmp/cert.pem \ /tmp/chain.pem'
-
Finally, deploy the certificate and restart the services to finish the deployment:
su - zextras -c \ 'zmcertmgr deploycrt comm /tmp/cert.pem /tmp/chain.pem' su - zextras -c 'zmcertmgr viewdeployedcrt' su - zextras -c 'zmcontrol restart'