summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2015-12-23 11:44:28 +0100
committerJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2015-12-23 11:44:28 +0100
commitdee5776f0b48f15be41ce6f72c2ad245b0a8d1f7 (patch)
tree2be51554a89c02c36a094ca7fd4e512b9a90f59d
parentfef3c832cdda978cf041c19527c9372f762d5783 (diff)
downloaddocker-dee5776f0b48f15be41ce6f72c2ad245b0a8d1f7.tar.gz
Check in what started as atomicapp development
-rw-r--r--.gitignore2
-rw-r--r--00-base/Dockerfile52
-rw-r--r--00-base/README.md7
-rwxr-xr-x00-base/entrypoint.sh7
-rw-r--r--00-base/functions.sh40
-rwxr-xr-x00-base/systemctl686
-rwxr-xr-x00-base/systemctl-socket-daemon67
-rw-r--r--01-base-asav/Dockerfile22
-rw-r--r--01-base-asav/README.md1
-rwxr-xr-x01-base-asav/entrypoint.sh48
-rw-r--r--01-base-imap/Dockerfile14
-rw-r--r--01-base-ldap/Dockerfile23
-rw-r--r--01-base-ldap/template.ldif142
-rw-r--r--01-base-mx/Dockerfile8
-rw-r--r--01-base-nodejs/Dockerfile47
-rw-r--r--01-base-web/Dockerfile16
-rw-r--r--02-base-web-rc/Dockerfile11
-rw-r--r--03-asav-in/Dockerfile3
-rw-r--r--03-asav-out/Dockerfile3
-rw-r--r--03-chwala/Dockerfile8
-rwxr-xr-x03-chwala/entrypoint.sh3
-rw-r--r--03-ext-mx-in/Dockerfile9
-rw-r--r--03-ext-mx-in/README.md2
-rwxr-xr-x03-ext-mx-in/entrypoint.sh47
-rw-r--r--03-ext-mx-out/Dockerfile9
-rw-r--r--03-ext-mx-out/README.md1
-rwxr-xr-x03-ext-mx-out/entrypoint.sh36
-rw-r--r--03-freebusy/Dockerfile8
-rwxr-xr-x03-freebusy/entrypoint.sh3
-rw-r--r--03-guam/Dockerfile16
-rw-r--r--03-guam/README.md10
-rwxr-xr-x03-guam/entrypoint.sh19
-rw-r--r--03-guam/sys.config84
-rw-r--r--03-http-prx/Dockerfile1
-rw-r--r--03-imap-mupdate/Dockerfile7
-rw-r--r--03-imap-mupdate/cyrus.conf.tpl16
-rwxr-xr-x03-imap-mupdate/entrypoint.sh44
-rw-r--r--03-imap-mupdate/imapd.conf.tpl57
-rw-r--r--03-imapb/Dockerfile7
-rwxr-xr-x03-imapb/entrypoint.sh6
-rw-r--r--03-imapf-ext/Dockerfile7
-rw-r--r--03-imapf-ext/cyrus.conf.tpl22
-rwxr-xr-x03-imapf-ext/entrypoint.sh44
-rw-r--r--03-imapf-ext/imapd.conf.tpl57
-rw-r--r--03-imapf-int/Dockerfile7
-rw-r--r--03-imapf-int/cyrus.conf.tpl22
-rwxr-xr-x03-imapf-int/entrypoint.sh44
-rw-r--r--03-imapf-int/imapd.conf.tpl57
-rw-r--r--03-int-mx/Dockerfile8
-rw-r--r--03-int-mx/README.md2
-rwxr-xr-x03-int-mx/entrypoint.sh41
-rw-r--r--03-irony/Dockerfile8
-rwxr-xr-x03-irony/entrypoint.sh3
-rw-r--r--03-jmap-proxy/Dockerfile102
-rw-r--r--03-jmap-proxy/Makefile5
-rw-r--r--03-jmap-proxy/bashrc13
-rw-r--r--03-jmap-proxy/entrypoint.sh8
-rw-r--r--03-jmap-proxy/nginx.conf140
-rw-r--r--03-ldap-master/Dockerfile16
-rwxr-xr-x03-ldap-master/entrypoint.sh74
-rw-r--r--03-ldap-slave/Dockerfile4
-rwxr-xr-x03-ldap-slave/entrypoint.sh5
-rw-r--r--03-manticore/Dockerfile49
-rw-r--r--03-manticore/entrypoint.sh19
-rw-r--r--03-roundcube-next/Dockerfile45
-rw-r--r--03-roundcube-next/entrypoint.sh11
-rw-r--r--03-roundcubemail/Dockerfile10
-rw-r--r--03-roundcubemail/entrypoint.sh53
-rw-r--r--03-submission/Dockerfile7
-rw-r--r--03-syncroton/Dockerfile8
-rwxr-xr-x03-syncroton/entrypoint.sh3
-rw-r--r--03-wallace/Dockerfile16
-rw-r--r--03-wallace/entrypoint.sh26
-rw-r--r--03-webadmin/Dockerfile11
-rw-r--r--03-webadmin/entrypoint.sh54
-rw-r--r--04-chwala-database/Dockerfile9
-rw-r--r--04-freebusy-database/Dockerfile9
-rw-r--r--04-irony-database/Dockerfile9
-rw-r--r--04-roundcubemail-database/Dockerfile9
-rw-r--r--04-syncroton-database/Dockerfile9
-rw-r--r--04-webadmin-database/Dockerfile9
-rw-r--r--05-asav-in-atomicapp/Dockerfile9
-rw-r--r--05-asav-in-atomicapp/Nulecule42
-rw-r--r--05-asav-in-atomicapp/artifacts/docker/run-pod7
-rw-r--r--05-asav-in-atomicapp/artifacts/kubernetes/pod.json30
-rw-r--r--05-asav-in-atomicapp/artifacts/kubernetes/service.json21
-rw-r--r--05-asav-out-atomicapp/Dockerfile9
-rw-r--r--05-asav-out-atomicapp/Nulecule42
-rw-r--r--05-asav-out-atomicapp/artifacts/docker/run-pod4
-rw-r--r--05-asav-out-atomicapp/artifacts/kubernetes/pod.json30
-rw-r--r--05-asav-out-atomicapp/artifacts/kubernetes/service.json21
-rw-r--r--05-chwala-atomicapp/Dockerfile9
-rw-r--r--05-chwala-atomicapp/Nulecule45
-rw-r--r--05-chwala-atomicapp/artifacts/docker/run-pod5
-rw-r--r--05-chwala-atomicapp/artifacts/kubernetes/pod.json48
-rw-r--r--05-chwala-atomicapp/artifacts/kubernetes/service.json28
-rw-r--r--05-ext-mx-in-atomicapp/Dockerfile9
-rw-r--r--05-ext-mx-in-atomicapp/Nulecule52
-rw-r--r--05-ext-mx-in-atomicapp/README.md2
-rw-r--r--05-ext-mx-in-atomicapp/artifacts/docker/run-pod7
-rw-r--r--05-ext-mx-in-atomicapp/artifacts/kubernetes/controller.json38
-rw-r--r--05-ext-mx-in-atomicapp/artifacts/kubernetes/pod.json37
-rw-r--r--05-ext-mx-in-atomicapp/artifacts/kubernetes/service.json23
-rw-r--r--05-ext-mx-out-atomicapp/Dockerfile9
-rw-r--r--05-ext-mx-out-atomicapp/Nulecule50
-rw-r--r--05-ext-mx-out-atomicapp/README.md1
-rw-r--r--05-ext-mx-out-atomicapp/artifacts/docker/run-pod4
-rw-r--r--05-ext-mx-out-atomicapp/artifacts/kubernetes/pod.json37
-rw-r--r--05-ext-mx-out-atomicapp/artifacts/kubernetes/service.json28
-rw-r--r--05-freebusy-atomicapp/Dockerfile9
-rw-r--r--05-freebusy-atomicapp/Nulecule65
-rw-r--r--05-freebusy-atomicapp/artifacts/docker/run-pod5
-rw-r--r--05-freebusy-atomicapp/artifacts/kubernetes/pod.json45
-rw-r--r--05-freebusy-atomicapp/artifacts/kubernetes/service.json28
-rwxr-xr-x05-freebusy-atomicapp/entrypoint.sh3
-rw-r--r--05-guam-atomicapp/Dockerfile9
-rw-r--r--05-guam-atomicapp/Nulecule38
-rw-r--r--05-guam-atomicapp/README.md10
-rw-r--r--05-guam-atomicapp/artifacts/docker/run-pod9
-rw-r--r--05-guam-atomicapp/artifacts/kubernetes/controller.json41
-rw-r--r--05-guam-atomicapp/artifacts/kubernetes/pod.json27
-rw-r--r--05-guam-atomicapp/artifacts/kubernetes/service.json28
-rwxr-xr-x05-guam-atomicapp/entrypoint.sh5
-rw-r--r--05-imap-mupdate-atomicapp/Dockerfile9
-rw-r--r--05-imap-mupdate-atomicapp/Nulecule50
-rw-r--r--05-imap-mupdate-atomicapp/artifacts/docker/run-pod1
-rw-r--r--05-imap-mupdate-atomicapp/artifacts/kubernetes/pod.json38
-rw-r--r--05-imap-mupdate-atomicapp/artifacts/kubernetes/service.json23
-rwxr-xr-x05-imap-mupdate-atomicapp/entrypoint.sh4
-rw-r--r--05-imapb-atomicapp/Dockerfile9
-rw-r--r--05-imapb-atomicapp/Nulecule47
-rw-r--r--05-imapb-atomicapp/artifacts/docker/run-pod9
-rw-r--r--05-imapb-atomicapp/artifacts/kubernetes/service.json43
-rw-r--r--05-imapb-atomicapp/artifacts/kubernetes/storage.json17
-rwxr-xr-x05-imapb-atomicapp/entrypoint.sh6
-rw-r--r--05-imapf-ext-atomicapp/Dockerfile9
-rw-r--r--05-imapf-ext-atomicapp/Nulecule50
-rw-r--r--05-imapf-ext-atomicapp/artifacts/docker/run-pod9
-rw-r--r--05-imapf-ext-atomicapp/artifacts/kubernetes/pod.json55
-rw-r--r--05-imapf-ext-atomicapp/artifacts/kubernetes/service.json43
-rwxr-xr-x05-imapf-ext-atomicapp/entrypoint.sh6
-rw-r--r--05-imapf-int-atomicapp/Dockerfile9
-rw-r--r--05-imapf-int-atomicapp/Nulecule50
-rw-r--r--05-imapf-int-atomicapp/artifacts/docker/run-pod9
-rw-r--r--05-imapf-int-atomicapp/artifacts/kubernetes/pod.json55
-rw-r--r--05-imapf-int-atomicapp/artifacts/kubernetes/service.json43
-rwxr-xr-x05-imapf-int-atomicapp/entrypoint.sh6
-rw-r--r--05-int-mx-atomicapp/Dockerfile9
-rw-r--r--05-int-mx-atomicapp/Nulecule54
-rw-r--r--05-int-mx-atomicapp/README.md2
-rw-r--r--05-int-mx-atomicapp/artifacts/docker/run-pod4
-rw-r--r--05-int-mx-atomicapp/artifacts/kubernetes/pod.json38
-rw-r--r--05-int-mx-atomicapp/artifacts/kubernetes/service.json28
-rwxr-xr-x05-int-mx-atomicapp/entrypoint.sh13
-rw-r--r--05-irony-atomicapp/Dockerfile9
-rw-r--r--05-irony-atomicapp/Nulecule45
-rw-r--r--05-irony-atomicapp/artifacts/docker/run-pod5
-rw-r--r--05-irony-atomicapp/artifacts/kubernetes/pod.json48
-rw-r--r--05-irony-atomicapp/artifacts/kubernetes/service.json28
-rw-r--r--05-jmap-proxy-atomicapp/Dockerfile9
-rw-r--r--05-jmap-proxy-atomicapp/Nulecule37
-rw-r--r--05-jmap-proxy-atomicapp/artifacts/docker/run-pod4
-rw-r--r--05-jmap-proxy-atomicapp/artifacts/kubernetes/pod.json23
-rw-r--r--05-jmap-proxy-atomicapp/artifacts/kubernetes/service.json23
-rw-r--r--05-ldap-master-atomicapp/Dockerfile9
-rw-r--r--05-ldap-master-atomicapp/Nulecule62
-rw-r--r--05-ldap-master-atomicapp/artifacts/docker/run-pod8
-rw-r--r--05-ldap-master-atomicapp/artifacts/kubernetes/pod.json49
-rw-r--r--05-ldap-master-atomicapp/artifacts/kubernetes/service.json28
-rwxr-xr-x05-ldap-master-atomicapp/entrypoint.sh8
-rw-r--r--05-ldap-slave-atomicapp/Dockerfile9
-rw-r--r--05-ldap-slave-atomicapp/Nulecule47
-rw-r--r--05-ldap-slave-atomicapp/artifacts/docker/run-pod9
-rw-r--r--05-ldap-slave-atomicapp/artifacts/kubernetes/service.json33
-rwxr-xr-x05-ldap-slave-atomicapp/entrypoint.sh5
-rw-r--r--05-manticore-atomicapp/Dockerfile9
-rw-r--r--05-manticore-atomicapp/Nulecule67
-rw-r--r--05-manticore-atomicapp/artifacts/docker/run-pod11
-rw-r--r--05-manticore-atomicapp/artifacts/kubernetes/pod.json50
-rw-r--r--05-manticore-atomicapp/artifacts/kubernetes/service.json24
-rw-r--r--05-roundcube-next-atomicapp/Dockerfile9
-rw-r--r--05-roundcube-next-atomicapp/Nulecule41
-rw-r--r--05-roundcube-next-atomicapp/artifacts/docker/run-pod5
-rw-r--r--05-roundcube-next-atomicapp/artifacts/kubernetes/pod.json48
-rw-r--r--05-roundcube-next-atomicapp/artifacts/kubernetes/service.json28
-rw-r--r--05-roundcubemail-atomicapp/Dockerfile9
-rw-r--r--05-roundcubemail-atomicapp/Nulecule64
-rw-r--r--05-roundcubemail-atomicapp/artifacts/docker/run-pod10
-rw-r--r--05-roundcubemail-atomicapp/artifacts/kubernetes/pod.json48
-rw-r--r--05-roundcubemail-atomicapp/artifacts/kubernetes/service.json28
-rw-r--r--05-submission-atomicapp/Dockerfile9
-rw-r--r--05-submission-atomicapp/Nulecule42
-rw-r--r--05-submission-atomicapp/artifacts/docker/run-pod4
-rw-r--r--05-submission-atomicapp/artifacts/kubernetes/controller.json37
-rw-r--r--05-submission-atomicapp/artifacts/kubernetes/service.json23
-rw-r--r--05-syncroton-atomicapp/Dockerfile9
-rw-r--r--05-syncroton-atomicapp/Nulecule59
-rw-r--r--05-syncroton-atomicapp/artifacts/docker/run-pod5
-rw-r--r--05-syncroton-atomicapp/artifacts/kubernetes/pod.json48
-rw-r--r--05-syncroton-atomicapp/artifacts/kubernetes/service.json28
-rw-r--r--05-wallace-atomicapp/Dockerfile9
-rw-r--r--05-wallace-atomicapp/Nulecule52
-rw-r--r--05-wallace-atomicapp/artifacts/docker/run-pod5
-rw-r--r--05-wallace-atomicapp/artifacts/kubernetes/pod.json38
-rw-r--r--05-wallace-atomicapp/artifacts/kubernetes/service.json23
-rw-r--r--05-webadmin-atomicapp/Dockerfile9
-rw-r--r--05-webadmin-atomicapp/Nulecule71
-rw-r--r--05-webadmin-atomicapp/artifacts/docker/run-pod5
-rw-r--r--05-webadmin-atomicapp/artifacts/kubernetes/pod.json53
-rw-r--r--05-webadmin-atomicapp/artifacts/kubernetes/service.json28
-rw-r--r--Makefile102
-rw-r--r--README.md30
-rw-r--r--atomicapp/Dockerfile9
-rw-r--r--atomicapp/Nulecule79
-rw-r--r--atomicapp/artifacts/kubernetes/pod.json33
-rw-r--r--atomicapp/artifacts/kubernetes/service.json31
-rw-r--r--docs/Makefile177
-rw-r--r--docs/conf.py261
-rw-r--r--docs/images/base-asav.rst12
-rw-r--r--docs/index.rst707
220 files changed, 7311 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6ba965a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+docs/_build/
+tmp/
diff --git a/00-base/Dockerfile b/00-base/Dockerfile
new file mode 100644
index 0000000..f3dd463
--- /dev/null
+++ b/00-base/Dockerfile
@@ -0,0 +1,52 @@
+FROM centos:centos7
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+# This should really be a part of the base image.
+RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
+
+# To speed things up, disable fastestmirror.
+RUN sed -r -i \
+ -e 's/^enabled.*$/enabled = 0/g' \
+ /etc/yum/pluginconf.d/fastestmirror.conf
+
+# Add EPEL.
+RUN yum -y install epel-release && \
+ yum clean all
+
+# Add the EPEL key.
+RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
+
+# Add the Kolab:Development repository.
+ADD http://obs.kolabsys.com/repositories/Kolab:/Development/CentOS_7/Kolab:Development.repo \
+ /etc/yum.repos.d/Kolab:Development.repo
+
+# Give the Kolab:Development repository priority over everything else.
+RUN echo "priority=60" >> /etc/yum.repos.d/Kolab:Development.repo
+
+# Add the Kolab:Development key.
+RUN rpm --import https://ssl.kolabsys.com/community.asc
+
+# Make YUM obey priorities configured.
+RUN yum -y install yum-plugin-priorities && \
+ yum clean all
+
+# Install some debugging utilities.
+RUN yum -y install \
+ bind-utils \
+ cyrus-imapd \
+ lsof \
+ net-tools \
+ nmap-ncat \
+ openldap-clients \
+ psmisc \
+ strace \
+ telnet \
+ traceroute \
+ vim-enhanced && \
+ yum clean all
+
+ADD /functions.sh /functions.sh
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+ENTRYPOINT [ "/entrypoint.sh" ]
diff --git a/00-base/README.md b/00-base/README.md
new file mode 100644
index 0000000..7039264
--- /dev/null
+++ b/00-base/README.md
@@ -0,0 +1,7 @@
+# Kolab Groupware Base Image
+
+Take `projectatomic/atomicapp`, then add the Kolab repositories, and
+for the time being, also ensure some debugging utilities and other such
+are installed (**lsof**, **strace**, **net-tools**, etc.).
+
+The resulting image forms the base for other images.
diff --git a/00-base/entrypoint.sh b/00-base/entrypoint.sh
new file mode 100755
index 0000000..9582f97
--- /dev/null
+++ b/00-base/entrypoint.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+if [ $# -lt 1 ]; then
+ exec top
+else
+ exec "$@"
+fi
diff --git a/00-base/functions.sh b/00-base/functions.sh
new file mode 100644
index 0000000..8523da7
--- /dev/null
+++ b/00-base/functions.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+exec 3>&1
+
+function check_var() {
+ if [ -z "$(eval "echo \$$1")" ]; then
+ echo "$1 not defined."
+ return 1
+ fi
+
+ return 0
+}
+
+function check_vars() {
+ retval=0
+
+ while [ $# -gt 0 ]; do
+ retval=$(( $(check_var $1 >&3; echo $?) + ${retval} ))
+ shift
+ done
+
+ return ${retval}
+}
+
+function domain_to_root_dn() {
+ echo "dc=$(echo $1 | sed -e 's/\./,dc=/g')"
+}
+
+function persist() {
+ while [ $# -gt 0 ]; do
+ if [ ! -d "/data$(dirname $1)" ]; then
+ mkdir -p "/data$(dirname $1)"
+ fi
+
+ echo -n "mv: "; mv -v $1 "/data$(dirname $1)"
+ echo -n "ln: "; ln -svf "/data$1" "$(dirname $1)/$(basename $1)"
+
+ shift
+ done
+}
diff --git a/00-base/systemctl b/00-base/systemctl
new file mode 100755
index 0000000..94c96b9
--- /dev/null
+++ b/00-base/systemctl
@@ -0,0 +1,686 @@
+#!/usr/bin/perl
+
+# Copyright 2014 Jan Pazdziora
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings FATAL => 'all';
+
+use IO::File ();
+use IO::Dir ();
+use IO::Socket::UNIX ();
+use Socket ();
+use Data::Dumper ();
+use POSIX ();
+use Time::HiRes qw(sleep time);
+
+sub log_command {
+ local * LOG;
+ open(LOG, '>>', '/var/log/systemctl.log');
+ print LOG @_;
+ close LOG;
+}
+log_command("[@ARGV]\n");
+shift if @ARGV and $ARGV[0] eq '-q';
+
+for (my $i = 0; $i < @ARGV; $i++) {
+ if ($ARGV[$i] eq '--ignore-dependencies') {
+ splice @ARGV, $i, 1;
+ last;
+ }
+}
+if (@ARGV == 1 and $ARGV[0] eq 'daemon-reload') {
+ exit 0;
+}
+if (@ARGV == 1 and $ARGV[0] eq 'preset') {
+ exit 0;
+}
+if (@ARGV == 1 and $ARGV[0] eq 'try-restart') {
+ exit 0;
+}
+if (@ARGV == 2 and $ARGV[0] eq '--system' and $ARGV[1] eq 'daemon-reload') {
+ exit 0;
+}
+
+for (keys %ENV) {
+ delete $ENV{$_} unless $_ eq '_SYSTEMCTL_LITE_STARTING';
+}
+
+my $RUNNING_DIR = '/run/systemctl-lite-running';
+if (not -d $RUNNING_DIR) {
+ mkdir $RUNNING_DIR;
+}
+my $ENABLED_DIR = '/etc/systemctl-lite-enabled';
+if (@ARGV == 1) {
+ if ($ARGV[0] eq 'start-enabled' and -d $ENABLED_DIR) {
+ local * ENABLED;
+ opendir ENABLED, $ENABLED_DIR;
+ my %services;
+ while (defined(my $f = readdir ENABLED)) {
+ next if $f eq '.' or $f eq '..';
+ my $modified = (stat "$ENABLED_DIR/$f")[9];
+ if (defined $modified) {
+ $services{$f} = $modified;
+ }
+ }
+ close ENABLED;
+ for my $s (sort { $services{$a} <=> $services{$b} or $a cmp $b } keys %services) {
+ print "Starting [$s]\n";
+ system $0, 'start', $s;
+ exit ($? >> 8) if ($? >> 8);
+ }
+ }
+ if ($ARGV[0] eq 'stop-running' and -d $RUNNING_DIR) {
+ local * RUNNING;
+ opendir RUNNING, $RUNNING_DIR;
+ my %services;
+ while (defined(my $f = readdir RUNNING)) {
+ next if $f eq '.' or $f eq '..';
+ my $modified = (stat "$RUNNING_DIR/$f")[9];
+ if (defined $modified) {
+ my $trimmed = $f;
+ $trimmed =~ s/\..+$//;
+ $services{$trimmed} = $modified;
+ }
+ }
+ close RUNNING;
+ for my $s (sort { $services{$b} <=> $services{$a} or $a cmp $b } keys %services) {
+ system $0, 'stop', $s;
+ }
+ }
+ exit;
+}
+
+if (@ARGV != 2) {
+ die "Usage: $0 (start|stop|status|...) (service|target|socket thing)\n";
+}
+
+my ($COMMAND, $SERVICE) = @ARGV;
+my $TYPE = 'service';
+if ($SERVICE =~ /\.(target|socket)$/) {
+ $TYPE = $1;
+} elsif (not $SERVICE =~ /\.service$/) {
+ $SERVICE .= '.service';
+}
+
+my @PATHS = (
+ '/etc/systemd/system',
+ '/run/systemd/system',
+ '/usr/lib/systemd/system',
+);
+
+my $FULL_SERVICE = $SERVICE;
+my $INSTANCE = undef;
+
+my $file = undef;
+if ($SERVICE =~ s/\@(.+)\.service$/\@.service/) {
+ $INSTANCE = $1;
+}
+for my $p (@PATHS) {
+ if (-e "$p/$SERVICE") {
+ if (-l "$p/$SERVICE") {
+ my $new_service = readlink("$p/$SERVICE");
+ log_command("Service [$p/$SERVICE] is a symlink to [$new_service]\n");
+ $new_service =~ s!^.*/!!;
+ $SERVICE = $new_service;
+ }
+ $file = "$p/$SERVICE";
+ last;
+ }
+}
+
+if ($SERVICE =~ s/\@(.+)\.service$/\@.service/) {
+ $INSTANCE = $1;
+ for my $p (@PATHS) {
+ if (-f "$p/$SERVICE") {
+ $file = "$p/$SERVICE";
+ last;
+ }
+ }
+}
+
+if (not defined $file) {
+ if ($COMMAND eq 'is-enabled') {
+ exit 1;
+ }
+ if ($COMMAND eq 'is-active') {
+ exit 3;
+ }
+ warn "No service definition found for [$FULL_SERVICE].\n";
+ exit 2;
+}
+
+sub parse_file {
+ my ($file, $data) = @_;
+ if (-d $file) {
+ my $op;
+ if ($file =~ /\.requires$/) {
+ $op = 'Unit.Requires';
+ } elsif ($file =~ /\.wants$/) {
+ $op = 'Unit.Wants';
+ } else {
+ die "Unknown directory [$file].\n";
+ }
+ my $dh = new IO::Dir($file);
+ while (defined(my $de = $dh->read)) {
+ next if $de eq '.' or $de eq '..';
+ push @{$data->{$op}}, $de unless $de =~ /\.target$/;
+ }
+ $dh->close;
+ return;
+ }
+ my $fh = new IO::File($file);
+ my $section = 'undefined';
+ while (my $line = <$fh>) {
+ chomp $line;
+ if ($line =~ /^\[(.+)\]\s*$/) {
+ $section = $1;
+ next;
+ }
+ next if $line =~ /^\s*(#|$)/;
+ if ($line =~ /^\.include\s(.+)/) {
+ parse_file($1, $data);
+ next;
+ }
+ my ($key, $value) = split /=/, $line, 2;
+ if (defined $INSTANCE) {
+ $value =~ s/\%i/$INSTANCE/g;
+ }
+ if ($key eq 'EnvironmentFile') {
+ if ($value eq '') {
+ delete $data->{"$section.$key"};
+ } else {
+ push @{ $data->{"$section.$key"} }, $value;
+ }
+ } elsif ($key =~ /^(Wants|Requires)$/) {
+ push @{ $data->{"$section.$key"} }, $value unless $value =~ /\.target$/;
+ } elsif ($key =~ /^(ExecStart(Pre|Post)|ExecReload|ExecStop(Pre|Post)?)$/) {
+ push @{ $data->{"$section.$key"} }, $value;
+ } else {
+ $data->{"$section.$key"} = $value;
+ }
+ }
+ $fh->close;
+ if (defined $data->{'Service.ExecStart'} and not defined $data->{'Service.PIDFile'}) {
+ my ($pidfile) = grep /^\/.+\.pid$/, split /\s+/, $data->{'Service.ExecStart'};
+ if (defined $pidfile) {
+ $data->{'Service.PIDFile'} = $pidfile;
+ log_command("Guessing pid file [$data->{'Service.PIDFile'}] from ExecStart [$data->{'Service.ExecStart'}]\n");
+ }
+ }
+}
+
+my $data = {};
+parse_file($file, $data);
+for my $p (@PATHS) {
+ if (-d "$p/$SERVICE.wants") {
+ $file = "$p/$SERVICE.wants";
+ parse_file("$p/$SERVICE.wants", $data);
+ last;
+ }
+}
+
+if ($COMMAND eq 'show') {
+ print Data::Dumper::Dumper $data;
+ exit;
+}
+
+sub pidof {
+ my $command = shift;
+ my $pids = `/usr/sbin/pidof $command`;
+ chomp $pids;
+ if ($pids ne '') {
+ return split /\s+/, $pids;
+ }
+ return;
+}
+
+sub get_exec_start {
+ my $data = shift;
+ my $d = $data->{'Service.ExecStart'};
+ if (not defined $d) {
+ warn "No ExecStart value found for [$SERVICE].\n";
+ exit 3;
+ }
+ return split /\s+/, $d;
+}
+
+sub get_pid {
+ my $file = shift;
+ if (not $file =~ m!^/!) {
+ $file = "$RUNNING_DIR/$file";
+ }
+ if (-f $file) {
+ local * PIDFILE;
+ open PIDFILE, '<', $file;
+ my $pid = <PIDFILE>;
+ close PIDFILE;
+ if (defined $pid) {
+ chomp $pid;
+ return $pid;
+ }
+ }
+}
+
+sub is_running {
+ my $data = shift;
+ my $ret;
+ if (-f "$RUNNING_DIR/$FULL_SERVICE.oneshot") {
+ return 1;
+ } elsif (defined $data->{'Service.PIDFile'}) {
+ my $pid = get_pid($data->{'Service.PIDFile'});
+ if (defined $pid) {
+ $ret = kill 0, $pid;
+ }
+ } else {
+ my $path = get_pid("$FULL_SERVICE.name");
+ if (defined $path) {
+ if (pidof($path)) {
+ $ret = 1;
+ }
+ } else {
+ my $pid = get_pid("$FULL_SERVICE.pid");
+ if (defined $pid) {
+ $ret = kill 0, $pid;
+ }
+ }
+ }
+ return $ret;
+}
+if ($COMMAND eq 'is-active' or $COMMAND eq 'status') {
+ if (is_running($data)) {
+ print "active\n";
+ exit;
+ }
+ print "inactive\n";
+ exit 3;
+}
+
+sub exec_stop_pre {
+ my ($data) = @_;
+ if (defined $data->{'Socket.ExecStopPre'}) {
+ for my $x (@{ $data->{'Socket.ExecStopPre'} }) {
+ log_command("Running stop pre [$x]\n");
+ system $x;
+ }
+ }
+}
+sub exec_stop_post {
+ my ($data) = @_;
+ if (defined $data->{'Service.ExecStopPost'}) {
+ for my $x (@{ $data->{'Service.ExecStopPost'} }) {
+ log_command("Running stop post [$x]\n");
+ system $x;
+ }
+ }
+}
+
+if ($TYPE eq 'target' and not defined $data->{'Unit.Wants'} and not defined $data->{'Unit.Requires'}) {
+ warn "No Unit.Wants/.wants/Unit.Requires/.requires list for target [$SERVICE]\n";
+ exit 8;
+}
+
+if ($COMMAND eq 'restart') {
+ if ($TYPE ne 'service' or is_running($data)) {
+ system $0, 'stop', $FULL_SERVICE;
+ }
+ system $0, 'start', $FULL_SERVICE;
+ exit;
+}
+
+sub pids_went_away_timeout {
+ my $timeout = shift;
+ my $start = time;
+ while (kill 0, @_) {
+ if (time - $start > $timeout) {
+ log_command(sprintf(" ** pid(s) [%s] not killed within %d s\n", join(', ', @_), $timeout));
+ return 0;
+ }
+ sleep 0.1;
+ }
+ log_command(sprintf(" ** pid(s) [%s] got killed after %.2f s\n", join(', ', @_), time - $start));
+ return 1;
+}
+
+sub stop_pids {
+ my @pids = @_;
+ kill 15, @pids;
+ if (not pids_went_away_timeout(5, @pids)) {
+ kill 9, @pids;
+ if (not pids_went_away_timeout(5, @pids)) {
+ log_command("Failed to kill [@pids] even with 9\n");
+ warn "Failed to kill [@pids].\n";
+ return 1;
+ }
+ log_command("Killed [@pids] with 9\n");
+ } else {
+ log_command("Killed [@pids] with 15\n");
+ }
+ return 0;
+}
+
+if ($COMMAND eq 'stop') {
+ my $mainpid;
+ if (defined $data->{'Service.PIDFile'}) {
+ $mainpid = get_pid($data->{'Service.PIDFile'});
+ } else {
+ $mainpid = get_pid("$FULL_SERVICE.pid");
+ }
+ if (defined $data->{'Service.ExecStop'}) {
+ for my $x (@{ $data->{'Service.ExecStop'} }) {
+ my $runit = 1;
+ if (defined $mainpid) {
+ $x =~ s!\$MAINPID\b|\$\{MAINPID\}!$mainpid!g;
+ } elsif ($x =~ /\$MAINPID\b|\$\{MAINPID\}/) {
+ $runit = 0;
+ log_command("Service [$FULL_SERVICE] would like to stop via ExecStop [$x] but we have no pid file, skipping.\n");
+ }
+ if ($runit) {
+ log_command("Running stop [$x]\n");
+ system $x;
+ sleep 1;
+ }
+ }
+ }
+ my $ret = undef;
+ if ($TYPE eq 'target') {
+ # noop
+ } elsif (defined $data->{'Service.Type'} and $data->{'Service.Type'} eq 'oneshot') {
+ # noop
+ } elsif ($TYPE eq 'socket') {
+ my $pids = `/usr/sbin/fuser $data->{'Socket.ListenStream'} 2> /dev/null`;
+ if (defined $pids) {
+ chomp $pids;
+ $pids =~ s/^\s+//;
+ my @pids = split /\s+/, $pids;
+ if (@pids) {
+ exec_stop_pre($data);
+ log_command("Will kill [@pids] as fuser [$data->{'Socket.ListenStream'}] of [$FULL_SERVICE]\n");
+ $ret = stop_pids(@pids);
+ }
+ }
+ } elsif (defined $data->{'Service.PIDFile'}) {
+ my $pid = get_pid($data->{'Service.PIDFile'});
+ if (defined $pid) {
+ log_command("Will kill [$pid] found in Service.PIDFile of [$FULL_SERVICE]\n");
+ $ret = stop_pids($pid);
+ }
+ } else {
+ my $path = get_pid("$FULL_SERVICE.name");
+ if (defined $path) {
+ if (my @pids = pidof($path)) {
+ log_command("Will kill [@pids] as pidof [$path] found in [$FULL_SERVICE.name]\n");
+ $ret = stop_pids(@pids);
+ } else {
+ warn "No pidof for [$path] found in [$FULL_SERVICE.name].\n";
+ }
+ } else {
+ my $pid = get_pid("$FULL_SERVICE.pid");
+ if (defined $pid) {
+ log_command("Will kill [$pid] found in [$FULL_SERVICE.pid]\n");
+ $ret = stop_pids($pid);
+ } else {
+ warn "No pid and no name for [$FULL_SERVICE].\n";
+ }
+ }
+ }
+ exec_stop_post($data);
+ unlink "$RUNNING_DIR/$FULL_SERVICE.pid", "$RUNNING_DIR/$FULL_SERVICE.name", "$RUNNING_DIR/$FULL_SERVICE.oneshot";
+ if (defined $data->{'Unit.Wants'}) {
+ for my $x (@{ $data->{'Unit.Wants'} }) {
+ system $0, 'stop', $x;
+ }
+ }
+ if (defined $data->{'Unit.Requires'}) {
+ for my $x (@{ $data->{'Unit.Requires'} }) {
+ system $0, 'stop', $x;
+ }
+ }
+ exit ( defined $ret ? $ret : 0 );
+}
+
+sub add_runuser {
+ my ($data, $cmd) = @_;
+ if (defined $data->{'Service.User'}) {
+ unshift @$cmd, '-u', $data->{'Service.User'}, '--';
+ if (defined $data->{'Service.Group'}) {
+ unshift @$cmd, '-g', $data->{'Service.Group'};
+ }
+ unshift @$cmd, '/usr/sbin/runuser';
+ }
+}
+
+if ($COMMAND eq 'start') {
+ my (@starting_stack, %starting_stack);
+ if (defined $ENV{_SYSTEMCTL_LITE_STARTING}) {
+ @starting_stack = split /:/, $ENV{_SYSTEMCTL_LITE_STARTING};
+ @starting_stack{@starting_stack} = ();
+ $ENV{_SYSTEMCTL_LITE_STARTING} .= ":$FULL_SERVICE";
+ } else {
+ $ENV{_SYSTEMCTL_LITE_STARTING} = $FULL_SERVICE;
+ }
+
+ if ($TYPE eq 'service' and is_running($data)) {
+ log_command("Service [$FULL_SERVICE] already found running, not starting again.\n");
+ exit;
+ }
+ if (defined $data->{'Service.PIDFile'}) {
+ log_command("Service [$FULL_SERVICE] defines PIDFile [$data->{'Service.PIDFile'}], unlinking it before start\n");
+ unlink $data->{'Service.PIDFile'};
+ }
+ if (defined $data->{'Unit.Wants'}) {
+ for my $x (@{ $data->{'Unit.Wants'} }) {
+ if (exists $starting_stack{$x}) {
+ log_command("Skipping start of [$x], we are already in the process of starting it.\n");
+ next;
+ }
+ my @cmd = ($0, 'start', $x);
+ log_command("Running [@cmd] for Unit.Wants of [$FULL_SERVICE]\n");
+ system @cmd;
+ }
+ }
+ if (defined $data->{'Unit.Requires'}) {
+ for my $x (@{ $data->{'Unit.Requires'} }) {
+ if (exists $starting_stack{$x}) {
+ log_command("Skipping start of [$x], we are already in the process of starting it.\n");
+ next;
+ }
+ my @cmd = ($0, 'start', $x);
+ log_command("Running [@cmd] for Unit.Requires of [$FULL_SERVICE]\n");
+ if (system @cmd) {
+ log_command("Failed to start [$x], aborting start\n");
+ exit 1;
+ }
+ }
+ }
+ if (defined $data->{'Service.PIDFile'} and is_running($data)) {
+ log_command("Service [$FULL_SERVICE] defines PIDFile [$data->{'Service.PIDFile'}] and it seems to have already started, not starting again.\n");
+ exit;
+ }
+
+ if ($TYPE eq 'target') {
+ exit;
+ }
+ if ($TYPE eq 'socket' and -S $data->{'Socket.ListenStream'}) {
+ my $out = `/usr/sbin/fuser $data->{'Socket.ListenStream'} 2> /dev/null`;
+ if (defined $out and $out ne '') {
+ log_command("Service [$FULL_SERVICE] already found active on socket [$data->{'Socket.ListenStream'}], not starting again.\n");
+ exit;
+ }
+ }
+ if (defined $data->{'Service.Type'} and $data->{'Service.Type'} eq 'dbus') {
+ my @cmd = ($0, 'start', 'dbus.socket');
+ log_command("Running [@cmd] for Service.Type dbus\n");
+ system @cmd;
+ }
+ if (defined $data->{'Service.ExecStartPre'}) {
+ for my $x (@{ $data->{'Service.ExecStartPre'} }) {
+ my $can_fail = 0;
+ if ($x =~ s/^-//) {
+ $can_fail = 1;
+ }
+ my @cmd = split /\s+/, $x;
+ if (not $data->{'Service.PermissionsStartOnly'} or $data->{'Service.PermissionsStartOnly'} =~ /^(false|0)$/i) {
+ add_runuser($data, \@cmd);
+ }
+ no warnings 'uninitialized';
+ log_command("Running start pre [@cmd]\n");
+ if (system @cmd and not $can_fail) {
+ exit 1;
+ }
+ }
+ }
+ my @paths;
+ if ($TYPE eq 'socket') {
+ my $service = $SERVICE;
+ if (defined $data->{'Socket.Accept'} and $data->{'Socket.Accept'} eq 'true') {
+ $service =~ s/\.socket$/\@.service/;
+ @paths = ( '/bin/systemctl-socket-daemon', $data->{'Socket.ListenStream'}, $data->{'Socket.SocketMode'} // '0666', $service );
+ } else {
+ $service =~ s/\.socket$/\.service/;
+ my $ret = system "$0 is-active $service > /dev/null";
+ if (($ret >> 8) == 0) {
+ log_command("Service [$service] is already running for [$SERVICE]\n");
+ exit;
+ }
+ @paths = ( $0, 'start', $service );
+ }
+ } else {
+ @paths = get_exec_start($data);
+ }
+ my $first_path = $paths[0];
+
+ my $ENV = '';
+ if (exists $data->{'Service.EnvironmentFile'}) {
+ for my $e (@{ $data->{'Service.EnvironmentFile'} }) {
+ my $error_fail = 1;
+ if ($e =~ s/^-//) {
+ $error_fail = 0;
+ }
+ my $fh = new IO::File($e);
+ if (not defined $fh) {
+ if ($error_fail) {
+ warn "Error reading EnvironmentFile [$e]: $!\n";
+ exit 5;
+ }
+ } else {
+ while (my $line = <$fh>) {
+ chomp $line;
+ next if $line =~ /^\s*(#|$)/;
+ $ENV .= "export $line; ";
+ }
+ $fh->close();
+ }
+ }
+ }
+ if (defined $data->{'Service.Environment'}) {
+ my $x = $data->{'Service.Environment'};
+ $x =~ s/^"(.*)"$/$1/;
+ $ENV .= "export $x; ";
+ }
+ add_runuser($data, \@paths);
+ log_command("Running [$ENV@paths]\n");
+ if (defined $data->{'Service.Type'} and $data->{'Service.Type'} eq 'oneshot') {
+ system "$ENV@paths";
+ if (defined $data->{'Service.RemainAfterExit'} and $data->{'Service.RemainAfterExit'} eq 'yes') {
+ local * PIDFILE;
+ open PIDFILE, '>', "$RUNNING_DIR/$FULL_SERVICE.oneshot";
+ close PIDFILE;
+ }
+ exit;
+ }
+ my $pid = fork();
+ die "Failed to fork for [@_]\n" if not defined $pid;
+ if ($pid == 0) {
+ open(STDOUT, '>>', '/var/log/systemctl.log');
+ open(STDERR, '>>', '/var/log/systemctl.log');
+ open(STDIN, '<', '/dev/null');
+ POSIX::setsid();
+ exec "$ENV@paths";
+ }
+ if (defined $data->{'Service.PIDFile'}) {
+ log_command("Service [$FULL_SERVICE] defines PIDFile [$data->{'Service.PIDFile'}], not marking pid\n");
+ unlink "$RUNNING_DIR/$FULL_SERVICE.pid";
+ my $i = 0;
+ while (not -f $data->{'Service.PIDFile'}) {
+ sleep 0.2;
+ $i++;
+ if ($i > 250) {
+ log_command("Starting [$FULL_SERVICE] did not create PIDFile [$data->{'Service.PIDFile'}]\n");
+ exit 10;
+ }
+ }
+ my $pid = get_pid($data->{'Service.PIDFile'});
+ if (not defined $pid or not kill 0, $pid) {
+ log_command("Starting [$FULL_SERVICE] created PIDFile [$data->{'Service.PIDFile'}] but the process is not running\n");
+ exit 11;
+ }
+ } else {
+ local * PIDFILE;
+ open PIDFILE, '>', "$RUNNING_DIR/$FULL_SERVICE.pid";
+ print PIDFILE "$pid\n";
+ close PIDFILE;
+ log_command("Marked pid [$pid] for [$FULL_SERVICE]\n");
+ sleep 1;
+ if (defined $data->{'Service.Type'} and $data->{'Service.Type'} ne 'simple' and $data->{'Service.Type'} ne 'notify' and pidof($first_path)) {
+ local * PIDFILE;
+ open PIDFILE, '>', "$RUNNING_DIR/$FULL_SERVICE.name";
+ print PIDFILE "$first_path\n";
+ close PIDFILE;
+ log_command("Marked process name [$first_path] for [$FULL_SERVICE]\n");
+ }
+ }
+ if (defined $data->{'Service.Type'}
+ and $data->{'Service.Type'} eq 'dbus'
+ and defined $data->{'Service.BusName'}) {
+ my $busname = $data->{'Service.BusName'};
+ my $objectpath = $busname;
+ $objectpath =~ s!^|\.!/!g;
+ for (0 .. 10) {
+ system "/usr/bin/dbus-send --system --type=method_call --print-reply --dest=$busname $objectpath org.freedesktop.DBus.Introspectable.Introspect > /dev/null";
+ exit if ($? >> 8) == 0;
+ sleep 1;
+ }
+ exit 9;
+ }
+ exit;
+}
+
+if ($COMMAND eq 'is-enabled') {
+ if (-e "$ENABLED_DIR/$FULL_SERVICE") {
+ print "enabled\n";
+ exit 0;
+ }
+ print "disabled\n";
+ exit 1;
+}
+
+if ($COMMAND eq 'enable') {
+ if (not -d $ENABLED_DIR) {
+ mkdir $ENABLED_DIR;
+ }
+ local * FILE;
+ open FILE, '>', "$ENABLED_DIR/$FULL_SERVICE";
+ exit;
+}
+
+if ($COMMAND eq 'disable') {
+ unlink "$ENABLED_DIR/$FULL_SERVICE";
+ exit;
+}
+
+die "Unknown command [$COMMAND].\n";
+
+1;
+
diff --git a/00-base/systemctl-socket-daemon b/00-base/systemctl-socket-daemon
new file mode 100755
index 0000000..5250cad
--- /dev/null
+++ b/00-base/systemctl-socket-daemon
@@ -0,0 +1,67 @@
+#!/usr/bin/perl
+
+# Copyright 2014 Jan Pazdziora
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings FATAL => 'all';
+
+use IO::Socket::UNIX ();
+use Socket ();
+use POSIX ();
+
+sub daemonize {
+ open(STDERR, '>>', '/var/log/systemctl-socket-daemon.log') || die "can't write log: $!";
+ open(STDOUT, '>&STDERR') || die "can't write stdout to log: $!";
+ chdir("/") || die "can't chdir to /: $!";
+ open(STDIN, '<', '/dev/null') || die "can't read /dev/null: $!";
+ defined(my $pid = fork()) || die "can't fork: $!";
+ exit if $pid; # non-zero now means I am the parent
+ (POSIX::setsid() != -1) || die "Can't start a new session: $!";
+}
+
+my ($socket_path, $socket_mode, $service) = @ARGV;
+if (not defined $socket_path or not defined $service) {
+ die "Usage: $0 /path/to/unix/socket service-to-run\n";
+}
+if (-e $socket_path) {
+ warn "Path [$socket_path] already exists, removing\n";
+ unlink $socket_path;
+}
+
+my $service_data = `/bin/systemctl show $service 2>&1`;
+if ($?) {
+ die "Failed to find service [$service]:\n$service_data";
+}
+
+my $socket = new IO::Socket::UNIX(
+ Type => Socket::SOCK_STREAM,
+ Local => $socket_path,
+ Listen => Socket::SOMAXCONN
+) or die "socket: $!\n";
+chmod oct($socket_mode), $socket_path;
+
+daemonize();
+
+while (1) {
+ next unless my $connection = $socket->accept;
+ my $pid = fork();
+ if ($pid == 0) {
+ *STDIN = $connection;
+ *STDOUT = $connection;
+ exec '/bin/systemctl', 'start', $service;
+ die "exec should have never reached here\n";
+ }
+}
+
diff --git a/01-base-asav/Dockerfile b/01-base-asav/Dockerfile
new file mode 100644
index 0000000..496b595
--- /dev/null
+++ b/01-base-asav/Dockerfile
@@ -0,0 +1,22 @@
+FROM kolab/base:latest
+
+RUN yum -y install \
+ amavisd-new \
+ clamav && \
+ yum clean all
+
+VOLUME [ "/data" ]
+
+EXPOSE 10024
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
+CMD [ \
+ "/usr/sbin/amavisd", \
+ "-u", "amavis", \
+ "-g", "amavis", \
+ "-c", "/etc/amavisd/amavisd.conf", \
+ "foreground" \
+ ]
+
diff --git a/01-base-asav/README.md b/01-base-asav/README.md
new file mode 100644
index 0000000..2844edd
--- /dev/null
+++ b/01-base-asav/README.md
@@ -0,0 +1 @@
+## Anti-Spam and Anti-Virus
diff --git a/01-base-asav/entrypoint.sh b/01-base-asav/entrypoint.sh
new file mode 100755
index 0000000..a8bf5fe
--- /dev/null
+++ b/01-base-asav/entrypoint.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_var KOLAB_EXT_MX_IN_SERVICE_HOST || check_var KOLAB_EXT_MX_OUT_SERVICE_HOST || exit 1
+
+check_vars \
+ DOMAIN \
+ KOLAB_ROLE \
+ || exit 1
+
+persist \
+ /var/spool/amavisd/
+
+su -s /bin/bash - amavis -c 'nohup /usr/sbin/clamd -c /etc/clamd.d/amavisd.conf --pid /var/run/amavisd/clamd.pid &'
+
+if [ -z "${DOMAIN}" -o "${DOMAIN}" == "" ]; then
+ DOMAIN="docker.container"
+fi
+
+if [ -z "$(hostname | awk -F'.' '{print $3}')" -a ! -z "${DOMAIN}" ]; then
+ sed -r -i \
+ -e "s/^\\\$mydomain = .*$/\$mydomain = '${DOMAIN}';/g" \
+ -e "s/^# \\\$myhostname.*$/\$myhostname = '$(hostname).${DOMAIN}';/g" \
+ /etc/amavisd/amavisd.conf
+fi
+
+if [ "${KOLAB_ROLE}" == "ASAV_IN" ]; then
+ FORWARD_METHOD="smtp:[${KOLAB_EXT_MX_IN_SERVICE_HOST}]:10025"
+elif [ "${KOLAB_ROLE}" == "ASAV_OUT" ]; then
+ FORWARD_METHOD="smtp:[${KOLAB_EXT_MX_OUT_SERVICE_HOST}]:10025"
+fi
+
+if [ ! -z "${FORWARD_METHOD}" ]; then
+ sed -r -i \
+ -e "s/^# \\\$forward_method.*$/\$forward_method = '${FORWARD_METHOD}';/g" \
+ /etc/amavisd/amavisd.conf
+fi
+
+if [ $# -lt 1 ]; then
+ exec /usr/sbin/amavisd \
+ -u amavis \
+ -g amavis \
+ -c /etc/amavisd/amavisd.conf \
+ foreground
+else
+ exec "$@"
+fi
diff --git a/01-base-imap/Dockerfile b/01-base-imap/Dockerfile
new file mode 100644
index 0000000..0959ceb
--- /dev/null
+++ b/01-base-imap/Dockerfile
@@ -0,0 +1,14 @@
+FROM kolab/base:latest
+
+RUN yum -y install \
+ cyrus-imapd \
+ kolab-saslauthd && \
+ yum clean all
+
+EXPOSE 110 143 993 995 4190
+
+CMD [ \
+ "/usr/lib/cyrus-imapd/cyrus-master", \
+ "-L", \
+ "/dev/null" \
+ ]
diff --git a/01-base-ldap/Dockerfile b/01-base-ldap/Dockerfile
new file mode 100644
index 0000000..0e612ca
--- /dev/null
+++ b/01-base-ldap/Dockerfile
@@ -0,0 +1,23 @@
+FROM kolab/base:latest
+
+RUN yum -y --setopt tsflags= install \
+ kolab-schema && \
+ yum -y install \
+ kolab-ldap \
+ net-tools && \
+ yum clean all
+
+RUN cp /usr/share/doc/kolab-schema-*/*.ldif \
+ /etc/dirsrv/schema/99kolab3.ldif && \
+ chown root:root /etc/dirsrv/schema/99kolab3.ldif && \
+ chmod 644 /etc/dirsrv/schema/99kolab3.ldif
+
+ADD /template.ldif /usr/share/dirsrv/data/template.ldif
+
+RUN mkdir -p /run/lock
+RUN ln -sf /bin/true /sbin/semanage
+RUN ln -sf /bin/true /bin/systemctl
+
+VOLUME [ "/data" ]
+
+EXPOSE 389 636
diff --git a/01-base-ldap/template.ldif b/01-base-ldap/template.ldif
new file mode 100644
index 0000000..a9b6a49
--- /dev/null
+++ b/01-base-ldap/template.ldif
@@ -0,0 +1,142 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# This Program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; version 2 of the License.
+#
+# This Program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA.
+#
+# In addition, as a special exception, Red Hat, Inc. gives You the additional
+# right to link the code of this Program with code not covered under the GNU
+# General Public License ("Non-GPL Code") and to distribute linked combinations
+# including the two, subject to the limitations in this paragraph. Non-GPL Code
+# permitted under this exception must only link to the code of this Program
+# through those well defined interfaces identified in the file named EXCEPTION
+# found in the source code files (the "Approved Interfaces"). The files of
+# Non-GPL Code may instantiate templates or use macros or inline functions from
+# the Approved Interfaces without causing the resulting work to be covered by
+# the GNU General Public License. Only Red Hat, Inc. may make changes or
+# additions to the list of Approved Interfaces. You must obey the GNU General
+# Public License in all respects for all of the Program code and other code used
+# in conjunction with the Program except the Non-GPL Code covered by this
+# exception. If you modify this file, you may extend this exception to your
+# version of the file, but you are not obligated to do so. If you do not wish to
+# provide this exception without modification, you must delete this exception
+# statement from your version and license this file solely under the GPL without
+# exception.
+#
+#
+# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+#
+# Note: %rootdn% (Directory Manager) has all rights on every entry by nature.
+# Thus, it is not needed to give any acis. This template has several
+# groupOfUniqueNames objects which MUST have uniqueMember. At this moment,
+# there is no entry which could be a uniqueMember. Just to satisfy the
+# objectclass, set %rootdn% to uniqueMember of the objectclass.
+#
+dn: %ds_suffix%
+changetype: modify
+replace: aci
+aci: (targetattr = "carLicense || description || displayName || facsimileTelephoneNumber || homePhone || homePostalAddress || initials || jpegPhoto || l || labeledURI || mobile || o || pager || photo || postOfficeBox || postalAddress || postalCode || preferredDeliveryMethod || preferredLanguage || registeredAddress || roomNumber || secretary || seeAlso || st || street || telephoneNumber || telexNumber || title || userCertificate || userPassword || userSMIMECertificate || x500UniqueIdentifier || kolabDelegate || kolabInvitationPolicy || kolabAllowSMTPSender") (version 3.0; acl "Enable self write for common attributes"; allow (read,compare,search,write)(userdn = "ldap:///self");)
+aci: (targetattr = "*")(version 3.0; acl "Directory Administrators Group"; allow (all) (groupdn = "ldap:///cn=Directory Administrators,%(rootdn)s" or roledn = "ldap:///cn=kolab-admin,%ds_suffix%");)
+aci: (targetattr = "*")(version 3.0; acl "Configuration Administrators Group"; allow (all) groupdn="ldap:///cn=Configuration Administrators,ou=Groups,ou=TopologyManagement,o=NetscapeRoot";)
+aci: (targetattr = "*")(version 3.0; acl "Configuration Administrator"; allow (all) userdn="ldap:///uid=admin,ou=Administrators,ou=TopologyManagement,o=NetscapeRoot";)
+aci: (targetattr = "*")(version 3.0; acl "SIE Group"; allow (all) groupdn = "ldap:///cn=slapd-%hostname%,cn=389 Directory Server,cn=Server Group,cn=%hostname%.%domain%,ou=%domain%,o=NetscapeRoot";)
+aci: (targetattr != "userPassword")(version 3.0; acl "Search Access";allow (read,compare,search)(userdn = "ldap:///all");)
+
+dn: cn=kolab-admin,%ds_suffix%
+objectclass: top
+objectclass: ldapsubentry
+objectclass: nsroledefinition
+objectclass: nssimpleroledefinition
+objectclass: nsmanagedroledefinition
+cn: kolab-admin
+
+dn: cn=Directory Administrators, %ds_suffix%
+objectClass: top
+objectClass: groupofuniquenames
+cn: Directory Administrators
+uniqueMember: %rootdn%
+
+dn: ou=Domains, %ds_suffix%
+objectclass: top
+objectclass: organizationalunit
+ou: Domains
+
+dn: associateddomain=%domain%,ou=Domains,%ds_suffix%
+objectclass: top
+objectclass: domainrelatedobject
+associateddomain: %domain%
+
+dn: ou=Groups, %ds_suffix%
+objectclass: top
+objectclass: organizationalunit
+ou: Groups
+
+dn: ou=Resources, %ds_suffix%
+objectclass: top
+objectclass: organizationalunit
+ou: Resources
+
+dn: ou=Shared Folders, %ds_suffix%
+objectclass: top
+objectclass: organizationalunit
+ou: Shared Folders
+
+dn: ou=People, %ds_suffix%
+objectclass: top
+objectclass: organizationalunit
+ou: People
+
+dn: ou=Special Users,%ds_suffix%
+objectclass: top
+objectclass: organizationalUnit
+ou: Special Users
+description: Special Administrative Accounts
+
+dn: uid=cyrus-admin,ou=Special Users,%ds_suffix%
+objectclass: top
+objectclass: inetorgperson
+objectclass: organizationalperson
+objectclass: person
+uid: cyrus-admin
+givenname: Cyrus
+surname: Administrator
+cn: Cyrus Administrator
+userpassword: %cyrus_admin_password%
+
+dn: uid=kolab-service,ou=Special Users,%ds_suffix%
+objectclass: top
+objectclass: inetorgperson
+objectclass: organizationalperson
+objectclass: person
+uid: kolab-service
+givenname: Kolab
+surname: Service
+cn: Kolab Service
+userpassword: %kolab_service_password%
+nslookthroughlimit: -1
+nssizelimit: -1
+nstimelimit: -1
+nsidletimeout: -1
+
+dn: cn=config
+changetype: modify
+replace: nsslapd-allow-anonymous-access
+nsslapd-allow-anonymous-access: off
+-
+replace: nsslapd-accesslog-logging-enabled
+nsslapd-accesslog-logging-enabled: off
+-
+replace: nsslapd-auditlog-logging-enabled
+nsslapd-auditlog-logging-enabled: on
diff --git a/01-base-mx/Dockerfile b/01-base-mx/Dockerfile
new file mode 100644
index 0000000..4547399
--- /dev/null
+++ b/01-base-mx/Dockerfile
@@ -0,0 +1,8 @@
+FROM kolab/base:latest
+
+RUN yum -y install \
+ postfix \
+ postfix-kolab && \
+ yum clean all
+
+VOLUME [ "/data" ]
diff --git a/01-base-nodejs/Dockerfile b/01-base-nodejs/Dockerfile
new file mode 100644
index 0000000..803bce1
--- /dev/null
+++ b/01-base-nodejs/Dockerfile
@@ -0,0 +1,47 @@
+FROM kolab/base:latest
+
+ENV NODE_VERSION=0.12.8
+
+#RUN yum -y install \
+# bzip2 \
+# gcc-c++ \
+# git \
+# libjpeg-turbo-utils \
+# libpng-devel \
+# make \
+# tar \
+# wget && \
+# yum clean all
+#
+#RUN cd /tmp && \
+# wget http://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}.tar.gz && \
+# tar zxvf node-v${NODE_VERSION}.tar.gz && \
+# rm -f node-v${NODE_VERSION}.tar.gz && \
+# cd node-v${NODE_VERSION}/ && \
+# ./configure --prefix=/usr && \
+# CXX="g++ -Wno-unused-local-typedefs" make && \
+# CXX="g++ -Wno-unused-local-typedefs" make install && \
+# cd /tmp && \
+# rm -rf /tmp/node-v* && \
+# npm config set registry http://registry.npmjs.org/ && \
+# npm install --verbose -g bower ember-cli npm && \
+# rm -rf /root/.npm/ && \
+# printf '\n# Node.js\nexport PATH="node_modules/.bin:$PATH"' >> /root/.bashrc
+
+RUN yum -y install \
+ git \
+ libjpeg-turbo-utils \
+ libpng-devel \
+ nodejs \
+ npm \
+ tar && \
+ yum clean all
+
+RUN npm config set registry http://registry.npmjs.org/
+
+RUN npm update --verbose -g \
+ node-gyp \
+ npm && \
+ npm install --verbose -g \
+ bower && \
+ rm -rf /root/.npm/
diff --git a/01-base-web/Dockerfile b/01-base-web/Dockerfile
new file mode 100644
index 0000000..d8d9408
--- /dev/null
+++ b/01-base-web/Dockerfile
@@ -0,0 +1,16 @@
+FROM kolab/base:latest
+
+RUN yum -y install \
+ httpd \
+ php \
+ mod_ssl && \
+ yum clean all
+
+RUN sed -r -i \
+ -e 's|^(\s*)CustomLog .* common$|\1CustomLog /proc/self/fd/1 common|g' \
+ -e 's|^(\s*)ErrorLog .*$|\1ErrorLog /proc/self/fd/2|g' \
+ /etc/httpd/conf/httpd.conf
+
+EXPOSE 80 443
+
+CMD [ "/usr/sbin/httpd" , "-DFOREGROUND" ]
diff --git a/02-base-web-rc/Dockerfile b/02-base-web-rc/Dockerfile
new file mode 100644
index 0000000..9f704ec
--- /dev/null
+++ b/02-base-web-rc/Dockerfile
@@ -0,0 +1,11 @@
+FROM kolab/base-web:latest
+
+RUN yum -y install \
+ libcalendaring \
+ libkolab \
+ libkolabxml \
+ php-kolab \
+ php-kolabformat && \
+ yum -y --setopt tsflags= install \
+ roundcubemail && \
+ yum clean all
diff --git a/03-asav-in/Dockerfile b/03-asav-in/Dockerfile
new file mode 100644
index 0000000..34e3d3d
--- /dev/null
+++ b/03-asav-in/Dockerfile
@@ -0,0 +1,3 @@
+FROM kolab/base-asav:latest
+
+ENV KOLAB_ROLE ASAV_IN
diff --git a/03-asav-out/Dockerfile b/03-asav-out/Dockerfile
new file mode 100644
index 0000000..93a50c6
--- /dev/null
+++ b/03-asav-out/Dockerfile
@@ -0,0 +1,3 @@
+FROM kolab/base-asav:latest
+
+ENV KOLAB_ROLE ASAV_OUT
diff --git a/03-chwala/Dockerfile b/03-chwala/Dockerfile
new file mode 100644
index 0000000..1805c49
--- /dev/null
+++ b/03-chwala/Dockerfile
@@ -0,0 +1,8 @@
+FROM kolab/base-web-rc:latest
+
+RUN yum -y install \
+ chwala && \
+ yum clean all
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
diff --git a/03-chwala/entrypoint.sh b/03-chwala/entrypoint.sh
new file mode 100755
index 0000000..5fc4448
--- /dev/null
+++ b/03-chwala/entrypoint.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+exec "$@"
diff --git a/03-ext-mx-in/Dockerfile b/03-ext-mx-in/Dockerfile
new file mode 100644
index 0000000..f160a71
--- /dev/null
+++ b/03-ext-mx-in/Dockerfile
@@ -0,0 +1,9 @@
+FROM kolab/base-mx:latest
+
+EXPOSE 25 10025
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
+CMD [ "/usr/libexec/postfix/master", "-D" ]
+
diff --git a/03-ext-mx-in/README.md b/03-ext-mx-in/README.md
new file mode 100644
index 0000000..fe3b928
--- /dev/null
+++ b/03-ext-mx-in/README.md
@@ -0,0 +1,2 @@
+## External Mail Exchanger (Inbound)
+
diff --git a/03-ext-mx-in/entrypoint.sh b/03-ext-mx-in/entrypoint.sh
new file mode 100755
index 0000000..0280814
--- /dev/null
+++ b/03-ext-mx-in/entrypoint.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_vars \
+ DOMAIN \
+ KOLAB_ASAV_IN_SERVICE_HOST \
+ KOLAB_ASAV_IN_SERVICE_PORT \
+ KOLAB_INT_MX_SERVICE_HOST \
+ KOLAB_LDAP_MASTER_SERVICE_HOST \
+ KOLAB_SERVICE_PASSWORD \
+ || exit 1
+
+if [ ! -d "/etc/postfix/ldap/" ]; then
+ cp /etc/kolab/kolab.conf /root/kolab.conf
+
+ # Subst. some config settings here.
+
+ setup-kolab --config /root/kolab.conf mta
+ systemctl stop postfix
+
+ sed -i -r \
+ -e "s/^server_host = .*$/server_host = ${KOLAB_LDAP_MASTER_SERVICE_HOST}/g" \
+ -e "s/^search_base = .*$/search_base = $(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_dn = .*$/bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_pw = .*$/bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ /etc/postfix/ldap/*.cf
+fi
+
+rm -rf /etc/postfix/ldap/local_recipient_maps.cf
+rm -rf /etc/postfix/ldap/virtual_alias_maps*.cf
+mv /etc/postfix/ldap/mydestination.cf /etc/postfix/ldap/relay_domains.cf
+
+persist \
+ /var/spool/postfix/
+
+systemctl stop kolab-saslauthd
+
+postconf -e "relay_host=smtp:[${KOLAB_INT_MX_SERVICE_HOST}]:25"
+postconf -e "local_recipient_maps="
+postconf -e "mydestination="
+postconf -e "relay_domains=ldap:/etc/postfix/ldap/relay_domains.cf"
+postconf -e "relay_recipient_maps="
+postconf -e "virtual_alias_maps="
+postconf -e "content_filter=smtp:[${KOLAB_ASAV_IN_SERVICE_HOST}]:${KOLAB_ASAV_IN_SERVICE_PORT}"
+
+exec "$@"
diff --git a/03-ext-mx-out/Dockerfile b/03-ext-mx-out/Dockerfile
new file mode 100644
index 0000000..f160a71
--- /dev/null
+++ b/03-ext-mx-out/Dockerfile
@@ -0,0 +1,9 @@
+FROM kolab/base-mx:latest
+
+EXPOSE 25 10025
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
+CMD [ "/usr/libexec/postfix/master", "-D" ]
+
diff --git a/03-ext-mx-out/README.md b/03-ext-mx-out/README.md
new file mode 100644
index 0000000..cb0f6e0
--- /dev/null
+++ b/03-ext-mx-out/README.md
@@ -0,0 +1 @@
+## External Mail Exchanger (Outbound)
diff --git a/03-ext-mx-out/entrypoint.sh b/03-ext-mx-out/entrypoint.sh
new file mode 100755
index 0000000..440f816
--- /dev/null
+++ b/03-ext-mx-out/entrypoint.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_vars \
+ DOMAIN \
+ KOLAB_ASAV_OUT_SERVICE_HOST \
+ KOLAB_ASAV_OUT_SERVICE_PORT \
+ KOLAB_LDAP_MASTER_SERVICE_HOST \
+ KOLAB_SERVICE_PASSWORD \
+ || exit 1
+
+if [ ! -d "/etc/postfix/ldap/" ]; then
+ cp /etc/kolab/kolab.conf /root/kolab.conf
+
+ # Subst. some config settings here.
+
+ setup-kolab --config /root/kolab.conf mta
+ systemctl stop postfix
+
+ sed -i -r \
+ -e "s/^server_host = .*$/server_host = ${KOLAB_LDAP_MASTER_SERVICE_HOST}/g" \
+ -e "s/^search_base = .*$/search_base = $(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_dn = .*$/bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_pw = .*$/bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ /etc/postfix/ldap/*.cf
+fi
+
+persist \
+ /var/spool/postfix/
+
+systemctl stop kolab-saslauthd
+
+postconf -e "content_filter=smtp:[${KOLAB_ASAV_OUT_SERVICE_HOST}]:${KOLAB_ASAV_OUT_SERVICE_PORT}"
+
+exec "$@"
diff --git a/03-freebusy/Dockerfile b/03-freebusy/Dockerfile
new file mode 100644
index 0000000..9df168e
--- /dev/null
+++ b/03-freebusy/Dockerfile
@@ -0,0 +1,8 @@
+FROM kolab/base-web-rc:latest
+
+RUN yum -y install \
+ kolab-freebusy && \
+ yum clean all
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
diff --git a/03-freebusy/entrypoint.sh b/03-freebusy/entrypoint.sh
new file mode 100755
index 0000000..5fc4448
--- /dev/null
+++ b/03-freebusy/entrypoint.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+exec "$@"
diff --git a/03-guam/Dockerfile b/03-guam/Dockerfile
new file mode 100644
index 0000000..cf57806
--- /dev/null
+++ b/03-guam/Dockerfile
@@ -0,0 +1,16 @@
+FROM kolab/base:latest
+
+RUN yum -y install guam && \
+ yum clean all
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
+ADD /sys.config /etc/guam/sys.config
+
+EXPOSE 143 993
+
+CMD [ \
+ "/usr/sbin/guam", \
+ "foreground" \
+ ]
diff --git a/03-guam/README.md b/03-guam/README.md
new file mode 100644
index 0000000..77acf09
--- /dev/null
+++ b/03-guam/README.md
@@ -0,0 +1,10 @@
+## The IMAP Reverse Proxy
+
+This is an IMAP Reverse Proxy for Kolab Groupware.
+
+It prevents clients that do not understand how to represent the
+contents of those IMAP folders that contain groupware data from reading
+and/or obtaining those very folders.
+
+It also bridges the gap between SPECIAL-USE clients and Kolab clients,
+whom may otherwise have to consider data in desync.
diff --git a/03-guam/entrypoint.sh b/03-guam/entrypoint.sh
new file mode 100755
index 0000000..ebac8a8
--- /dev/null
+++ b/03-guam/entrypoint.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_var \
+ KOLAB_IMAPF_EXT_SERVICE_HOST \
+ || exit 1
+
+if [ ! -f "/etc/pki/tls/private/localhost.pem" ]; then
+ pushd /etc/pki/tls/certs/
+ ./make-dummy-cert ../private/localhost.pem
+ popd
+fi
+
+sed -r -i \
+ -e "s/host, \"127\.0\.0\.1\"/host, \"${KOLAB_IMAPF_EXT_SERVICE_HOST}\"/g" \
+ /etc/guam/sys.config
+
+$@
diff --git a/03-guam/sys.config b/03-guam/sys.config
new file mode 100644
index 0000000..def33e7
--- /dev/null
+++ b/03-guam/sys.config
@@ -0,0 +1,84 @@
+[
+ {
+ kolab_guam, [
+ {
+ imap_servers, [
+ {
+ imap, [
+ { host, "192.168.56.101" },
+ { port, 143 },
+ { tls, starttls }
+ ]
+ },
+ {
+ imaps, [
+ { host, "192.168.56.101" },
+ { port, 993 },
+ { tls, true }
+ ]
+ }
+ ]
+ },
+ {
+ listeners, [
+ {
+ imap, [
+ { port, 143 },
+ { imap_server, imap },
+ {
+ rules, [
+ { filter_groupware, [] }
+ ]
+ },
+ {
+ tls_config, [
+ { certfile, "/etc/ssl/sample.pem" }
+ ]
+ }
+ ]
+ },
+ {
+ imaps, [
+ { port, 993 },
+ { implicit_tls, true },
+ { imap_server, imaps },
+ {
+ rules, [
+ { filter_groupware, [] }
+ ]
+ },
+ {
+ tls_config, [
+ { certfile, "/etc/ssl/sample.pem" }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+
+ {
+ lager, [
+ {
+ handlers, [
+ { lager_console_backend, debug },
+ { lager_file_backend, [ { file, "log/error.log"}, { level, error } ] },
+ { lager_file_backend, [ { file, "log/console.log"}, { level, info } ] }
+ ]
+ }
+ ]
+ },
+
+ %% SASL config
+ {
+ sasl, [
+ { sasl_error_logger, { file, "log/sasl-error.log" } },
+ { errlog_type, error },
+ { error_logger_mf_dir, "log/sasl" }, % Log directory
+ { error_logger_mf_maxbytes, 10485760 }, % 10 MB max file size
+ { error_logger_mf_maxfiles, 5 } % 5 files max
+ ]
+ }
+].
diff --git a/03-http-prx/Dockerfile b/03-http-prx/Dockerfile
new file mode 100644
index 0000000..cef9647
--- /dev/null
+++ b/03-http-prx/Dockerfile
@@ -0,0 +1 @@
+FROM microwebapps/haproxy-frontend-atomicapp:latest
diff --git a/03-imap-mupdate/Dockerfile b/03-imap-mupdate/Dockerfile
new file mode 100644
index 0000000..5b8c052
--- /dev/null
+++ b/03-imap-mupdate/Dockerfile
@@ -0,0 +1,7 @@
+FROM kolab/base-imap:latest
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
+ADD /cyrus.conf.tpl /etc/kolab/templates/cyrus.conf.tpl
+ADD /imapd.conf.tpl /etc/kolab/templates/imapd.conf.tpl
diff --git a/03-imap-mupdate/cyrus.conf.tpl b/03-imap-mupdate/cyrus.conf.tpl
new file mode 100644
index 0000000..1354d83
--- /dev/null
+++ b/03-imap-mupdate/cyrus.conf.tpl
@@ -0,0 +1,16 @@
+START {
+ # do not delete this entry!
+ recover cmd="ctl_cyrusdb -r"
+}
+
+SERVICES {
+ mupdate cmd="mupdate -m" listen=3905 prefork=1 babysit=1
+ ptloader cmd="ptloader" listen="/data/var/lib/imap/ptclient/ptsock" prefork=1
+}
+
+EVENTS {
+ # this is required
+ checkpoint cmd="ctl_cyrusdb -c" period=30
+
+ tlsprune cmd="tls_prune" at=0400
+}
diff --git a/03-imap-mupdate/entrypoint.sh b/03-imap-mupdate/entrypoint.sh
new file mode 100755
index 0000000..d4de514
--- /dev/null
+++ b/03-imap-mupdate/entrypoint.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_vars \
+ CYRUS_ADMIN_PASSWORD \
+ DOMAIN \
+ KOLAB_LDAP_MASTER_SERVICE_HOST \
+ KOLAB_LDAP_MASTER_SERVICE_PORT \
+ KOLAB_SERVICE_PASSWORD \
+ || exit 1
+
+sed -i -r \
+ -e "s/^primary_domain = .*$/primary_domain = ${DOMAIN}/g" \
+ -e "s|^ldap_uri = .*$|ldap_uri = ldap://${KOLAB_LDAP_MASTER_SERVICE_HOST}:${KOLAB_LDAP_MASTER_SERVICE_PORT}|g" \
+ -e "s/^base_dn = .*$/base_dn = $(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^domain_base_dn = .*$/domain_base_dn = ou=Domains,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_dn = .*$/bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_pw = .*$/bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ -e "s/^admin_password = .*$/admin_password = ${CYRUS_ADMIN_PASSWORD}/g" \
+ -e "s/^service_bind_dn = .*$/service_bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^service_bind_pw = .*$/service_bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ /etc/kolab/kolab.conf
+
+sed -i -r \
+ -e "s/%CYRUS_ADMIN_PASSWORD%/${CYRUS_ADMIN_PASSWORD}/g" \
+ -e "s/%KOLAB_IMAP_MUPDATE_SERVICE_HOST%/127.0.0.1/g" \
+ -e "s/%KOLAB_IMAP_MUPDATE_SERVICE_PORT%/3905/g" \
+ -e "s/%KOLAB_SERVICE_PASSWORD%/${KOLAB_SERVICE_PASSWORD}/g" \
+ /etc/kolab/templates/imapd.conf.tpl
+
+cp /etc/kolab/kolab.conf /root/kolab.conf
+
+setup-kolab --config /root/kolab.conf imap
+
+persist \
+ /etc/cyrus.conf \
+ /etc/imapd.conf \
+ /etc/imapd.annotations.conf \
+ /var/lib/imap/ \
+ /var/spool/imap/
+
+exec "$@"
+
diff --git a/03-imap-mupdate/imapd.conf.tpl b/03-imap-mupdate/imapd.conf.tpl
new file mode 100644
index 0000000..5119ee1
--- /dev/null
+++ b/03-imap-mupdate/imapd.conf.tpl
@@ -0,0 +1,57 @@
+configdirectory: /var/lib/imap
+partition-default: /var/spool/imap
+admins: $admins
+sievedir: /var/lib/imap/sieve
+sendmail: /usr/sbin/sendmail
+sasl_pwcheck_method: saslauthd
+sasl_mech_list: PLAIN LOGIN
+allowplaintext: no
+tls_server_cert: /etc/pki/cyrus-imapd/cyrus-imapd.pem
+tls_server_key: /etc/pki/cyrus-imapd/cyrus-imapd.pem
+# uncomment this if you're operating in a DSCP environment (RFC-4594)
+# qosmarking: af13
+auth_mech: pts
+pts_module: ldap
+ldap_servers: $ldap_servers
+ldap_sasl: 0
+ldap_base: $ldap_base
+ldap_bind_dn: $ldap_bind_dn
+ldap_password: $ldap_password
+ldap_filter: $ldap_filter
+ldap_user_attribute: $ldap_user_attribute
+ldap_group_base: $ldap_group_base
+ldap_group_filter: $ldap_group_filter
+ldap_group_scope: $ldap_group_scope
+ldap_member_base: $ldap_member_base
+ldap_member_method: $ldap_member_method
+ldap_member_attribute: $ldap_member_attribute
+ldap_restart: 1
+ldap_timeout: 10
+ldap_time_limit: 10
+unixhierarchysep: 1
+virtdomains: userid
+annotation_definitions: /etc/imapd.annotations.conf
+sieve_extensions: fileinto reject envelope body vacation imapflags notify include regex subaddress relational copy date index
+allowallsubscribe: 0
+allowusermoves: 1
+altnamespace: 1
+hashimapspool: 1
+anysievefolder: 1
+fulldirhash: 0
+sieveusehomedir: 0
+sieve_allowreferrals: 0
+lmtp_downcase_rcpt: 1
+lmtp_fuzzy_mailbox_match: 1
+username_tolower: 1
+deletedprefix: DELETED
+delete_mode: delayed
+expunge_mode: delayed
+postuser: shared
+
+mupdate_config: standard
+mupdate_server: %KOLAB_IMAP_MUPDATE_SERVICE_HOST%
+mupdate_port: %KOLAB_IMAP_MUPDATE_SERVICE_PORT%
+mupdate_authname: cyrus-admin
+mupdate_username: cyrus-admin
+mupdate_password: %CYRUS_ADMIN_PASSWORD%
+
diff --git a/03-imapb/Dockerfile b/03-imapb/Dockerfile
new file mode 100644
index 0000000..566140f
--- /dev/null
+++ b/03-imapb/Dockerfile
@@ -0,0 +1,7 @@
+FROM kolab/base-imap:latest
+
+VOLUME [ "/data" ]
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
diff --git a/03-imapb/entrypoint.sh b/03-imapb/entrypoint.sh
new file mode 100755
index 0000000..d606f56
--- /dev/null
+++ b/03-imapb/entrypoint.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+# Apply some configuration
+exec "$@"
+
+exec top
diff --git a/03-imapf-ext/Dockerfile b/03-imapf-ext/Dockerfile
new file mode 100644
index 0000000..5b8c052
--- /dev/null
+++ b/03-imapf-ext/Dockerfile
@@ -0,0 +1,7 @@
+FROM kolab/base-imap:latest
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
+ADD /cyrus.conf.tpl /etc/kolab/templates/cyrus.conf.tpl
+ADD /imapd.conf.tpl /etc/kolab/templates/imapd.conf.tpl
diff --git a/03-imapf-ext/cyrus.conf.tpl b/03-imapf-ext/cyrus.conf.tpl
new file mode 100644
index 0000000..46193a5
--- /dev/null
+++ b/03-imapf-ext/cyrus.conf.tpl
@@ -0,0 +1,22 @@
+START {
+ # do not delete this entry!
+ recover cmd="ctl_cyrusdb -r"
+}
+
+SERVICES {
+ mupdate cmd="mupdate" listen=3905 prefork=1 babysit=1
+
+ imap cmd="proxyd" listen="imap" prefork=1
+ imaps cmd="proxyd -s" listen="imaps" prefork=1
+
+ sieve cmd="timsieved" listen="managesieve" prefork=1
+
+ ptloader cmd="ptloader" listen="/data/var/lib/imap/ptclient/ptsock" prefork=1
+}
+
+EVENTS {
+ # this is required
+ checkpoint cmd="ctl_cyrusdb -c" period=30
+
+ tlsprune cmd="tls_prune" at=0400
+}
diff --git a/03-imapf-ext/entrypoint.sh b/03-imapf-ext/entrypoint.sh
new file mode 100755
index 0000000..cfc3b66
--- /dev/null
+++ b/03-imapf-ext/entrypoint.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_vars \
+ DOMAIN \
+ KOLAB_IMAP_MUPDATE_SERVICE_HOST \
+ KOLAB_IMAP_MUPDATE_SERVICE_PORT \
+ KOLAB_LDAP_MASTER_SERVICE_HOST \
+ KOLAB_SERVICE_PASSWORD \
+ CYRUS_ADMIN_PASSWORD \
+ || exit 1
+
+sed -i -r \
+ -e "s/^primary_domain = .*$/primary_domain = ${DOMAIN}/g" \
+ -e "s|^ldap_uri = .*$|ldap_uri = ldap://${KOLAB_LDAP_MASTER_SERVICE_HOST}:${KOLAB_LDAP_MASTER_SERVICE_PORT}|g" \
+ -e "s/^base_dn = .*$/base_dn = $(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^domain_base_dn = .*$/domain_base_dn = ou=Domains,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_dn = .*$/bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_pw = .*$/bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ -e "s/^admin_password = .*$/admin_password = ${CYRUS_ADMIN_PASSWORD}/g" \
+ -e "s/^service_bind_dn = .*$/service_bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^service_bind_pw = .*$/service_bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ /etc/kolab/kolab.conf
+
+sed -i -r \
+ -e "s/%CYRUS_ADMIN_PASSWORD%/${CYRUS_ADMIN_PASSWORD}/g" \
+ -e "s/%KOLAB_IMAP_MUPDATE_SERVICE_HOST%/${KOLAB_IMAP_MUPDATE_SERVICE_HOST}/g" \
+ -e "s/%KOLAB_IMAP_MUPDATE_SERVICE_PORT%/${KOLAB_IMAP_MUPDATE_SERVICE_PORT}/g" \
+ -e "s/%KOLAB_SERVICE_PASSWORD%/${KOLAB_SERVICE_PASSWORD}/g" \
+ /etc/kolab/templates/imapd.conf.tpl
+
+cp /etc/kolab/kolab.conf /root/kolab.conf
+
+setup-kolab --config /root/kolab.conf imap
+
+persist \
+ /etc/cyrus.conf \
+ /etc/imapd.conf \
+ /etc/imapd.annotations.conf \
+ /var/lib/imap/ \
+ /var/spool/imap/
+
+exec "$@"
diff --git a/03-imapf-ext/imapd.conf.tpl b/03-imapf-ext/imapd.conf.tpl
new file mode 100644
index 0000000..5119ee1
--- /dev/null
+++ b/03-imapf-ext/imapd.conf.tpl
@@ -0,0 +1,57 @@
+configdirectory: /var/lib/imap
+partition-default: /var/spool/imap
+admins: $admins
+sievedir: /var/lib/imap/sieve
+sendmail: /usr/sbin/sendmail
+sasl_pwcheck_method: saslauthd
+sasl_mech_list: PLAIN LOGIN
+allowplaintext: no
+tls_server_cert: /etc/pki/cyrus-imapd/cyrus-imapd.pem
+tls_server_key: /etc/pki/cyrus-imapd/cyrus-imapd.pem
+# uncomment this if you're operating in a DSCP environment (RFC-4594)
+# qosmarking: af13
+auth_mech: pts
+pts_module: ldap
+ldap_servers: $ldap_servers
+ldap_sasl: 0
+ldap_base: $ldap_base
+ldap_bind_dn: $ldap_bind_dn
+ldap_password: $ldap_password
+ldap_filter: $ldap_filter
+ldap_user_attribute: $ldap_user_attribute
+ldap_group_base: $ldap_group_base
+ldap_group_filter: $ldap_group_filter
+ldap_group_scope: $ldap_group_scope
+ldap_member_base: $ldap_member_base
+ldap_member_method: $ldap_member_method
+ldap_member_attribute: $ldap_member_attribute
+ldap_restart: 1
+ldap_timeout: 10
+ldap_time_limit: 10
+unixhierarchysep: 1
+virtdomains: userid
+annotation_definitions: /etc/imapd.annotations.conf
+sieve_extensions: fileinto reject envelope body vacation imapflags notify include regex subaddress relational copy date index
+allowallsubscribe: 0
+allowusermoves: 1
+altnamespace: 1
+hashimapspool: 1
+anysievefolder: 1
+fulldirhash: 0
+sieveusehomedir: 0
+sieve_allowreferrals: 0
+lmtp_downcase_rcpt: 1
+lmtp_fuzzy_mailbox_match: 1
+username_tolower: 1
+deletedprefix: DELETED
+delete_mode: delayed
+expunge_mode: delayed
+postuser: shared
+
+mupdate_config: standard
+mupdate_server: %KOLAB_IMAP_MUPDATE_SERVICE_HOST%
+mupdate_port: %KOLAB_IMAP_MUPDATE_SERVICE_PORT%
+mupdate_authname: cyrus-admin
+mupdate_username: cyrus-admin
+mupdate_password: %CYRUS_ADMIN_PASSWORD%
+
diff --git a/03-imapf-int/Dockerfile b/03-imapf-int/Dockerfile
new file mode 100644
index 0000000..5b8c052
--- /dev/null
+++ b/03-imapf-int/Dockerfile
@@ -0,0 +1,7 @@
+FROM kolab/base-imap:latest
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
+ADD /cyrus.conf.tpl /etc/kolab/templates/cyrus.conf.tpl
+ADD /imapd.conf.tpl /etc/kolab/templates/imapd.conf.tpl
diff --git a/03-imapf-int/cyrus.conf.tpl b/03-imapf-int/cyrus.conf.tpl
new file mode 100644
index 0000000..46193a5
--- /dev/null
+++ b/03-imapf-int/cyrus.conf.tpl
@@ -0,0 +1,22 @@
+START {
+ # do not delete this entry!
+ recover cmd="ctl_cyrusdb -r"
+}
+
+SERVICES {
+ mupdate cmd="mupdate" listen=3905 prefork=1 babysit=1
+
+ imap cmd="proxyd" listen="imap" prefork=1
+ imaps cmd="proxyd -s" listen="imaps" prefork=1
+
+ sieve cmd="timsieved" listen="managesieve" prefork=1
+
+ ptloader cmd="ptloader" listen="/data/var/lib/imap/ptclient/ptsock" prefork=1
+}
+
+EVENTS {
+ # this is required
+ checkpoint cmd="ctl_cyrusdb -c" period=30
+
+ tlsprune cmd="tls_prune" at=0400
+}
diff --git a/03-imapf-int/entrypoint.sh b/03-imapf-int/entrypoint.sh
new file mode 100755
index 0000000..cfc3b66
--- /dev/null
+++ b/03-imapf-int/entrypoint.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_vars \
+ DOMAIN \
+ KOLAB_IMAP_MUPDATE_SERVICE_HOST \
+ KOLAB_IMAP_MUPDATE_SERVICE_PORT \
+ KOLAB_LDAP_MASTER_SERVICE_HOST \
+ KOLAB_SERVICE_PASSWORD \
+ CYRUS_ADMIN_PASSWORD \
+ || exit 1
+
+sed -i -r \
+ -e "s/^primary_domain = .*$/primary_domain = ${DOMAIN}/g" \
+ -e "s|^ldap_uri = .*$|ldap_uri = ldap://${KOLAB_LDAP_MASTER_SERVICE_HOST}:${KOLAB_LDAP_MASTER_SERVICE_PORT}|g" \
+ -e "s/^base_dn = .*$/base_dn = $(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^domain_base_dn = .*$/domain_base_dn = ou=Domains,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_dn = .*$/bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_pw = .*$/bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ -e "s/^admin_password = .*$/admin_password = ${CYRUS_ADMIN_PASSWORD}/g" \
+ -e "s/^service_bind_dn = .*$/service_bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^service_bind_pw = .*$/service_bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ /etc/kolab/kolab.conf
+
+sed -i -r \
+ -e "s/%CYRUS_ADMIN_PASSWORD%/${CYRUS_ADMIN_PASSWORD}/g" \
+ -e "s/%KOLAB_IMAP_MUPDATE_SERVICE_HOST%/${KOLAB_IMAP_MUPDATE_SERVICE_HOST}/g" \
+ -e "s/%KOLAB_IMAP_MUPDATE_SERVICE_PORT%/${KOLAB_IMAP_MUPDATE_SERVICE_PORT}/g" \
+ -e "s/%KOLAB_SERVICE_PASSWORD%/${KOLAB_SERVICE_PASSWORD}/g" \
+ /etc/kolab/templates/imapd.conf.tpl
+
+cp /etc/kolab/kolab.conf /root/kolab.conf
+
+setup-kolab --config /root/kolab.conf imap
+
+persist \
+ /etc/cyrus.conf \
+ /etc/imapd.conf \
+ /etc/imapd.annotations.conf \
+ /var/lib/imap/ \
+ /var/spool/imap/
+
+exec "$@"
diff --git a/03-imapf-int/imapd.conf.tpl b/03-imapf-int/imapd.conf.tpl
new file mode 100644
index 0000000..5119ee1
--- /dev/null
+++ b/03-imapf-int/imapd.conf.tpl
@@ -0,0 +1,57 @@
+configdirectory: /var/lib/imap
+partition-default: /var/spool/imap
+admins: $admins
+sievedir: /var/lib/imap/sieve
+sendmail: /usr/sbin/sendmail
+sasl_pwcheck_method: saslauthd
+sasl_mech_list: PLAIN LOGIN
+allowplaintext: no
+tls_server_cert: /etc/pki/cyrus-imapd/cyrus-imapd.pem
+tls_server_key: /etc/pki/cyrus-imapd/cyrus-imapd.pem
+# uncomment this if you're operating in a DSCP environment (RFC-4594)
+# qosmarking: af13
+auth_mech: pts
+pts_module: ldap
+ldap_servers: $ldap_servers
+ldap_sasl: 0
+ldap_base: $ldap_base
+ldap_bind_dn: $ldap_bind_dn
+ldap_password: $ldap_password
+ldap_filter: $ldap_filter
+ldap_user_attribute: $ldap_user_attribute
+ldap_group_base: $ldap_group_base
+ldap_group_filter: $ldap_group_filter
+ldap_group_scope: $ldap_group_scope
+ldap_member_base: $ldap_member_base
+ldap_member_method: $ldap_member_method
+ldap_member_attribute: $ldap_member_attribute
+ldap_restart: 1
+ldap_timeout: 10
+ldap_time_limit: 10
+unixhierarchysep: 1
+virtdomains: userid
+annotation_definitions: /etc/imapd.annotations.conf
+sieve_extensions: fileinto reject envelope body vacation imapflags notify include regex subaddress relational copy date index
+allowallsubscribe: 0
+allowusermoves: 1
+altnamespace: 1
+hashimapspool: 1
+anysievefolder: 1
+fulldirhash: 0
+sieveusehomedir: 0
+sieve_allowreferrals: 0
+lmtp_downcase_rcpt: 1
+lmtp_fuzzy_mailbox_match: 1
+username_tolower: 1
+deletedprefix: DELETED
+delete_mode: delayed
+expunge_mode: delayed
+postuser: shared
+
+mupdate_config: standard
+mupdate_server: %KOLAB_IMAP_MUPDATE_SERVICE_HOST%
+mupdate_port: %KOLAB_IMAP_MUPDATE_SERVICE_PORT%
+mupdate_authname: cyrus-admin
+mupdate_username: cyrus-admin
+mupdate_password: %CYRUS_ADMIN_PASSWORD%
+
diff --git a/03-int-mx/Dockerfile b/03-int-mx/Dockerfile
new file mode 100644
index 0000000..29b557a
--- /dev/null
+++ b/03-int-mx/Dockerfile
@@ -0,0 +1,8 @@
+FROM kolab/base-mx:latest
+
+EXPOSE 25 587
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
+CMD [ "/usr/libexec/postfix/master", "-D" ]
diff --git a/03-int-mx/README.md b/03-int-mx/README.md
new file mode 100644
index 0000000..fe3b928
--- /dev/null
+++ b/03-int-mx/README.md
@@ -0,0 +1,2 @@
+## External Mail Exchanger (Inbound)
+
diff --git a/03-int-mx/entrypoint.sh b/03-int-mx/entrypoint.sh
new file mode 100755
index 0000000..71f9905
--- /dev/null
+++ b/03-int-mx/entrypoint.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_vars \
+ DOMAIN \
+ KOLAB_LDAP_MASTER_SERVICE_HOST \
+ KOLAB_SERVICE_PASSWORD \
+ KOLAB_WALLACE_SERVICE_HOST \
+ KOLAB_WALLACE_SERVICE_PORT \
+ || exit 1
+
+if [ -z "${KOLAB_LDAP_MASTER_SERVICE_HOST}" ]; then
+ sleep 10
+ exit 1
+fi
+
+if [ ! -d "/etc/postfix/ldap/" ]; then
+ cp /etc/kolab/kolab.conf /root/kolab.conf
+
+ # Subst. some config settings here.
+
+ setup-kolab --config /root/kolab.conf mta
+ systemctl stop postfix
+
+ sed -i -r \
+ -e "s/^server_host = .*$/server_host = ${KOLAB_LDAP_MASTER_SERVICE_HOST}/g" \
+ -e "s/^search_base = .*$/search_base = $(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_dn = .*$/bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_pw = .*$/bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ /etc/postfix/ldap/*.cf
+fi
+
+persist \
+ /var/spool/postfix/
+
+systemctl stop kolab-saslauthd
+
+postconf -e "content_filter=smtp:[${KOLAB_WALLACE_SERVICE_HOST}]:${KOLAB_WALLACE_SERVICE_PORT}"
+
+exec "$@"
diff --git a/03-irony/Dockerfile b/03-irony/Dockerfile
new file mode 100644
index 0000000..365e52d
--- /dev/null
+++ b/03-irony/Dockerfile
@@ -0,0 +1,8 @@
+FROM kolab/base-web-rc:latest
+
+RUN yum -y install \
+ iRony && \
+ yum clean all
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
diff --git a/03-irony/entrypoint.sh b/03-irony/entrypoint.sh
new file mode 100755
index 0000000..5fc4448
--- /dev/null
+++ b/03-irony/entrypoint.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+exec "$@"
diff --git a/03-jmap-proxy/Dockerfile b/03-jmap-proxy/Dockerfile
new file mode 100644
index 0000000..25e2b8f
--- /dev/null
+++ b/03-jmap-proxy/Dockerfile
@@ -0,0 +1,102 @@
+FROM docker.io/library/centos:centos7
+MAINTAINER Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>
+
+RUN yum -y install epel-release && \
+ yum -y install \
+ @fedora-packager \
+ gcc \
+ git \
+ libuuid-devel \
+ net-tools \
+ nginx \
+ perl-AnyEvent-HTTP \
+ perl-Archive-Tar \
+ perl-CPAN \
+ perl-CPAN-Meta \
+ perl-CPAN-Meta-Requirements \
+ perl-CPAN-Meta-YAML \
+ perl-Data-UUID \
+ perl-DateTime \
+ perl-DBD-SQLite \
+ perl-DBI \
+ perl-Email-Address \
+ perl-Email-MIME \
+ perl-ExtUtils-CBuilder \
+ perl-ExtUtils-MakeMaker \
+ perl-HTML-Parser \
+ perl-HTML-Strip \
+ perl-HTTP-Tiny \
+ perl-Image-Size \
+ perl-IO-Socket-SSL \
+ perl-JSON \
+ perl-JSON-PP \
+ perl-JSON-XS \
+ perl-Locale-Maketext-Gettext \
+ perl-Object-Event \
+ perl-Parse-CPAN-Meta \
+ perl-Switch \
+ screen \
+ vim-enhanced
+
+RUN ( sleep 1; \
+ echo "yes"; \
+ ) | perl -MCPAN -e shell || :
+
+ADD bashrc /root/.bashrc
+
+WORKDIR /srv/
+RUN git clone https://github.com/jmapio/jmap-perl.git jmap-perl.git
+WORKDIR /srv/jmap-perl.git
+RUN echo notest install $(grep -r "^use " bin/ Email/ JMAP/ Mail/ AnyEvent/ | awk '{print $2}' | sed -re 's/;$//g' | sort -u | grep -vE "(base|constant|lib|strict|warnings)") | perl -MCPAN -e shell || :
+
+RUN ( echo "notest install CPAN" ) | perl -MCPAN -e shell
+RUN ( echo "notest install List::Pairwise" ) | perl -MCPAN -e shell
+
+WORKDIR /srv/
+RUN git clone https://github.com/CindyLinz/Perl-AnyEvent-HTTPD-SendMultiHeaderPatch.git Perl-AnyEvent-HTTPD-SendMultiHeaderPatch.git
+WORKDIR /srv/Perl-AnyEvent-HTTPD-SendMultiHeaderPatch.git
+RUN perl Makefile.PL && \
+ make && \
+ make install
+
+WORKDIR /srv/
+RUN git clone https://github.com/fastmail/Net-CardDAVTalk.git Net-CardDAVTalk.git
+WORKDIR /srv/Net-CardDAVTalk.git
+RUN perl Makefile.PL && \
+ make && \
+ make install
+
+WORKDIR /srv/jmap-perl.git
+RUN echo notest install $(grep -r "^use " bin/ Email/ JMAP/ Mail/ AnyEvent/ | awk '{print $2}' | sed -re 's/;$//g' | sort -u | grep -vE "(base|constant|lib|strict|warnings)") | perl -MCPAN -e shell || :
+
+ADD nginx.conf /etc/nginx/nginx.conf
+
+ADD http://cgit.kolab.org/docker/plain/ci/files.d/dbus.service /etc/systemd/system/dbus.service
+RUN ln -sf dbus.service /etc/systemd/system/messagebus.service
+
+ADD http://cgit.kolab.org/docker/plain/ci/files.d/httpd.service /etc/systemd/system/httpd.service
+
+ADD http://cgit.kolab.org/docker/plain/ci/files.d/systemctl /usr/bin/systemctl
+ADD http://cgit.kolab.org/docker/plain/ci/files.d/systemctl-socket-daemon /usr/bin/systemctl-socket-daemon
+
+RUN chmod -v a+rx \
+ /usr/bin/systemctl \
+ /usr/bin/systemctl-socket-daemon
+
+WORKDIR /root/
+RUN mkdir -p /home/jmap/data/ && ln -s /srv/jmap-perl.git/ /home/jmap/jmap-perl
+
+RUN sed -i -e 's/https:/http:/g' /srv/jmap-perl.git/bin/server.pl
+
+RUN rm -rf \
+ /srv/Perl-AnyEvent-HTTPD-SendMultiHeaderPatch.git \
+ /srv/Net-CardDAVTalk.git \
+ /root/.cpan
+
+EXPOSE 80
+
+ENV jmaphost 172.17.42.1
+
+ADD entrypoint.sh /root/entrypoint.sh
+RUN chmod 755 /root/entrypoint.sh
+ENTRYPOINT /root/entrypoint.sh
diff --git a/03-jmap-proxy/Makefile b/03-jmap-proxy/Makefile
new file mode 100644
index 0000000..38877d6
--- /dev/null
+++ b/03-jmap-proxy/Makefile
@@ -0,0 +1,5 @@
+all:
+ docker build -t kolab/jmap-proxy .
+
+run:
+ docker run -d -p 80:80 kolab/jmap-proxy
diff --git a/03-jmap-proxy/bashrc b/03-jmap-proxy/bashrc
new file mode 100644
index 0000000..2d375b7
--- /dev/null
+++ b/03-jmap-proxy/bashrc
@@ -0,0 +1,13 @@
+# .bashrc
+
+# Source global definitions
+if [ -f /etc/bashrc ]; then
+ . /etc/bashrc
+fi
+
+export PERL_LOCAL_LIB_ROOT="$PERL_LOCAL_LIB_ROOT:/root/perl5";
+export PERL_MB_OPT="--install_base /root/perl5";
+export PERL_MM_OPT="INSTALL_BASE=/root/perl5";
+export PERL5LIB="/root/perl5/lib/perl5:$PERL5LIB";
+export PATH="/root/perl5/bin:$PATH";
+
diff --git a/03-jmap-proxy/entrypoint.sh b/03-jmap-proxy/entrypoint.sh
new file mode 100644
index 0000000..e539117
--- /dev/null
+++ b/03-jmap-proxy/entrypoint.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+cd /srv/jmap-perl.git
+
+screen -Amd -S api bin/apiendpoint.pl
+systemctl start nginx
+
+bin/server.pl
diff --git a/03-jmap-proxy/nginx.conf b/03-jmap-proxy/nginx.conf
new file mode 100644
index 0000000..2de222e
--- /dev/null
+++ b/03-jmap-proxy/nginx.conf
@@ -0,0 +1,140 @@
+user nginx;
+worker_processes auto;
+error_log /var/log/nginx/error.log;
+pid /run/nginx.pid;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+
+ access_log /var/log/nginx/access.log main;
+
+ sendfile on;
+ tcp_nopush on;
+ tcp_nodelay on;
+ keepalive_timeout 65;
+ types_hash_max_size 2048;
+
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ server {
+ listen 80;
+ server_name _;
+
+ root /srv/jmap-perl.git/htdocs/;
+ index index.html index.htm;
+
+ location / {
+ # First attempt to serve request as file, then
+ # as directory, then fall back to displaying a 404.
+ try_files $uri $uri/ /index.html;
+ }
+
+ location = / {
+ if ( $request_method = 'OPTIONS' ) {
+ add_header 'Access-Control-Allow-Origin' '*';
+ # -D GAPING_SECURITY_HOLE
+ add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers;
+ add_header 'Access-Control-Allow-Methods' 'POST, GET, OPTIONS';
+ add_header 'Access-Control-Max-Age' 600;
+ add_header 'Content-Type' 'text/plain; charset=UTF-8';
+ add_header 'Content-Length' 0;
+
+ return 204;
+ }
+
+ # First attempt to serve request as file, then
+ # as directory, then fall back to displaying a 404.
+ proxy_pass http://127.0.0.1:9000/home;
+ }
+
+ location /events/ {
+ if ( $request_method = 'OPTIONS' ) {
+ add_header 'Access-Control-Allow-Origin' '*';
+ # -D GAPING_SECURITY_HOLE
+ add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers;
+ add_header 'Access-Control-Allow-Methods' 'POST, GET, OPTIONS';
+ add_header 'Access-Control-Max-Age' 600;
+ add_header 'Content-Type' 'text/plain; charset=UTF-8';
+ add_header 'Content-Length' 0;
+
+ return 204;
+ }
+
+ # Immediately send backend responses back to client
+ proxy_buffering off;
+
+ # Disable keepalive to browser
+ keepalive_timeout 0;
+
+ # It's a long lived backend connection with potentially a long time between
+ # push events, make sure proxy doesn't timeout
+ proxy_read_timeout 7200;
+
+ proxy_pass http://127.0.0.1:9001/events/;
+ }
+
+ location /files/ {
+ proxy_pass http://127.0.0.1:9000/files/;
+ }
+
+ location /jmap/ {
+ if ( $request_method = 'OPTIONS' ) {
+ add_header 'Access-Control-Allow-Origin' '*';
+ # -D GAPING_SECURITY_HOLE
+ add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers;
+ add_header 'Access-Control-Allow-Methods' 'POST, GET, OPTIONS';
+ add_header 'Access-Control-Max-Age' 600;
+ add_header 'Content-Type' 'text/plain; charset=UTF-8';
+ add_header 'Content-Length' 0;
+
+ return 204;
+ }
+
+ proxy_pass http://127.0.0.1:9000/jmap/;
+ }
+
+ location /upload/ {
+ proxy_pass http://127.0.0.1:9000/upload/;
+ }
+
+ location /raw/ {
+ proxy_pass http://127.0.0.1:9000/raw/;
+ }
+
+ location /A {
+ proxy_pass http://127.0.0.1:9000/A;
+ }
+
+ location /J {
+ proxy_pass http://127.0.0.1:9000/J;
+ }
+
+ location /U {
+ proxy_pass http://127.0.0.1:9000/U;
+ }
+
+ location /register {
+ proxy_pass http://127.0.0.1:9000/register;
+ }
+
+ location /signup {
+ proxy_pass http://127.0.0.1:9000/signup;
+ }
+
+ location /delete {
+ proxy_pass http://127.0.0.1:9000/delete;
+ }
+
+ location /cb {
+ proxy_pass http://127.0.0.1:9000/cb;
+ }
+ }
+}
+
diff --git a/03-ldap-master/Dockerfile b/03-ldap-master/Dockerfile
new file mode 100644
index 0000000..609b818
--- /dev/null
+++ b/03-ldap-master/Dockerfile
@@ -0,0 +1,16 @@
+FROM kolab/base-ldap:latest
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
+CMD [ \
+ "/usr/sbin/ns-slapd", \
+ "-D", \
+ "/data/etc/dirsrv/slapd-ldap", \
+ "-i", \
+ "/var/run/dirsrv/slapd-ldap.pid", \
+ "-w", \
+ "/var/run/dirsrv/slapd-ldap.startpid", \
+ "-d", \
+ "0" \
+ ]
diff --git a/03-ldap-master/entrypoint.sh b/03-ldap-master/entrypoint.sh
new file mode 100755
index 0000000..e362147
--- /dev/null
+++ b/03-ldap-master/entrypoint.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_vars \
+ DOMAIN \
+ HOSTNAME \
+ CYRUS_ADMIN_PASSWORD \
+ KOLAB_SERVICE_PASSWORD \
+ ADMIN_PASSWORD \
+ DIRECTORY_MANAGER_PASSWORD \
+ || exit 1
+
+if [ -z "${KOLAB_LDAP_MASTER_SERVICE_HOST}" ]; then
+ export KOLAB_LDAP_MASTER_SERVICE_HOST=$(ip a sh dev $(route -n | grep ^0.0.0.0 | awk '{print $8}') | grep " inet " | awk '{print $2}' | awk -F'/' '{print $1}')
+fi
+
+cp -vf /etc/hosts /etc/hosts.docker
+if echo "# test access" >> /etc/hosts || umount /etc/hosts 2>/dev/null ; then
+ echo "${KOLAB_LDAP_MASTER_SERVICE_HOST} ${HOSTNAME}.${DOMAIN} ${HOSTNAME}" > /etc/hosts
+fi
+
+sed -i \
+ -e "s/%hostname%/${HOSTNAME}/g" \
+ -e "s/%domain%/${DOMAIN}/g" \
+ -e "s/%cyrus_admin_password%/${CYRUS_ADMIN_PASSWORD}/g" \
+ -e "s/%kolab_service_password%/${KOLAB_SERVICE_PASSWORD}/g" \
+ /usr/share/dirsrv/data/template.ldif
+
+cat >/tmp/setup-ds.inf <<EOF
+[General]
+FullMachineName = ${HOSTNAME}.${DOMAIN}
+SuiteSpotUserID = nobody
+SuiteSpotGroup = nobody
+AdminDomain = ${DOMAIN}
+ConfigDirectoryLdapURL = ldap://${KOLAB_LDAP_MASTER_SERVICE_HOST}:389/o=NetscapeRoot
+ConfigDirectoryAdminID = admin
+ConfigDirectoryAdminPwd = ${ADMIN_PASSWORD}
+
+[slapd]
+SlapdConfigForMC = Yes
+UseExistingMC = 0
+ServerPort = 389
+ServerIdentifier = ldap
+Suffix = $(domain_to_root_dn ${DOMAIN})
+RootDN = cn=Directory Manager
+RootDNPwd = ${DIRECTORY_MANAGER_PASSWORD}
+ds_bename = $(echo ${DOMAIN} | sed -e 's/\./_/g')
+AddSampleEntries = No
+EOF
+
+if [ ! -d "/etc/dirsrv/slapd-ldap/" ]; then
+ timeout 40s setup-ds.pl --debug --silent --file=/tmp/setup-ds.inf || :
+ kill -15 ns-slapd
+
+ if [ -f /var/run/dirsrv/slapd-ldap.pid ]; then
+
+ tries=1
+ while [ ! -z "$(cat /var/run/dirsrv/slapd-ldap.pid) 2>/dev/null)" -a ${tries} -le 20 ]; do
+ echo "Waiting for process $(cat /var/run/dirsrv/slapd-ldap.pid) to terminate..."
+ sleep 1
+ let tries++
+ done
+
+ kill -9 $(cat /var/run/dirsrv/slapd-ldap.pid) 2>/dev/null || :
+ fi
+fi
+
+persist \
+ /etc/dirsrv/ \
+ /etc/kolab/ \
+ /var/lib/dirsrv/
+
+exec "$@"
diff --git a/03-ldap-slave/Dockerfile b/03-ldap-slave/Dockerfile
new file mode 100644
index 0000000..b0651a4
--- /dev/null
+++ b/03-ldap-slave/Dockerfile
@@ -0,0 +1,4 @@
+FROM kolab/base-ldap:latest
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
diff --git a/03-ldap-slave/entrypoint.sh b/03-ldap-slave/entrypoint.sh
new file mode 100755
index 0000000..3999ac7
--- /dev/null
+++ b/03-ldap-slave/entrypoint.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+exec "$@"
+
+exec top
diff --git a/03-manticore/Dockerfile b/03-manticore/Dockerfile
new file mode 100644
index 0000000..ec864f2
--- /dev/null
+++ b/03-manticore/Dockerfile
@@ -0,0 +1,49 @@
+FROM kolab/base-nodejs:latest
+
+MAINTAINER Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>
+
+RUN npm install -g \
+ grunt-cli \
+ phantomjs && \
+ rm -rf /root/.npm/
+
+WORKDIR /var/www/
+RUN git clone https://git.kolab.org/diffusion/M/manticore.git /var/www/manticore.git/
+
+WORKDIR /var/www/manticore.git/
+RUN npm install && \
+ npm dedupe && \
+ rm -rf /root/.npm/
+
+RUN bower install --allow-root
+RUN grunt build
+
+RUN mv server/config/local.env.sample.js server/config/local.env.js
+RUN sed -r -i \
+ -e "s|DOMAIN:.*,$|DOMAIN: 'http://localhost:8080',|g" \
+ -e "s|STORAGE:.*$|STORAGE: 'local'|g" \
+ -e "/WEBDAV_/d" \
+ -e "/LDAP_/d" \
+ -e "/LOCODOC_/d" \
+ server/config/local.env.js
+
+RUN sed -r -i \
+ -e 's|^(\s+)root:.*,$|\1root: "/var/www/manticore.git",|g' \
+ server/config/environment/index.js
+
+RUN chown nobody:nobody \
+ /var/www/manticore.git/server/config/seed.js \
+ /var/www/manticore.git/server/config/
+
+RUN ln -s dist/public/ public
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+ENTRYPOINT [ "/entrypoint.sh" ]
+
+USER nobody
+
+ENV NODE_PATH /usr/lib/node_modules:/var/www/manticore.git/node_modules
+ENV NODE_ENV production
+
+CMD [ "/bin/node", "/var/www/manticore.git/server/app.js" ]
diff --git a/03-manticore/entrypoint.sh b/03-manticore/entrypoint.sh
new file mode 100644
index 0000000..b583756
--- /dev/null
+++ b/03-manticore/entrypoint.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_vars \
+ MONGODB_DATABASE \
+ MONGODB_PASSWORD \
+ MONGODB_SERVICE_HOST \
+ MONGODB_USERNAME \
+ || exit 1
+
+sed -i \
+ -e "s/email: 'admin@admin.com',/email: '${MONGODB_ADMIN_EMAIL:-admin@admin.com}',/g" \
+ -e "s/password: 'admin',/password: '${MONGODB_ADMIN_PASSWORD:-password}'/g" \
+ /var/www/manticore.git/server/config/seed.js
+
+export MONGOLAB_URI="mongodb://${MONGODB_USERNAME}:${MONGODB_PASSWORD}@${MONGODB_SERVICE_HOST}/${MONGODB_DATABASE}"
+
+exec "$@"
diff --git a/03-roundcube-next/Dockerfile b/03-roundcube-next/Dockerfile
new file mode 100644
index 0000000..c8d486c
--- /dev/null
+++ b/03-roundcube-next/Dockerfile
@@ -0,0 +1,45 @@
+FROM kolab/base-nodejs:latest
+
+MAINTAINER Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>
+
+#ENV GITHUB_ACCOUNT=kanarip
+#ENV GIT_BRANCH=dev/ember-build-fails
+
+RUN yum -y install \
+ ruby-devel \
+ rubygem-bundler && \
+ yum clean all
+
+RUN npm install --verbose -g \
+ ember-cli && \
+ rm -rf /root/.npm/
+
+RUN git clone \
+ -b ${GIT_BRANCH:-master} \
+ https://github.com/${GITHUB_ACCOUNT:-roundcube-next}/roundcube-shell.git \
+ /var/www/roundcube-shell.git/ && \
+ rm -rf /var/www/roundcube-shell.git/.git/
+
+WORKDIR /var/www/roundcube-shell.git/
+
+RUN npm install --verbose && \
+ rm -rf /root/.npm/
+
+RUN bower --allow-root install
+
+# These fail, see https://git.kolab.org/T858
+RUN sed -i \
+ -e '/ES6 only/,+19d' \
+ node_modules/jscs/lib/config/configuration.js
+
+# This fails without setting JMAP_HOST environment variable
+#RUN ember build --environment production
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
+CMD [ \
+ "ember", \
+ "server", \
+ "--live-reload=false" \
+ ]
diff --git a/03-roundcube-next/entrypoint.sh b/03-roundcube-next/entrypoint.sh
new file mode 100644
index 0000000..4196f23
--- /dev/null
+++ b/03-roundcube-next/entrypoint.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_var KOLAB_JMAP_PROXY_SERVICE_HOST || check_var JMAP_HOST || exit 1
+
+if [ ! -z "${KOLAB_JMAP_PROXY_SERVICE_HOST}" ]; then
+ export JMAP_HOST="http://${KOLAB_JMAP_PROXY_SERVICE_HOST}:${KOLAB_JMAP_PROXY_SERVICE_PORT:-80}"
+fi
+
+exec "$@"
diff --git a/03-roundcubemail/Dockerfile b/03-roundcubemail/Dockerfile
new file mode 100644
index 0000000..eb27e58
--- /dev/null
+++ b/03-roundcubemail/Dockerfile
@@ -0,0 +1,10 @@
+FROM kolab/base-web-rc:latest
+
+RUN yum -y install \
+ roundcubemail \
+ roundcubemail-plugin-contextmenu \
+ roundcubemail-plugins-kolab && \
+ yum clean all
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
diff --git a/03-roundcubemail/entrypoint.sh b/03-roundcubemail/entrypoint.sh
new file mode 100644
index 0000000..11a8840
--- /dev/null
+++ b/03-roundcubemail/entrypoint.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_var MARIADB_SERVICE_HOST || check_var ROUNDCUBEMAIL_DATABASE_SERVICE_HOST || exit 1
+
+check_vars \
+ DOMAIN \
+ KOLAB_LDAP_MASTER_SERVICE_HOST \
+ KOLAB_LDAP_MASTER_SERVICE_PORT \
+ KOLAB_SERVICE_PASSWORD \
+ KOLAB_ROUNDCUBEMAIL_DATABASE_USERNAME \
+ KOLAB_ROUNDCUBEMAIL_DATABASE_PASSWORD \
+ KOLAB_ROUNDCUBEMAIL_DATABASE_NAME \
+ || exit 1
+
+if [ ! -z "${MARIADB_SERVICE_HOST}" ]; then
+ db_host=${MARIADB_SERVICE_HOST}
+else
+ db_host=${ROUNDCUBEMAIL_DATABASE_SERVICE_HOST}
+fi
+
+sed -i -r \
+ -e "s/^primary_domain = .*$/primary_domain = ${DOMAIN}/g" \
+ -e "s|^ldap_uri = .*$|ldap_uri = ldap://${KOLAB_LDAP_MASTER_SERVICE_HOST}:${KOLAB_LDAP_MASTER_SERVICE_PORT}|g" \
+ -e "s/^base_dn = .*$/base_dn = $(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^domain_base_dn = .*$/domain_base_dn = ou=Domains,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_dn = .*$/bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_pw = .*$/bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ -e "s/^service_bind_dn = .*$/service_bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^service_bind_pw = .*$/service_bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ /etc/kolab/kolab.conf
+
+export TERM=xterm
+tables=$(mysql \
+ -h ${db_host} \
+ -u ${KOLAB_ROUNDCUBEMAIL_DATABASE_USERNAME} \
+ --password=${KOLAB_ROUNDCUBEMAIL_DATABASE_PASSWORD} \
+ ${KOLAB_ROUNDCUBEMAIL_DATABASE_NAME} \
+ -e 'show tables;' \
+ 2>/dev/null
+ )
+
+if [ -z "${tables}" ]; then
+ mysql \
+ -h ${db_host} \
+ -u ${KOLAB_ROUNDCUBEMAIL_DATABASE_USERNAME} \
+ --password=${KOLAB_ROUNDCUBEMAIL_DATABASE_PASSWORD} \
+ ${KOLAB_ROUNDCUBEMAIL_DATABASE_NAME} \
+ < /usr/share/doc/roundcubemail-*/SQL/mysql.initial.sql
+fi
+
+exec "$@"
diff --git a/03-submission/Dockerfile b/03-submission/Dockerfile
new file mode 100644
index 0000000..a56f427
--- /dev/null
+++ b/03-submission/Dockerfile
@@ -0,0 +1,7 @@
+FROM kolab/base-mx:latest
+
+RUN yum -y install \
+ kolab-saslauthd && \
+ yum clean all
+
+EXPOSE 587
diff --git a/03-syncroton/Dockerfile b/03-syncroton/Dockerfile
new file mode 100644
index 0000000..0a8df1f
--- /dev/null
+++ b/03-syncroton/Dockerfile
@@ -0,0 +1,8 @@
+FROM kolab/base-web-rc:latest
+
+RUN yum -y install \
+ kolab-syncroton && \
+ yum clean all
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
diff --git a/03-syncroton/entrypoint.sh b/03-syncroton/entrypoint.sh
new file mode 100755
index 0000000..5fc4448
--- /dev/null
+++ b/03-syncroton/entrypoint.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+exec "$@"
diff --git a/03-wallace/Dockerfile b/03-wallace/Dockerfile
new file mode 100644
index 0000000..38aa7f5
--- /dev/null
+++ b/03-wallace/Dockerfile
@@ -0,0 +1,16 @@
+FROM kolab/base:latest
+
+RUN yum -y install \
+ wallace && \
+ yum clean all
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
+
+VOLUME [ "/var/spool/pykolab/wallace" ]
+
+EXPOSE 10026
+
+CMD [ \
+ "wallaced" \
+ ]
diff --git a/03-wallace/entrypoint.sh b/03-wallace/entrypoint.sh
new file mode 100644
index 0000000..5c1ebd7
--- /dev/null
+++ b/03-wallace/entrypoint.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_vars \
+ DOMAIN \
+ KOLAB_LDAP_MASTER_SERVICE_HOST \
+ KOLAB_LDAP_MASTER_SERVICE_PORT \
+ KOLAB_SERVICE_PASSWORD \
+ || exit 1
+
+sed -i -r \
+ -e "s/^primary_domain = .*$/primary_domain = ${DOMAIN}/g" \
+ -e "s|^ldap_uri = .*$|ldap_uri = ldap://${KOLAB_LDAP_MASTER_SERVICE_HOST}:${KOLAB_LDAP_MASTER_SERVICE_PORT}|g" \
+ -e "s/^base_dn = .*$/base_dn = $(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^domain_base_dn = .*$/domain_base_dn = ou=Domains,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_dn = .*$/bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_pw = .*$/bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ -e "s/^service_bind_dn = .*$/service_bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^service_bind_pw = .*$/service_bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ /etc/kolab/kolab.conf
+
+persist \
+ /var/spool/pykolab/wallace/
+
+exec "$@"
diff --git a/03-webadmin/Dockerfile b/03-webadmin/Dockerfile
new file mode 100644
index 0000000..65c12d1
--- /dev/null
+++ b/03-webadmin/Dockerfile
@@ -0,0 +1,11 @@
+FROM kolab/base-web-rc:latest
+
+RUN yum -y --setopt tsflags= install \
+ kolab-webadmin && \
+ yum -y install \
+ mariadb \
+ pykolab && \
+ yum clean all
+
+ADD /entrypoint.sh /entrypoint.sh
+RUN chmod a+x /entrypoint.sh
diff --git a/03-webadmin/entrypoint.sh b/03-webadmin/entrypoint.sh
new file mode 100644
index 0000000..c1facb7
--- /dev/null
+++ b/03-webadmin/entrypoint.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+. /functions.sh
+
+check_var MARIADB_SERVICE_HOST || check_var WEBADMIN_DATABASE_SERVICE_HOST || exit 1
+
+check_vars \
+ DOMAIN \
+ KOLAB_LDAP_MASTER_SERVICE_HOST \
+ KOLAB_LDAP_MASTER_SERVICE_PORT \
+ KOLAB_SERVICE_PASSWORD \
+ KOLAB_WEBADMIN_DATABASE_USERNAME \
+ KOLAB_WEBADMIN_DATABASE_PASSWORD \
+ KOLAB_WEBADMIN_DATABASE_NAME \
+ || exit 1
+
+if [ ! -z "${MARIADB_SERVICE_HOST}" ]; then
+ db_host=${MARIADB_SERVICE_HOST}
+else
+ db_host=${WEBADMIN_DATABASE_SERVICE_HOST}
+fi
+
+sed -i -r \
+ -e "s/^primary_domain = .*$/primary_domain = ${DOMAIN}/g" \
+ -e "s|^ldap_uri = .*$|ldap_uri = ldap://${KOLAB_LDAP_MASTER_SERVICE_HOST}:${KOLAB_LDAP_MASTER_SERVICE_PORT}|g" \
+ -e "s/^base_dn = .*$/base_dn = $(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^domain_base_dn = .*$/domain_base_dn = ou=Domains,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_dn = .*$/bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^bind_pw = .*$/bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ -e "s/^service_bind_dn = .*$/service_bind_dn = uid=kolab-service,ou=Special Users,$(domain_to_root_dn ${DOMAIN})/g" \
+ -e "s/^service_bind_pw = .*$/service_bind_pw = ${KOLAB_SERVICE_PASSWORD}/g" \
+ -e "s|^sql_uri = .*$|sql_uri = mysql://${KOLAB_WEBADMIN_DATABASE_USERNAME}:${KOLAB_WEBADMIN_DATABASE_PASSWORD}@${db_host}/${KOLAB_WEBADMIN_DATABASE_NAME}|g" \
+ /etc/kolab/kolab.conf
+
+export TERM=xterm
+tables=$(mysql \
+ -h ${db_host} \
+ -u ${KOLAB_WEBADMIN_DATABASE_USERNAME} \
+ --password=${KOLAB_WEBADMIN_DATABASE_PASSWORD} \
+ ${KOLAB_WEBADMIN_DATABASE_NAME} \
+ -e 'show tables;' \
+ 2>/dev/null
+ )
+
+if [ -z "${tables}" ]; then
+ mysql \
+ -h ${db_host} \
+ -u ${KOLAB_WEBADMIN_DATABASE_USERNAME} \
+ --password=${KOLAB_WEBADMIN_DATABASE_PASSWORD} \
+ ${KOLAB_WEBADMIN_DATABASE_NAME} \
+ < /usr/share/doc/kolab-webadmin-*/kolab_wap.sql
+fi
+
+exec "$@"
diff --git a/04-chwala-database/Dockerfile b/04-chwala-database/Dockerfile
new file mode 100644
index 0000000..fae1fbc
--- /dev/null
+++ b/04-chwala-database/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/mariadb-centos7-atomicapp
+
+RUN sed -i -r \
+ -e 's/name: mariadb/name: chwala-database/g' \
+ /application-entity/artifacts/kubernetes/*.yaml
+
+RUN sed -i -r \
+ -e 's/(id|name): mariadb-/\1: chwala-database-/g' \
+ /application-entity/Nulecule
diff --git a/04-freebusy-database/Dockerfile b/04-freebusy-database/Dockerfile
new file mode 100644
index 0000000..e9ec8f6
--- /dev/null
+++ b/04-freebusy-database/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/mariadb-centos7-atomicapp
+
+RUN sed -i -r \
+ -e 's/name: mariadb/name: freebusy-database/g' \
+ /application-entity/artifacts/kubernetes/*.yaml
+
+RUN sed -i -r \
+ -e 's/(id|name): mariadb-/\1: freebusy-database-/g' \
+ /application-entity/Nulecule
diff --git a/04-irony-database/Dockerfile b/04-irony-database/Dockerfile
new file mode 100644
index 0000000..9f281d0
--- /dev/null
+++ b/04-irony-database/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/mariadb-centos7-atomicapp
+
+RUN sed -i -r \
+ -e 's/name: mariadb/name: irony-database/g' \
+ /application-entity/artifacts/kubernetes/*.yaml
+
+RUN sed -i -r \
+ -e 's/(id|name): mariadb-/\1: irony-database-/g' \
+ /application-entity/Nulecule
diff --git a/04-roundcubemail-database/Dockerfile b/04-roundcubemail-database/Dockerfile
new file mode 100644
index 0000000..69f11f3
--- /dev/null
+++ b/04-roundcubemail-database/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/mariadb-centos7-atomicapp
+
+RUN sed -i -r \
+ -e 's/name: mariadb/name: roundcubemail-database/g' \
+ /application-entity/artifacts/kubernetes/*.yaml
+
+RUN sed -i -r \
+ -e 's/(id|name): mariadb-/\1: roundcubemail-database-/g' \
+ /application-entity/Nulecule
diff --git a/04-syncroton-database/Dockerfile b/04-syncroton-database/Dockerfile
new file mode 100644
index 0000000..41f3904
--- /dev/null
+++ b/04-syncroton-database/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/mariadb-centos7-atomicapp
+
+RUN sed -i -r \
+ -e 's/name: mariadb/name: syncroton-database/g' \
+ /application-entity/artifacts/kubernetes/*.yaml
+
+RUN sed -i -r \
+ -e 's/(id|name): mariadb-/\1: syncroton-database-/g' \
+ /application-entity/Nulecule
diff --git a/04-webadmin-database/Dockerfile b/04-webadmin-database/Dockerfile
new file mode 100644
index 0000000..c6572a7
--- /dev/null
+++ b/04-webadmin-database/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/mariadb-centos7-atomicapp
+
+RUN sed -i -r \
+ -e 's/name: mariadb/name: webadmin-database/g' \
+ /application-entity/artifacts/kubernetes/*.yaml
+
+RUN sed -i -r \
+ -e 's/(id|name): mariadb-/\1: webadmin-database-/g' \
+ /application-entity/Nulecule
diff --git a/05-asav-in-atomicapp/Dockerfile b/05-asav-in-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-asav-in-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-asav-in-atomicapp/Nulecule b/05-asav-in-atomicapp/Nulecule
new file mode 100644
index 0000000..89c3148
--- /dev/null
+++ b/05-asav-in-atomicapp/Nulecule
@@ -0,0 +1,42 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-asav-in",
+ "metadata": {
+ "name": "Kolab Inbound Anti-Spam and Anti-Virus",
+ "appversion": "development",
+ "description": "Kolab Inbound Anti-Spam and Anti-Virus"
+ },
+ "graph": [
+ {
+ "name": "kolab-asav-in",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/asav-in"
+ },
+ {
+ "name": "domain",
+ "description": "Domain",
+ "default": "docker.container"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-asav-in-atomicapp/artifacts/docker/run-pod b/05-asav-in-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..fcc9800
--- /dev/null
+++ b/05-asav-in-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,7 @@
+docker run -d \
+ --name kolab-asav-in-atomicapp-app \
+ --link kolab-ext-mx-in-atomicapp-app:10025 \
+ -p 10024:10024 \
+ -e DOMAIN=${domain} \
+ -e FORWARD_METHOD=${forward_method} \
+ $image
diff --git a/05-asav-in-atomicapp/artifacts/kubernetes/pod.json b/05-asav-in-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..d617064
--- /dev/null
+++ b/05-asav-in-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,30 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-asav-in",
+ "metadata": {
+ "name": "kolab-asav-in",
+ "labels": {
+ "name": "kolab-asav-in"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-asav-in",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 10024
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-asav-in-atomicapp/artifacts/kubernetes/service.json b/05-asav-in-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..91f9217
--- /dev/null
+++ b/05-asav-in-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,21 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-asav-in",
+ "labels": {
+ "name": "kolab-asav-in"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "port": 10024,
+ "targetPort": 10024
+ }
+ ],
+ "selector": {
+ "name": "kolab-asav-in"
+ }
+ }
+}
diff --git a/05-asav-out-atomicapp/Dockerfile b/05-asav-out-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-asav-out-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-asav-out-atomicapp/Nulecule b/05-asav-out-atomicapp/Nulecule
new file mode 100644
index 0000000..009cbd5
--- /dev/null
+++ b/05-asav-out-atomicapp/Nulecule
@@ -0,0 +1,42 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-asav-out",
+ "metadata": {
+ "name": "Kolab Inbound Anti-Spam and Anti-Virus",
+ "appversion": "development",
+ "description": "Kolab Inbound Anti-Spam and Anti-Virus"
+ },
+ "graph": [
+ {
+ "name": "kolab-asav-out",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/asav-out"
+ },
+ {
+ "name": "domain",
+ "description": "Domain",
+ "default": "docker.container"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-asav-out-atomicapp/artifacts/docker/run-pod b/05-asav-out-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..d06bd31
--- /dev/null
+++ b/05-asav-out-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,4 @@
+docker run -d \
+ -p 10024:10024 \
+ -e DOMAIN=${domain} \
+ $image
diff --git a/05-asav-out-atomicapp/artifacts/kubernetes/pod.json b/05-asav-out-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..5e7bd45
--- /dev/null
+++ b/05-asav-out-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,30 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-asav-out",
+ "metadata": {
+ "name": "kolab-asav-out",
+ "labels": {
+ "name": "kolab-asav-out"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-asav-out",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 10024
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-asav-out-atomicapp/artifacts/kubernetes/service.json b/05-asav-out-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..805d50b
--- /dev/null
+++ b/05-asav-out-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,21 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-asav-out",
+ "labels": {
+ "name": "kolab-asav-out"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "port": 10024,
+ "targetPort": 10024
+ }
+ ],
+ "selector": {
+ "name": "kolab-asav-out"
+ }
+ }
+}
diff --git a/05-chwala-atomicapp/Dockerfile b/05-chwala-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-chwala-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-chwala-atomicapp/Nulecule b/05-chwala-atomicapp/Nulecule
new file mode 100644
index 0000000..4d1bae9
--- /dev/null
+++ b/05-chwala-atomicapp/Nulecule
@@ -0,0 +1,45 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-chwala",
+ "metadata": {
+ "name": "Kolab File Cloud Interface",
+ "appversion": "development",
+ "description": "File Cloud Interface"
+ },
+ "graph": [
+ {
+ "name": "kolab-chwala",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/chwala"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": "kolab-chwala-database",
+ "source": "docker://kolab/chwala-database"
+ }
+ ]
+}
diff --git a/05-chwala-atomicapp/artifacts/docker/run-pod b/05-chwala-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..8d0b129
--- /dev/null
+++ b/05-chwala-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,5 @@
+docker run -d \
+ -p 80:80 \
+ -p 443:443 \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-chwala-atomicapp/artifacts/kubernetes/pod.json b/05-chwala-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..bd69ac8
--- /dev/null
+++ b/05-chwala-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,48 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-chwala",
+ "labels": {
+ "name": "kolab-chwala"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-chwala",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 80
+ },
+ {
+ "containerPort": 443
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ },
+ {
+ "name": "KOLAB_CHWALA_DATABASE_NAME",
+ "value": "$kolab_chwala_database_name"
+ },
+ {
+ "name": "KOLAB_CHWALA_DATABASE_PASSWORD",
+ "value": "$kolab_chwala_database_password"
+ },
+ {
+ "name": "KOLAB_CHWALA_DATABASE_USERNAME",
+ "value": "$kolab_chwala_database_username"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-chwala-atomicapp/artifacts/kubernetes/service.json b/05-chwala-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..0972140
--- /dev/null
+++ b/05-chwala-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,28 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-chwala",
+ "labels": {
+ "name": "kolab-chwala"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "http",
+ "port": 80,
+ "targetPort": 80
+ },
+ {
+ "name": "https",
+ "port": 443,
+ "targetPort": 443
+ }
+ ],
+ "selector": {
+ "name": "kolab-chwala"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-ext-mx-in-atomicapp/Dockerfile b/05-ext-mx-in-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-ext-mx-in-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-ext-mx-in-atomicapp/Nulecule b/05-ext-mx-in-atomicapp/Nulecule
new file mode 100644
index 0000000..c0b5bcc
--- /dev/null
+++ b/05-ext-mx-in-atomicapp/Nulecule
@@ -0,0 +1,52 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-ext-mx-in",
+ "metadata": {
+ "name": "Kolab External Mail Exchanger for Inbound Traffic",
+ "appversion": "1.0.0",
+ "description": "Atomic Application for Inbound Message Traffic"
+ },
+ "graph": [
+ {
+ "name": "kolab-asav-in",
+ "source": "docker://kolab/asav-in-atomicapp"
+ },
+ {
+ "name": "kolab-ext-mx-in",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/ext-mx-in"
+ },
+ {
+ "name": "domain",
+ "description": "Domain name space",
+ "default": "docker.container"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password",
+ "default": "welcome123"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/controller.json",
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-ext-mx-in-atomicapp/README.md b/05-ext-mx-in-atomicapp/README.md
new file mode 100644
index 0000000..fe3b928
--- /dev/null
+++ b/05-ext-mx-in-atomicapp/README.md
@@ -0,0 +1,2 @@
+## External Mail Exchanger (Inbound)
+
diff --git a/05-ext-mx-in-atomicapp/artifacts/docker/run-pod b/05-ext-mx-in-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..7685819
--- /dev/null
+++ b/05-ext-mx-in-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,7 @@
+docker run -d \
+ --name kolab-ext-mx-in-atomicapp-app \
+ --link kolab-asav-in-atomicapp-app:amavis \
+ -p 25:25 \
+ -p 10025:10025 \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-ext-mx-in-atomicapp/artifacts/kubernetes/controller.json b/05-ext-mx-in-atomicapp/artifacts/kubernetes/controller.json
new file mode 100644
index 0000000..7b1ea51
--- /dev/null
+++ b/05-ext-mx-in-atomicapp/artifacts/kubernetes/controller.json
@@ -0,0 +1,38 @@
+{
+ "kind": "ReplicationController",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-ext-mx-in",
+ "labels": {
+ "name": "kolab-ext-mx-in"
+ }
+ },
+ "spec": {
+ "replicas": 1,
+ "selector": {
+ "name": "kolab-ext-mx-in"
+ },
+ "template": {
+ "metadata": {
+ "labels": {
+ "name": "kolab-ext-mx-in"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-ext-mx-in",
+ "image": "$image",
+ "ports": [
+ {
+ "name": "smtp",
+ "containerPort": 25,
+ "nodePort": 25
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/05-ext-mx-in-atomicapp/artifacts/kubernetes/pod.json b/05-ext-mx-in-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..3c28a81
--- /dev/null
+++ b/05-ext-mx-in-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,37 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-ext-mx-in",
+ "metadata": {
+ "name": "kolab-ext-mx-in",
+ "labels": {
+ "name": "kolab-ext-mx-in"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-ext-mx-in",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 25
+ },
+ {
+ "containerPort": 10025
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-ext-mx-in-atomicapp/artifacts/kubernetes/service.json b/05-ext-mx-in-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..6e27cb1
--- /dev/null
+++ b/05-ext-mx-in-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,23 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-ext-mx-in",
+ "labels": {
+ "name": "kolab-ext-mx-in"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "smtp",
+ "port": 25,
+ "targetPort": 25
+ }
+ ],
+ "selector": {
+ "name": "kolab-ext-mx-in"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-ext-mx-out-atomicapp/Dockerfile b/05-ext-mx-out-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-ext-mx-out-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-ext-mx-out-atomicapp/Nulecule b/05-ext-mx-out-atomicapp/Nulecule
new file mode 100644
index 0000000..b2f90a7
--- /dev/null
+++ b/05-ext-mx-out-atomicapp/Nulecule
@@ -0,0 +1,50 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-ext-mx-out",
+ "metadata": {
+ "name": "kolab-ext-mx-out",
+ "appversion": "development",
+ "description": "External Mail Exchanger (Outbound)"
+ },
+ "graph": [
+ {
+ "name": "kolab-asav-out",
+ "source": "docker://kolab/asav-out-atomicapp"
+ },
+ {
+ "name": "kolab-ext-mx-out",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/ext-mx-out"
+ },
+ {
+ "name": "domain",
+ "description": "Domain name space",
+ "default": "docker.container"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Account Password"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-ext-mx-out-atomicapp/README.md b/05-ext-mx-out-atomicapp/README.md
new file mode 100644
index 0000000..cb0f6e0
--- /dev/null
+++ b/05-ext-mx-out-atomicapp/README.md
@@ -0,0 +1 @@
+## External Mail Exchanger (Outbound)
diff --git a/05-ext-mx-out-atomicapp/artifacts/docker/run-pod b/05-ext-mx-out-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..b3c2855
--- /dev/null
+++ b/05-ext-mx-out-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,4 @@
+docker run -d \
+ -p 25:25 \
+ -p 10025:10025 \
+ $image
diff --git a/05-ext-mx-out-atomicapp/artifacts/kubernetes/pod.json b/05-ext-mx-out-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..54573cc
--- /dev/null
+++ b/05-ext-mx-out-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,37 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-ext-mx-out",
+ "metadata": {
+ "name": "kolab-ext-mx-out",
+ "labels": {
+ "name": "kolab-ext-mx-out"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-ext-mx-out",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 25
+ },
+ {
+ "containerPort": 10025
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-ext-mx-out-atomicapp/artifacts/kubernetes/service.json b/05-ext-mx-out-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..76ef520
--- /dev/null
+++ b/05-ext-mx-out-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,28 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-ext-mx-out",
+ "labels": {
+ "name": "kolab-ext-mx-out"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "smtp",
+ "port": 25,
+ "targetPort": 25
+ },
+ {
+ "name": "submission",
+ "port": 10025,
+ "targetPort": 10025
+ }
+ ],
+ "selector": {
+ "name": "kolab-ext-mx-out"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-freebusy-atomicapp/Dockerfile b/05-freebusy-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-freebusy-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-freebusy-atomicapp/Nulecule b/05-freebusy-atomicapp/Nulecule
new file mode 100644
index 0000000..9622edd
--- /dev/null
+++ b/05-freebusy-atomicapp/Nulecule
@@ -0,0 +1,65 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-freebusy",
+ "metadata": {
+ "name": "Kolab Free/Busy Interface",
+ "appversion": "14.0",
+ "description": "Free/Busy Interface"
+ },
+ "graph": [
+ {
+ "name": "kolab-freebusy",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/freebusy"
+ },
+ {
+ "name": "domain",
+ "description": "Domain Name Space",
+ "default": "docker.container"
+ },
+ {
+ "name": "kolab_freebusy_database_name",
+ "description": "Database name",
+ "default": "freebusy"
+ },
+ {
+ "name": "kolab_freebusy_database_password",
+ "description": "Database password",
+ "default": "welcome123"
+ },
+ {
+ "name": "kolab_freebusy_database_username",
+ "description": "Database user",
+ "default": "kolab"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": "kolab-freebusy-database",
+ "source": "docker://kolab/freebusy-database"
+ }
+ ]
+}
diff --git a/05-freebusy-atomicapp/artifacts/docker/run-pod b/05-freebusy-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..8d0b129
--- /dev/null
+++ b/05-freebusy-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,5 @@
+docker run -d \
+ -p 80:80 \
+ -p 443:443 \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-freebusy-atomicapp/artifacts/kubernetes/pod.json b/05-freebusy-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..6615730
--- /dev/null
+++ b/05-freebusy-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,45 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-freebusy",
+ "labels": {
+ "name": "kolab-freebusy"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-freebusy",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 80
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ },
+ {
+ "name": "KOLAB_FREEBUSY_DATABASE_NAME",
+ "value": "$kolab_freebusy_database_name"
+ },
+ {
+ "name": "KOLAB_FREEBUSY_DATABASE_PASSWORD",
+ "value": "$kolab_freebusy_database_password"
+ },
+ {
+ "name": "KOLAB_FREEBUSY_DATABASE_USERNAME",
+ "value": "$kolab_freebusy_database_username"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-freebusy-atomicapp/artifacts/kubernetes/service.json b/05-freebusy-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..d3def10
--- /dev/null
+++ b/05-freebusy-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,28 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-freebusy",
+ "labels": {
+ "name": "kolab-freebusy"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "http",
+ "port": 80,
+ "targetPort": 80
+ },
+ {
+ "name": "https",
+ "port": 443,
+ "targetPort": 443
+ }
+ ],
+ "selector": {
+ "name": "kolab-freebusy"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-freebusy-atomicapp/entrypoint.sh b/05-freebusy-atomicapp/entrypoint.sh
new file mode 100755
index 0000000..6792eeb
--- /dev/null
+++ b/05-freebusy-atomicapp/entrypoint.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+exec top
diff --git a/05-guam-atomicapp/Dockerfile b/05-guam-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-guam-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-guam-atomicapp/Nulecule b/05-guam-atomicapp/Nulecule
new file mode 100644
index 0000000..6548f54
--- /dev/null
+++ b/05-guam-atomicapp/Nulecule
@@ -0,0 +1,38 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-guam",
+ "metadata": {
+ "name": "Kolab IMAP Backend",
+ "appversion": "2.5.6",
+ "description": "Cyrus IMAP Backend Container"
+ },
+ "graph": [
+ {
+ "name": "kolab-guam",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/guam"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/controller.json",
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-guam-atomicapp/README.md b/05-guam-atomicapp/README.md
new file mode 100644
index 0000000..77acf09
--- /dev/null
+++ b/05-guam-atomicapp/README.md
@@ -0,0 +1,10 @@
+## The IMAP Reverse Proxy
+
+This is an IMAP Reverse Proxy for Kolab Groupware.
+
+It prevents clients that do not understand how to represent the
+contents of those IMAP folders that contain groupware data from reading
+and/or obtaining those very folders.
+
+It also bridges the gap between SPECIAL-USE clients and Kolab clients,
+whom may otherwise have to consider data in desync.
diff --git a/05-guam-atomicapp/artifacts/docker/run-pod b/05-guam-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..0948d3c
--- /dev/null
+++ b/05-guam-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,9 @@
+docker run -d \
+ -p 110:110 \
+ -p 143:143 \
+ -p 993:993 \
+ -p 995:995 \
+ -p 4190:4190 \
+ -e CYRUS_ADMIN_PASSWORD=$cyrus_admin_password \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-guam-atomicapp/artifacts/kubernetes/controller.json b/05-guam-atomicapp/artifacts/kubernetes/controller.json
new file mode 100644
index 0000000..3f9b26f
--- /dev/null
+++ b/05-guam-atomicapp/artifacts/kubernetes/controller.json
@@ -0,0 +1,41 @@
+{
+ "kind": "ReplicationController",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-guam",
+ "labels": {
+ "name": "kolab-guam"
+ }
+ },
+ "spec": {
+ "replicas": 1,
+ "selector": {
+ "name": "kolab-guam"
+ },
+ "template": {
+ "metadata": {
+ "labels": {
+ "name": "kolab-guam"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-guam",
+ "image": "$image",
+ "ports": [
+ {
+ "name": "imap",
+ "containerPort": 143
+ },
+ {
+ "name": "imaps",
+ "containerPort": 993
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/05-guam-atomicapp/artifacts/kubernetes/pod.json b/05-guam-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..ca04aee
--- /dev/null
+++ b/05-guam-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,27 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-guam",
+ "metadata": {
+ "name": "kolab-guam",
+ "labels": {
+ "name": "kolab-guam"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-guam",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 143
+ },
+ {
+ "containerPort": 993
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-guam-atomicapp/artifacts/kubernetes/service.json b/05-guam-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..50e386d
--- /dev/null
+++ b/05-guam-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,28 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-guam",
+ "labels": {
+ "name": "kolab-guam"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "imap",
+ "port": 143,
+ "targetPort": 143
+ },
+ {
+ "name": "imaps",
+ "port": 993,
+ "targetPort": 993
+ }
+ ],
+ "selector": {
+ "name": "kolab-guam"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-guam-atomicapp/entrypoint.sh b/05-guam-atomicapp/entrypoint.sh
new file mode 100755
index 0000000..3999ac7
--- /dev/null
+++ b/05-guam-atomicapp/entrypoint.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+exec "$@"
+
+exec top
diff --git a/05-imap-mupdate-atomicapp/Dockerfile b/05-imap-mupdate-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-imap-mupdate-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-imap-mupdate-atomicapp/Nulecule b/05-imap-mupdate-atomicapp/Nulecule
new file mode 100644
index 0000000..cf20d72
--- /dev/null
+++ b/05-imap-mupdate-atomicapp/Nulecule
@@ -0,0 +1,50 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-imap-mupdate",
+ "metadata": {
+ "name": "Kolab Cyrus IMAP Mupdate server",
+ "appversion": "2.5.6",
+ "description": "Maintains mailbox information across the Cyrus IMAP Murder."
+ },
+ "graph": [
+ {
+ "name": "kolab-imap-mupdate",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/imap-mupdate"
+ },
+ {
+ "name": "domain",
+ "description": "Domain Name Space",
+ "default": "docker.container"
+ },
+ {
+ "name": "cyrus_admin_password",
+ "description": "Cyrus Administrator Password"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-imap-mupdate-atomicapp/artifacts/docker/run-pod b/05-imap-mupdate-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..bb18029
--- /dev/null
+++ b/05-imap-mupdate-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1 @@
+docker run -d -p 3905:3905 -e CYRUS_ADMIN_PASSWORD=$cyrus_admin_password -e KOLAB_SERVICE_PASSWORD=$kolab_service_password kolab/imap-mupdate
diff --git a/05-imap-mupdate-atomicapp/artifacts/kubernetes/pod.json b/05-imap-mupdate-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..7e7bfd2
--- /dev/null
+++ b/05-imap-mupdate-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,38 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-imap-mupdate",
+ "metadata": {
+ "name": "kolab-imap-mupdate",
+ "labels": {
+ "name": "kolab-imap-mupdate"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-imap-mupdate",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 3905
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "CYRUS_ADMIN_PASSWORD",
+ "value": "$cyrus_admin_password"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-imap-mupdate-atomicapp/artifacts/kubernetes/service.json b/05-imap-mupdate-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..3a8c31e
--- /dev/null
+++ b/05-imap-mupdate-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,23 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-imap-mupdate",
+ "labels": {
+ "name": "kolab-imap-mupdate"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "mupdate",
+ "port": 3905,
+ "targetPort": 3905
+ }
+ ],
+ "selector": {
+ "name": "kolab-imap-mupdate"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-imap-mupdate-atomicapp/entrypoint.sh b/05-imap-mupdate-atomicapp/entrypoint.sh
new file mode 100755
index 0000000..c8d10e7
--- /dev/null
+++ b/05-imap-mupdate-atomicapp/entrypoint.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+# Apply some configuration
+exec "$@"
diff --git a/05-imapb-atomicapp/Dockerfile b/05-imapb-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-imapb-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-imapb-atomicapp/Nulecule b/05-imapb-atomicapp/Nulecule
new file mode 100644
index 0000000..b675800
--- /dev/null
+++ b/05-imapb-atomicapp/Nulecule
@@ -0,0 +1,47 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-imapb",
+ "metadata": {
+ "name": "Kolab IMAP Backend",
+ "appversion": "development",
+ "description": "Cyrus IMAP Backend Container"
+ },
+ "graph": [
+ {
+ "name": "kolab-imapb",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/imapb"
+ },
+ {
+ "name": "cyrus_admin_password",
+ "description": "Cyrus Administrator Password",
+ "default": "$cyrus_admin_password"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password",
+ "default": "$kolab_service_password"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-imapb-atomicapp/artifacts/docker/run-pod b/05-imapb-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..0948d3c
--- /dev/null
+++ b/05-imapb-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,9 @@
+docker run -d \
+ -p 110:110 \
+ -p 143:143 \
+ -p 993:993 \
+ -p 995:995 \
+ -p 4190:4190 \
+ -e CYRUS_ADMIN_PASSWORD=$cyrus_admin_password \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-imapb-atomicapp/artifacts/kubernetes/service.json b/05-imapb-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..e67ac95
--- /dev/null
+++ b/05-imapb-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,43 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-imapb",
+ "labels": {
+ "name": "kolab-imapb"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "pop",
+ "port": 110,
+ "targetPort": 110
+ },
+ {
+ "name": "imap",
+ "port": 143,
+ "targetPort": 143
+ },
+ {
+ "name": "imaps",
+ "port": 993,
+ "targetPort": 993
+ },
+ {
+ "name": "pops",
+ "port": 995,
+ "targetPort": 995
+ },
+ {
+ "name": "managesieve",
+ "port": 4190,
+ "targetPort": 4190
+ }
+ ],
+ "selector": {
+ "name": "kolab-imapb"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-imapb-atomicapp/artifacts/kubernetes/storage.json b/05-imapb-atomicapp/artifacts/kubernetes/storage.json
new file mode 100644
index 0000000..851fc0c
--- /dev/null
+++ b/05-imapb-atomicapp/artifacts/kubernetes/storage.json
@@ -0,0 +1,17 @@
+{
+ "kind": "PersistentVolumeClaim",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-imapb"
+ },
+ "spec": {
+ "accessModes": [
+ "ReadWriteOnce"
+ ],
+ "resources": {
+ "requests": {
+ "storage": 3
+ }
+ }
+ }
+}
diff --git a/05-imapb-atomicapp/entrypoint.sh b/05-imapb-atomicapp/entrypoint.sh
new file mode 100755
index 0000000..d606f56
--- /dev/null
+++ b/05-imapb-atomicapp/entrypoint.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+# Apply some configuration
+exec "$@"
+
+exec top
diff --git a/05-imapf-ext-atomicapp/Dockerfile b/05-imapf-ext-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-imapf-ext-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-imapf-ext-atomicapp/Nulecule b/05-imapf-ext-atomicapp/Nulecule
new file mode 100644
index 0000000..668b23f
--- /dev/null
+++ b/05-imapf-ext-atomicapp/Nulecule
@@ -0,0 +1,50 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-imapf-ext",
+ "metadata": {
+ "name": "Kolab External IMAP Frontend",
+ "appversion": "development",
+ "description": "Used for external IMAP connections"
+ },
+ "graph": [
+ {
+ "name": "kolab-imapf-ext",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/imapf-ext"
+ },
+ {
+ "name": "domain",
+ "description": "Domain Name Space",
+ "default": "docker.container"
+ },
+ {
+ "name": "cyrus_admin_password",
+ "description": "Cyrus Administrator Password"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-imapf-ext-atomicapp/artifacts/docker/run-pod b/05-imapf-ext-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..0948d3c
--- /dev/null
+++ b/05-imapf-ext-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,9 @@
+docker run -d \
+ -p 110:110 \
+ -p 143:143 \
+ -p 993:993 \
+ -p 995:995 \
+ -p 4190:4190 \
+ -e CYRUS_ADMIN_PASSWORD=$cyrus_admin_password \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-imapf-ext-atomicapp/artifacts/kubernetes/pod.json b/05-imapf-ext-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..67ac15b
--- /dev/null
+++ b/05-imapf-ext-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,55 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-imapf-ext",
+ "metadata": {
+ "name": "kolab-imapf-ext",
+ "labels": {
+ "name": "kolab-imapf-ext"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-imapf-ext",
+ "image": "$image",
+ "ports": [
+ {
+ "name": "pop",
+ "containerPort": 110
+ },
+ {
+ "name": "imap",
+ "containerPort": 143
+ },
+ {
+ "name": "imaps",
+ "containerPort": 993
+ },
+ {
+ "name": "pops",
+ "containerPort": 995
+ },
+ {
+ "name": "managesieve",
+ "containerPort": 4190
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "CYRUS_ADMIN_PASSWORD",
+ "value": "$cyrus_admin_password"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-imapf-ext-atomicapp/artifacts/kubernetes/service.json b/05-imapf-ext-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..73efb4c
--- /dev/null
+++ b/05-imapf-ext-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,43 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-imapf-ext",
+ "labels": {
+ "name": "kolab-imapf-ext"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "pop",
+ "port": 110,
+ "targetPort": 110
+ },
+ {
+ "name": "imap",
+ "port": 143,
+ "targetPort": 143
+ },
+ {
+ "name": "imaps",
+ "port": 993,
+ "targetPort": 993
+ },
+ {
+ "name": "pops",
+ "port": 995,
+ "targetPort": 995
+ },
+ {
+ "name": "managesieve",
+ "port": 4190,
+ "targetPort": 4190
+ }
+ ],
+ "selector": {
+ "name": "kolab-imapf-ext"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-imapf-ext-atomicapp/entrypoint.sh b/05-imapf-ext-atomicapp/entrypoint.sh
new file mode 100755
index 0000000..d606f56
--- /dev/null
+++ b/05-imapf-ext-atomicapp/entrypoint.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+# Apply some configuration
+exec "$@"
+
+exec top
diff --git a/05-imapf-int-atomicapp/Dockerfile b/05-imapf-int-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-imapf-int-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-imapf-int-atomicapp/Nulecule b/05-imapf-int-atomicapp/Nulecule
new file mode 100644
index 0000000..e561269
--- /dev/null
+++ b/05-imapf-int-atomicapp/Nulecule
@@ -0,0 +1,50 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-imapf-int",
+ "metadata": {
+ "name": "Kolab Internal IMAP Frontend",
+ "appversion": "2.5.6",
+ "description": "Used for internal IMAP connections"
+ },
+ "graph": [
+ {
+ "name": "kolab-imapf-int",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/imapf-int"
+ },
+ {
+ "name": "domain",
+ "description": "Domain Name Space",
+ "default": "docker.container"
+ },
+ {
+ "name": "cyrus_admin_password",
+ "description": "Cyrus Administrator Password"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-imapf-int-atomicapp/artifacts/docker/run-pod b/05-imapf-int-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..0948d3c
--- /dev/null
+++ b/05-imapf-int-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,9 @@
+docker run -d \
+ -p 110:110 \
+ -p 143:143 \
+ -p 993:993 \
+ -p 995:995 \
+ -p 4190:4190 \
+ -e CYRUS_ADMIN_PASSWORD=$cyrus_admin_password \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-imapf-int-atomicapp/artifacts/kubernetes/pod.json b/05-imapf-int-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..0f60ba8
--- /dev/null
+++ b/05-imapf-int-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,55 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-imapf-int",
+ "metadata": {
+ "name": "kolab-imapf-int",
+ "labels": {
+ "name": "kolab-imapf-int"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-imapf-int",
+ "image": "$image",
+ "ports": [
+ {
+ "name": "pop",
+ "containerPort": 110
+ },
+ {
+ "name": "imap",
+ "containerPort": 143
+ },
+ {
+ "name": "imaps",
+ "containerPort": 993
+ },
+ {
+ "name": "pops",
+ "containerPort": 995
+ },
+ {
+ "name": "managesieve",
+ "containerPort": 4190
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "CYRUS_ADMIN_PASSWORD",
+ "value": "$cyrus_admin_password"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-imapf-int-atomicapp/artifacts/kubernetes/service.json b/05-imapf-int-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..7a7130e
--- /dev/null
+++ b/05-imapf-int-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,43 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-imapf-int",
+ "labels": {
+ "name": "kolab-imapf-int"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "pop",
+ "port": 110,
+ "targetPort": 110
+ },
+ {
+ "name": "imap",
+ "port": 143,
+ "targetPort": 143
+ },
+ {
+ "name": "imaps",
+ "port": 993,
+ "targetPort": 993
+ },
+ {
+ "name": "pops",
+ "port": 995,
+ "targetPort": 995
+ },
+ {
+ "name": "managesieve",
+ "port": 4190,
+ "targetPort": 4190
+ }
+ ],
+ "selector": {
+ "name": "kolab-imapf-int"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-imapf-int-atomicapp/entrypoint.sh b/05-imapf-int-atomicapp/entrypoint.sh
new file mode 100755
index 0000000..d606f56
--- /dev/null
+++ b/05-imapf-int-atomicapp/entrypoint.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+# Apply some configuration
+exec "$@"
+
+exec top
diff --git a/05-int-mx-atomicapp/Dockerfile b/05-int-mx-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-int-mx-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-int-mx-atomicapp/Nulecule b/05-int-mx-atomicapp/Nulecule
new file mode 100644
index 0000000..0b58fea
--- /dev/null
+++ b/05-int-mx-atomicapp/Nulecule
@@ -0,0 +1,54 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-int-mx",
+ "metadata": {
+ "name": "Kolab Internal Mail Exchanger",
+ "appversion": "development",
+ "description": "Kolab Internal Mail Exchanger"
+ },
+ "graph": [
+ {
+ "name": "kolab-wallace",
+ "source": "docker://kolab/wallace-atomicapp"
+ },
+ {
+ "name": "kolab-int-mx",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/int-mx"
+ },
+ {
+ "name": "cyrus_admin_password",
+ "description": "Cyrus Administrator Password"
+ },
+ {
+ "name": "domain",
+ "description": "Domain Name Space",
+ "default": "docker.container"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-int-mx-atomicapp/README.md b/05-int-mx-atomicapp/README.md
new file mode 100644
index 0000000..fe3b928
--- /dev/null
+++ b/05-int-mx-atomicapp/README.md
@@ -0,0 +1,2 @@
+## External Mail Exchanger (Inbound)
+
diff --git a/05-int-mx-atomicapp/artifacts/docker/run-pod b/05-int-mx-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..94b989b
--- /dev/null
+++ b/05-int-mx-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,4 @@
+docker run -d \
+ -p 25:25 \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-int-mx-atomicapp/artifacts/kubernetes/pod.json b/05-int-mx-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..1f02ee9
--- /dev/null
+++ b/05-int-mx-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,38 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-int-mx",
+ "metadata": {
+ "name": "kolab-int-mx",
+ "labels": {
+ "name": "kolab-int-mx"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-int-mx",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 25
+ }
+ ],
+ "env": [
+ {
+ "name": "CYRUS_ADMIN_PASSWORD",
+ "value": "$cyrus_admin_password"
+ },
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-int-mx-atomicapp/artifacts/kubernetes/service.json b/05-int-mx-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..b33759a
--- /dev/null
+++ b/05-int-mx-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,28 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-int-mx",
+ "labels": {
+ "name": "kolab-int-mx"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "smtp",
+ "port": 25,
+ "targetPort": 25
+ },
+ {
+ "name": "submission",
+ "port": 587,
+ "targetPort": 587
+ }
+ ],
+ "selector": {
+ "name": "kolab-int-mx"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-int-mx-atomicapp/entrypoint.sh b/05-int-mx-atomicapp/entrypoint.sh
new file mode 100755
index 0000000..296f405
--- /dev/null
+++ b/05-int-mx-atomicapp/entrypoint.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+if [ ! -d "/etc/postfix/ldap/" ]; then
+ setup-kolab --default mta
+ systemctl stop postfix
+fi
+
+systemctl start kolab-saslauthd
+
+# Apply some configuration
+exec "$@"
+
+exec top
diff --git a/05-irony-atomicapp/Dockerfile b/05-irony-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-irony-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-irony-atomicapp/Nulecule b/05-irony-atomicapp/Nulecule
new file mode 100644
index 0000000..3286c54
--- /dev/null
+++ b/05-irony-atomicapp/Nulecule
@@ -0,0 +1,45 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-irony",
+ "metadata": {
+ "name": "Kolab CalDAV, CardDAV and WebDAV Interface",
+ "appversion": "14.0",
+ "description": "CalDAV, CardDAV and WebDAV Interface"
+ },
+ "graph": [
+ {
+ "name": "kolab-irony",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/irony"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": "kolab-irony-database",
+ "source": "docker://kolab/irony-database"
+ }
+ ]
+}
diff --git a/05-irony-atomicapp/artifacts/docker/run-pod b/05-irony-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..8d0b129
--- /dev/null
+++ b/05-irony-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,5 @@
+docker run -d \
+ -p 80:80 \
+ -p 443:443 \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-irony-atomicapp/artifacts/kubernetes/pod.json b/05-irony-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..a26a015
--- /dev/null
+++ b/05-irony-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,48 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-irony",
+ "labels": {
+ "name": "kolab-irony"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-irony",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 80
+ },
+ {
+ "containerPort": 443
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ },
+ {
+ "name": "KOLAB_IRONY_DATABASE_NAME",
+ "value": "$kolab_irony_database_name"
+ },
+ {
+ "name": "KOLAB_IRONY_DATABASE_PASSWORD",
+ "value": "$kolab_irony_database_password"
+ },
+ {
+ "name": "KOLAB_IRONY_DATABASE_USERNAME",
+ "value": "$kolab_irony_database_username"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-irony-atomicapp/artifacts/kubernetes/service.json b/05-irony-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..d091ec1
--- /dev/null
+++ b/05-irony-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,28 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-irony",
+ "labels": {
+ "name": "kolab-irony"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "http",
+ "port": 80,
+ "targetPort": 80
+ },
+ {
+ "name": "https",
+ "port": 443,
+ "targetPort": 443
+ }
+ ],
+ "selector": {
+ "name": "kolab-irony"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-jmap-proxy-atomicapp/Dockerfile b/05-jmap-proxy-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-jmap-proxy-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-jmap-proxy-atomicapp/Nulecule b/05-jmap-proxy-atomicapp/Nulecule
new file mode 100644
index 0000000..c6737d2
--- /dev/null
+++ b/05-jmap-proxy-atomicapp/Nulecule
@@ -0,0 +1,37 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-jmap-proxy",
+ "metadata": {
+ "name": "JMAP Proxy",
+ "appversion": "development",
+ "description": "JMAP Proxy"
+ },
+ "graph": [
+ {
+ "name": "kolab-jmap-proxy",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/jmap-proxy"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-jmap-proxy-atomicapp/artifacts/docker/run-pod b/05-jmap-proxy-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..766484e
--- /dev/null
+++ b/05-jmap-proxy-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,4 @@
+docker run -d \
+ --name kolab-jmap-proxy \
+ -p 80:80 \
+ $image
diff --git a/05-jmap-proxy-atomicapp/artifacts/kubernetes/pod.json b/05-jmap-proxy-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..ce62005
--- /dev/null
+++ b/05-jmap-proxy-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,23 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-jmap-proxy",
+ "labels": {
+ "name": "kolab-jmap-proxy"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-jmap-proxy",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 80
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-jmap-proxy-atomicapp/artifacts/kubernetes/service.json b/05-jmap-proxy-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..a99c78f
--- /dev/null
+++ b/05-jmap-proxy-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,23 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-jmap-proxy",
+ "labels": {
+ "name": "kolab-jmap-proxy"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "http",
+ "port": 80,
+ "targetPort": 80
+ }
+ ],
+ "selector": {
+ "name": "kolab-jmap-proxy"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-ldap-master-atomicapp/Dockerfile b/05-ldap-master-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-ldap-master-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-ldap-master-atomicapp/Nulecule b/05-ldap-master-atomicapp/Nulecule
new file mode 100644
index 0000000..8e7b2ed
--- /dev/null
+++ b/05-ldap-master-atomicapp/Nulecule
@@ -0,0 +1,62 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-ldap-master",
+ "metadata": {
+ "name": "Kolab LDAP Master",
+ "appversion": "development",
+ "description": "Kolab LDAP Master"
+ },
+ "graph": [
+ {
+ "name": "kolab-ldap-master",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use to fulfill the LDAP master role",
+ "default": "kolab/ldap-master"
+ },
+ {
+ "name": "domain",
+ "description": "Domain",
+ "default": "docker.container"
+ },
+ {
+ "name": "admin_password",
+ "description": "Administrator Password",
+ "default": "welcome123"
+ },
+ {
+ "name": "cyrus_admin_password",
+ "description": "Cyrus Administrator Password",
+ "default": "welcome123"
+ },
+ {
+ "name": "directory_manager_password",
+ "description": "Directory Manager Password",
+ "default": "welcome123"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Account Password",
+ "default": "welcome123"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-ldap-master-atomicapp/artifacts/docker/run-pod b/05-ldap-master-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..50c570e
--- /dev/null
+++ b/05-ldap-master-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,8 @@
+docker run -d \
+ -p 389:389 \
+ -p 636:636 \
+ -h ldap-master.$admin_domain \
+ -e ADMIN_PASSWORD=$admin_password \
+ -e DIRECTORY_MANAGER_PASSWORD=$directory_manager_password \
+ -e DOMAIN=$domain \
+ $image
diff --git a/05-ldap-master-atomicapp/artifacts/kubernetes/pod.json b/05-ldap-master-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..ee89609
--- /dev/null
+++ b/05-ldap-master-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,49 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-ldap-master",
+ "metadata": {
+ "name": "kolab-ldap-master",
+ "labels": {
+ "name": "kolab-ldap-master"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-ldap-master",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 389
+ },
+ {
+ "containerPort": 636
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "ADMIN_PASSWORD",
+ "value": "$admin_password"
+ },
+ {
+ "name": "CYRUS_ADMIN_PASSWORD",
+ "value": "$cyrus_admin_password"
+ },
+ {
+ "name": "DIRECTORY_MANAGER_PASSWORD",
+ "value": "$directory_manager_password"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-ldap-master-atomicapp/artifacts/kubernetes/service.json b/05-ldap-master-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..f62d002
--- /dev/null
+++ b/05-ldap-master-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,28 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-ldap-master",
+ "labels": {
+ "name": "kolab-ldap-master"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "ldap",
+ "port": 389,
+ "targetPort": 389
+ },
+ {
+ "name": "ldaps",
+ "port": 636,
+ "targetPort": 636
+ }
+ ],
+ "selector": {
+ "name": "kolab-ldap-master"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-ldap-master-atomicapp/entrypoint.sh b/05-ldap-master-atomicapp/entrypoint.sh
new file mode 100755
index 0000000..37abed4
--- /dev/null
+++ b/05-ldap-master-atomicapp/entrypoint.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# Environment variables:
+# ADMIN_PASSWORD
+# DIRECTORY_MANAGER_PASSWORD
+# DOMAIN
+
+exec top
diff --git a/05-ldap-slave-atomicapp/Dockerfile b/05-ldap-slave-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-ldap-slave-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-ldap-slave-atomicapp/Nulecule b/05-ldap-slave-atomicapp/Nulecule
new file mode 100644
index 0000000..9f089cf
--- /dev/null
+++ b/05-ldap-slave-atomicapp/Nulecule
@@ -0,0 +1,47 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-ldap-slave",
+ "metadata": {
+ "name": "Kolab LDAP",
+ "appversion": "1.2.11.15",
+ "description": "Kolab LDAP"
+ },
+ "graph": [
+ {
+ "name": "kolab-ldap",
+ "params": [
+ {
+ "name": "domain",
+ "description": "Domain",
+ "default": "docker.container"
+ },
+ {
+ "name": "admin_password",
+ "description": "Administrator Password",
+ "default": "welcome123"
+ },
+ {
+ "name": "directory_manager_password",
+ "description": "Directory Manager Password",
+ "default": "welcome123"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-ldap-slave-atomicapp/artifacts/docker/run-pod b/05-ldap-slave-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..66e71d4
--- /dev/null
+++ b/05-ldap-slave-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,9 @@
+docker run -d \
+ -p 389:389 \
+ -p 636:636 \
+ -p 9830:9830 \
+ -h $hostname \
+ -e ADMIN_PASSWORD=$admin_password \
+ -e DIRECTORY_MANAGER_PASSWORD=$directory_manager_password \
+ -e ROOT_DN=$root_dn \
+ $image
diff --git a/05-ldap-slave-atomicapp/artifacts/kubernetes/service.json b/05-ldap-slave-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..31478bd
--- /dev/null
+++ b/05-ldap-slave-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,33 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-ldap-slave",
+ "labels": {
+ "name": "kolab-ldap-slave"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "ldap",
+ "port": 389,
+ "targetPort": 389
+ },
+ {
+ "name": "ldaps",
+ "port": 636,
+ "targetPort": 636
+ },
+ {
+ "name": "389-admin",
+ "port": 9830,
+ "targetPort": 9830
+ }
+ ],
+ "selector": {
+ "name": "kolab-ldap-slave"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-ldap-slave-atomicapp/entrypoint.sh b/05-ldap-slave-atomicapp/entrypoint.sh
new file mode 100755
index 0000000..3999ac7
--- /dev/null
+++ b/05-ldap-slave-atomicapp/entrypoint.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+exec "$@"
+
+exec top
diff --git a/05-manticore-atomicapp/Dockerfile b/05-manticore-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-manticore-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-manticore-atomicapp/Nulecule b/05-manticore-atomicapp/Nulecule
new file mode 100644
index 0000000..095fa47
--- /dev/null
+++ b/05-manticore-atomicapp/Nulecule
@@ -0,0 +1,67 @@
+{
+ "specversion": "0.0.2",
+ "id": "manticore",
+ "metadata": {
+ "name": "Manticore Server",
+ "appversion": "1.0.0",
+ "description": "Manticore Collaborative Editing Server"
+ },
+ "graph": [
+ {
+ "name": "manticore-mongodb",
+ "source": "docker://kolab/mongodb-centos7-atomicapp"
+ },
+ {
+ "name": "manticore",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/manticore"
+ },
+ {
+ "name": "manticore_admin_email",
+ "description": "Administrator email address",
+ "default": "admin@cluster.local"
+ },
+ {
+ "name": "manticore_admin_password",
+ "description": "Administrator password"
+ },
+ {
+ "name": "mongodb_database",
+ "description": "MongoDB Database Name"
+ },
+ {
+ "name": "mongodb_hostname",
+ "description": "MongoDB Server Hostname",
+ "default": "mongodb:27017"
+ },
+ {
+ "name": "mongodb_password",
+ "description": "MongoDB User Password"
+ },
+ {
+ "name": "mongodb_username",
+ "description": "MongoDB Username"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-manticore-atomicapp/artifacts/docker/run-pod b/05-manticore-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..98ceed8
--- /dev/null
+++ b/05-manticore-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,11 @@
+docker run -d \
+ --name manticore-atomicapp-app \
+ --link mongodb-atomicapp-app:manticore \
+ -e MANTICORE_ADMIN_EMAIL=$manticore_admin_email \
+ -e MANTICORE_ADMIN_PASSWORD=$manticore_admin_password \
+ -e MONGODB_DATABASE=$mongodb_database \
+ -e MONGODB_HOSTNAME=$mongodb_hostname \
+ -e MONGODB_PASSWORD=$mongodb_password \
+ -e MONGODB_USERNAME=$mongodb_username \
+ -p 8080:8080 \
+ $image
diff --git a/05-manticore-atomicapp/artifacts/kubernetes/pod.json b/05-manticore-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..caaee5a
--- /dev/null
+++ b/05-manticore-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,50 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "manticore",
+ "metadata": {
+ "name": "manticore",
+ "labels": {
+ "name": "manticore"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "manticore",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 8080
+ }
+ ],
+ "env": [
+ {
+ "name": "MANTICORE_ADMIN_EMAIL",
+ "value": "$manticore_admin_email"
+ },
+ {
+ "name": "MANTICORE_ADMIN_PASSWORD",
+ "value": "$manticore_admin_password"
+ },
+ {
+ "name": "MONGODB_DATABASE",
+ "value": "$mongodb_database"
+ },
+ {
+ "name": "MONGODB_HOSTNAME",
+ "value": "$mongodb_hostname"
+ },
+ {
+ "name": "MONGODB_PASSWORD",
+ "value": "$mongodb_password"
+ },
+ {
+ "name": "MONGODB_USERNAME",
+ "value": "$mongodb_username"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-manticore-atomicapp/artifacts/kubernetes/service.json b/05-manticore-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..aecd131
--- /dev/null
+++ b/05-manticore-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,24 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "manticore",
+ "labels": {
+ "name": "manticore"
+ },
+ "annotations": {
+ "description": "Exposes and load balances the application pods"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "port": 8080,
+ "targetPort": 8080
+ }
+ ],
+ "selector": {
+ "name": "manticore"
+ }
+ }
+}
diff --git a/05-roundcube-next-atomicapp/Dockerfile b/05-roundcube-next-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-roundcube-next-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-roundcube-next-atomicapp/Nulecule b/05-roundcube-next-atomicapp/Nulecule
new file mode 100644
index 0000000..3975f81
--- /dev/null
+++ b/05-roundcube-next-atomicapp/Nulecule
@@ -0,0 +1,41 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-roundcube-next",
+ "metadata": {
+ "name": "Kolab Web Client Interface",
+ "appversion": "14.0",
+ "description": "Web Client Interface"
+ },
+ "graph": [
+ {
+ "name": "kolab-roundcube-next",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/roundcube-next"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": "roundcube-next-jmap-proxy",
+ "source": "docker://kolab/jmap-proxy-atomicapp"
+ }
+ ]
+}
diff --git a/05-roundcube-next-atomicapp/artifacts/docker/run-pod b/05-roundcube-next-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..80ea1d7
--- /dev/null
+++ b/05-roundcube-next-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,5 @@
+docker run -d \
+ --name kolab-roundcube-next \
+ -p 80:80 \
+ -p 443:443 \
+ $image
diff --git a/05-roundcube-next-atomicapp/artifacts/kubernetes/pod.json b/05-roundcube-next-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..0c2594b
--- /dev/null
+++ b/05-roundcube-next-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,48 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-roundcube-next",
+ "labels": {
+ "name": "kolab-roundcube-next"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-roundcube-next",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 80
+ },
+ {
+ "containerPort": 443
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ },
+ {
+ "name": "KOLAB_ROUNDCUBE-NEXT_DATABASE_NAME",
+ "value": "$kolab_roundcube-next_database_name"
+ },
+ {
+ "name": "KOLAB_ROUNDCUBE-NEXT_DATABASE_PASSWORD",
+ "value": "$kolab_roundcube-next_database_password"
+ },
+ {
+ "name": "KOLAB_ROUNDCUBE-NEXT_DATABASE_USERNAME",
+ "value": "$kolab_roundcube-next_database_username"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-roundcube-next-atomicapp/artifacts/kubernetes/service.json b/05-roundcube-next-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..ec2f01c
--- /dev/null
+++ b/05-roundcube-next-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,28 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-roundcube-next",
+ "labels": {
+ "name": "kolab-roundcube-next"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "http",
+ "port": 80,
+ "targetPort": 80
+ },
+ {
+ "name": "https",
+ "port": 443,
+ "targetPort": 443
+ }
+ ],
+ "selector": {
+ "name": "kolab-roundcube-next"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-roundcubemail-atomicapp/Dockerfile b/05-roundcubemail-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-roundcubemail-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-roundcubemail-atomicapp/Nulecule b/05-roundcubemail-atomicapp/Nulecule
new file mode 100644
index 0000000..b3664c8
--- /dev/null
+++ b/05-roundcubemail-atomicapp/Nulecule
@@ -0,0 +1,64 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-roundcubemail",
+ "metadata": {
+ "name": "Kolab Web Client Interface",
+ "appversion": "14.0",
+ "description": "Web Client Interface"
+ },
+ "graph": [
+ {
+ "name": "kolab-roundcubemail",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/roundcubemail"
+ },
+ {
+ "name": "domain",
+ "description": "Domain Name Space",
+ "default": "docker.container"
+ },
+ {
+ "name": "kolab_roundcubemail_database_name",
+ "description": "Database name",
+ "default": "roundcubemail"
+ },
+ {
+ "name": "kolab_roundcubemail_database_password",
+ "description": "Database password"
+ },
+ {
+ "name": "kolab_roundcubemail_database_username",
+ "description": "Database user",
+ "default": "kolab"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": "kolab-roundcubemail-database",
+ "source": "docker://kolab/roundcubemail-database"
+ }
+ ]
+}
diff --git a/05-roundcubemail-atomicapp/artifacts/docker/run-pod b/05-roundcubemail-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..4bf50b8
--- /dev/null
+++ b/05-roundcubemail-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,10 @@
+docker run -d \
+ --name kolab-roundcubemail \
+ -p 80:80 \
+ -p 443:443 \
+ --link mariadb-atomicapp-app:mysql \
+ -e KOLAB_ROUNDCUBEMAIL_DB_NAME=$db_name \
+ -e KOLAB_ROUNDCUBEMAIL_DB_PASS=$db_pass \
+ -e KOLAB_ROUNDCUBEMAIL_DB_USER=$db_user \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-roundcubemail-atomicapp/artifacts/kubernetes/pod.json b/05-roundcubemail-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..84956f1
--- /dev/null
+++ b/05-roundcubemail-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,48 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-roundcubemail",
+ "labels": {
+ "name": "kolab-roundcubemail"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-roundcubemail",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 80
+ },
+ {
+ "containerPort": 443
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ },
+ {
+ "name": "KOLAB_ROUNDCUBEMAIL_DATABASE_NAME",
+ "value": "$kolab_roundcubemail_database_name"
+ },
+ {
+ "name": "KOLAB_ROUNDCUBEMAIL_DATABASE_PASSWORD",
+ "value": "$kolab_roundcubemail_database_password"
+ },
+ {
+ "name": "KOLAB_ROUNDCUBEMAIL_DATABASE_USERNAME",
+ "value": "$kolab_roundcubemail_database_username"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-roundcubemail-atomicapp/artifacts/kubernetes/service.json b/05-roundcubemail-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..0d08a97
--- /dev/null
+++ b/05-roundcubemail-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,28 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-roundcubemail",
+ "labels": {
+ "name": "kolab-roundcubemail"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "http",
+ "port": 80,
+ "targetPort": 80
+ },
+ {
+ "name": "https",
+ "port": 443,
+ "targetPort": 443
+ }
+ ],
+ "selector": {
+ "name": "kolab-roundcubemail"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-submission-atomicapp/Dockerfile b/05-submission-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-submission-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-submission-atomicapp/Nulecule b/05-submission-atomicapp/Nulecule
new file mode 100644
index 0000000..a50e92c
--- /dev/null
+++ b/05-submission-atomicapp/Nulecule
@@ -0,0 +1,42 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-submission",
+ "metadata": {
+ "name": "Kolab Message Submission Agent",
+ "appversion": "development",
+ "description": "Kolab Message Submission Agent"
+ },
+ "graph": [
+ {
+ "name": "kolab-submission",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/submission"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password",
+ "default": "$kolab_service_password"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-submission-atomicapp/artifacts/docker/run-pod b/05-submission-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..a6eb7d1
--- /dev/null
+++ b/05-submission-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,4 @@
+docker run -d \
+ -p 587:587 \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-submission-atomicapp/artifacts/kubernetes/controller.json b/05-submission-atomicapp/artifacts/kubernetes/controller.json
new file mode 100644
index 0000000..d66ca39
--- /dev/null
+++ b/05-submission-atomicapp/artifacts/kubernetes/controller.json
@@ -0,0 +1,37 @@
+{
+ "kind": "ReplicationController",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-submission",
+ "labels": {
+ "name": "kolab-submission"
+ }
+ },
+ "spec": {
+ "replicas": 1,
+ "selector": {
+ "name": "kolab-submission"
+ },
+ "template": {
+ "metadata": {
+ "labels": {
+ "name": "kolab-submission"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-submission",
+ "image": "kolab/mta",
+ "ports": [
+ {
+ "name": "submission",
+ "containerPort": 587
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/05-submission-atomicapp/artifacts/kubernetes/service.json b/05-submission-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..53fcbf4
--- /dev/null
+++ b/05-submission-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,23 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-submission",
+ "labels": {
+ "name": "kolab-submission"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "submission",
+ "port": 587,
+ "targetPort": 587
+ }
+ ],
+ "selector": {
+ "name": "kolab-submission"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-syncroton-atomicapp/Dockerfile b/05-syncroton-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-syncroton-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-syncroton-atomicapp/Nulecule b/05-syncroton-atomicapp/Nulecule
new file mode 100644
index 0000000..8a7c881
--- /dev/null
+++ b/05-syncroton-atomicapp/Nulecule
@@ -0,0 +1,59 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-syncroton",
+ "metadata": {
+ "name": "Kolab ActiveSync Interface",
+ "appversion": "development",
+ "description": "ActiveSync Interface"
+ },
+ "graph": [
+ {
+ "name": "kolab-syncroton",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/syncroton"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password"
+ },
+ {
+ "name": "kolab_syncroton_database_name",
+ "description": "Database name",
+ "default": "syncroton"
+ },
+ {
+ "name": "kolab_syncroton_database_password",
+ "description": "Database password"
+ },
+ {
+ "name": "kolab_syncroton_database_username",
+ "description": "Database user",
+ "default": "syncroton"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": "kolab-syncroton-database",
+ "source": "docker://kolab/syncroton-database"
+ }
+ ]
+}
diff --git a/05-syncroton-atomicapp/artifacts/docker/run-pod b/05-syncroton-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..8d0b129
--- /dev/null
+++ b/05-syncroton-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,5 @@
+docker run -d \
+ -p 80:80 \
+ -p 443:443 \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-syncroton-atomicapp/artifacts/kubernetes/pod.json b/05-syncroton-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..2a87490
--- /dev/null
+++ b/05-syncroton-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,48 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-syncroton",
+ "labels": {
+ "name": "kolab-syncroton"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-syncroton",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 80
+ },
+ {
+ "containerPort": 443
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ },
+ {
+ "name": "KOLAB_SYNCROTON_DATABASE_NAME",
+ "value": "$kolab_syncroton_database_name"
+ },
+ {
+ "name": "KOLAB_SYNCROTON_DATABASE_PASSWORD",
+ "value": "$kolab_syncroton_database_password"
+ },
+ {
+ "name": "KOLAB_SYNCROTON_DATABASE_USERNAME",
+ "value": "$kolab_syncroton_database_username"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-syncroton-atomicapp/artifacts/kubernetes/service.json b/05-syncroton-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..5b77eff
--- /dev/null
+++ b/05-syncroton-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,28 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-syncroton",
+ "labels": {
+ "name": "kolab-syncroton"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "http",
+ "port": 80,
+ "targetPort": 80
+ },
+ {
+ "name": "https",
+ "port": 443,
+ "targetPort": 443
+ }
+ ],
+ "selector": {
+ "name": "kolab-syncroton"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-wallace-atomicapp/Dockerfile b/05-wallace-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-wallace-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-wallace-atomicapp/Nulecule b/05-wallace-atomicapp/Nulecule
new file mode 100644
index 0000000..0a00990
--- /dev/null
+++ b/05-wallace-atomicapp/Nulecule
@@ -0,0 +1,52 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-wallace",
+ "metadata": {
+ "name": "Kolab Content-Filter",
+ "appversion": "development",
+ "description": "Kolab Content-Filter"
+ },
+ "graph": [
+ {
+ "name": "kolab-wallace",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/wallace"
+ },
+ {
+ "name": "domain",
+ "description": "Domain Name Space",
+ "default": "docker.container"
+ },
+ {
+ "name": "cyrus_admin_password",
+ "description": "Cyrus Administrator Password",
+ "default": "welcome123"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password",
+ "default": "welcome123"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/05-wallace-atomicapp/artifacts/docker/run-pod b/05-wallace-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..e4f0ae3
--- /dev/null
+++ b/05-wallace-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,5 @@
+docker run -d \
+ -p 10026:10026 \
+ -e CYRUS_ADMIN_PASSWORD=$cyrus_admin_password \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-wallace-atomicapp/artifacts/kubernetes/pod.json b/05-wallace-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..b3db7f9
--- /dev/null
+++ b/05-wallace-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,38 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-wallace",
+ "metadata": {
+ "name": "kolab-wallace",
+ "labels": {
+ "name": "kolab-wallace"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-wallace",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 10026
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "CYRUS_ADMIN_PASSWORD",
+ "value": "$cyrus_admin_password"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-wallace-atomicapp/artifacts/kubernetes/service.json b/05-wallace-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..6b26a81
--- /dev/null
+++ b/05-wallace-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,23 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-wallace",
+ "labels": {
+ "name": "kolab-wallace"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "wallace",
+ "port": 10026,
+ "targetPort": 10026
+ }
+ ],
+ "selector": {
+ "name": "kolab-wallace"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/05-webadmin-atomicapp/Dockerfile b/05-webadmin-atomicapp/Dockerfile
new file mode 100644
index 0000000..ffa5b00
--- /dev/null
+++ b/05-webadmin-atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.specversion="0.0.2" \
+ io.projectatomic.nulecule.providers="docker,kubernetes,openshift"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/05-webadmin-atomicapp/Nulecule b/05-webadmin-atomicapp/Nulecule
new file mode 100644
index 0000000..fe4c8c0
--- /dev/null
+++ b/05-webadmin-atomicapp/Nulecule
@@ -0,0 +1,71 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab-webadmin",
+ "metadata": {
+ "name": "Kolab Web Administration Interface",
+ "appversion": "development",
+ "description": "Kolab Web Administration Interface"
+ },
+ "graph": [
+ {
+ "name": "kolab-webadmin",
+ "params": [
+ {
+ "name": "image",
+ "description": "Image to use",
+ "default": "kolab/webadmin"
+ },
+ {
+ "name": "domain",
+ "description": "Domain Name Space",
+ "default": "docker.container"
+ },
+ {
+ "name": "kolab_webadmin_database_name",
+ "description": "Database name",
+ "default": "kolab"
+ },
+ {
+ "name": "kolab_webadmin_database_password",
+ "description": "Database password",
+ "default": "welcome123"
+ },
+ {
+ "name": "kolab_webadmin_database_username",
+ "description": "Database user",
+ "default": "kolab"
+ },
+ {
+ "name": "directory_manager_password",
+ "description": "Directory Manager Password",
+ "default": "welcome123"
+ },
+ {
+ "name": "kolab_service_password",
+ "description": "Kolab Service Password",
+ "default": "welcome123"
+ }
+ ],
+ "artifacts": {
+ "docker": [
+ "file://artifacts/docker/run-pod"
+ ],
+ "kubernetes": [
+ "file://artifacts/kubernetes/pod.json",
+ "file://artifacts/kubernetes/service.json"
+ ],
+ "openshift": [
+ {
+ "inherit": [
+ "kubernetes"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "name": "kolab-webadmin-database",
+ "source": "docker://kolab/webadmin-database"
+ }
+ ]
+}
diff --git a/05-webadmin-atomicapp/artifacts/docker/run-pod b/05-webadmin-atomicapp/artifacts/docker/run-pod
new file mode 100644
index 0000000..8d0b129
--- /dev/null
+++ b/05-webadmin-atomicapp/artifacts/docker/run-pod
@@ -0,0 +1,5 @@
+docker run -d \
+ -p 80:80 \
+ -p 443:443 \
+ -e KOLAB_SERVICE_PASSWORD=$kolab_service_password \
+ $image
diff --git a/05-webadmin-atomicapp/artifacts/kubernetes/pod.json b/05-webadmin-atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..d7747f3
--- /dev/null
+++ b/05-webadmin-atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,53 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab-webadmin",
+ "metadata": {
+ "name": "kolab-webadmin",
+ "labels": {
+ "name": "kolab-webadmin"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "kolab-webadmin",
+ "image": "$image",
+ "ports": [
+ {
+ "containerPort": 80
+ },
+ {
+ "containerPort": 443
+ }
+ ],
+ "env": [
+ {
+ "name": "DOMAIN",
+ "value": "$domain"
+ },
+ {
+ "name": "DIRECTORY_MANAGER_PASSWORD",
+ "value": "$directory_manager_password"
+ },
+ {
+ "name": "KOLAB_SERVICE_PASSWORD",
+ "value": "$kolab_service_password"
+ },
+ {
+ "name": "KOLAB_WEBADMIN_DATABASE_NAME",
+ "value": "$kolab_webadmin_database_name"
+ },
+ {
+ "name": "KOLAB_WEBADMIN_DATABASE_PASSWORD",
+ "value": "$kolab_webadmin_database_password"
+ },
+ {
+ "name": "KOLAB_WEBADMIN_DATABASE_USERNAME",
+ "value": "$kolab_webadmin_database_username"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/05-webadmin-atomicapp/artifacts/kubernetes/service.json b/05-webadmin-atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..21fe4a7
--- /dev/null
+++ b/05-webadmin-atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,28 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab-webadmin",
+ "labels": {
+ "name": "kolab-webadmin"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "http",
+ "port": 80,
+ "targetPort": 80
+ },
+ {
+ "name": "https",
+ "port": 443,
+ "targetPort": 443
+ }
+ ],
+ "selector": {
+ "name": "kolab-webadmin"
+ },
+ "type": "LoadBalancer"
+ }
+}
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..5215d22
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,102 @@
+BRANCH := $(shell git rev-parse --abbrev-ref HEAD | sed -e 's/master/latest/g')
+NOCACHE := $(shell test 0$(NOCACHE) -eq 0 || echo "--no-cache")
+
+all: docs
+ for image in $$(find . -mindepth 2 -maxdepth 2 -type f -name "Dockerfile" -exec dirname {} \; | sort); do \
+ echo "== $$image ==" ; \
+ docker build \
+ -t kolab/$$(basename $$image | sed -r -e 's/[0-9]+-//g'):$(BRANCH) \
+ $$image/. ; \
+ docker tag -f kolab/$$(basename $$image | sed -r -e 's/[0-9]+-//g'):$(BRANCH) \
+ docker.io/kolab/$$(basename $$image | sed -r -e 's/[0-9]+-//g'):$(BRANCH) ; \
+ done
+
+list:
+ @for image in $$(find . -mindepth 2 -maxdepth 2 -type f -name "Dockerfile" -exec dirname {} \; | sort); do \
+ echo "kolab/$$(basename $$image | sed -r -e 's/[0-9]+-//g'):$(BRANCH)" ; \
+ done
+
+docs:
+ make -C docs clean html || :
+
+pull:
+ docker pull centos:centos7 && \
+ docker tag -f docker.io/library/centos:centos7 centos:centos7
+ docker pull centos/mariadb && \
+ docker tag -f docker.io/centos/mariadb centos/mariadb
+ docker pull projectatomic/mariadb-centos7-atomicapp && \
+ docker tag -f docker.io/projectatomic/mariadb-centos7-atomicapp projectatomic/mariadb-centos7-atomicapp
+ docker pull projectatomic/atomicapp:latest && \
+ docker tag -f docker.io/projectatomic/atomicapp:latest projectatomic/atomicapp:latest
+ docker pull projectatomic/atomicapp:0.2.1 && \
+ docker tag -f docker.io/projectatomic/atomicapp:0.2.1 projectatomic/atomicapp:0.2.1
+ docker pull microwebapps/haproxy-frontend-atomicapp:latest && \
+ docker tag -f docker.io/microwebapps/haproxy-frontend-atomicapp:latest microwebapps/haproxy-frontend-atomicapp:latest
+ for image in $$(find . -mindepth 2 -maxdepth 2 -type f -name "Dockerfile" -exec dirname {} \; | sort); do \
+ docker pull kolab/$$(basename $${image} | sed -r -e 's/[0-9]+-//g'):$(BRANCH) && \
+ docker tag -f docker.io/kolab/$$(basename $${image} | sed -r -e 's/[0-9]+-//g'):$(BRANCH) kolab/$$(basename $${image} | sed -r -e 's/[0-9]+-//g'):$(BRANCH) || : ; \
+ done
+
+push:
+ for image in $$(find . -mindepth 2 -maxdepth 2 -type f -name "Dockerfile" -exec dirname {} \; | sort); do \
+ docker push --force docker.io/kolab/$$(basename $${image} | sed -r -e 's/[0-9]+-//g'):$(BRANCH) ; \
+ done
+
+run: clean all
+ sudo atomicapp --verbose install --destination /var/lib/atomicapp/kolab-atomicapp/ kolab/atomicapp:$(BRANCH) && \
+ cd /var/lib/atomicapp/kolab-atomicapp/ && \
+ sed \
+ -e 's/_password = None/_password = welcome123/g' \
+ -e 's/^mongodb_database = None/mongodb_database = manticore/g' \
+ -e 's/^mongodb_username = None/mongodb_username = manticore/g' \
+ -e 's/^db_user = None/db_user = kolab/g' \
+ -e 's/^db_name = None/db_name = kolab/g' \
+ -e 's/^db_pass = None/db_pass = welcome123/g' \
+ answers.conf.sample | sudo tee answers.conf && \
+ sudo atomicapp --verbose run -a /var/lib/atomicapp/kolab-atomicapp/answers.conf kolab/atomicapp:$(BRANCH) || \
+ sudo atomicapp --verbose -a /var/lib/atomicapp/kolab-atomicapp/answers.conf run kolab/atomicapp:$(BRANCH)
+
+clean:
+ for replicationcontroller in $$(kubectl get --no-headers=true replicationcontrollers | awk '{print $$1}' | grep -v kubernetes); do \
+ kubectl delete replicationcontroller $${replicationcontroller} 2>/dev/null || : ; \
+ done
+ for service in $$(kubectl get --no-headers=true services | awk '{print $$1}' | grep -v kubernetes); do \
+ kubectl delete service $${service} 2>/dev/null || : ; \
+ done
+ for pod in $$(kubectl get --no-headers=true pods | awk '{print $$1}' | grep -v kubernetes); do \
+ kubectl delete pod $${pod} 2>/dev/null || : ; \
+ done
+ for container in $$(docker ps -q); do \
+ docker kill --signal="SIGKILL" $${container} 2>/dev/null || : ; \
+ done
+ for container in $$(docker ps -aq); do \
+ docker rm $${container} ; \
+ done
+ for image in $$(docker images -q --filter dangling=true); do \
+ docker rmi $${image} ; \
+ done
+ sudo rm -rf /var/lib/atomicapp/kolab-atomicapp/ || :
+
+really-clean:
+ while [ ! -z "$$(docker images -aq)" ]; do \
+ for image in $$(docker images -aq); do \
+ docker rmi -f $${image} 2>/dev/null || : ; \
+ done ; \
+ done
+
+restart:
+ for service in kubelet kube-apiserver kube-scheduler kube-controller-manager kube-proxy etcd; do \
+ sudo systemctl stop $${service} ; \
+ done
+ for service in kubelet kube-apiserver kube-scheduler kube-controller-manager kube-proxy etcd; do \
+ sudo systemctl start $${service} ; \
+ done
+ for service in kubelet kube-apiserver kube-scheduler kube-controller-manager kube-proxy etcd; do \
+ sudo systemctl status $${service} >/dev/null 2>&1 || sudo systemctl restart $${service}; \
+ done
+
+%:
+ docker build $(NOCACHE) -t kolab/$@:$(BRANCH) *-$@
+ docker tag -f kolab/$@:$(BRANCH) docker.io/kolab/$@:$(BRANCH)
+
+.PHONY: all docs push
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e350178
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+# Kolab as an Atomic Application
+
+This repository contains the development of
+[Kolab Groupware](https://kolab.org) as an
+[Atomic Application](http://www.projectatomic.io/docs/atomicapp/) for
+deployment on Kubernetes-based environments, such as
+[OpenShift](https://www.openshift.com/) /
+[Atomic](http://www.projectatomic.io), using
+[Nulecule](http://www.projectatomic.io/docs/nulecule/).
+
+## Run in Vagrant
+
+Run the Kolab Atomic Application in the Atomic Developer Bundle Vagrant
+image.
+
+ $ vagrant up
+ $ vagrant ssh
+ $ atomic install kolab/atomicapp
+
+Edit `./answers.conf.sample` and save off as `./answers.conf`.
+
+ $ atomic run kolab/atomicapp
+
+## Limitations
+
+ * Nulecule does yet provide containers with persistent volumes.
+
+ * Option value (i.e. use MySQL, MariaDB or PostgreSQL) cannot simply
+ be orchestrated.
+
diff --git a/atomicapp/Dockerfile b/atomicapp/Dockerfile
new file mode 100644
index 0000000..5496ab9
--- /dev/null
+++ b/atomicapp/Dockerfile
@@ -0,0 +1,9 @@
+FROM projectatomic/atomicapp:0.3.0
+
+MAINTAINER Kolab Systems <contact@kolabsys.com>
+
+LABEL io.projectatomic.nulecule.providers="kubernetes" \
+ io.projectatomic.nulecule.specversion="0.0.2"
+
+ADD /Nulecule /Dockerfile /application-entity/
+ADD /artifacts /application-entity/artifacts/
diff --git a/atomicapp/Nulecule b/atomicapp/Nulecule
new file mode 100644
index 0000000..1cadd73
--- /dev/null
+++ b/atomicapp/Nulecule
@@ -0,0 +1,79 @@
+{
+ "specversion": "0.0.2",
+ "id": "kolab",
+ "metadata": {
+ "name": "Kolab Groupware",
+ "appversion": "1.0.0",
+ "description": "Kolab Groupware"
+ },
+ "graph": [
+ {
+ "name": "kolab-chwala",
+ "source": "docker://kolab/chwala-atomicapp"
+ },
+ {
+ "name": "kolab-ext-mx-in",
+ "source": "docker://kolab/ext-mx-in-atomicapp"
+ },
+ {
+ "name": "kolab-ext-mx-out",
+ "source": "docker://kolab/ext-mx-out-atomicapp"
+ },
+ {
+ "name": "kolab-freebusy",
+ "source": "docker://kolab/freebusy-atomicapp"
+ },
+ {
+ "name": "kolab-guam",
+ "source": "docker://kolab/guam-atomicapp"
+ },
+ {
+ "name": "kolab-irony",
+ "source": "docker://kolab/irony-atomicapp"
+ },
+ {
+ "name": "kolab-imapb",
+ "source": "docker://kolab/imapb-atomicapp"
+ },
+ {
+ "name": "kolab-imapf-ext",
+ "source": "docker://kolab/imapf-ext-atomicapp"
+ },
+ {
+ "name": "kolab-imapf-int",
+ "source": "docker://kolab/imapf-int-atomicapp"
+ },
+ {
+ "name": "kolab-imap-mupdate",
+ "source": "docker://kolab/imap-mupdate-atomicapp"
+ },
+ {
+ "name": "kolab-int-mx",
+ "source": "docker://kolab/int-mx-atomicapp"
+ },
+ {
+ "name": "kolab-ldap-master",
+ "source": "docker://kolab/ldap-master-atomicapp"
+ },
+ {
+ "name": "kolab-manticore",
+ "source": "docker://kolab/manticore-atomicapp"
+ },
+ {
+ "name": "kolab-roundcubemail",
+ "source": "docker://kolab/roundcubemail-atomicapp"
+ },
+ {
+ "name": "kolab-roundcube-next",
+ "source": "docker://kolab/roundcube-next-atomicapp"
+ },
+ {
+ "name": "kolab-syncroton",
+ "source": "docker://kolab/syncroton-atomicapp"
+ },
+ {
+ "name": "kolab-webadmin",
+ "source": "docker://kolab/webadmin-atomicapp"
+ }
+ ]
+}
diff --git a/atomicapp/artifacts/kubernetes/pod.json b/atomicapp/artifacts/kubernetes/pod.json
new file mode 100644
index 0000000..f3d9109
--- /dev/null
+++ b/atomicapp/artifacts/kubernetes/pod.json
@@ -0,0 +1,33 @@
+{
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "id": "kolab",
+ "metadata": {
+ "name": "kolab",
+ "labels": {
+ "name": "kolab"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "name": "manticore",
+ "image": "kolab/manticore",
+ "ports": [
+ {
+ "containerPort": 8080
+ }
+ ]
+ },
+ {
+ "name": "mongodb",
+ "image": "centos/mongodb-26-centos7",
+ "ports": [
+ {
+ "containerPort": 27017
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/atomicapp/artifacts/kubernetes/service.json b/atomicapp/artifacts/kubernetes/service.json
new file mode 100644
index 0000000..06a82e1
--- /dev/null
+++ b/atomicapp/artifacts/kubernetes/service.json
@@ -0,0 +1,31 @@
+{
+ "kind": "Service",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "kolab",
+ "labels": {
+ "name": "kolab"
+ }
+ },
+ "spec": {
+ "ports": [
+ {
+ "name": "manticore",
+ "protocol": "TCP",
+ "port": 8080,
+ "targetPort": 8080,
+ "nodePort": 0
+ },
+ {
+ "name": "mongodb",
+ "protocol": "TCP",
+ "port": 27017,
+ "targetPort": 27017,
+ "nodePort": 0
+ }
+ ],
+ "selector": {
+ "name": "kolab"
+ }
+ }
+}
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..07b1f5b
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,177 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " xml to make Docutils-native XML files"
+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/KolabAtomicApplication.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/KolabAtomicApplication.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/KolabAtomicApplication"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/KolabAtomicApplication"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+latexpdfja:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through platex and dvipdfmx..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+xml:
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+ @echo
+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+pseudoxml:
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+ @echo
+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..beb01db
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,261 @@
+# -*- coding: utf-8 -*-
+#
+# Kolab Atomic Application documentation build configuration file, created by
+# sphinx-quickstart on Thu Nov 5 09:58:18 2015.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'sphinx.ext.graphviz',
+ 'sphinx.ext.todo',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Kolab Atomic Application'
+copyright = u'2015, Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '2015-11'
+# The full version, including alpha/beta/rc tags.
+release = '2015-11-05'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'sphinxdoc'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'KolabAtomicApplicationdoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ ('index', 'KolabAtomicApplication.tex', u'Kolab Atomic Application Documentation',
+ u'Jeroen van Meeuwen (Kolab Systems) \\textless{}vanmeeuwen@kolabsys.com\\textgreater{}', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'kolabatomicapplication', u'Kolab Atomic Application Documentation',
+ [u'Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'KolabAtomicApplication', u'Kolab Atomic Application Documentation',
+ u'Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>', 'KolabAtomicApplication', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
diff --git a/docs/images/base-asav.rst b/docs/images/base-asav.rst
new file mode 100644
index 0000000..cf5516f
--- /dev/null
+++ b/docs/images/base-asav.rst
@@ -0,0 +1,12 @@
+===================
+``kolab/base-asav``
+===================
+
+``/entrypoint.sh``
+==================
+
+Setup Required
+--------------
+
+* Amavis requires a Fully Qualified Domain Name to be available or
+ configured as ``$myhostname``.
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..1254db3
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,707 @@
+========================
+Kolab Atomic Application
+========================
+
+The Kolab Atomic application is a suite of Nulecule applications built
+for the most elastic type of environments.
+
+Every application itself, as well as every role such application may
+take in the overall environment, is separated out in to separate
+containers.
+
+For example, Inbound Mail Exchangers are designed to offer the highest
+grade of protection against spammers and other abusers. This means the
+mail exchanger applies :command:`postscreen`, grey-listing, anti-spam
+and anti-virus (running in another container), but only recipient
+domain validation, and no recipient validation.
+
+Image Inheritance
+=================
+
+Inherit images to allow a rebuild of an image to be fast, and for the
+sake of de-duplication when deploying.
+
+.. graphviz::
+
+ digraph docker {
+ splines = true;
+ overlab = prism;
+
+ edge [color=gray50, fontname=Calibri, fontsize=11];
+ node [shape=record, fontname=Calibri, fontsize=11];
+
+ "centos/centos7";
+ "projectatomic/atomicapp";
+ "rhel7";
+
+ "kolab/base";
+ "kolab/base-asav";
+ "kolab/base-imap";
+ "kolab/base-ldap";
+ "kolab/base-mx";
+ "kolab/base-web";
+ "kolab/base-web-rc";
+
+ "kolab/mongodb";
+
+ subgraph cluster_asav {
+ color = white;
+
+ "kolab/asav-in";
+ "kolab/asav-out";
+ }
+
+ subgraph cluster_imap {
+ color = white;
+
+ "kolab/guam";
+ "kolab/imapf-ext";
+ "kolab/imapf-int";
+ "kolab/imap-mupdate";
+ "kolab/imapb";
+ }
+
+ subgraph cluster_ldap {
+ color = "white";
+
+ "kolab/ldap-master";
+ "kolab/ldap-slave";
+ }
+
+ subgraph cluster_mx {
+ color = white;
+
+ "kolab/asav-in";
+ "kolab/asav-out";
+ "kolab/ext-mx-in";
+ "kolab/ext-mx-out";
+ "kolab/int-mx";
+ "kolab/submission";
+ "kolab/wallace";
+ }
+
+ subgraph cluster_web {
+ color = white;
+
+ "kolab/chwala";
+ "kolab/freebusy";
+ "kolab/http-prx";
+ "kolab/irony";
+ "kolab/manticore";
+ "kolab/roundcubemail";
+ "kolab/syncroton";
+ "kolab/webadmin";
+ }
+
+ "centos/centos7" -> "kolab/mongodb" [dir=back];
+ "rhel7" -> "projectatomic/atomicapp" [dir=back];
+ "projectatomic/atomicapp" -> "kolab/base" [dir=back];
+
+ "kolab/base" -> "kolab/base-asav" [dir=back];
+ "kolab/base" -> "kolab/base-imap" [dir=back];
+ "kolab/base" -> "kolab/base-ldap" [dir=back];
+ "kolab/base" -> "kolab/base-mx" [dir=back];
+ "kolab/base" -> "kolab/base-web" [dir=back];
+ "kolab/base" -> "kolab/kolabd" [dir=back];
+ "kolab/base" -> "kolab/manticore" [dir=back];
+
+ "kolab/base-asav" ->
+ "kolab/asav-in",
+ "kolab/asav-out" [dir=back];
+
+ "kolab/base-imap" ->
+ "kolab/guam",
+ "kolab/imapf-int",
+ "kolab/imapf-ext",
+ "kolab/imap-mupdate",
+ "kolab/imapb" [dir=back];
+
+ "kolab/base-ldap" ->
+ "kolab/ldap-master",
+ "kolab/ldap-slave" [dir=back];
+
+ "kolab/base-mx" ->
+ "kolab/ext-mx-in",
+ "kolab/ext-mx-out",
+ "kolab/int-mx",
+ "kolab/submission",
+ "kolab/wallace" [dir=back];
+
+ "kolab/base-web" ->
+ "kolab/http-prx",
+ "kolab/webadmin",
+ "kolab/base-web-rc" [dir=back];
+
+ "kolab/base-web-rc" ->
+ "kolab/chwala",
+ "kolab/freebusy",
+ "kolab/irony",
+ "kolab/roundcubemail",
+ "kolab/syncroton" [dir=back];
+ }
+
+Container Connection Model
+==========================
+
+.. graphviz::
+
+ digraph {
+ splines = true;
+ overlab = prism;
+
+ edge [color=gray50, fontname=Calibri, fontsize=11];
+ node [style=filled, shape=record, fontname=Calibri, fontsize=11];
+
+ "External SMTP Servers" [color="#FFEEEE"];
+ "User / Client" [color="#FFEEEE"];
+
+ subgraph cluster_db {
+ color = "white";
+
+ "kolab/mongdb-centos7-atomicapp";
+ "projectatomic/mariadb-centos7-atomicapp";
+ }
+
+ "kolab/kolabd";
+
+ subgraph cluster_asav {
+ color = white;
+
+ "kolab/asav-in";
+ "kolab/asav-out";
+ }
+
+ subgraph cluster_imap {
+ color = white;
+
+ "kolab/guam";
+ "kolab/imapf-ext";
+ "kolab/imapf-int";
+ "kolab/imap-mupdate";
+ "kolab/imapb";
+ }
+
+ subgraph cluster_ldap {
+ color = white;
+
+ "kolab/ldap-master";
+ "kolab/ldap-slave";
+ }
+
+ subgraph cluster_mx {
+ color = white;
+
+ "kolab/ext-mx-in";
+ "kolab/ext-mx-out";
+ "kolab/int-mx";
+ "kolab/submission";
+ "kolab/wallace";
+ }
+
+ subgraph cluster_web {
+ color = white;
+
+ "kolab/chwala";
+ "kolab/freebusy";
+ "kolab/http-prx";
+ "kolab/irony";
+ "kolab/manticore";
+ "kolab/roundcubemail";
+ "kolab/syncroton";
+ "kolab/webadmin";
+ }
+
+ "kolab/asav-in" -> "kolab/ext-mx-in" [label="(1)"];
+ "kolab/asav-out" -> "kolab/ext-mx-out" [label="(2)"];
+
+ "kolab/chwala" -> "kolab/imapf-int" [label="(61)"];
+ "kolab/chwala" -> "kolab/ldap-slave" [label="(62)"];
+ "kolab/chwala" -> "projectatomic/mariadb-centos7-atomicapp" [label="(63)"];
+
+ "kolab/ext-mx-in" -> "kolab/asav-in" [label="(3)"];
+ "kolab/ext-mx-in" -> "kolab/int-mx" [label="(4)"];
+ "kolab/ext-mx-in" -> "kolab/ldap-slave" [label="(5)"];
+
+ "kolab/ext-mx-out" -> "kolab/asav-out" [label="(6)"];
+ "kolab/ext-mx-out" -> "kolab/int-mx" [label="(7)"];
+
+ "kolab/freebusy" -> "kolab/imapf-int" [label="(8)"];
+ "kolab/freebusy" -> "kolab/ldap-slave" [label="(9)"];
+ "kolab/freebusy" -> "projectatomic/mariadb-centos7-atomicapp" [label="(10)"];
+
+ "kolab/http-prx" -> "kolab/chwala" [label="(60)"];
+ "kolab/http-prx" -> "kolab/freebusy" [label="(48)"];
+ "kolab/http-prx" -> "kolab/irony" [label="(49)"];
+ "kolab/http-prx" -> "kolab/manticore" [label="(66)"];
+ "kolab/http-prx" -> "kolab/roundcubemail" [label="(50)"];
+ "kolab/http-prx" -> "kolab/syncroton" [label="(51)"];
+ "kolab/http-prx" -> "kolab/webadmin" [label="(52)"];
+
+ "kolab/imap-mupdate" -> "kolab/imapf-ext" [label="(11)"];
+ "kolab/imap-mupdate" -> "kolab/imapf-int" [label="(12)"];
+ "kolab/imap-mupdate" -> "kolab/ldap-slave" [label="(13)"];
+
+ "kolab/imapb" -> "kolab/imap-mupdate" [label="(14)"];
+ "kolab/imapb" -> "kolab/int-mx" [label="(15)"];
+ "kolab/imapb" -> "kolab/ldap-slave" [label="(16)"];
+
+ "kolab/imapf-ext" -> "kolab/imap-mupdate" [label="(17)"];
+ "kolab/imapf-ext" -> "kolab/imapb" [label="(18)"];
+ "kolab/imapf-ext" -> "kolab/ldap-slave" [label="(19)"];
+
+ "kolab/imapf-int" -> "kolab/imap-mupdate" [label="(20)"];
+ "kolab/imapf-int" -> "kolab/imapb" [label="(21)"];
+ "kolab/imapf-int" -> "kolab/ldap-slave" [label="(22)"];
+
+ "kolab/guam" -> "kolab/imapf-ext" [label="(26)"];
+ "kolab/guam" -> "kolab/ldap-slave" [label="(27)"];
+
+ "kolab/int-mx" -> "kolab/ext-mx-out" [label="(28)"];
+ "kolab/int-mx" -> "kolab/imapb" [label="(29)"];
+ "kolab/int-mx" -> "kolab/ldap-slave" [label="(30)"];
+ "kolab/int-mx" -> "kolab/wallace" [label="(31)"];
+
+ "kolab/irony" -> "kolab/imapf-int" [label="(32)"];
+ "kolab/irony" -> "kolab/ldap-slave" [label="(33)"];
+ "kolab/irony" -> "projectatomic/mariadb-centos7-atomicapp" [label="(34)"];
+
+ "kolab/kolabd" -> "kolab/imapb" [label="(53)"];
+ "kolab/kolabd" -> "kolab/imapf-int" [label="(54)"];
+ "kolab/kolabd" -> "kolab/ldap-master" [label="(55)"];
+
+ "kolab/ldap-master" -> "kolab/ldap-slave" [label="(35)"];
+
+ "kolab/manticore" -> "centos/mongodb-26-centos7" [label="(64)"];
+ "kolab/manticore" -> "kolab/chwala" [label="(65)"];
+
+ "kolab/roundcubemail" -> "kolab/freebusy" [label="(36)"];
+ "kolab/roundcubemail" -> "kolab/imapf-int" [label="(37)"];
+ "kolab/roundcubemail" -> "projectatomic/mariadb-centos7-atomicapp" [label="(38)"];
+
+ "kolab/submission" -> "kolab/int-mx" [label="(39)"];
+ "kolab/submission" -> "kolab/ldap-slave" [label="(40)"];
+
+ "kolab/syncroton" -> "kolab/imapf-int" [label="(41)"];
+ "kolab/syncroton" -> "projectatomic/mariadb-centos7-atomicapp" [label="(42)"];
+
+ "kolab/wallace" -> "kolab/imapf-int" [label="(43)"];
+ "kolab/wallace" -> "kolab/int-mx" [label="(44)"];
+ "kolab/wallace" -> "kolab/ldap-slave" [label="(45)"];
+
+ "kolab/webadmin" -> "kolab/ldap-master" [label="(46)"];
+ "kolab/webadmin" -> "projectatomic/mariadb-centos7-atomicapp" [label="(47)"];
+
+ "External SMTP Servers" -> "kolab/ext-mx-in"[label="(56)"];
+ "User / Client" -> "kolab/http-prx" [label="(57)"];
+ "User / Client" -> "kolab/guam" [label="(58)"];
+ "User / Client" -> "kolab/submission" [label="(59)"];
+ }
+
+.. table:: Connection Diagram Table
+
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | # | Source Container | Target Pod | Target Port | Description |
+ +====+=====================+=========================================+=============+=======================+
+ | 1 | kolab/asav-in | kolab/ext-mx-in | 10024/tcp | Re-submission after |
+ | | | | | Anti-Spam and Anti- |
+ | | | | | Virus checks. [#]_ |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 2 | kolab/asav-out | kolab/ext-mx-out | 10024/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 3 | kolab/ext-mx-in | kolab/asav-in | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 4 | kolab/ext-mx-in | kolab/int-mx | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 5 | kolab/ext-mx-in | kolab/ldap-slave | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 6 | kolab/ext-mx-out | kolab/asav-out | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 7 | kolab/ext-mx-out | kolab/int-mx | ??/tcp | NDR and DSN messages. |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 8 | kolab/freebusy | kolab/imapf-int | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 9 | kolab/freebusy | kolab/ldap-slave | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 10 | kolab/freebusy | projectatomic/mariadb-centos7-atomicapp | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 11 | kolab/imap-mupdate | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 12 | kolab/imap-mupdate | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 13 | kolab/imap-mupdate | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 14 | kolab/imapb | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 15 | kolab/imapb | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 16 | kolab/imapb | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 17 | kolab/imapf-ext | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 18 | kolab/imapf-ext | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 19 | kolab/imapf-ext | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 20 | kolab/imapf-int | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 21 | kolab/imapf-int | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 22 | kolab/imapf-int | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 26 | kolab/guam | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 27 | kolab/guam | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 28 | kolab/int-mx | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 29 | kolab/int-mx | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 30 | kolab/int-mx | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 31 | kolab/int-mx | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 32 | kolab/irony | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 33 | kolab/irony | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 34 | kolab/irony | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 35 | kolab/ldap-master | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 36 | kolab/roundcubemail | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 37 | kolab/roundcubemail | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 38 | kolab/roundcubemail | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 39 | kolab/submission | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 40 | kolab/submission | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 41 | kolab/syncroton | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 42 | kolab/syncroton | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 43 | kolab/wallace | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 44 | kolab/wallace | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 45 | kolab/wallace | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 46 | kolab/webadmin | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 47 | kolab/webadmin | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 48 | kolab/http-prx | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 49 | kolab/http-prx | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 50 | kolab/http-prx | kolab/roundcubemail | 80,443/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 51 | kolab/http-prx | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 52 | kolab/http-prx | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 53 | kolab/kolabd | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 54 | kolab/kolabd | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 55 | kolab/kolabd | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 56 | Ext. SMTP Servers | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 57 | User / Client | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 58 | User / Client | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 59 | User / Client | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 60 | kolab/http-prx | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 61 | kolab/chwala | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 62 | kolab/chwala | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 63 | kolab/chwala | kolab/... | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 64 | kolab/manticore | centos/mongodb-26-centos7 | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 65 | kolab/manticore | kolab/chwala | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+ | 66 | kolab/http-prx | kolab/manticore | ??/tcp | |
+ +----+---------------------+-----------------------------------------+-------------+-----------------------+
+
+
+Container Images
+================
+
+``base``
+--------
+
+Based on ``centos:centos7``.
+
+Installs the ``Kolab:Development/CentOS_7`` software repository, the
+**yum-plugin-priorities** package, and installs the GPG key.
+
+Adds common functionality used in other images' entry points in a file
+:file:`/functions.sh`.
+
+``base-asav``
+-------------
+
+Installs the necessary Anti-Spam and Anti-Virus software. As it does not need to
+be customized further, also adds the :file:`/entrypoint.sh`. Consumer images
+should set an environment variable ``KOLAB_ROLE`` to either ``ASAV_IN`` or
+``ASAV_OUT``, so that the entrypoint can decide whether to re-inject messages
+to the server at ``KOLAB_EXT_MX_IN_SERVICE_HOST`` or
+``KOLAB_EXT_MX_OUT_SERVICE_HOST``, and what policy banks to apply.
+
+``base-imap``
+-------------
+
+Installs the necessary software for IMAP functionality, such as **cyrus-imapd**
+and **kolab-saslauthd**.
+
+Configures the command to run upon executing the container's entrypoint, along
+the lines of :command:`/usr/lib/cyrus-imapd/cyrus-master -L /dev/null`.
+
+``base-ldap``
+-------------
+
+Installs the necessary software for LDAP functionality, such as **389-ds**.
+
+Also installs the Kolab schema extensions, and replaces the default
+:file:`/usr/share/dirsrv/data/template.ldif` with a version that makes Kolab
+function.
+
+``base-mx``
+-----------
+
+Installs the necessary software for mail-exchanger functionality, such as
+**postfix** and **postfix-kolab**.
+
+Also sets the command to run upon executing a container's entry point to
+something along the lines of :command:`/usr/libexec/postfix/master -D`.
+
+``base-web``
+------------
+
+Installs the necessary software to run web services, such as **httpd**.
+
+Also sets the command to execute upon entry to
+:command:`/usr/sbin/httpd -DFOREGROUND`.
+
+``base-web-rc``
+---------------
+
+In addition to the software installed on ``base-web``, installs
+**roundcubemail** and **roundcubemail-plugins-kolab**.
+
+Keeping this a separate image helps to re-use the base image for a variety of
+other micro-services.
+
+``asav-in``
+-----------
+
+Anti-Spam and Anti-Virus tailored to entertain inbound message traffic.
+
+``asav-out``
+------------
+
+Anti-Spam and Anti-Virus tailored to entertain outbound message traffic -- such
+as applying DKIM signatures.
+
+``chwala``
+----------
+
+File Cloud.
+
+``ext-mx-in``
+-------------
+
+Inbound External Mail Exchanger. Must be able to take a degree of abuse.
+
+``ext-mx-out``
+--------------
+
+Outbound External Mail Exchanger. Should aid to eliviate Internal Mail
+Exchanger's message queues should recipient mail exchangers not be available.
+
+``freebusy``
+------------
+
+Scheduling information.
+
+``guam``
+--------
+
+Reverse proxy for IMAP with spicy sauce. Enables filtering IMAP folders that
+contain groupware data for those clients that do not understand how to interpret
+such -- i.e. all IMAP clients aside from Kontact and Roundcube with Kolab
+plugins.
+
+``http-prx``
+------------
+
+For all the micro-services that are web services, have one entrypoint.
+
+``imapb``
+---------
+
+An IMAP backend. Contains payload (mailboxes).
+
+``imapf-ext``
+-------------
+
+An external-facing IMAP frontend. Must be able to take a degree of abuse.
+
+``imapf-int``
+-------------
+
+An internal-facing IMAP frontend, for use with internal micro-services such as
+many of the web-based micro-services.
+
+This functionality is separated from the ``imapf-ext`` functionality, because
+internal traffic has far lower security and audit requirements.
+
+``imap-mupdate``
+----------------
+
+The IMAP aggregator master service.
+
+``int-mx``
+----------
+
+Internal mail exchanger. For a domain ``example.org``, all inbound traffic is
+ultimately relayed to this service, all internal traffic is submitted here,
+aliases are translated here, distribution groups are expanded here.
+
+``irony``
+---------
+
+*DAV protocol access layer to Kolab Groupware.
+
+``ldap-master``
+---------------
+
+389 Directory Server services set up just right for Kolab. Scalability and
+redundancy requirements dictate that the read- and write- functionality is split
+between at least a master and one-or-more slaves.
+
+``ldap-slave``
+--------------
+
+``manticore``
+-------------
+
+Collaborative editing services for documents in the Open Document Format (ODF).
+
+``roundcubemail``
+-----------------
+
+The webmail client.
+
+``submission``
+--------------
+
+Submission services for external clients.
+
+``syncroton``
+-------------
+
+ActiveSync.
+
+``wallace``
+-----------
+
+Kolab content filter with resource scheduling, invitation policies and GPG
+encryption.
+
+``webadmin``
+------------
+
+The Web Administration Panel to LDAP.
+
+``chwala-database``
+-------------------
+
+``freebusy-database``
+---------------------
+
+``irony-database``
+------------------
+
+``roundcubemail-database``
+--------------------------
+
+``syncroton-database``
+----------------------
+
+``webadmin-database``
+---------------------
+
+``asav-in-atomicapp``
+---------------------
+
+``asav-out-atomicapp``
+----------------------
+
+``chwala-atomicapp``
+--------------------
+
+``ext-mx-in-atomicapp``
+-----------------------
+
+``ext-mx-out-atomicapp``
+------------------------
+
+``freebusy-atomicapp``
+----------------------
+
+``guam-atomicapp``
+------------------
+
+``imapb-atomicapp``
+-------------------
+
+``imapf-ext-atomicapp``
+-----------------------
+
+``imapf-int-atomicapp``
+-----------------------
+
+``imap-mupdate-atomicapp``
+--------------------------
+
+``int-mx-atomicapp``
+--------------------
+
+``irony-atomicapp``
+-------------------
+
+``ldap-master-atomicapp``
+-------------------------
+
+``ldap-slave-atomicapp``
+------------------------
+
+``manticore-atomicapp``
+-----------------------
+
+``roundcubemail-atomicapp``
+---------------------------
+
+``submission-atomicapp``
+------------------------
+
+``syncroton-atomicapp``
+-----------------------
+
+``wallace-atomicapp``
+---------------------
+
+``webadmin-atomicapp``
+----------------------
+
+``atomicapp``
+-------------