• Resources
  • USEnglish
  • [HOWTO] Install mailcow in a LXC container on Proxmox 6.4-13 for home usage

I am aware that Mailcow team doesn’t provide support and advise to use LXC container to run a mailcow dockerized version.
But accept community usage without support for them ! (mailcow/mailcow-dockerized4215)
It’s important to have access to the hypervisor, so you can’t use LXC for VPS provider ! But your own server with LXC VMs on it.
But in some case (mine for example) is mandatory. The ressource of the hardware that going to run the VPS is not enought for a full KVM machine.

I finnaly manage to succesfully run mailcow January Update 2022 on in a unprivileged LXC container with Proxmox.
You may need to modify some configuration, the max number of process for dovecot docker for example.

I - Prepare your proxmox hypervisor

Loging into your proxmox hypervisor.

Need to load overlay and naufs module on proxmox :

echo -e “overlay\naufs” >> /etc/modules-load.d/modules.conf

Install cgroups-mount (don’t really knwon if finally need but it’s done in my case) :

apt-get install cgroups-mount
reboot

II - Prepare a unprivileged LXC container

I choose to use debian-11-standard_11.0-1_amd64 as CT template.

Make a new container, as usual via the proxmox GUI. My basic configuration was :

arch: amd64
cores: 2
hostname: mail.domain.wan
memory: 6144
net0: name=eth0,bridge=vmbr0,firewall=1,gw=192.168.0.254,hwaddr=B2:F9:44:FB:4E:EC,ip=192.168.0.4/24,type=veth
ostype: debian
rootfs: local:102/vm-102-disk-0.raw,size=60G
swap: 2048
unprivileged: 1

Loging into your VPS (LXC container just created).

Be sure to be with the last version of all your system :
apt-get update
apt-get upgrade
apt-get dist-upgrade

Configure your timezone :
dpkg-reconfigure tzdata

I choose to remove postfix and use msmtp (a smtp client) to manage local mail of the container.
For the cron task and other system app who want to send me a mail !
That’s going to let free the port 25 of the LXC container (localy).
apt-get purge postfix
apt-get install msmtp-mta
(be carefull, use msmtp-mta, not only msmtp because msmtp-mta include a sendmail emulation)

Edit the config file,and paste the line below to it, of msmtp with :
nano /etc/msmtprc

I use gmail to manage system email, of course don’t use email for mailcow because if you have some issue on it, you will not
be advise by the system. I choose gmail by IMAP (by sure to enable less secure apps on Gmail for IMAP).
This is my config of msmtp (change USERNAME and PASSWORD) :

#account default
defaults
account default
auth on
tls on
tls_starttls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile /var/log/msmtp.log
host smtp.gmail.com
port 587
from USERNAME@gmail.com
user USERNAME@gmail.com
password PASSWORD
aliases /etc/aliases

Now, we going to install a command line mail client :
apt-get install bsd-mailx

Edit your aliases files, with
nano /etc/aliases

This is my aliases file you need to personnalize with your mail :
postmaster: root
webmaster: root
root: USERNAME@gmail.com
local: USERNAME@gmail.com
default: USERNAME@gmail.com

And finally, secure a little bit your LXC container with a mail each time someone log to your system (My TIPS). Edit bash config :
nano /etc/bash.bashrc

And add this line at the end of the file :

echo ‘ALERT - Shell Access on: ’ `date` `who` | mail -s “Alert: Shell Access on `hostname -f`” root

If you log out, and loging again, you should receive a mail with this alert. Great, everything seems to work.
If not, take a look on /var/log/msmtp.log to debug.

OPTION (just for daily backup cronjob, see mailcow.github.io Icon Backup - mailcow: dockerized documentation

) :
I choose to share my BACKUP storage of my proxmox (a external NAS) with my mailcow LXC container. This is the storage where I put of my VM backup with vzdump on Proxmox.
I will add a crontask to manage a daily backup of my data, so I have to make a local mount folder :
mkdir /mnt/NAS
chmod 777 /mnt/NAS

The VPS is almost done now, stop with :
halt

Now add this configuration in the proxmox LXC config, add the end of the file (/etc/pve/lxc/VMID.conf on a proxmox shell) :
lxc.apparmor.profile: unconfined
lxc.cgroup.devices.allow: a
lxc.cap.drop:
#OPTION for daily cronjob, should be personnalize with your own storage
lxc.mount.entry: /mnt/pve/NAS mnt/NAS/ none rw,bind 0 0

You can now run again your VPS, we are ready to install mailcow !

