[DOCKER][MAIL] Fused services into single container
This commit is contained in:
parent
86a95def01
commit
419a2ceb1a
@ -84,5 +84,23 @@ services:
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
mail:
|
||||
build: docker/php
|
||||
restart: always
|
||||
tty: true
|
||||
ports:
|
||||
- "25:25"
|
||||
- "143:143"
|
||||
- "587:587"
|
||||
- "993:993"
|
||||
environment:
|
||||
- DOMAINNAME=mail.test
|
||||
- HOSTNAME=mail
|
||||
- POSTMASTER=postmaster@mail.test
|
||||
- SSL_CERT=/etc/dovecot/ssl/mailserver.crt
|
||||
- SSL_KEY=/etc/dovecot/ssl/mailserver.key
|
||||
|
||||
|
||||
|
||||
volumes:
|
||||
database:
|
||||
|
47
docker/mail/Dockerfile
Normal file
47
docker/mail/Dockerfile
Normal file
@ -0,0 +1,47 @@
|
||||
FROM debian:buster-slim
|
||||
|
||||
ENV \
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
DOMAINNAME=example.com \
|
||||
MAILNAME=mail \
|
||||
POSTMASTER=postmaster@example.com \
|
||||
SSL_CERT=/etc/ssl/mailserver.crt \
|
||||
SSL_KEY=/etc/ssl/mailserver.key
|
||||
|
||||
RUN \
|
||||
apt-get update \
|
||||
&& apt-get upgrade -y \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
postfix \
|
||||
telnet \
|
||||
dovecot-core \
|
||||
dovecot-pop3d \
|
||||
dovecot-imapd \
|
||||
dovecot-lmtpd \
|
||||
supervisor \
|
||||
rsyslog \
|
||||
opendkim \
|
||||
opendkim-tools \
|
||||
&& apt-get autoclean \
|
||||
&& apt-get autoremove
|
||||
|
||||
RUN \
|
||||
rm /etc/postfix/main.cf /etc/postfix/master.cf /etc/dovecot/dovecot.conf /etc/dovecot/conf.d/* /etc/rsyslog.conf /etc/rsyslog.d/* \
|
||||
&& groupadd -g 5000 vmail \
|
||||
&& useradd -d /var/mail -M -s /usr/sbin/nologin -u 5000 -g 5000 vmail \
|
||||
&& usermod -aG vmail postfix \
|
||||
&& usermod -aG vmail dovecot \
|
||||
&& usermod -aG vmail opendkim\
|
||||
&& mkdir -p -m 751 /var/mail/ \
|
||||
&& mkdir -p -m 755 /etc/mail/ \
|
||||
&& mkdir -p -m 755 /etc/ssl/ \
|
||||
&& mkdir -p -m 700 /etc/opendkim/keys \
|
||||
&& chown vmail:vmail /var/mail \
|
||||
&& chown opendkim:opendkim /etc/opendkim/keys
|
||||
|
||||
# Copy config files
|
||||
COPY rootfs/ /
|
||||
|
||||
EXPOSE 25 143 587 993
|
||||
|
||||
ENTRYPOINT /usr/bin/start.sh
|
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Jeffrey Boehm
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,9 +0,0 @@
|
||||
POP3 STARTTLS 127.0.0.1:110
|
||||
POP3S 127.0.0.1:995
|
||||
IMAP STARTTLS 127.0.0.1:143
|
||||
IMAPS 127.0.0.1:993
|
||||
SMTP 127.0.0.1:25
|
||||
Mail Submission STARTTLS 127.0.0.1:587
|
||||
Management Interface 127.0.0.1:81/manager/
|
||||
Webmail 127.0.0.1:81/webmail/
|
||||
Rspamd interface 127.0.0.1:81/rspamd/
|
@ -1,10 +0,0 @@
|
||||
FROM mysql:5.7
|
||||
LABEL maintainer="jeff@ressourcenkonflikt.de"
|
||||
|
||||
ENV MYSQL_DATABASE=mailserver \
|
||||
MYSQL_USER=mailserver \
|
||||
MYSQL_PASSWORD=changeme \
|
||||
MYSQL_ROOT_PASSWORD=changeme
|
||||
|
||||
COPY rootfs/ /
|
||||
VOLUME /run/mysqld
|
@ -1,82 +0,0 @@
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
|
||||
# Export von Tabelle mail_aliases
|
||||
# ------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `mail_aliases`;
|
||||
|
||||
CREATE TABLE `mail_aliases` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`domain_id` int(11) DEFAULT NULL,
|
||||
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||
`destination` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `alias_idx` (`domain_id`,`name`,`destination`),
|
||||
KEY `IDX_85AF3A56115F0EE5` (`domain_id`),
|
||||
CONSTRAINT `FK_5F12BB39115F0EE5` FOREIGN KEY (`domain_id`) REFERENCES `mail_domains` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
# Export von Tabelle mail_domains
|
||||
# ------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `mail_domains`;
|
||||
|
||||
CREATE TABLE `mail_domains` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `UNIQ_56C63EF25E237E06` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
# Export von Tabelle mail_users
|
||||
# ------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `mail_users`;
|
||||
|
||||
CREATE TABLE `mail_users` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`domain_id` int(11) DEFAULT NULL,
|
||||
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||
`password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `user_idx` (`name`,`domain_id`),
|
||||
KEY `IDX_20400786115F0EE5` (`domain_id`),
|
||||
CONSTRAINT `FK_1483A5E9115F0EE5` FOREIGN KEY (`domain_id`) REFERENCES `mail_domains` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
# Export von Tabelle migration_versions
|
||||
# ------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `migration_versions`;
|
||||
|
||||
CREATE TABLE `migration_versions` (
|
||||
`version` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`version`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
LOCK TABLES `migration_versions` WRITE;
|
||||
/*!40000 ALTER TABLE `migration_versions` DISABLE KEYS */;
|
||||
|
||||
INSERT INTO `migration_versions` (`version`)
|
||||
VALUES
|
||||
('20180320164351'),
|
||||
('20180320171339');
|
||||
|
||||
/*!40000 ALTER TABLE `migration_versions` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
@ -1,226 +0,0 @@
|
||||
-- Roundcube Webmail initial database structure
|
||||
|
||||
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=0 */;
|
||||
|
||||
-- Table structure for table `session`
|
||||
|
||||
CREATE TABLE `session` (
|
||||
`sess_id` varchar(128) NOT NULL,
|
||||
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
|
||||
`ip` varchar(40) NOT NULL,
|
||||
`vars` mediumtext NOT NULL,
|
||||
PRIMARY KEY(`sess_id`),
|
||||
INDEX `changed_index` (`changed`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
|
||||
-- Table structure for table `users`
|
||||
|
||||
CREATE TABLE `users` (
|
||||
`user_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`username` varchar(128) BINARY NOT NULL,
|
||||
`mail_host` varchar(128) NOT NULL,
|
||||
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
|
||||
`last_login` datetime DEFAULT NULL,
|
||||
`failed_login` datetime DEFAULT NULL,
|
||||
`failed_login_counter` int(10) UNSIGNED DEFAULT NULL,
|
||||
`language` varchar(5),
|
||||
`preferences` longtext,
|
||||
PRIMARY KEY(`user_id`),
|
||||
UNIQUE `username` (`username`, `mail_host`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
|
||||
-- Table structure for table `cache`
|
||||
|
||||
CREATE TABLE `cache` (
|
||||
`user_id` int(10) UNSIGNED NOT NULL,
|
||||
`cache_key` varchar(128) BINARY NOT NULL,
|
||||
`expires` datetime DEFAULT NULL,
|
||||
`data` longtext NOT NULL,
|
||||
PRIMARY KEY (`user_id`, `cache_key`),
|
||||
CONSTRAINT `user_id_fk_cache` FOREIGN KEY (`user_id`)
|
||||
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
INDEX `expires_index` (`expires`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
|
||||
-- Table structure for table `cache_shared`
|
||||
|
||||
CREATE TABLE `cache_shared` (
|
||||
`cache_key` varchar(255) BINARY NOT NULL,
|
||||
`expires` datetime DEFAULT NULL,
|
||||
`data` longtext NOT NULL,
|
||||
PRIMARY KEY (`cache_key`),
|
||||
INDEX `expires_index` (`expires`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
|
||||
-- Table structure for table `cache_index`
|
||||
|
||||
CREATE TABLE `cache_index` (
|
||||
`user_id` int(10) UNSIGNED NOT NULL,
|
||||
`mailbox` varchar(255) BINARY NOT NULL,
|
||||
`expires` datetime DEFAULT NULL,
|
||||
`valid` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`data` longtext NOT NULL,
|
||||
CONSTRAINT `user_id_fk_cache_index` FOREIGN KEY (`user_id`)
|
||||
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
INDEX `expires_index` (`expires`),
|
||||
PRIMARY KEY (`user_id`, `mailbox`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
|
||||
-- Table structure for table `cache_thread`
|
||||
|
||||
CREATE TABLE `cache_thread` (
|
||||
`user_id` int(10) UNSIGNED NOT NULL,
|
||||
`mailbox` varchar(255) BINARY NOT NULL,
|
||||
`expires` datetime DEFAULT NULL,
|
||||
`data` longtext NOT NULL,
|
||||
CONSTRAINT `user_id_fk_cache_thread` FOREIGN KEY (`user_id`)
|
||||
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
INDEX `expires_index` (`expires`),
|
||||
PRIMARY KEY (`user_id`, `mailbox`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
|
||||
-- Table structure for table `cache_messages`
|
||||
|
||||
CREATE TABLE `cache_messages` (
|
||||
`user_id` int(10) UNSIGNED NOT NULL,
|
||||
`mailbox` varchar(255) BINARY NOT NULL,
|
||||
`uid` int(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`expires` datetime DEFAULT NULL,
|
||||
`data` longtext NOT NULL,
|
||||
`flags` int(11) NOT NULL DEFAULT '0',
|
||||
CONSTRAINT `user_id_fk_cache_messages` FOREIGN KEY (`user_id`)
|
||||
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
INDEX `expires_index` (`expires`),
|
||||
PRIMARY KEY (`user_id`, `mailbox`, `uid`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
|
||||
-- Table structure for table `contacts`
|
||||
|
||||
CREATE TABLE `contacts` (
|
||||
`contact_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
|
||||
`del` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`name` varchar(128) NOT NULL DEFAULT '',
|
||||
`email` text NOT NULL,
|
||||
`firstname` varchar(128) NOT NULL DEFAULT '',
|
||||
`surname` varchar(128) NOT NULL DEFAULT '',
|
||||
`vcard` longtext NULL,
|
||||
`words` text NULL,
|
||||
`user_id` int(10) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY(`contact_id`),
|
||||
CONSTRAINT `user_id_fk_contacts` FOREIGN KEY (`user_id`)
|
||||
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
INDEX `user_contacts_index` (`user_id`,`del`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
-- Table structure for table `contactgroups`
|
||||
|
||||
CREATE TABLE `contactgroups` (
|
||||
`contactgroup_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(10) UNSIGNED NOT NULL,
|
||||
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
|
||||
`del` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`name` varchar(128) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY(`contactgroup_id`),
|
||||
CONSTRAINT `user_id_fk_contactgroups` FOREIGN KEY (`user_id`)
|
||||
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
INDEX `contactgroups_user_index` (`user_id`,`del`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
CREATE TABLE `contactgroupmembers` (
|
||||
`contactgroup_id` int(10) UNSIGNED NOT NULL,
|
||||
`contact_id` int(10) UNSIGNED NOT NULL,
|
||||
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
|
||||
PRIMARY KEY (`contactgroup_id`, `contact_id`),
|
||||
CONSTRAINT `contactgroup_id_fk_contactgroups` FOREIGN KEY (`contactgroup_id`)
|
||||
REFERENCES `contactgroups`(`contactgroup_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `contact_id_fk_contacts` FOREIGN KEY (`contact_id`)
|
||||
REFERENCES `contacts`(`contact_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
INDEX `contactgroupmembers_contact_index` (`contact_id`)
|
||||
) /*!40000 ENGINE=INNODB */;
|
||||
|
||||
|
||||
-- Table structure for table `identities`
|
||||
|
||||
CREATE TABLE `identities` (
|
||||
`identity_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(10) UNSIGNED NOT NULL,
|
||||
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
|
||||
`del` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`standard` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`name` varchar(128) NOT NULL,
|
||||
`organization` varchar(128) NOT NULL DEFAULT '',
|
||||
`email` varchar(128) NOT NULL,
|
||||
`reply-to` varchar(128) NOT NULL DEFAULT '',
|
||||
`bcc` varchar(128) NOT NULL DEFAULT '',
|
||||
`signature` longtext,
|
||||
`html_signature` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY(`identity_id`),
|
||||
CONSTRAINT `user_id_fk_identities` FOREIGN KEY (`user_id`)
|
||||
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
INDEX `user_identities_index` (`user_id`, `del`),
|
||||
INDEX `email_identities_index` (`email`, `del`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
|
||||
-- Table structure for table `dictionary`
|
||||
|
||||
CREATE TABLE `dictionary` (
|
||||
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, -- redundant, for compat. with Galera Cluster
|
||||
`user_id` int(10) UNSIGNED DEFAULT NULL, -- NULL here is for "shared dictionaries"
|
||||
`language` varchar(5) NOT NULL,
|
||||
`data` longtext NOT NULL,
|
||||
CONSTRAINT `user_id_fk_dictionary` FOREIGN KEY (`user_id`)
|
||||
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
UNIQUE `uniqueness` (`user_id`, `language`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
|
||||
-- Table structure for table `searches`
|
||||
|
||||
CREATE TABLE `searches` (
|
||||
`search_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(10) UNSIGNED NOT NULL,
|
||||
`type` int(3) NOT NULL DEFAULT '0',
|
||||
`name` varchar(128) NOT NULL,
|
||||
`data` text,
|
||||
PRIMARY KEY(`search_id`),
|
||||
CONSTRAINT `user_id_fk_searches` FOREIGN KEY (`user_id`)
|
||||
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
UNIQUE `uniqueness` (`user_id`, `type`, `name`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
-- Table structure for table `filestore`
|
||||
|
||||
CREATE TABLE `filestore` (
|
||||
`file_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(10) UNSIGNED NOT NULL,
|
||||
`context` varchar(32) NOT NULL,
|
||||
`filename` varchar(128) NOT NULL,
|
||||
`mtime` int(10) NOT NULL,
|
||||
`data` longtext NOT NULL,
|
||||
PRIMARY KEY (`file_id`),
|
||||
CONSTRAINT `user_id_fk_filestore` FOREIGN KEY (`user_id`)
|
||||
REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
UNIQUE `uniqueness` (`user_id`, `context`, `filename`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
-- Table structure for table `system`
|
||||
|
||||
CREATE TABLE `system` (
|
||||
`name` varchar(64) NOT NULL,
|
||||
`value` mediumtext,
|
||||
PRIMARY KEY(`name`)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
|
||||
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=1 */;
|
||||
|
||||
INSERT INTO `system` (`name`, `value`) VALUES ('roundcube-version', '2019092900');
|
@ -1,125 +1,28 @@
|
||||
version: '3.5'
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# Creates self signed tls certificates. Remove if you
|
||||
# use your own.
|
||||
ssl:
|
||||
image: jeboehm/mailserver-ssl:latest
|
||||
build: ./ssl
|
||||
env_file: .env
|
||||
volumes:
|
||||
- data-tls:/media/tls:rw
|
||||
|
||||
# Responsible for storing users and their aliases. Remove
|
||||
# if you already have a MySQL server.
|
||||
db:
|
||||
image: jeboehm/mailserver-db:latest
|
||||
build: ./db
|
||||
restart: on-failure:5
|
||||
env_file: .env
|
||||
volumes:
|
||||
- data-db:/var/lib/mysql
|
||||
|
||||
# The Mail Transfer Agent (Postfix) receives incoming mail
|
||||
# on TCP port 25.
|
||||
mta:
|
||||
image: jeboehm/mailserver-mta:latest
|
||||
build: ./mta
|
||||
restart: on-failure:5
|
||||
env_file: .env
|
||||
volumes:
|
||||
- data-tls:/media/tls:ro
|
||||
# For using external certificates uncomment the following lines
|
||||
# and change the path on the left side of the colon.
|
||||
# - /home/user/certs/mail.example.com.crt:/media/tls/mailserver.crt:ro
|
||||
# - /home/user/certs/mail.example.com.key:/media/tls/mailserver.key:ro
|
||||
mail:
|
||||
image: mail
|
||||
build: .
|
||||
environment:
|
||||
DOMAINNAME: mail.test
|
||||
MAILNAME: mail.mail.test
|
||||
POSTMASTER: postmaster@mail.test
|
||||
SSL_CERT: /etc/ssl/mailserver.crt
|
||||
SSL_KEY: /etc/ssl/mailserver.key
|
||||
container_name: mail
|
||||
privileged: true
|
||||
ports:
|
||||
- "0.0.0.0:25:25"
|
||||
|
||||
# The Mail Delivery Agent (Dovecot) is responsible for storing
|
||||
# incoming mail into a users mailbox and also delivers them
|
||||
# via POP3 or IMAP4.
|
||||
mda:
|
||||
image: jeboehm/mailserver-mda:latest
|
||||
build: ./mda
|
||||
restart: on-failure:5
|
||||
env_file: .env
|
||||
- "25:25"
|
||||
- "143:143"
|
||||
- "587:587"
|
||||
- "993:993"
|
||||
volumes:
|
||||
- data-mail:/var/vmail
|
||||
- data-tls:/media/tls:ro
|
||||
# For using external certificates uncomment the following lines
|
||||
# and change the path on the left side of the colon.
|
||||
# - /home/user/certs/mail.example.com.crt:/media/tls/mailserver.crt:ro
|
||||
# - /home/user/certs/mail.example.com.key:/media/tls/mailserver.key:ro
|
||||
ports:
|
||||
- "0.0.0.0:143:143"
|
||||
- "0.0.0.0:993:993"
|
||||
- "0.0.0.0:110:110"
|
||||
- "0.0.0.0:995:995"
|
||||
- "0.0.0.0:587:587"
|
||||
- maildata:/var/mail
|
||||
- mailconf:/etc/mail
|
||||
|
||||
# The admin (mailserver-admin) and webmail (roundcube) interfaces
|
||||
# live here. Can be removed if not needed.
|
||||
web:
|
||||
image: jeboehm/mailserver-web:latest
|
||||
build: ./web
|
||||
restart: on-failure:5
|
||||
env_file: .env
|
||||
volumes:
|
||||
- data-dkim:/media/dkim
|
||||
# For use with jwilder/nginx-proxy.
|
||||
# environment:
|
||||
# - VIRTUAL_HOST=mail.example.com
|
||||
ports:
|
||||
- "0.0.0.0:81:80"
|
||||
|
||||
# Incoming spam is (hopefully) filtered by rspamd which runs
|
||||
# in this service.
|
||||
filter:
|
||||
image: jeboehm/mailserver-filter:latest
|
||||
build: ./filter
|
||||
restart: on-failure:5
|
||||
env_file: .env
|
||||
volumes:
|
||||
- data-filter:/var/lib/rspamd
|
||||
- data-dkim:/media/dkim
|
||||
links:
|
||||
- virus:virus.local
|
||||
|
||||
# Incoming viruses or malware is detected and rejected by
|
||||
# this service. Can be removed if FILTER_VIRUS is set to false.
|
||||
virus:
|
||||
image: jeboehm/mailserver-virus:latest
|
||||
build: ./virus
|
||||
restart: on-failure:5
|
||||
env_file: .env
|
||||
volumes:
|
||||
- data-virusdb:/var/lib/clamav
|
||||
|
||||
# If you want unhealthy containers to be restarted automatically
|
||||
# just uncomment the following lines.
|
||||
# autoheal:
|
||||
# image: willfarrell/autoheal:latest
|
||||
# restart: always
|
||||
# networks: []
|
||||
# volumes:
|
||||
# - /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
# environment:
|
||||
# - AUTOHEAL_CONTAINER_LABEL=de.ressourcenkonflikt.docker-mailserver.autoheal
|
||||
|
||||
# Optional service: extend ClamAV (used in the virus service)
|
||||
# by downloading additional databases provided by different
|
||||
# companys. Run it regulary.
|
||||
# virus_unof_sig_updater:
|
||||
# build: ./virus/contrib/unofficial-sigs
|
||||
# env_file: .env
|
||||
# volumes:
|
||||
# - data-virusdb:/var/lib/clamav
|
||||
|
||||
volumes:
|
||||
data-db:
|
||||
data-dkim:
|
||||
data-mail:
|
||||
data-tls:
|
||||
data-filter:
|
||||
data-virusdb:
|
||||
maildata:
|
||||
mailconf:
|
||||
|
14
docker/mail/exec.sh
Normal file
14
docker/mail/exec.sh
Normal file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$1" == "new" ]
|
||||
then
|
||||
if [ "$2" == "domain" ]
|
||||
then
|
||||
docker exec mail new-domain "${*,3}"
|
||||
elif [ "$2" == "user" ]
|
||||
then
|
||||
docker exec mail new-user "${*,3}"
|
||||
elif [ "$2" == "alias" ]
|
||||
docker exec mail new-alias "${*,3}"
|
||||
fi
|
||||
fi
|
@ -1,45 +0,0 @@
|
||||
ARG DOCKERIZE_VER=0.6.0
|
||||
ARG ALPINE_VER=3.9
|
||||
|
||||
FROM jwilder/dockerize:${DOCKERIZE_VER} AS dockerize
|
||||
FROM alpine:${ALPINE_VER}
|
||||
|
||||
LABEL maintainer="jeff@ressourcenkonflikt.de"
|
||||
LABEL vendor="https://github.com/jeboehm/docker-mailserver"
|
||||
LABEL de.ressourcenkonflikt.docker-mailserver.autoheal="true"
|
||||
|
||||
ENV FILTER_VIRUS=false \
|
||||
FILTER_VIRUS_HOST=virus.local \
|
||||
WAITSTART_TIMEOUT=1m \
|
||||
CONTROLLER_PASSWORD=changeme
|
||||
|
||||
RUN apk --no-cache add \
|
||||
openssl \
|
||||
rspamd \
|
||||
rspamd-client \
|
||||
rspamd-controller \
|
||||
rspamd-proxy && \
|
||||
mkdir /run/rspamd && \
|
||||
touch \
|
||||
/etc/rspamd/local.d/antivirus.conf \
|
||||
/etc/rspamd/local.d/worker-controller.inc && \
|
||||
chown -R rspamd \
|
||||
/run/rspamd \
|
||||
/var/lib/rspamd \
|
||||
/etc/rspamd/local.d/antivirus.conf \
|
||||
/etc/rspamd/local.d/worker-controller.inc && \
|
||||
wget -O /usr/share/rspamd/bayes.spam.sqlite https://rspamd.com/rspamd_statistics/bayes.spam.sqlite && \
|
||||
wget -O /usr/share/rspamd/bayes.ham.sqlite https://rspamd.com/rspamd_statistics/bayes.ham.sqlite && \
|
||||
apk --no-cache del \
|
||||
openssl
|
||||
|
||||
COPY --from=dockerize /usr/local/bin/dockerize /usr/local/bin
|
||||
COPY rootfs/ /
|
||||
|
||||
EXPOSE 11332 11334
|
||||
USER rspamd
|
||||
|
||||
VOLUME ["/var/lib/rspamd"]
|
||||
|
||||
HEALTHCHECK CMD wget -O- -T 10 http://127.0.0.1:11334/stat
|
||||
CMD ["/usr/local/bin/entrypoint.sh"]
|
@ -1,11 +0,0 @@
|
||||
{{ $filter_virus := eq (or ($.Env.FILTER_VIRUS) "") "true" }}
|
||||
|
||||
{{ if $filter_virus }}
|
||||
clamav {
|
||||
scan_mime_parts = false;
|
||||
symbol = "CLAM_VIRUS";
|
||||
type = "clamav";
|
||||
action = "reject";
|
||||
servers = "{{$.Env.FILTER_VIRUS_HOST}}:3310";
|
||||
}
|
||||
{{ end }}
|
@ -1 +0,0 @@
|
||||
autolearn = true;
|
@ -1,2 +0,0 @@
|
||||
path = "/media/dkim/$domain.$selector.key";
|
||||
selector_map = "/media/dkim/dkim_selectors.map";
|
@ -1 +0,0 @@
|
||||
type = console
|
@ -1,11 +0,0 @@
|
||||
group "rbl" {
|
||||
symbol "RBL_NIXSPAM_BAD" {
|
||||
weight = 7.0;
|
||||
description = "From address is listed in ix.dnsbl.manitu.net BL";
|
||||
}
|
||||
|
||||
symbol "RBL_NIXSPAM" {
|
||||
weight = 0.0;
|
||||
description = "Unrecognised result from ix.dnsbl.manitu.net BL";
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
extended_spam_headers = true;
|
@ -1,7 +0,0 @@
|
||||
dns {
|
||||
timeout = 1s;
|
||||
sockets = 16;
|
||||
retransmits = 2;
|
||||
nameserver = [ "8.8.8.8:53", "8.8.4.4:53", "1.1.1.1:53", "1.0.0.1:53" ];
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
rbls {
|
||||
nixspam {
|
||||
symbol = "RBL_NIXSPAM";
|
||||
rbl = "ix.dnsbl.manitu.net";
|
||||
returncodes {
|
||||
RBL_NIXSPAM_BAD = "127.0.0.2";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
bind_socket = "*:11334";
|
||||
secure_ip = "127.0.0.1";
|
||||
secure_ip = "::1";
|
||||
secure_ip = "172.16.0.0/12";
|
||||
password = "{{$.Env.CONTROLLER_PASSWORD_ENC}}"
|
@ -1 +0,0 @@
|
||||
bind_socket = "*:11332";
|
@ -1,32 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
FILTER_VIRUS_ARGS=""
|
||||
if [ ${FILTER_VIRUS} == "true" ]
|
||||
then
|
||||
FILTER_VIRUS_ARGS="-wait tcp://${FILTER_VIRUS_HOST}:3310"
|
||||
fi
|
||||
|
||||
if ! [ -f /var/lib/rspamd/bayes.spam.sqlite ]
|
||||
then
|
||||
cp /usr/share/rspamd/bayes.spam.sqlite /var/lib/rspamd/bayes.spam.sqlite
|
||||
fi
|
||||
|
||||
if ! [ -f /var/lib/rspamd/bayes.ham.sqlite ]
|
||||
then
|
||||
cp /usr/share/rspamd/bayes.ham.sqlite /var/lib/rspamd/bayes.ham.sqlite
|
||||
fi
|
||||
|
||||
if [ "${CONTROLLER_PASSWORD}" == "changeme" ]
|
||||
then
|
||||
# q1 is disabled in rspamd.
|
||||
export CONTROLLER_PASSWORD_ENC="q1"
|
||||
else
|
||||
export CONTROLLER_PASSWORD_ENC=`rspamadm pw -e -p ${CONTROLLER_PASSWORD}`
|
||||
fi
|
||||
|
||||
dockerize \
|
||||
-template /etc/rspamd/local.d/antivirus.conf.templ:/etc/rspamd/local.d/antivirus.conf \
|
||||
-template /etc/rspamd/local.d/worker-controller.inc.templ:/etc/rspamd/local.d/worker-controller.inc \
|
||||
${FILTER_VIRUS_ARGS} \
|
||||
-timeout ${WAITSTART_TIMEOUT} \
|
||||
/usr/sbin/rspamd -c /etc/rspamd/rspamd.conf -f
|
@ -1,47 +0,0 @@
|
||||
ARG DOCKERIZE_VER=0.6.0
|
||||
ARG ALPINE_VER=3.9
|
||||
|
||||
FROM jwilder/dockerize:${DOCKERIZE_VER} AS dockerize
|
||||
|
||||
FROM alpine:${ALPINE_VER}
|
||||
LABEL maintainer="jeff@ressourcenkonflikt.de"
|
||||
LABEL vendor="https://github.com/jeboehm/docker-mailserver"
|
||||
LABEL de.ressourcenkonflikt.docker-mailserver.autoheal="true"
|
||||
|
||||
ENV MYSQL_HOST=db \
|
||||
MYSQL_USER=root \
|
||||
MYSQL_PASSWORD=changeme \
|
||||
MYSQL_DATABASE=mailserver \
|
||||
MAILNAME=mail.example.com \
|
||||
POSTMASTER=postmaster@example.com \
|
||||
SUBMISSION_HOST=mta \
|
||||
ENABLE_POP3=true \
|
||||
ENABLE_IMAP=true \
|
||||
SSL_CERT=/media/tls/mailserver.crt \
|
||||
SSL_KEY=/media/tls/mailserver.key \
|
||||
WAITSTART_TIMEOUT=1m
|
||||
|
||||
RUN apk --no-cache add \
|
||||
curl \
|
||||
dovecot \
|
||||
dovecot-lmtpd \
|
||||
dovecot-mysql \
|
||||
dovecot-pigeonhole-plugin \
|
||||
dovecot-pop3d \
|
||||
dovecot-submissiond && \
|
||||
adduser -h /var/vmail -u 5000 -D vmail && \
|
||||
rm -rf /etc/ssl/dovecot && \
|
||||
openssl dhparam -out /etc/dovecot/dh.pem 2048
|
||||
|
||||
COPY --from=dockerize /usr/local/bin/dockerize /usr/local/bin
|
||||
COPY rootfs/ /
|
||||
|
||||
RUN sievec /etc/dovecot/sieve/global/spam-to-folder.sieve && \
|
||||
sievec /etc/dovecot/sieve/global/learn-ham.sieve && \
|
||||
sievec /etc/dovecot/sieve/global/learn-spam.sieve
|
||||
|
||||
EXPOSE 2003 4190 143 110 993 995
|
||||
VOLUME ["/var/vmail"]
|
||||
|
||||
HEALTHCHECK CMD echo "? LOGOUT" | nc 127.0.0.1 143 | grep "Dovecot ready."
|
||||
CMD ["/usr/local/bin/entrypoint.sh"]
|
@ -1,3 +0,0 @@
|
||||
auth_mechanisms = plain login
|
||||
|
||||
!include auth-sql.conf.ext
|
@ -1,2 +0,0 @@
|
||||
log_path = /dev/stderr
|
||||
info_log_path = /dev/stdout
|
@ -1,10 +0,0 @@
|
||||
mail_location = maildir:/var/vmail/%d/%n/Maildir
|
||||
mail_home = /var/vmail/%d/%n
|
||||
mail_uid = vmail
|
||||
mail_gid = vmail
|
||||
mail_privileged_group = vmail
|
||||
mail_plugins = $mail_plugins quota
|
||||
|
||||
namespace inbox {
|
||||
inbox = yes
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
protocols = lmtp submission
|
||||
|
||||
{{ $enable_pop3 := eq (or ($.Env.ENABLE_POP3) "") "true" }}
|
||||
{{ $enable_imap := eq (or ($.Env.ENABLE_IMAP) "") "true" }}
|
||||
|
||||
{{ if $enable_imap }}
|
||||
service imap-login {
|
||||
inet_listener imap {
|
||||
#port = 143
|
||||
}
|
||||
|
||||
inet_listener imaps {
|
||||
#port = 993
|
||||
#ssl = yes
|
||||
}
|
||||
}
|
||||
|
||||
service imap {
|
||||
}
|
||||
|
||||
protocols = $protocols imap
|
||||
{{ end }}
|
||||
|
||||
{{ if $enable_pop3 }}
|
||||
service pop3-login {
|
||||
inet_listener pop3 {
|
||||
#port = 110
|
||||
}
|
||||
|
||||
inet_listener pop3s {
|
||||
#port = 995
|
||||
#ssl = yes
|
||||
}
|
||||
}
|
||||
|
||||
service pop3 {
|
||||
}
|
||||
|
||||
protocols = $protocols pop3
|
||||
{{ end }}
|
||||
|
||||
service submission-login {
|
||||
inet_listener submission {
|
||||
#port = 587
|
||||
}
|
||||
}
|
||||
|
||||
service submission {
|
||||
#process_limit = 1024
|
||||
}
|
||||
|
||||
service lmtp {
|
||||
inet_listener lmtp {
|
||||
port = 2003
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
ssl = yes
|
||||
ssl_cert = </media/tls/mailserver.crt
|
||||
ssl_key = </media/tls/mailserver.key
|
||||
ssl_dh = </etc/dovecot/dh.pem
|
@ -1,5 +0,0 @@
|
||||
postmaster_address = {{ .Env.POSTMASTER }}
|
||||
hostname = {{ .Env.MAILNAME }}
|
||||
submission_host = {{ .Env.SUBMISSION_HOST }}
|
||||
lda_mailbox_autosubscribe = yes
|
||||
recipient_delimiter = -
|
@ -1,24 +0,0 @@
|
||||
namespace inbox {
|
||||
mailbox Drafts {
|
||||
auto = subscribe
|
||||
special_use = \Drafts
|
||||
}
|
||||
|
||||
mailbox Junk {
|
||||
auto = subscribe
|
||||
special_use = \Junk
|
||||
}
|
||||
|
||||
mailbox Trash {
|
||||
auto = subscribe
|
||||
special_use = \Trash
|
||||
}
|
||||
|
||||
mailbox Sent {
|
||||
special_use = \Sent
|
||||
}
|
||||
|
||||
mailbox "Sent Messages" {
|
||||
special_use = \Sent
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
protocol imap {
|
||||
mail_plugins = $mail_plugins imap_sieve imap_quota
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
protocol lmtp {
|
||||
mail_plugins = $mail_plugins sieve
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
protocols = $protocols sieve
|
||||
|
||||
service managesieve-login {
|
||||
inet_listener sieve {
|
||||
port = 4190
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
submission_relay_host = {{ .Env.SUBMISSION_HOST }}
|
||||
submission_relay_port = 25
|
||||
submission_relay_trusted = yes
|
||||
|
||||
protocol submission {
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
plugin {
|
||||
quota = maildir:User quota
|
||||
quota_exceeded_message = "Benutzer %u hat das Speichervolumen überschritten. / User %u has exhausted allowed storage space."
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
plugin {
|
||||
sieve_plugins = sieve_imapsieve sieve_extprograms
|
||||
sieve_global_extensions = +vnd.dovecot.pipe
|
||||
sieve = file:~/sieve;active=~/.dovecot.sieve
|
||||
sieve_before = /etc/dovecot/sieve/global/spam-to-folder.sieve
|
||||
sieve_pipe_bin_dir = /usr/lib/dovecot/sieve
|
||||
sieve_pipe_exec_timeout = 60s
|
||||
recipient_delimiter = -
|
||||
|
||||
# From somewhere to junk folder
|
||||
imapsieve_mailbox1_name = Junk
|
||||
imapsieve_mailbox1_causes = COPY
|
||||
imapsieve_mailbox1_before = file:/etc/dovecot/sieve/global/learn-spam.sieve
|
||||
|
||||
# From junk folder to elsewhere
|
||||
imapsieve_mailbox2_name = *
|
||||
imapsieve_mailbox2_from = Junk
|
||||
imapsieve_mailbox2_causes = COPY
|
||||
imapsieve_mailbox2_before = file:/etc/dovecot/sieve/global/learn-ham.sieve
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
passdb {
|
||||
driver = sql
|
||||
args = /etc/dovecot/dovecot-sql.conf.ext
|
||||
}
|
||||
|
||||
userdb {
|
||||
driver = sql
|
||||
args = /etc/dovecot/dovecot-sql.conf.ext
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
driver = mysql
|
||||
connect = host={{ .Env.MYSQL_HOST }} dbname={{ .Env.MYSQL_DATABASE }} user={{ .Env.MYSQL_USER }} password={{ .Env.MYSQL_PASSWORD }}
|
||||
default_pass_scheme = SHA256-CRYPT
|
||||
password_query = SELECT mail_users.name AS user, mail_domains.name AS domain, password FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id WHERE mail_users.name = '%n' AND mail_domains.name = '%d' AND enabled = 1 AND NOT (send_only = 1 AND "%s" in ('imap', 'pop3'));
|
||||
user_query = SELECT concat('*:storage=', quota, 'M') AS quota_rule FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id WHERE mail_users.name = '%n' AND mail_domains.name = '%d';
|
||||
iterate_query = SELECT mail_users.name AS username, mail_domains.name AS domain FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id;
|
@ -1,2 +0,0 @@
|
||||
require ["vnd.dovecot.pipe", "copy", "imapsieve"];
|
||||
pipe :copy "rspamc" ["learnham"];
|
@ -1,2 +0,0 @@
|
||||
require ["vnd.dovecot.pipe", "copy", "imapsieve"];
|
||||
pipe :copy "rspamc" ["learnspam"];
|
@ -1,6 +0,0 @@
|
||||
require ["fileinto","mailbox"];
|
||||
|
||||
if header :contains "X-Spam" "YES" {
|
||||
fileinto :create "Junk";
|
||||
stop;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
ACTION=${1}
|
||||
|
||||
curl -q -s --connect-timeout 60 --data-binary @- http://filter:11334/${ACTION}
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
openssl dhparam -out /etc/dovecot/dh.pem.tmp 4096
|
||||
mv /etc/dovecot/dh.pem.tmp /etc/dovecot/dh.pem
|
||||
touch /etc/dovecot/dh.pem.created
|
||||
|
||||
echo "The Diffie Hellman file was generated."
|
||||
echo "YOU SHOULD RESTART THIS CONTAINER NOW."
|
||||
|
||||
exit 0
|
@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if ! [ -r /etc/dovecot/dh.pem.created ]
|
||||
then
|
||||
echo "Using pre-generated Diffie Hellman parameters until the new one is generated."
|
||||
/usr/local/bin/dh.sh &
|
||||
fi
|
||||
|
||||
rm -f /run/dovecot/master.pid
|
||||
|
||||
dockerize \
|
||||
-template /etc/dovecot/conf.d/10-master.conf.templ:/etc/dovecot/conf.d/10-master.conf \
|
||||
-template /etc/dovecot/conf.d/15-lda.conf.templ:/etc/dovecot/conf.d/15-lda.conf \
|
||||
-template /etc/dovecot/conf.d/20-submission.conf.templ:/etc/dovecot/conf.d/20-submission.conf \
|
||||
-template /etc/dovecot/dovecot-sql.conf.ext.templ:/etc/dovecot/dovecot-sql.conf.ext \
|
||||
-wait tcp://${MYSQL_HOST}:3306 \
|
||||
-wait file://${SSL_CERT} \
|
||||
-wait file://${SSL_KEY} \
|
||||
-timeout ${WAITSTART_TIMEOUT} \
|
||||
/usr/sbin/dovecot -F
|
@ -1,66 +0,0 @@
|
||||
ARG DOCKERIZE_VER=0.6.0
|
||||
ARG ALPINE_VER=3.9
|
||||
|
||||
FROM jwilder/dockerize:${DOCKERIZE_VER} AS dockerize
|
||||
FROM alpine:${ALPINE_VER}
|
||||
|
||||
LABEL maintainer="jeff@ressourcenkonflikt.de"
|
||||
LABEL vendor="https://github.com/jeboehm/docker-mailserver"
|
||||
LABEL de.ressourcenkonflikt.docker-mailserver.autoheal="true"
|
||||
|
||||
ENV MAILNAME=mail.example.com \
|
||||
MYNETWORKS=127.0.0.0/8\ 10.0.0.0/8\ 172.16.0.0/12\ 192.168.0.0/16 \
|
||||
MYSQL_HOST=db \
|
||||
MYSQL_USER=root \
|
||||
MYSQL_PASSWORD=changeme \
|
||||
MYSQL_DATABASE=mailserver \
|
||||
FILTER_MIME=false \
|
||||
RSPAMD_HOST=filter \
|
||||
MDA_HOST=mda \
|
||||
MTA_HOST=mta \
|
||||
RELAYHOST=false \
|
||||
SSL_CERT=/media/tls/mailserver.crt \
|
||||
SSL_KEY=/media/tls/mailserver.key \
|
||||
WAITSTART_TIMEOUT=1m
|
||||
|
||||
RUN apk --no-cache add \
|
||||
postfix-mysql \
|
||||
postfix \
|
||||
supervisor && \
|
||||
postconf virtual_mailbox_domains=mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf && \
|
||||
postconf virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf && \
|
||||
postconf virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf,mysql:/etc/postfix/mysql-email2email.cf && \
|
||||
postconf smtpd_recipient_restrictions="check_recipient_access mysql:/etc/postfix/mysql-recipient-access.cf" && \
|
||||
postconf smtputf8_enable=no && \
|
||||
postconf smtpd_milters="inet:${RSPAMD_HOST}:11332" && \
|
||||
postconf non_smtpd_milters="inet:${RSPAMD_HOST}:11332" && \
|
||||
postconf milter_protocol=6 && \
|
||||
postconf milter_mail_macros="i {mail_addr} {client_addr} {client_name} {auth_authen}" && \
|
||||
postconf milter_default_action=accept && \
|
||||
postconf virtual_transport="lmtp:${MDA_HOST}:2003" && \
|
||||
postconf smtp_tls_security_level=may && \
|
||||
postconf smtpd_tls_security_level=may && \
|
||||
postconf smtpd_tls_auth_only=yes && \
|
||||
postconf smtpd_tls_cert_file="${SSL_CERT}" && \
|
||||
postconf smtpd_tls_key_file="${SSL_KEY}" && \
|
||||
postconf smtpd_discard_ehlo_keywords="silent-discard, dsn" && \
|
||||
postconf soft_bounce=no && \
|
||||
postconf message_size_limit=52428800 && \
|
||||
postconf mailbox_size_limit=0 && \
|
||||
postconf recipient_delimiter=- && \
|
||||
postconf mynetworks="$MYNETWORKS" && \
|
||||
postconf maximal_queue_lifetime=1h && \
|
||||
postconf bounce_queue_lifetime=1h && \
|
||||
postconf maximal_backoff_time=15m && \
|
||||
postconf minimal_backoff_time=5m && \
|
||||
postconf queue_run_delay=5m && \
|
||||
newaliases
|
||||
|
||||
COPY --from=dockerize /usr/local/bin/dockerize /usr/local/bin
|
||||
COPY rootfs/ /
|
||||
|
||||
EXPOSE 25
|
||||
VOLUME ["/var/spool/postfix"]
|
||||
|
||||
HEALTHCHECK CMD postfix status || exit 1
|
||||
CMD ["/usr/local/bin/entrypoint.sh"]
|
@ -1 +0,0 @@
|
||||
/name=[^>]*\.(bat|com|exe|dll|vbs|docm|doc|dzip)/ REJECT
|
@ -1,5 +0,0 @@
|
||||
user = {{ .Env.MYSQL_USER }}
|
||||
password = {{ .Env.MYSQL_PASSWORD }}
|
||||
hosts = {{ .Env.MYSQL_HOST }}
|
||||
dbname = {{ .Env.MYSQL_DATABASE }}
|
||||
query = SELECT CONCAT(mail_users.name, '@', mail_domains.name) AS email FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id HAVING email='%s'
|
@ -1,5 +0,0 @@
|
||||
user = {{ .Env.MYSQL_USER }}
|
||||
password = {{ .Env.MYSQL_PASSWORD }}
|
||||
hosts = {{ .Env.MYSQL_HOST }}
|
||||
dbname = {{ .Env.MYSQL_DATABASE }}
|
||||
query = SELECT IF(send_only = true, 'REJECT', 'OK') AS access FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id WHERE mail_users.name = '%u' AND mail_domains.name = '%d'
|
@ -1,5 +0,0 @@
|
||||
user = {{ .Env.MYSQL_USER }}
|
||||
password = {{ .Env.MYSQL_PASSWORD }}
|
||||
hosts = {{ .Env.MYSQL_HOST }}
|
||||
dbname = {{ .Env.MYSQL_DATABASE }}
|
||||
query = SELECT destination FROM mail_aliases JOIN mail_domains ON mail_aliases.domain_id = mail_domains.id WHERE CONCAT(mail_aliases.name, '@', mail_domains.name) = '%s'
|
@ -1,5 +0,0 @@
|
||||
user = {{ .Env.MYSQL_USER }}
|
||||
password = {{ .Env.MYSQL_PASSWORD }}
|
||||
hosts = {{ .Env.MYSQL_HOST }}
|
||||
dbname = {{ .Env.MYSQL_DATABASE }}
|
||||
query = SELECT 1 FROM mail_domains WHERE name='%s'
|
@ -1,5 +0,0 @@
|
||||
user = {{ .Env.MYSQL_USER }}
|
||||
password = {{ .Env.MYSQL_PASSWORD }}
|
||||
hosts = {{ .Env.MYSQL_HOST }}
|
||||
dbname = {{ .Env.MYSQL_DATABASE }}
|
||||
query = SELECT 1 FROM mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id WHERE mail_users.name = '%u' AND mail_domains.name = '%d' AND enabled = 1
|
@ -1,18 +0,0 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/dev/stderr
|
||||
logfile_maxbytes=0
|
||||
pidfile=/tmp/supervisord.pid
|
||||
user=root
|
||||
|
||||
[program:syslogd]
|
||||
command=/bin/busybox syslogd -n -O - -S
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/dev/stderr
|
||||
stdout_logfile_maxbytes=0
|
||||
|
||||
[program:postfix]
|
||||
command=/usr/libexec/postfix/master -d
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/dev/stderr
|
||||
stdout_logfile_maxbytes=0
|
@ -1,29 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
postconf myhostname="${MAILNAME}"
|
||||
postconf mynetworks="${MYNETWORKS}"
|
||||
|
||||
if [ "${FILTER_MIME}" == "true" ]
|
||||
then
|
||||
postconf mime_header_checks=regexp:/etc/postfix/mime_header_checks
|
||||
fi
|
||||
|
||||
if [ "${RELAYHOST}" != "false" ]
|
||||
then
|
||||
postconf relayhost=${RELAYHOST}
|
||||
fi
|
||||
|
||||
dockerize \
|
||||
-template /etc/postfix/mysql-email2email.cf.templ:/etc/postfix/mysql-email2email.cf \
|
||||
-template /etc/postfix/mysql-virtual-alias-maps.cf.templ:/etc/postfix/mysql-virtual-alias-maps.cf \
|
||||
-template /etc/postfix/mysql-virtual-mailbox-domains.cf.templ:/etc/postfix/mysql-virtual-mailbox-domains.cf \
|
||||
-template /etc/postfix/mysql-virtual-mailbox-maps.cf.templ:/etc/postfix/mysql-virtual-mailbox-maps.cf \
|
||||
-template /etc/postfix/mysql-recipient-access.cf.templ:/etc/postfix/mysql-recipient-access.cf \
|
||||
-wait tcp://${MYSQL_HOST}:3306 \
|
||||
-wait tcp://${MDA_HOST}:2003 \
|
||||
-wait tcp://${RSPAMD_HOST}:11332 \
|
||||
-wait file://${SSL_CERT} \
|
||||
-wait file://${SSL_KEY} \
|
||||
-timeout ${WAITSTART_TIMEOUT} \
|
||||
/usr/bin/supervisord
|
55
docker/mail/rootfs/etc/dovecot/dovecot.conf
Normal file
55
docker/mail/rootfs/etc/dovecot/dovecot.conf
Normal file
@ -0,0 +1,55 @@
|
||||
protocols = imap pop3 lmtp
|
||||
|
||||
ssl = yes
|
||||
ssl_cert = </etc/ssl/mailcerts/mailserver.crt
|
||||
ssl_key = </etc/ssl/mailcerts/mailserver.key
|
||||
ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL
|
||||
|
||||
listen = *, ::
|
||||
dict {
|
||||
#quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
|
||||
#expire = sqlite:/etc/dovecot/dovecot-dict-sql.conf.ext
|
||||
}
|
||||
|
||||
disable_plaintext_auth = yes
|
||||
auth_mechanisms = plain login
|
||||
mail_access_groups = vmail
|
||||
default_login_user = vmail
|
||||
first_valid_uid = 5000
|
||||
first_valid_gid = 5000
|
||||
mail_location = maildir:/var/mail/%d/%n
|
||||
|
||||
passdb {
|
||||
driver = passwd-file
|
||||
args = scheme=SHA1 /etc/mail/passwd
|
||||
}
|
||||
userdb {
|
||||
driver = static
|
||||
args = uid=5000 gid=5000 home=/var/mail/%d/%n allow_all_users=yes
|
||||
}
|
||||
|
||||
service auth {
|
||||
unix_listener auth-client {
|
||||
group = postfix
|
||||
mode = 0660
|
||||
user = postfix
|
||||
}
|
||||
user = root
|
||||
}
|
||||
|
||||
service imap-login {
|
||||
process_min_avail = 1
|
||||
user = vmail
|
||||
}
|
||||
|
||||
protocol lmtp {
|
||||
postmaster_address =
|
||||
mail_plugins = $mail_plugins sieve
|
||||
}
|
||||
|
||||
protocol imap {
|
||||
mail_max_userip_connections = 30
|
||||
}
|
||||
|
||||
!include_try conf.d/*.conf
|
||||
!include_try local.conf
|
7
docker/mail/rootfs/etc/opendkim/TrustedHosts
Normal file
7
docker/mail/rootfs/etc/opendkim/TrustedHosts
Normal file
@ -0,0 +1,7 @@
|
||||
127.0.0.1
|
||||
localhost
|
||||
192.168.1.0/24
|
||||
#HOSTNAME
|
||||
|
||||
#host.example.com
|
||||
#192.168.1.0/24
|
16
docker/mail/rootfs/etc/opendkim/opendkim.conf
Normal file
16
docker/mail/rootfs/etc/opendkim/opendkim.conf
Normal file
@ -0,0 +1,16 @@
|
||||
PidFile /var/run/opendkim/opendkim.pid
|
||||
Mode s
|
||||
Syslog yes
|
||||
SyslogSuccess yes
|
||||
LogWhy yes
|
||||
UserID opendkim:opendkim
|
||||
Socket inet:8891@127.0.0.1
|
||||
Umask 002
|
||||
SoftwareHeader yes
|
||||
Canonicalization relaxed/simple
|
||||
Domain file:/etc/mail/domains
|
||||
Selector default
|
||||
MinimumKeyBits 1024
|
||||
KeyFile /etc/opendkim/keys/default.private
|
||||
InternalHosts refile:/etc/opendkim/TrustedHosts
|
||||
OversignHeaders From
|
77
docker/mail/rootfs/etc/postfix/main.cf
Normal file
77
docker/mail/rootfs/etc/postfix/main.cf
Normal file
@ -0,0 +1,77 @@
|
||||
smtpd_banner = $myhostname ESMTP
|
||||
biff = no
|
||||
append_dot_mydomain = no
|
||||
compatibility_level=2
|
||||
queue_directory = /var/spool/postfix
|
||||
command_directory = /usr/sbin
|
||||
data_directory = /var/lib/postfix
|
||||
mail_owner = postfix
|
||||
myhostname = %MAIL_HOSTNAME%
|
||||
mydomain = %MAIL_HOSTNAME_FQDN%
|
||||
myorigin = $myhostname
|
||||
inet_interfaces = all
|
||||
inet_protocols = all
|
||||
mydestination = $myhostname, localhost.$mydomain, localhost
|
||||
unknown_local_recipient_reject_code = 550
|
||||
mynetworks = 127.0.0.0/8, [::1]/128
|
||||
|
||||
mailbox_command = /usr/libexec/dovecot/deliver
|
||||
|
||||
debug_peer_level = 2
|
||||
debugger_command =
|
||||
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
|
||||
ddd $daemon_directory/$process_name $process_id & sleep 5
|
||||
sendmail_path = /usr/sbin/sendmail.postfix
|
||||
newaliases_path = /usr/bin/newaliases.postfix
|
||||
mailq_path = /usr/bin/mailq.postfix
|
||||
setgid_group = postdrop
|
||||
html_directory = no
|
||||
manpage_directory = /usr/share/man
|
||||
sample_directory = /usr/share/doc/postfix-2.10.1/samples
|
||||
readme_directory = /usr/share/doc/postfix-2.10.1/README_FILES
|
||||
|
||||
smtp_tls_security_level = may
|
||||
smtp_tls_loglevel = 1
|
||||
smtp_tls_protocols = !SSLv2
|
||||
smtp_tls_exclude_ciphers = EXPORT, LOW
|
||||
|
||||
### VIRTUAL MAIL CONFIG PARAMS ###
|
||||
relay_domains = *
|
||||
virtual_alias_maps = hash:/etc/mail/aliases
|
||||
virtual_mailbox_domains = hash:/etc/mail/domains
|
||||
virtual_mailbox_maps = hash:/etc/mail/mailboxes
|
||||
|
||||
virtual_mailbox_base = /var/mail
|
||||
virtual_minimum_uid = 5000
|
||||
virtual_transport = dovecot
|
||||
virtual_uid_maps = static:5000
|
||||
virtual_gid_maps = static:5000
|
||||
|
||||
dovecot_destination_recipient_limit = 1
|
||||
|
||||
milter_protocol = 2
|
||||
milter_default_action = accept
|
||||
smtpd_milters = inet:localhost:8891
|
||||
non_smtpd_milters = "inet:localhost:8891"
|
||||
|
||||
smtpd_sasl_auth_enable = yes
|
||||
smtpd_sasl_type = dovecot
|
||||
smtpd_sasl_path = /var/run/dovecot/auth-client
|
||||
smtpd_sasl_security_options = noanonymous
|
||||
smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
|
||||
smtpd_sasl_local_domain = $mydomain
|
||||
broken_sasl_auth_clients = yes
|
||||
|
||||
smtpd_tls_security_level = may
|
||||
smtpd_tls_key_file = /etc/ssl/mailserver.key
|
||||
smtpd_tls_cert_file = /etc/ssl/mailserver.crt
|
||||
smtpd_tls_loglevel = 1
|
||||
smtpd_tls_session_cache_timeout = 3600s
|
||||
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_tls_cache
|
||||
smtpd_tls_protocols = $smtp_tls_protocols
|
||||
tls_random_source = dev:/dev/urandom
|
||||
tls_random_exchange_name = /var/lib/postfix/prng_exch
|
||||
smtpd_tls_auth_only = yes
|
||||
|
||||
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
|
||||
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
|
41
docker/mail/rootfs/etc/postfix/master.cf
Normal file
41
docker/mail/rootfs/etc/postfix/master.cf
Normal file
@ -0,0 +1,41 @@
|
||||
smtp inet n - - - - smtpd
|
||||
8080 inet n - - - - smtpd
|
||||
smtps inet n - - - - smtpd
|
||||
submission inet n - n - - smtpd
|
||||
pickup fifo n - - 60 1 pickup
|
||||
cleanup unix n - - - 0 cleanup
|
||||
qmgr fifo n - n 300 1 qmgr
|
||||
tlsmgr unix - - - 1000? 1 tlsmgr
|
||||
rewrite unix - - - - - trivial-rewrite
|
||||
bounce unix - - - - 0 bounce
|
||||
defer unix - - - - 0 bounce
|
||||
trace unix - - - - 0 bounce
|
||||
verify unix - - - - 1 verify
|
||||
flush unix n - - 1000? 0 flush
|
||||
postlog unix-dgram n - n - 1 postlogd
|
||||
proxymap unix - - n - - proxymap
|
||||
proxywrite unix - - n - 1 proxymap
|
||||
smtp unix - - - - - smtp
|
||||
relay unix - - - - - smtp
|
||||
showq unix n - - - - showq
|
||||
error unix - - - - - error
|
||||
retry unix - - - - - error
|
||||
discard unix - - - - - discard
|
||||
local unix - n n - - local
|
||||
virtual unix - n n - - virtual
|
||||
lmtp unix - - - - - lmtp
|
||||
anvil unix - - - - 1 anvil
|
||||
scache unix - - - - 1 scache
|
||||
uucp unix - n n - - pipe
|
||||
flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
|
||||
ifmail unix - n n - - pipe
|
||||
flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
|
||||
bsmtp unix - n n - - pipe
|
||||
flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
|
||||
scalemail-backend unix - n n - 2 pipe
|
||||
flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
|
||||
mailman unix - n n - - pipe
|
||||
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
|
||||
${nexthop} ${user}
|
||||
dovecot unix - n n - - pipe
|
||||
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}
|
44
docker/mail/rootfs/etc/rsyslogd/rsyslogd.conf
Normal file
44
docker/mail/rootfs/etc/rsyslogd/rsyslogd.conf
Normal file
@ -0,0 +1,44 @@
|
||||
#### MODULES ####
|
||||
|
||||
# The imjournal module bellow is now used as a message source instead of imuxsock.
|
||||
$ModLoad imuxsock # provides support for local system logging (e.g. via logger command)
|
||||
|
||||
#### GLOBAL DIRECTIVES ####
|
||||
|
||||
# Where to place auxiliary files
|
||||
#$WorkDirectory /var/lib/rsyslog
|
||||
|
||||
# Use default timestamp format
|
||||
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
|
||||
|
||||
# Include all config files in /etc/rsyslog.d/
|
||||
$IncludeConfig /etc/rsyslog.d/*.conf
|
||||
|
||||
# Turn off message reception via local log socket;
|
||||
# local messages are retrieved through imjournal now.
|
||||
$OmitLocalLogging off
|
||||
|
||||
#### RULES ####
|
||||
|
||||
# Log anything (except mail) of level info or higher.
|
||||
# Don't log private authentication messages!
|
||||
*.info;mail.none;authpriv.none;cron.none /var/log/messages
|
||||
|
||||
# The authpriv file has restricted access.
|
||||
authpriv.* /var/log/secure
|
||||
|
||||
# Log all the mail messages in one place.
|
||||
mail.* -/var/log/maillog
|
||||
|
||||
|
||||
# Log cron stuff
|
||||
cron.* /var/log/cron
|
||||
|
||||
# Everybody gets emergency messages
|
||||
*.emerg :omusrmsg:*
|
||||
|
||||
# Save news errors of level crit and higher in a special file.
|
||||
uucp,news.crit /var/log/spooler
|
||||
|
||||
# Save boot messages also to boot.log
|
||||
local7.* /var/log/boot.log
|
46
docker/mail/rootfs/etc/supervisord/supervisord.conf
Normal file
46
docker/mail/rootfs/etc/supervisord/supervisord.conf
Normal file
@ -0,0 +1,46 @@
|
||||
[unix_http_server]
|
||||
file=/tmp/supervisor.sock
|
||||
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
user=root
|
||||
loglevel=warn
|
||||
|
||||
[supervisorctl]
|
||||
serverurl=unix:///tmp/supervisor.sock
|
||||
user=root
|
||||
|
||||
[rpcinterface:supervisor]
|
||||
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||
|
||||
[program:opendkim]
|
||||
autostart=false
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
redirect_stderr=true
|
||||
command=opendkim -x /etc/opendkim/opendkim.conf
|
||||
|
||||
[program:postfix]
|
||||
autostart=false
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
redirect_stderr=true
|
||||
command=postfix -c /etc/postfix/postfix.conf
|
||||
|
||||
[program:dovecot]
|
||||
autostart=false
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
redirect_stderr=true
|
||||
command=dovecot -c /etc/dovecot/dovecot.conf
|
||||
|
||||
[program:rsyslog]
|
||||
autostart=false
|
||||
autorestart=true
|
||||
stdout_logfile=/dev/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
redirect_stderr=true
|
||||
command=rsyslog -f /etc/rsyslog/rsyslog.conf
|
21
docker/mail/rootfs/usr/bin/new-alias.sh
Normal file
21
docker/mail/rootfs/usr/bin/new-alias.sh
Normal file
@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
USAGE="Usage: $0 ALIAS TARGET";
|
||||
|
||||
if [ -z "$2" ]
|
||||
then
|
||||
echo "$USAGE";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
DOMAINPART=$(echo $1 | sed -e "s/^.*\@//")
|
||||
|
||||
if ! grep "^$DOMAINPART\s" /etc/mail/domains &> /dev/null; then
|
||||
echo "This server is not responsible for the domain of this alias."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "$1\t\t$2" >> /etc/mail/aliases
|
||||
postmap /etc/mail/aliases
|
||||
postfix reload
|
||||
|
||||
echo "Alias added."
|
16
docker/mail/rootfs/usr/bin/new-domain.sh
Normal file
16
docker/mail/rootfs/usr/bin/new-domain.sh
Normal file
@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
USAGE="Usage: $0 DOMAIN";
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "$USAGE";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
echo -e "$1" >> /etc/mail/domains
|
||||
postmap /etc/mail/domains
|
||||
mkdir "/var/mail/$1"
|
||||
chown vmail:vmail "/var/mail/$1"
|
||||
postfix reload
|
||||
|
||||
echo "Domain added."
|
30
docker/mail/rootfs/usr/bin/new-user.sh
Normal file
30
docker/mail/rootfs/usr/bin/new-user.sh
Normal file
@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
USAGE="Usage: $0 EMAIL PASSWORD";
|
||||
|
||||
if [ -z "$2" ]
|
||||
then
|
||||
echo "$USAGE";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
DOMAINPART=$(echo $1 | sed -e "s/^.*\@//")
|
||||
USERPART=$(echo $1 | sed -e "s/\@.*$//")
|
||||
|
||||
if ! grep -q "^$DOMAINPART" /etc/mail/domains
|
||||
then
|
||||
echo "This server is not responsible for the domain of this user."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PASSHASH=$(doveadm pw -s SHA512-CRYPT)
|
||||
|
||||
new-alias.sh $1 $1
|
||||
echo "$1 $DOMAINPART/$USERPART/" >> /etc/mail/mailboxes
|
||||
postmap /etc/mail/mailboxes
|
||||
echo "$1:$PASSHASH" >> /etc/mail/passwd
|
||||
mkdir "/var/mail/$DOMAINPART/$USERPART"
|
||||
chown vmail:vmail "/var/mail/$DOMAINPART/$USERPART"
|
||||
postfix reload
|
||||
dovecot reload
|
||||
|
||||
echo "User added"
|
35
docker/mail/rootfs/usr/bin/start.sh
Normal file
35
docker/mail/rootfs/usr/bin/start.sh
Normal file
@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
|
||||
postconf -e myhostname="$MAILNAME"
|
||||
postconf -e mydomain="$DOMAINNAME"
|
||||
postconf -e smtpd_tls_cert_file="$SSL_CERT"
|
||||
postconf -e smtpd_tls_key_file="$SSL_KEY"
|
||||
|
||||
touch /etc/mail/aliases /etc/mail/domains /etc/mail/mailbox /etc/mail/passwd
|
||||
if [ ! -d "/var/mail/$DOMAINNAME" ]
|
||||
then
|
||||
echo "$DOMAINNAME #OK" >> /etc/mail/domains
|
||||
mkdir "/var/mail/$DOMAINNAME"
|
||||
chown vmail:vmail "/var/mail/$DOMAINNAME"
|
||||
fi
|
||||
postmap /etc/mail/aliases && postmap /etc/mail/domains && postmap /etc/mail/mailbox
|
||||
|
||||
sed -i -e "s#^\s*ssl_cert\s*=.*#ssl_cert = $SSL_CERT#" /etc/dovecot/dovecot.conf
|
||||
sed -i -e "s#^\s*ssl_key\s*=.*#ssl_key = $SSL_KEY#" /etc/dovecot/dovecot.conf
|
||||
sed -i -e "s#^\s*hostname\s*=.*#hostname = $MAILNAME#" /etc/dovecot/dovecot.conf
|
||||
sed -i -e "s#^\s*postmaster_address\s*=.*#postmaster_address = $POSTMASTER#" /etc/dovecot/dovecot.conf
|
||||
|
||||
sed -i -e "s/#HOSTNAME/$MAILNAME/" /etc/opendkim/TrustedHosts
|
||||
|
||||
if [ ! -e "/etc/opendkim/keys/default.private" ]
|
||||
then
|
||||
opendkim-genkey -d "$DOMAINNAME" -D "/etc/opendkim/keys"
|
||||
fi
|
||||
|
||||
# Start services
|
||||
|
||||
rsyslogd -f /etc/rsyslogd/rsyslogd.conf
|
||||
/usr/sbin/opendkim #-x /etc/opendkim/opendkim.conf
|
||||
dovecot -c /etc/dovecot/dovecot.conf
|
||||
postfix start -c /etc/postfix
|
||||
supervisord -c /etc/supervisord/supervisord.conf
|
@ -1,20 +0,0 @@
|
||||
ARG ALPINE_VER=3.9
|
||||
|
||||
FROM alpine:${ALPINE_VER}
|
||||
|
||||
LABEL maintainer="jeff@ressourcenkonflikt.de"
|
||||
LABEL vendor="https://github.com/jeboehm/docker-mailserver"
|
||||
|
||||
ENV SSL_CERT=/media/tls/mailserver.crt \
|
||||
SSL_KEY=/media/tls/mailserver.key \
|
||||
SSL_CSR=/media/tls/mailserver.csr \
|
||||
SSL_SUBJ_COUNTRY=DE \
|
||||
SSL_SUBJ_STATE=Northrhine-Westfalia \
|
||||
SSL_SUBJ_LOCALITY=Duesseldorf \
|
||||
SSL_SUBJ_ORGANIZATION=Mail \
|
||||
SSL_SUBJ_ORGANIZATIONAL_UNIT=Mail
|
||||
|
||||
RUN apk --no-cache add openssl
|
||||
COPY create_tls.sh /usr/local/bin
|
||||
|
||||
CMD ["/usr/local/bin/create_tls.sh"]
|
@ -1,17 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if [ -r ${SSL_CERT} ]
|
||||
then
|
||||
echo "SSL certificate found. Exiting..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "No SSL certificate found. Creating a new one..."
|
||||
|
||||
openssl req -nodes -newkey rsa:2048 -keyout ${SSL_KEY} -out ${SSL_CSR} -subj "/C=${SSL_SUBJ_COUNTRY}/ST=${SSL_SUBJ_STATE}/L=${SSL_SUBJ_LOCALITY}/O=${SSL_SUBJ_ORGANIZATION}/OU=${SSL_SUBJ_ORGANIZATIONAL_UNIT}/CN=${MAILNAME}"
|
||||
openssl x509 -req -days 3000 -in ${SSL_CSR} -signkey ${SSL_KEY} -out ${SSL_CERT}
|
||||
|
||||
echo "SSL certificate was successfully created! Exiting..."
|
||||
|
||||
exit 0
|
@ -1,46 +0,0 @@
|
||||
ARG DOCKERIZE_VER=0.6.0
|
||||
ARG ALPINE_VER=3.9
|
||||
|
||||
FROM jwilder/dockerize:${DOCKERIZE_VER} AS dockerize
|
||||
FROM alpine:${ALPINE_VER}
|
||||
|
||||
LABEL maintainer="jeff@ressourcenkonflikt.de"
|
||||
LABEL vendor="https://github.com/jeboehm/docker-mailserver"
|
||||
|
||||
ENV MYSQL_HOST=db \
|
||||
MYSQL_USER=root \
|
||||
MYSQL_PASSWORD=changeme \
|
||||
MYSQL_DATABASE=mailserver \
|
||||
WAITSTART_TIMEOUT=1m
|
||||
|
||||
# Iconv fix: https://github.com/docker-library/php/issues/240#issuecomment-305038173
|
||||
RUN apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/community/ gnu-libiconv
|
||||
ENV LD_PRELOAD=/usr/lib/preloadable_libiconv.so
|
||||
|
||||
RUN apk --no-cache add \
|
||||
bash \
|
||||
bats \
|
||||
curl \
|
||||
docker \
|
||||
jq \
|
||||
mariadb-client \
|
||||
openssl \
|
||||
perl \
|
||||
perl-net-ssleay \
|
||||
php7 \
|
||||
php7-imap \
|
||||
php7-phar \
|
||||
php7-iconv \
|
||||
php7-openssl \
|
||||
&& wget -q -O /usr/local/bin/swaks https://www.jetmore.org/john/code/swaks/files/swaks-20130209.0/swaks \
|
||||
&& chmod +x /usr/local/bin/swaks \
|
||||
&& wget -q -O /usr/local/bin/imap-tester https://github.com/jeboehm/imap-tester/releases/download/v0.2.1/imap-tester.phar \
|
||||
&& chmod +x /usr/local/bin/imap-tester \
|
||||
&& mkdir -p /usr/share/fixtures \
|
||||
&& wget -q -O /usr/share/fixtures/gtube.txt https://spamassassin.apache.org/gtube/gtube.txt \
|
||||
&& wget -q -O /usr/share/fixtures/eicar.com https://secure.eicar.org/eicar.com
|
||||
|
||||
COPY --from=dockerize /usr/local/bin/dockerize /usr/local/bin
|
||||
COPY rootfs/ /
|
||||
|
||||
CMD ["/usr/local/bin/run-tests.sh"]
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
dockerize \
|
||||
-wait tcp://db:3306 \
|
||||
-wait tcp://mta:25 \
|
||||
-wait tcp://web:80 \
|
||||
-wait tcp://mda:143 \
|
||||
-wait tcp://filter:11334 \
|
||||
-timeout ${WAITSTART_TIMEOUT} \
|
||||
bats /usr/share/tests/*.bats
|
@ -1,30 +0,0 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "certificates were created" {
|
||||
[ -f /media/tls/mailserver.crt ]
|
||||
}
|
||||
|
||||
@test "connection to imaps" {
|
||||
true | openssl s_client -showcerts -connect mda:993
|
||||
[ "$?" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "connection to pop3s" {
|
||||
true | openssl s_client -showcerts -connect mda:995
|
||||
[ "$?" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "connection to pop3 with starttls" {
|
||||
true | openssl s_client -showcerts -connect mda:110 -starttls pop3
|
||||
[ "$?" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "connection to imap with starttls" {
|
||||
true | openssl s_client -showcerts -connect mda:143 -starttls imap
|
||||
[ "$?" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "connection to smtp with starttls" {
|
||||
true | openssl s_client -showcerts -connect mta:25 -starttls smtp
|
||||
[ "$?" -eq 0 ]
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "user table exists" {
|
||||
run mysql --batch -u "${MYSQL_USER}" --password="${MYSQL_PASSWORD}" -h "${MYSQL_HOST}" "${MYSQL_DATABASE}" -e "select * from mail_users;"
|
||||
[ "$status" = 0 ]
|
||||
}
|
||||
|
||||
@test "alias table exists" {
|
||||
run mysql --batch -u "${MYSQL_USER}" --password="${MYSQL_PASSWORD}" -h "${MYSQL_HOST}" "${MYSQL_DATABASE}" -e "select * from mail_aliases;"
|
||||
[ "$status" = 0 ]
|
||||
}
|
||||
|
||||
@test "domain table exists" {
|
||||
run mysql --batch -u "${MYSQL_USER}" --password="${MYSQL_PASSWORD}" -h "${MYSQL_HOST}" "${MYSQL_DATABASE}" -e "select * from mail_domains;"
|
||||
[ "$status" = 0 ]
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "send mail to local account address" {
|
||||
run swaks -s mta --to admin@example.com --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "send mail to local address with extension" {
|
||||
run swaks -s mta --to admin-test@example.com --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "authentification on smtp with disabled account should fail" {
|
||||
run swaks -s mta --to admin@example.com --from disabled@example.com -a -au disabled@example.com -ap test1234 -tls --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 28 ]
|
||||
}
|
||||
|
||||
@test "authentification on smtp with disabled and send only account should fail" {
|
||||
run swaks -s mta --to admin@example.com --from disabledsendonly@example.com -a -au disabled@example.com -ap test1234 -tls --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 28 ]
|
||||
}
|
||||
|
||||
@test "send mail to mda with smtp authentification (submission service)" {
|
||||
run swaks -s mda --port 587 --to admin@example.com --from admin@example.com -a -au admin@example.com -ap changeme -tls --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "send mail to mda with smtp authentification, with address extension (submission service)" {
|
||||
run swaks -s mda --port 587 --to admin@example.com --from admin-extension@example.com -a -au admin@example.com -ap changeme -tls --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "send mail to mda from sendonly account with smtp authentification (submission service)" {
|
||||
run swaks -s mda --port 587 --to admin@example.com --from sendonly@example.com -a -au sendonly@example.com -ap test1234 -tls --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "send mail to local alias" {
|
||||
run swaks -s mta --to foo@example.com --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "send junk mail to local address" {
|
||||
run swaks -s mta --to admin@example.com --body "$BATS_TEST_DESCRIPTION" --header "X-Spam: Yes"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "send mail with too big attachment to quota user" {
|
||||
dd if=/dev/urandom of=/tmp/bigfile bs=1M count=5
|
||||
run swaks -s mta --to quota@example.com --body "$BATS_TEST_DESCRIPTION" --attach /tmp/bigfile
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "send mail to disabled user" {
|
||||
run swaks -s mta --to disabled@example.com --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "maildir was created" {
|
||||
sleep 10 # MTA + MDA need some time. :)
|
||||
[ -d /var/vmail/example.com/admin/Maildir/new/ ]
|
||||
}
|
||||
|
||||
@test "mail to local account address is stored" {
|
||||
run grep -r "send mail to local account address" /var/vmail/example.com/admin/Maildir/
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "mail to local alias is stored" {
|
||||
run grep -r "send mail to local alias" /var/vmail/example.com/admin/Maildir/
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "mail to local address with extension is stored" {
|
||||
run grep -r "send mail to local address with extension" /var/vmail/example.com/admin/Maildir/
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "mail to mda with smtp authentification (submission service) is stored" {
|
||||
run grep -r "send mail to mda with smtp authentification (submission service)" /var/vmail/example.com/admin/Maildir/
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "send mail to mda with smtp authentification, with address extension (submission service) is stored" {
|
||||
run grep -r "send mail to mda with smtp authentification, with address extension (submission service)" /var/vmail/example.com/admin/Maildir/
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "send mail to mda from sendonly account with smtp authentification (submission service) is stored" {
|
||||
run grep -r "send mail to mda from sendonly account with smtp authentification (submission service)" /var/vmail/example.com/admin/Maildir/
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "junk mail is assorted to the junk folder" {
|
||||
run grep -r "send junk mail to local address" /var/vmail/example.com/admin/Maildir/.Junk/
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "mail with too big attachment is not found" {
|
||||
run grep -r "send mail with too big attachment to quota user" /var/vmail/example.com/quota/Maildir/
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "mail to disabled user is stored anyway" {
|
||||
run grep -r "send mail to disabled user" /var/vmail/example.com/disabled/Maildir/
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "send gtube mail is rejected" {
|
||||
run swaks -s mta --to admin@example.com --data /usr/share/fixtures/gtube.txt
|
||||
[ "$status" -eq 26 ]
|
||||
}
|
||||
|
||||
@test "mail to send only mailbox is rejected" {
|
||||
run swaks -s mta --to sendonly@example.com --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 24 ]
|
||||
}
|
||||
|
||||
@test "mail to disabled and send only mailbox is rejected anyway" {
|
||||
run swaks -s mta --to disabledsendonly@example.com --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 24 ]
|
||||
}
|
||||
|
||||
@test "virus is rejected" {
|
||||
if [ ${FILTER_VIRUS} = "false" ]; then
|
||||
skip
|
||||
fi
|
||||
|
||||
run swaks -s mta --to admin@example.com --attach - < /usr/share/fixtures/eicar.com
|
||||
[ "$status" -eq 26 ]
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "http connection to manager web interface" {
|
||||
curl -L http://web/manager/ | grep "Email address"
|
||||
[ "$?" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "http connection to webmail interface" {
|
||||
curl http://web/webmail/ | grep "jeboehm"
|
||||
[ "$?" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "http connection to rspamd interface" {
|
||||
curl http://web/rspamd/ | grep "Rspamd Web Interface"
|
||||
[ "$?" -eq 0 ]
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "send mail to mda from disabled account with smtp authentification (submission service)" {
|
||||
run swaks -s mda --port 587 --to admin@example.com --from disabled@example.com -a -au disabled@example.com -ap test1234 -tls --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 28 ]
|
||||
}
|
||||
|
||||
@test "send mail to mda without authentification (submission service)" {
|
||||
run swaks -s mda --port 587 --to admin@example.com --from disabled@example.com -tls --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 23 ]
|
||||
}
|
||||
|
||||
@test "send mail to mda without tls (submission service)" {
|
||||
run swaks -s mda --port 587 --to admin@example.com --from admin@example.com -a -au admin@example.com -ap changeme --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 28 ]
|
||||
}
|
||||
|
||||
@test "count mails in inbox via imap" {
|
||||
run imap-tester test:count mda 143 admin@example.com changeme INBOX
|
||||
[ "$output" -gt 3 ]
|
||||
}
|
||||
|
||||
@test "count mails in inbox via imaps" {
|
||||
run imap-tester test:count mda 993 admin@example.com changeme INBOX
|
||||
[ "$output" -gt 3 ]
|
||||
}
|
||||
|
||||
@test "count mails in inbox via pop3" {
|
||||
run imap-tester test:count mda 110 admin@example.com changeme INBOX
|
||||
[ "$output" -gt 3 ]
|
||||
}
|
||||
|
||||
@test "count mails in inbox via pop3s" {
|
||||
run imap-tester test:count mda 995 admin@example.com changeme INBOX
|
||||
[ "$output" -gt 3 ]
|
||||
}
|
||||
|
||||
@test "imap login to send only mailbox is not possible" {
|
||||
run imap-tester test:count mda 143 sendonly@example.com test1234 INBOX
|
||||
[ "$status" -eq 1 ]
|
||||
}
|
||||
|
||||
@test "pop3 login to send only mailbox is not possible" {
|
||||
run imap-tester test:count mda 110 sendonly@example.com test1234 INBOX
|
||||
[ "$status" -eq 1 ]
|
||||
}
|
||||
|
||||
@test "pop3 login to quota mailbox is possible" {
|
||||
run imap-tester test:count mda 110 quota@example.com test1234 INBOX
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "imap login to quota mailbox is possible" {
|
||||
run imap-tester test:count mda 143 quota@example.com test1234 INBOX
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "pop3 login to disabled mailbox is not possible" {
|
||||
run imap-tester test:count mda 110 disabled@example.com test1234 INBOX
|
||||
[ "$status" -eq 1 ]
|
||||
}
|
||||
|
||||
@test "imap login to disabled mailbox is not possible" {
|
||||
run imap-tester test:count mda 143 disabled@example.com test1234 INBOX
|
||||
[ "$status" -eq 1 ]
|
||||
}
|
||||
|
||||
@test "mails are owned by vmail" {
|
||||
run find /var/vmail/example.com/ -not -user 5000
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "" ]
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "no unhealthy containers exist" {
|
||||
run docker ps -q --filter health=unhealthy
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "" ]
|
||||
}
|
||||
|
||||
@test "Virus container is not running when filtering is disabled" {
|
||||
if [ ${FILTER_VIRUS} = "true" ]; then
|
||||
echo '# Filtering is disabled, skipping test' >&3
|
||||
skip
|
||||
fi
|
||||
|
||||
run docker ps -q --filter name=docker-mailserver_virus_1
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "" ]
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "check mailhog api for messages" {
|
||||
if [ ${RELAYHOST} = "false" ]; then
|
||||
echo '# Relayhost is disabled, skipping test' >&3
|
||||
skip
|
||||
fi
|
||||
|
||||
run curl "http://mailhog:8025/api/v2/messages"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "send mail to mda with smtp authentification, external recipient" {
|
||||
if [ ${RELAYHOST} = "false" ]; then
|
||||
echo '# Relayhost is disabled, skipping test' >&3
|
||||
skip
|
||||
fi
|
||||
|
||||
run swaks -s mda --port 587 --to nobody@ressourcenkonflikt.de --from admin@example.com -a -au admin@example.com -ap changeme -tls --body "$BATS_TEST_DESCRIPTION"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "check mailhog api for outgoing message" {
|
||||
if [ ${RELAYHOST} = "false" ]; then
|
||||
echo '# Relayhost is disabled, skipping test' >&3
|
||||
skip
|
||||
fi
|
||||
|
||||
sleep 5 # Give mailhog some time
|
||||
|
||||
RESULT=$(curl -s "http://mailhog:8025/api/v2/messages" | jq -cr .items[0].Content.Body | tr -d '[:space:]')
|
||||
|
||||
[ "$RESULT" = "sendmailtomdawithsmtpauthentification,externalrecipient" ]
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "check DKIM selector map exists" {
|
||||
[ -r /media/dkim/dkim_selectors.map ]
|
||||
}
|
||||
|
||||
@test "check DKIM key for example.com exists" {
|
||||
[ -r /media/dkim/example.com.1337.key ]
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
ARG ALPINE_VER=3.11
|
||||
|
||||
FROM alpine:${ALPINE_VER}
|
||||
|
||||
LABEL maintainer="jeff@ressourcenkonflikt.de"
|
||||
LABEL vendor="https://github.com/jeboehm/docker-mailserver"
|
||||
LABEL de.ressourcenkonflikt.docker-mailserver.autoheal="true"
|
||||
|
||||
ENV FILTER_VIRUS=true
|
||||
|
||||
RUN apk --no-cache add \
|
||||
clamav-daemon \
|
||||
clamav-libunrar && \
|
||||
rm -rf /var/log/clamav
|
||||
|
||||
COPY rootfs/ /
|
||||
|
||||
EXPOSE 3310
|
||||
USER clamav
|
||||
|
||||
RUN /usr/bin/freshclam -l /dev/null
|
||||
|
||||
VOLUME ["/var/lib/clamav"]
|
||||
|
||||
HEALTHCHECK CMD echo PING | nc 127.0.0.1 3310 | grep PONG
|
||||
CMD ["/usr/local/bin/entrypoint.sh"]
|
@ -1,35 +0,0 @@
|
||||
ARG ALPINE_VER=3.9
|
||||
|
||||
FROM alpine:${ALPINE_VER}
|
||||
|
||||
LABEL maintainer="jeff@ressourcenkonflikt.de"
|
||||
LABEL vendor="https://github.com/jeboehm/docker-mailserver"
|
||||
|
||||
# hadolint ignore=DL3003
|
||||
RUN apk --no-cache add \
|
||||
bash \
|
||||
bind-tools \
|
||||
clamav-scanner \
|
||||
gnupg \
|
||||
ncurses \
|
||||
rsync \
|
||||
wget && \
|
||||
wget -q -O /tmp/master.tar.gz https://github.com/extremeshok/clamav-unofficial-sigs/archive/master.tar.gz && \
|
||||
cd /tmp && \
|
||||
tar -xvf master.tar.gz && \
|
||||
cd clamav-unofficial-sigs-master && \
|
||||
cp clamav-unofficial-sigs.sh /usr/local/bin/ && \
|
||||
chmod +x /usr/local/bin/clamav-unofficial-sigs.sh && \
|
||||
cp -r config /etc/clamav-unofficial-sigs && \
|
||||
mkdir /var/lib/clamav-unofficial-sigs && \
|
||||
chown clamav /var/lib/clamav-unofficial-sigs && \
|
||||
cp /etc/clamav-unofficial-sigs/os/os.ubuntu.conf /etc/clamav-unofficial-sigs/os.conf && \
|
||||
echo "user_configuration_complete=\"yes\"" >> /etc/clamav-unofficial-sigs/user.conf && \
|
||||
echo "logging_enabled=\"no\"" >> /etc/clamav-unofficial-sigs/user.conf && \
|
||||
echo "enable_random=\"no\"" >> /etc/clamav-unofficial-sigs/user.conf && \
|
||||
echo "reload_dbs=\"no\"" >> /etc/clamav-unofficial-sigs/user.conf && \
|
||||
rm -rf /tmp/* /var/log/* /etc/clamav-unofficial-sigs/os/
|
||||
|
||||
USER clamav
|
||||
|
||||
CMD ["/usr/local/bin/clamav-unofficial-sigs.sh"]
|
@ -1,2 +0,0 @@
|
||||
TCPSocket 3310
|
||||
Foreground true
|
@ -1,4 +0,0 @@
|
||||
DatabaseOwner clamav
|
||||
DatabaseMirror database.clamav.net
|
||||
ScriptedUpdates yes
|
||||
NotifyClamd /etc/clamav/clamd.conf
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "${FILTER_VIRUS}" = "false" ]
|
||||
then
|
||||
echo "Virus filtering is disabled, exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
/usr/bin/freshclam -d -l /dev/stdout &
|
||||
/usr/sbin/clamd
|
@ -1,50 +0,0 @@
|
||||
ARG ROUNDCUBE_VER=1.4.x-fpm
|
||||
ARG PHP_VER=7.4
|
||||
ARG DOCKERIZE_VER=0.6.0
|
||||
|
||||
FROM jwilder/dockerize:${DOCKERIZE_VER} AS dockerize
|
||||
|
||||
FROM roundcube/roundcubemail:${ROUNDCUBE_VER} AS roundcube
|
||||
|
||||
FROM jeboehm/php-nginx-base:${PHP_VER}
|
||||
|
||||
ARG ADMIN_VER=1.6.1
|
||||
|
||||
LABEL maintainer="jeff@ressourcenkonflikt.de"
|
||||
LABEL vendor="https://github.com/jeboehm/docker-mailserver"
|
||||
LABEL de.ressourcenkonflikt.docker-mailserver.autoheal="true"
|
||||
|
||||
ENV MYSQL_HOST=db \
|
||||
MYSQL_DATABASE=mailserver \
|
||||
MYSQL_USER=mailserver \
|
||||
MYSQL_PASSWORD=changeme \
|
||||
MTA_HOST=mta \
|
||||
MDA_HOST=mda \
|
||||
FILTER_HOST=filter \
|
||||
SUPPORT_URL=https://github.com/jeboehm/docker-mailserver \
|
||||
APP_ENV=prod \
|
||||
TRUSTED_PROXIES=172.16.0.0/12 \
|
||||
WAITSTART_TIMEOUT=1m \
|
||||
ADMIN_VER=${ADMIN_VER}
|
||||
|
||||
COPY --from=roundcube /usr/src/roundcubemail/ /var/www/html/webmail/
|
||||
COPY --from=dockerize /usr/local/bin/dockerize /usr/local/bin
|
||||
COPY rootfs/ /
|
||||
|
||||
WORKDIR /opt/manager
|
||||
|
||||
RUN wget -O /tmp/admin.tar.gz -q https://github.com/jeboehm/mailserver-admin/archive/${ADMIN_VER}.tar.gz && \
|
||||
tar -xf /tmp/admin.tar.gz -C /opt/manager --strip=1 && \
|
||||
rm /tmp/admin.tar.gz && \
|
||||
composer install --no-dev -o
|
||||
|
||||
RUN ln -s /opt/manager/public /var/www/html/manager && \
|
||||
chown -R www-data \
|
||||
/opt/manager/var/cache/ \
|
||||
/opt/manager/var/log/ \
|
||||
/var/www/html/webmail/temp/ \
|
||||
/var/www/html/webmail/logs/
|
||||
|
||||
WORKDIR /var/www/html
|
||||
HEALTHCHECK CMD curl -s http://127.0.0.1/login | grep docker-mailserver
|
||||
CMD ["/usr/local/bin/entrypoint.sh"]
|
@ -1,6 +0,0 @@
|
||||
# mailserver-web
|
||||
|
||||
This image contains
|
||||
|
||||
[roundcube](https://roundcube.net)
|
||||
and [mailserver-admin](https://github.com/jeboehm/mailserver-admin).
|
@ -1,68 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
absolute_redirect off;
|
||||
|
||||
root /var/www/html/manager;
|
||||
|
||||
location = /favicon.ico {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location /manager {
|
||||
return 301 /;
|
||||
}
|
||||
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location ~ \.(tpl|yml|ini|log)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri /index.php$is_args$args;
|
||||
}
|
||||
|
||||
location /webmail {
|
||||
alias /var/www/html/webmail;
|
||||
index index.php;
|
||||
try_files $uri $uri/ @webmail;
|
||||
|
||||
location ~ \.php$ {
|
||||
include fastcgi_params;
|
||||
# Mitigate httpoxy vulnerability, see: https://httpoxy.org/
|
||||
fastcgi_param HTTP_PROXY "";
|
||||
|
||||
fastcgi_buffers 8 16k;
|
||||
fastcgi_buffer_size 32k;
|
||||
|
||||
client_max_body_size 24M;
|
||||
client_body_buffer_size 128k;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
fastcgi_pass php-fpm;
|
||||
}
|
||||
}
|
||||
|
||||
location @webmail {
|
||||
rewrite /webmail/(.*)$ /webmail/index.php?/$1 last;
|
||||
}
|
||||
|
||||
location ~ ^/index\.php(/|$) {
|
||||
fastcgi_pass php-fpm;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||
fastcgi_param DOCUMENT_ROOT $realpath_root;
|
||||
internal;
|
||||
}
|
||||
|
||||
location /rspamd/ {
|
||||
proxy_pass http://filter:11334/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
manager_init() {
|
||||
cd /opt/manager
|
||||
|
||||
bin/console doctrine:migrations:migrate -n
|
||||
bin/console doctrine:schema:update --force
|
||||
}
|
||||
|
||||
roundcube_init() {
|
||||
cd /var/www/html/webmail
|
||||
PWD=`pwd`
|
||||
|
||||
bin/initdb.sh --dir=$PWD/SQL || bin/updatedb.sh --dir=$PWD/SQL --package=roundcube || echo "Failed to initialize databse. Please run $PWD/bin/initdb.sh manually."
|
||||
}
|
||||
|
||||
permissions() {
|
||||
chown -R www-data /media/dkim
|
||||
chmod 777 /media/dkim
|
||||
}
|
||||
|
||||
dkim_refresh() {
|
||||
cd /opt/manager
|
||||
|
||||
bin/console dkim:refresh
|
||||
}
|
||||
|
||||
dockerize \
|
||||
-wait tcp://${MYSQL_HOST}:3306 \
|
||||
-wait tcp://${MDA_HOST}:143 \
|
||||
-wait tcp://${MTA_HOST}:25 \
|
||||
-wait tcp://${FILTER_HOST}:11334 \
|
||||
-wait file:///media/dkim/ \
|
||||
-timeout ${WAITSTART_TIMEOUT}
|
||||
|
||||
manager_init
|
||||
roundcube_init
|
||||
permissions
|
||||
dkim_refresh
|
||||
|
||||
/usr/bin/supervisord
|
@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
dockerize \
|
||||
-wait tcp://web:80 \
|
||||
-wait tcp://${MYSQL_HOST}:3306 \
|
||||
-timeout ${WAITSTART_TIMEOUT} \
|
||||
${@}
|
@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/local/bin/fixtures.sh \
|
||||
/opt/manager/bin/console init:setup
|
@ -1,39 +0,0 @@
|
||||
<?php
|
||||
$config = [];
|
||||
$config['smtp_log'] = false;
|
||||
$config['log_dir'] = '/tmp/';
|
||||
$config['temp_dir'] = '/tmp/';
|
||||
$config['imap_cache'] = 'apc';
|
||||
$config['db_dsnw'] = sprintf(
|
||||
'mysql://%s:%s@%s/%s',
|
||||
getenv('MYSQL_USER'),
|
||||
getenv('MYSQL_PASSWORD'),
|
||||
getenv('MYSQL_HOST'),
|
||||
getenv('MYSQL_DATABASE')
|
||||
);
|
||||
$config['default_host'] = 'tls://' . getenv('MDA_HOST');
|
||||
$config['smtp_server'] = 'tls://' . getenv('MDA_HOST');
|
||||
$config['smtp_port'] = 587;
|
||||
$config['smtp_user'] = '%u';
|
||||
$config['smtp_pass'] = '%p';
|
||||
$config['support_url'] = getenv('SUPPORT_URL');
|
||||
$config['plugins'] = [
|
||||
'archive',
|
||||
'zipdownload',
|
||||
'managesieve',
|
||||
'password',
|
||||
];
|
||||
$config['imap_conn_options'] = [
|
||||
'ssl' => [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
'allow_self_signed' => false,
|
||||
],
|
||||
];
|
||||
$config['smtp_conn_options'] = [
|
||||
'ssl' => [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
'allow_self_signed' => false,
|
||||
],
|
||||
];
|
@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
$config['managesieve_port'] = 4190;
|
||||
$config['managesieve_host'] = '%h';
|
||||
$config['managesieve_auth_type'] = 'PLAIN';
|
||||
$config['managesieve_auth_cid'] = null;
|
||||
$config['managesieve_auth_pw'] = null;
|
||||
$config['managesieve_usetls'] = true;
|
||||
$config['managesieve_conn_options'] = [
|
||||
'ssl' => [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
'allow_self_signed' => false,
|
||||
],
|
||||
];
|
||||
$config['managesieve_default'] = '/etc/dovecot/sieve/global';
|
||||
$config['managesieve_script_name'] = 'managesieve';
|
||||
$config['managesieve_mbox_encoding'] = 'UTF-8';
|
||||
$config['managesieve_replace_delimiter'] = '';
|
||||
$config['managesieve_disabled_extensions'] = [];
|
||||
$config['managesieve_debug'] = false;
|
||||
$config['managesieve_kolab_master'] = false;
|
||||
$config['managesieve_filename_extension'] = '.sieve';
|
||||
$config['managesieve_filename_exceptions'] = [];
|
||||
$config['managesieve_domains'] = [];
|
||||
$config['managesieve_vacation'] = 0;
|
||||
$config['managesieve_vacation_interval'] = 0;
|
||||
$config['managesieve_vacation_addresses_init'] = false;
|
||||
$config['managesieve_notify_methods'] = ['mailto'];
|
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
$config['password_driver'] = 'sql';
|
||||
$config['password_confirm_current'] = true;
|
||||
$config['password_minimum_length'] = 6;
|
||||
$config['password_require_nonalpha'] = false;
|
||||
$config['password_log'] = false;
|
||||
$config['password_login_exceptions'] = null;
|
||||
$config['password_hosts'] = null;
|
||||
$config['password_force_save'] = true;
|
||||
$config['password_force_new_user'] = false;
|
||||
$config['password_algorithm'] = 'clear';
|
||||
$config['password_algorithm_prefix'] = '';
|
||||
$config['password_blowfish_cost'] = 12;
|
||||
$config['password_disabled'] = false;
|
||||
$config['password_db_dsn'] = sprintf(
|
||||
'mysql://%s:%s@%s/%s',
|
||||
getenv('MYSQL_USER'),
|
||||
getenv('MYSQL_PASSWORD'),
|
||||
getenv('MYSQL_HOST'),
|
||||
getenv('MYSQL_DATABASE')
|
||||
);
|
||||
$config['password_query'] = "UPDATE mail_users JOIN mail_domains ON mail_users.domain_id = mail_domains.id SET password=CONCAT('{SHA256-CRYPT}', ENCRYPT (%p, CONCAT('$5$', SUBSTRING(SHA(RAND()), -16)))) WHERE CONCAT(mail_users.name, '@', mail_domains.name)=%u;";
|
||||
$config['password_crypt_hash'] = 'md5';
|
||||
$config['password_idn_ascii'] = false;
|
||||
$config['password_dovecotpw_with_method'] = false;
|
||||
$config['password_hash_algorithm'] = 'sha1';
|
||||
$config['password_hash_base64'] = false;
|
Loading…
Reference in New Issue
Block a user