Docker Mailserver and Rainloop Webclient

From KG7QIN's Wiki
Jump to navigation Jump to search

Docker Mailserver and Rainloop Webclient

Fully dockerized email server and dockerized Rainloop webmail client setup


NGINX Proxy

docker-compose.yml

   version: '2'
   services:
     nginx-proxy:
       image: jwilder/nginx-proxy
       container_name: nginx-proxy
       environment:
         - "HTTPS_METHOD=noredirect"
       labels:
         - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
       ports:
         - "80:80"
         - "443:443"
       restart: always
       volumes:
         - "./data/etc/certs:/etc/nginx/certs"
         - "./data/etc/nginx/vhost.d:/etc/nginx/vhost.d"
         - "./data/etc/nginx/htpasswd:/etc/nginx/htpasswd"
         - "./data/etc/nginx/html:/usr/share/nginx/html"
         - "/var/run/docker.sock:/tmp/docker.sock:ro"
   
   
     letsencrypt:
       image: jrcs/letsencrypt-nginx-proxy-companion
       environment:
       ### ToDo: Change to your e-mail address
       #      - DEFAULT_EMAIL=admin@demo.io
         - NGINX_PROXY_CONTAINER=nginx-proxy
       volumes_from:
         - nginx-proxy
       volumes:
         - /var/run/docker.sock:/var/run/docker.sock:ro
         - ./data/etc/certs:/etc/nginx/certs:rw
       restart: always
   
   networks:
     default:
       external:
         name: nginx-proxy
   
  • Create nginx-proxy network:
  docker network create nginx-proxy

Docker-Mailserver

Follow the https://github.com/docker-mailserver/docker-mailserver#get-the-tools link, but use the docker-compose.yml file below instead of the one in the repo.

Edit mailserver.env as required for the settings you want/need

docker-compose.yml

  version: '3.8'
  
  services:
    mailserver:
      image: docker.io/mailserver/docker-mailserver:latest
      hostname: <domain>
      domainname: <domain>
      container_name: mail
      env_file: mailserver.env
      ports:
        - "25:25"
        - "143:143"
        - "587:587"
        - "993:993"
       volumes:
        - ./data/mail:/var/mail
        - ./data/mail-state:/var/mail-state
        - ./log:/var/log/mail
        - ./config/:/tmp/docker-mailserver
       #- ./config/:/tmp/docker-mailserver/${SELINUX_LABEL}
     - /etc/letsencrypt:/etc/letsencrypt
      restart: always
      cap_add: [ "NET_ADMIN", "SYS_PTRACE" ]
  
  volumes:
    maildata:
    mailstate:
    maillogs:

Get Up and Running

  docker-compose up -d mailserver
  
  # for SELinux, use -Z 
  ./setup.sh [-Z] email add <user@domain> [<password>]
  ./setup.sh [-Z] alias add postmaster@<domain> <user@domain>
  ./setup.sh [-Z] config dkim

Rainloop

A slightly modified version of what is in the Github repo shown in the Introduction section

docker-compose.yml

  version: '3'
  
  volumes:
    rainloop-root:
  #  rainloop-data:
  #     driver: default-driver
  #     driver_opts:
  #       mountpoint: ./data/rainloop/data
  
  services:
    webserver:
      image: nginx:alpine
      volumes:
        - ./config/nginx.conf:/etc/nginx/nginx.conf:ro
        - rainloop-root:/rainloop
      depends_on:
        - application
      environment:
        - VIRTUAL_HOST=<domain>
          #      - VIRTUAL_PROTO=https
          #      - VIRTUAL_PORT=443
        - HTTPS_METHOD=nohttp
        - LETSENCRYPT_HOST=<domain>
        - LETSENCRYPT_EMAIL=<admin email>
      restart: always
      networks:
        - default
        - nginxproxy
  
    application:
  #    image: hermsi/alpine-rainloop
      build: .
      volumes:
        - rainloop-root:/rainloop
        - ./data/rainloop-data:/rainloop/data
      restart: always
      networks:
        default:
          aliases:
            - rainloop
  
  networks:
    nginxproxy:
      external:
        name: nginx-proxy