III - Mailcow installation

Boot your VPS, and login into to again and follow the installation documentation : https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/

At the step 5, don’t run “docker-compose up -d”, we going to modify some config before.

Edit /opt/mailcow-dockerized/docker-compose.yml with :
nano /opt/mailcow-dockerized/docker-compose.yml

In redis-mailcow section, comment/remove thoses lines ( https://community.mailcow.email/d/1054-sysctl-for-redis-breaks-on-lxclcd/2

)
# sysctls:
# - net.core.somaxconn=4096

For us, it’s totally useless, because on 5.4 kernel (it’s the case of proxmox 6.4-13 somaxconn is already 4096 but docker in LXC does’nt support this option).

Finally in dovecot-mailcow section, modify nproc limits
ulimits :
nproc: 30000 #(Instead of 65535)

Not a big deal on a home usage even for more, it’s limit the number of process inside the dovecot docker.

You should now run :
docker-compose up -d

Mailcow-dockerized version should run now just fine, you are ready to finalize your mailcow configuration !

Don’t forget, if you choose the option, to make the cronjob for daily bakcup (mailcow.github.io Icon Backup - mailcow: dockerized documentation

)

Enjoy !

23 days later

How to upgrade your mailcow version in LXC :

1- Desactivate all the port redirection in your firewall (SMTP, POP, etc.)
2- Login to the VM, and halt it with the command “halt”
3- In the proxmox GUI, make a full bakcup of the VM
4- Start again your VM
5- Follow this guide, by using (update.sh –skip-start)
https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_update/


