Webmail / Web Proxy Server – Docker

There are several ways to configure your servers, but Docker is a great system for keeping the various components in separate and relatively-isolated “Containers.” There are some great sources for understanding the Docker ecosystem.

Docker for CONTAINERization

You can run the Webmail / Web Proxy Server services on separate physical computers, or on the same physical computer, and can even run them on the same computer that is running your Firewall, but Docker requires some special firewall configuration to prevent access to your Webmail and Web Proxy services from the outside network.

I have run the services on the firewall computer, but I recommend that you set up a separate physical inexpensive computer running Docker under Ubuntu and running these server services in Docker containers using docker-compose.

Here is the docker-compose.yml :

version:  '3.7'

services:
  roundcubemail:
    image: roundcube/roundcubemail
             # You can enable this port mapping to access the roundcube directly 
             # rather than only through nginx
    #ports:
    #  - 8082:80
    restart: always
    networks:
      - app-network
    env_file:
      - ./client.env
    volumes:
      - ./roundcubeconfig/:/var/roundcube/config/
      - ./roundcubesource/:/var/www/html
        # for log, container redirects to /dev/stdout and /dev/stderr, so that is another option
      - /var/log/roundcubemail:/var/log/apache2

  webserver:
    depends_on:
      - roundcubemail
    image: nginx:1.15.12-alpine
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx-conf:/etc/nginx/conf.d
      - /home/mylocalusername/certs:/etc/certs
        # for log, container redirects to /dev/stdout and /dev/stderr, so that is another option
      - /var/log/nginx:/var/log/nginx
    networks:
      - app-network
    logging:
        driver: "json-file"
        options:
            max-file: "5"
            max-size: "10m"

  squid:
    image: sameersbn/squid:3.5.27-2
    ports:
      - "3128:3128"
    volumes:
      - ./squid-conf:/etc/squid
      - /var/log/squid:/var/log/squid
    restart: always


networks:
  app-network:
    driver: bridge

You will need to look into Docker to understand how this works, but it sets up three containers.

The first container “roundcubemail” runs Roundcube, making it available on port 80 of the container. However, unless you use Docker to map that port outside the internal Docker network (I have commented out the code for that mapping) you will not be able to access the Roundcube container directly outside Docker engine.

The roundcubemail container has three volume mappings. The roundcubesource maps /var/www/html inside the container to roundcubesource within the host directory. When this container starts for the first time, it checks /var/www/html, and if empty, it copies the roundcube source into that folder. Run this container first, to copy the roundcube source into that host folder, so you can edit that folder within the host.

The second mapping is for roundcubeconfig, and may be useful for some configuration.

The third mapping maps the log files, which go into /var/log/apache in the container to the host /var/log/roundcubemail so they can be easily seen outside the container. If you do not use this mapping, the container will map these log files to stdout and stderr, so they can be managed by Docker.

There is also a client.env file in the same folder, which allows configuration of the roundcube, and configures the webmail client to access the Pair servers for receiving and sending email. My client.env is:

ROUNDCUBEMAIL_DEFAULT_HOST=ssl://yourpairusername.mail.pairserver.com
ROUNDCUBEMAIL_DEFAULT_PORT=993
ROUNDCUBEMAIL_SMTP_SERVER=tls://yourpairusername.mail.pairserver.com
ROUNDCUBEMAIL_SMTP_PORT=587

The roundcube configuration so that office PCs can access email without attachments is described on a different page.

The second container “webserver” runs the nginx web server software and acts as a proxy to make the roundcubemail container visible and using https to keep traffic to the roundcubemail container encrypted.

webserver maps ports 80 and 443 to the host, so the http and https ports can be reached from the outside.

webserver has three volume mappings. The first maps the container’s /etc/nginx/conf.d to a local subdirectory, so it can be used to configure nginx.

The second volume mapping maps the directory containing your SSL certificates, so you can use https within the office without getting a warning about the certificate not being trusted. If you choose to do that, you will need to get a certificate from a certificate issuing company. I use a wildcard certificate, and then set up the DNS for my domain to have an A record that points to the internal address of the web proxy server, e.g. 192.168.20.201 .

The third volume mapping for webserver is for mapping the log files into the host; that works the same as for roundcubemail.

The nginx-conf directory contains nginx.proxy.conf because nginx will load all .conf files in conf.d automatically. nginx.proxy.conf :

server {
        listen 80;
        listen [::]:80;

        #server_name 

	# this stanza allows letsencrypt challenges to succeed, if we are using letsencrypt
        location ~ /.well-known/acme-challenge {
                allow all;
                root /var/www/html;
        }

	# this stanza refers everything else to https
        location / {
                rewrite ^ https://$host$request_uri? permanent;
                #rewrite ^ https://$host:8443$request_uri? permanent;
        }

	# this would allow access to roundcube over http
	#location / {
	#	proxy_pass http://roundcubemail:80;
	#}
}

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        # server_name 

        server_tokens off;

        ssl_certificate /etc/certs/mycertificatechain.fullchain.pem;
        ssl_certificate_key /etc/certs/privkey.pem;

        include /etc/nginx/conf.d/options-ssl-nginx.conf;

        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "no-referrer-when-downgrade" always;
        add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
        # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        # enable strict transport security only if you understand the implications

        location / {
		proxy_pass http://roundcubemail:80;
        }


        location ~ /\.ht {
                deny all;
        }

}

nginx-conf also has options-ssl-nginx.conf to set currently-recommended ssl options. You might want to see if these have been updated :

ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_timeout 1440m;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS";

The third container runs the squid proxy server. It maps port 3128 to the host, so that the office PCs can access the proxy server. Other than the log mapping, there is one volume mapping for configuration.

The squid configuration is described on a different page, but a sample configuration, as well as the default squid configuration, is included with the sample files. You can find the customizations by searching for “JMN” within squid.conf