Dockerfile

  FROM    hermsi/alpine-fpm-php
  
  LABEL	maintainer "https://github.com/hermsi1337"
  
  # Get some stuff in order to work properly
  RUN apk --no-cache --update --virtual .build-dependencies add gnupg openssl wget zip \
      && update-ca-certificates
  
  # Download and install RainLoop
  ENV RAINLOOP_ROOT="/rainloop"
  ARG GPG_FINGERPRINT="3B79 7ECE 694F 3B7B 70F3  11A4 ED7C 49D9 87DA 4591"
  
  RUN export TMP_DIR="/tmp" && \
      export RAINLOOP_ZIP="${TMP_DIR}/RainLoop.zip" && \
      export RAINLOOP_ZIP_ASC="${RAINLOOP_ZIP}.asc" && \
      export RAINLOOP_ASC="${TMP_DIR}/RainLoop.asc" && \
      wget -q "https://www.rainloop.net/repository/webmail/rainloop-community-latest.zip" -O "${RAINLOOP_ZIP}" && \
      wget -q "https://www.rainloop.net/repository/webmail/rainloop-community-latest.zip.asc" -O "${RAINLOOP_ZIP_ASC}" && \
      wget -q "https://www.rainloop.net/repository/RainLoop.asc" -O "${RAINLOOP_ASC}" && \
      gpg --import "${RAINLOOP_ASC}" && \
  	   FINGERPRINT="$(LANG=C gpg --verify ${RAINLOOP_ZIP_ASC} ${RAINLOOP_ZIP} 2>&1 \
    	   | sed -n "s#Primary key fingerprint: \(.*\)#\1#p")" && \ 
      if [ -z "${FINGERPRINT}" ]; then echo "Warning! Invalid GPG signature!" && exit 1; fi && \
      if [ "${FINGERPRINT}" != "${GPG_FINGERPRINT}" ]; then echo "Warning! Wrong GPG fingerprint!" && exit 1; fi && \
      mkdir "${RAINLOOP_ROOT}" && \
      unzip -q "${RAINLOOP_ZIP}" -d "${RAINLOOP_ROOT}" && \
      apk del .build-dependencies && \
      rm -rf "${TMP_DIR}/*" "/var/cache/apk/*" "/root/.gnupg"
   
  # Take care of additional configuration stuff
  ENV MEMORY_LIMIT="128M" \
      UPLOAD_MAX_FILESIZE="32M" \
      POST_MAX_SIZE="64M"
  
  RUN chown "www-data." "${RAINLOOP_ROOT}" -R && \
      find "${RAINLOOP_ROOT}" -type d -exec chmod 755 {} \; && \
      find "${RAINLOOP_ROOT}" -type f -exec chmod 644 {} \; && \
     printf "%s\n%s\n%s" "memory_limit = ${MEMORY_LIMIT}" "upload_max_filesize = ${UPLOAD_MAX_FILESIZE}" "post_max_size = ${POST_MAX_SIZE}" > "${RAINLOOP_ROOT}/.user.ini"; \


  • Make a config/ directory and place the following file into it:

nginx.conf

  events {
    worker_connections 768;
  }
  
  http {
      upstream backend {
          server rainloop:9000;
      }
      include /etc/nginx/mime.types;
      default_type application/octet-stream;
      gzip on;
      gzip_disable "msie6";
  
      server {
          listen      80 default;
          server_name rainloop;
  
          root /rainloop;
  
          index index.php index.html;
   
          charset utf-8;
  
          location / {
              try_files $uri $uri/ index.php;
          }
  
          location = /favicon.ico { access_log off; log_not_found off; }
          location = /robots.txt  { access_log off; log_not_found off; }
  
          sendfile off;
  
                  location ~* \.php$ {
          fastcgi_index index.php;
          fastcgi_pass rainloop:9000;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          include /etc/nginx/fastcgi_params;
          }
  
          location ~ /\.ht {
              deny all;
          }
  
                  location ^~ /data {
                          deny all;
                  }
  
          client_max_body_size 1G;
      }
  }

Upgrading

  • Rename ./data to ./data-old
  • Delete rainloop-root volume
   docker volume rm rainloop_rainloop-root
  • Re-build Docker image
   docker-compose build