6- When update was done, please check if your manual modifications of docker-compose.yml was always there.
7- Run docker-compose up -d
8- If all is running without error, activate all the port redirection in your firewall (SMTP, POP, etc.)

    Have something to say?

    Join the community by quickly registering to participate in this discussion. We'd like to see you joining our great moo-community!

    a year later

    Hello kicou somme question about you’re installation
    1/ do you run it on production ?
    2/ all mailcow composants runs in separate lxc containers ?
    3/ do you have benefice of HA in proxmox with mailcow lxc containers ?

    Thanks

      Hi aukfood

      1\ Yes, I run it in production since more than one year without issue.
      2\ I have only one LXC container (VM) for mailcow, and all dockers are inside this VM
      3\ I never try to use HA

      BR

      ok why to choose a lxc container and not a virtual machine on proxmox ?

        I guess its MUCH easier to run Mailcow in a Proxmox VM with debian and docker. There is almost no overhead, as Debians footprint is quite small if you install it without GUI.

          aukfood just for limit usage of RAM, CPU etc…
          I use it on a Celeron / 8GB / SSD computer with 3 LXC containers on it.

          Not possible with 3 regular KVM machine, but ok with LXC CT.

          3 months later

          Hi all,
          Just migrate my old Proxmox 6.x to the new version 8.0.3.
          Backup the Proxmox VM (CT) and restore on the new Proxmox.

          It works like a charmn, without any preparation on the new Proxmox (Overlay and Naufs) just restore and run.
          So now, you can at least skip the first step “I - Prepare your proxmox hypervisor”

            2 months later

            esackbauer I guess its MUCH easier to run Mailcow in a Proxmox VM with debian and docker. There is almost no overhead, as Debians footprint is quite small if you install it without GUI.

            Good day, I’m new to mailcow, so this is my first post/question.

            Here’s my setup:
            one static IP –> opnsense –> proxmox –> debian 12 as VM –> mailcow-dockerized. The opnsense, proxmox and debian VM are in the same subnet. On the proxmox is running a not containerized server, also in the same subnet. No firewall(s) on the proxmox.

            Install of debian 12 went smooth, the VM is up and running. Same with mailcow-dockerized, no problems so far. mailcow is connected to a domain, DNS records are set as described. mailcow is able to send and receive email.

            During acme-challenge the static IP is detected, but it stalls with the hostname. No cert is created, BTW the server in the other machine has no problem with let’s encrypt certs. Difference for sure is docker.

            I’m not firm with docker. But if I’m guided I’m able to provide any information to work this through. I’ve access to the opnsense and to the network over VPN.

            So while reading the intro of mailcow that installations in a VM are supported or possible, where did I miss the point? I tried to get information in opnsense- and proxmox-forum but I must admit, the more I read the more I’m confused. I also read the mailcow docs, but I simply don’t understand where do I have to investigate. Is it the opnsense part or is it the mailcow part, or both?

            Any help would be greatly appreciated.
            regards, stefan

              stefan21 BTW the server in the other machine has no problem with let’s encrypt certs.

              That seems the problem. You need to NAT all ports in this list to the mailcow VM:
              https://docs.mailcow.email/prerequisite/prerequisite-system/#default-ports


              The Acme challence for mailcow certs cannot work if port 80 goes to another server.
              So you are better off to disable Acme in mailcow and use a proper nginxproxymanager.com Icon reverse proxy
              nginxproxymanager.com Icon nginxproxymanager.com
              Nginx Proxy Manager
              Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt
              nginxproxymanager.com
              which handles all certificates for all your VMs.
              Configure mailcow for reverse proxy:
              docs.mailcow.email Icon Overview - mailcow: dockerized documentation
              docs.mailcow.email Icon docs.mailcow.email
              Overview - mailcow: dockerized documentation
              None
              docs.mailcow.email

              Then you need to copy the certificates from that reverse proxy to the mailcow VM:
              docs.mailcow.email Icon Advanced SSL - mailcow: dockerized documentation
              docs.mailcow.email Icon docs.mailcow.email
              Advanced SSL - mailcow: dockerized documentation
              None
              docs.mailcow.email

              Yes, esackbauer is right !

              My certificate was renewed with the ACME challenge by my NAS (Port 80/433 routed on it).
              I made a script to copy the generated certificate each night to my mailcow server (reboot it also to take the new certificate).

              Works well since months !

              First I’d like to thank for taking the time to reply to my questions.

              I understand the easy advice as follows:

              1. in opnsense I install the acme plugin and let the opnsense take care for the let’s encrypt certs. I already tested this way, this plugin works.
              2. I daily copy, preferably with a cron job, the certs to mailcow - what path/location exactly?
              3. the mailcow VM has to be daily rebooted, to recognize the new certs?

              @esackbauer

              Thank you for describing the way with a reverse proxy. I tried this but honestly, as a part time admin, this is way too complicated for me.

              Everything works really pretty well out of the box, if mailcow does not sit in a VM (and probably in lxc container) and behind a firewall like opnsense or pfsense. I tested mailcow at home on a laptop running with arch linux. There’s an asus router in front of the home network. No problem to configure a port forward to the laptop, so everything works as intended.

              Anyway, if I take the road kicou suggests, where in mailcow can acme be safely disabled? Is it in the GUI or better with the command line?

                stefan21 what path/location exactly?
                mailcow VM has to be daily rebooted, to recognize the new certs?

                All your questions are already answered in the last link of my previous posting…

                My script on the NAS (Auth by key) :
                #!/bin/bash
                scp -i /root/.ssh/id_rsa /usr/syno/etc/certificate/archive/hkbWEi/fullchain.pem root@192.168.0.3:/root
                scp -i /root/.ssh/id_rsa /usr/syno/etc/certificate/
                archive/hkbWEi/privkey.pem root@192.168.0.3:/root

                My daily cron script on mailcow server :
                #!/bin/sh

                copy cert to data folder

                cp -f /root/fullchain.pem /opt/mailcow-dockerized/data/assets/ssl/cert.pem
                cp -f /root/privkey.pem /opt/mailcow-dockerized/data/assets/ssl/key.pem
                rm -f /root/fullchain.pem
                rm -f /root/privkey.pem

                restart needed docker

                docker restart $(docker ps -qaf name=postfix-mailcow)
                docker restart $(docker ps -qaf name=nginx-mailcow)
                docker restart $(docker ps -qaf name=dovecot-mailcow)

                  Doing this daily seems unnecessary. Certs are good for 90 days with renewal possible after 60.

                  I run a script on mailcow instance itself to check renewal weekly using dns challenge (cloudflare) as I don’t want any more open ports than absolutely necessary. Dns challenge requires the use of an api key to update the require txt record.

                  kicou

                  I managed to fetch certs with opnsense acme-plugin. Already tested, works fine. I also managed to automate the deploy of the cert to mailcow. In the mailcow-docs is said:
                  "How to use your own certificate¶

                  Make sure you disable mailcows internal LE client (see above).

                  To use your own certificates, just save the combined certificate (containing the certificate and intermediate CA/CA if any) to data/assets/ssl/cert.pem and the corresponding key to data/assets/ssl/key.pem"

                  The copy of the certs from the opnsense is in:

                  /opt/mailcow-dockerized/data/assets/ssl/FQHN/

                  • ca.pem
                  • cert.pem
                  • fullchain.pem
                  • key.pem

                  Will that work?