mirror of
https://github.com/the-djmaze/snappymail.git
synced 2025-02-28 16:54:27 +08:00
Add better Docker development and prod support
This commit is contained in:
parent
e0462af9da
commit
fcf2c2468d
27 changed files with 1453 additions and 66 deletions
0
.docker/mail/setup.sh → .docker/dev/mail/setup.sh
Executable file → Normal file
0
.docker/mail/setup.sh → .docker/dev/mail/setup.sh
Executable file → Normal file
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80 default;
|
listen 80 default;
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
|
@ -1,6 +0,0 @@
|
||||||
FROM node:10.16.0-alpine
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
RUN yarn global add gulp
|
|
||||||
|
|
||||||
CMD ["node", "--version"]
|
|
48
.docker/release/Dockerfile
Normal file
48
.docker/release/Dockerfile
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# Inspired by the original Rainloop dockerfile from youtous on GitLab
|
||||||
|
FROM php:7.3-fpm-buster
|
||||||
|
|
||||||
|
ARG FILES_ZIP
|
||||||
|
LABEL org.label-schema.description="SnappyMail webmail client image using nginx, php-fpm based on Debian Buster"
|
||||||
|
|
||||||
|
ENV UID=991 GID=991 UPLOAD_MAX_SIZE=50M LOG_TO_STDERR=true MEMORY_LIMIT=128M SECURE_COOKIES=true
|
||||||
|
ENV fpm.pool.clear_env=false
|
||||||
|
|
||||||
|
# Install dependencies such as nginx
|
||||||
|
RUN mkdir -p /usr/share/man/man1/ /usr/share/man/man3/ /usr/share/man/man7/ && \
|
||||||
|
apt-get update -q --fix-missing && \
|
||||||
|
apt-get -y upgrade && \
|
||||||
|
apt-get install --no-install-recommends -y \
|
||||||
|
apt-transport-https gnupg openssl wget curl ca-certificates nginx supervisor sudo \
|
||||||
|
unzip libzip-dev libxml2-dev libldb-dev libldap2-dev \
|
||||||
|
sqlite3 libsqlite3-dev libsqlite3-0 libpq-dev postgresql-client mariadb-client logrotate \
|
||||||
|
zip mlocate libmcrypt-dev libpcre3-dev libicu-dev \
|
||||||
|
build-essential chrpath libssl-dev \
|
||||||
|
libxft-dev libfreetype6 libfreetype6-dev \
|
||||||
|
libpng-dev libjpeg62-turbo-dev \
|
||||||
|
libfontconfig1 libfontconfig1-dev \
|
||||||
|
&& \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install PHP extensions
|
||||||
|
RUN php -m && \
|
||||||
|
docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ && \
|
||||||
|
docker-php-ext-configure intl && \
|
||||||
|
docker-php-ext-configure gd --with-freetype-dir=/usr/include --with-jpeg-dir=/usr/include/ && \
|
||||||
|
docker-php-ext-install ldap opcache pdo_mysql pdo_pgsql zip intl gd && \
|
||||||
|
php -m
|
||||||
|
|
||||||
|
# Install snappymail
|
||||||
|
WORKDIR /tmp
|
||||||
|
COPY ${FILES_ZIP} .
|
||||||
|
RUN mkdir /snappymail && \
|
||||||
|
unzip -q ${FILES_ZIP} -d /snappymail && \
|
||||||
|
find /snappymail -type d -exec chmod 755 {} \; && \
|
||||||
|
find /snappymail -type f -exec chmod 644 {} \; && \
|
||||||
|
rm -rf ${FILES_ZIP}
|
||||||
|
|
||||||
|
# Install other content
|
||||||
|
COPY files /
|
||||||
|
RUN chmod +x /entrypoint.sh && chmod +x /logrotate-loop.sh
|
||||||
|
VOLUME /snappymail/data
|
||||||
|
EXPOSE 8888
|
||||||
|
CMD ["/entrypoint.sh"]
|
77
.docker/release/files/entrypoint.sh
Normal file
77
.docker/release/files/entrypoint.sh
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Create not root user
|
||||||
|
groupadd --gid "$GID" php-cli -f
|
||||||
|
adduser --uid "$UID" --disabled-password --gid "$GID" --shell /bin/bash --home /home/php-cli php-cli --force --gecos ""
|
||||||
|
|
||||||
|
|
||||||
|
# Set attachment size limit
|
||||||
|
sed -i "s/<UPLOAD_MAX_SIZE>/$UPLOAD_MAX_SIZE/g" /usr/local/etc/php-fpm.d/php-fpm.conf /etc/nginx/nginx.conf
|
||||||
|
sed -i "s/<MEMORY_LIMIT>/$MEMORY_LIMIT/g" /usr/local/etc/php-fpm.d/php-fpm.conf
|
||||||
|
|
||||||
|
# Remove postfixadmin-change-password plugin if exist
|
||||||
|
if [ -d "/snappymail/data/_data_/_default_/plugins/postfixadmin-change-password" ]; then
|
||||||
|
rm -rf /snappymail/data/_data_/_default_/plugins/postfixadmin-change-password
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set log output to STDERR if wanted (LOG_TO_STDERR=true)
|
||||||
|
if [ "$LOG_TO_STDERR" = true ]; then
|
||||||
|
echo "[INFO] Logging to stderr activated"
|
||||||
|
sed -i "s/.*error_log.*$/error_log \/dev\/stderr warn;/" /etc/nginx/nginx.conf
|
||||||
|
sed -i "s/.*error_log.*$/php_admin_value[error_log] = \/dev\/stderr/" /usr/local/etc/php-fpm.d/php-fpm.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Secure cookies
|
||||||
|
if [ "${SECURE_COOKIES}" = true ]; then
|
||||||
|
echo "[INFO] Secure cookies activated"
|
||||||
|
{
|
||||||
|
echo 'session.cookie_httponly = On';
|
||||||
|
echo 'session.cookie_secure = On';
|
||||||
|
echo 'session.use_only_cookies = On';
|
||||||
|
} > /usr/local/etc/php/conf.d/cookies.ini;
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add postfixadmin-change-password plugin
|
||||||
|
mkdir -p /snappymail/data/_data_/_default_/plugins/
|
||||||
|
cp -r /usr/local/include/postfixadmin-change-password /snappymail/data/_data_/_default_/plugins/
|
||||||
|
|
||||||
|
# Copy snappymail default config if absent
|
||||||
|
SNAPPYMAIL_CONFIG_FILE=/snappymail/data/_data_/_default_/configs/application.ini
|
||||||
|
if [ ! -f "$SNAPPYMAIL_CONFIG_FILE" ]; then
|
||||||
|
echo "[INFO] Creating default Snappymail configuration"
|
||||||
|
mkdir -p $(dirname $SNAPPYMAIL_CONFIG_FILE)
|
||||||
|
cp /usr/local/include/application.ini $SNAPPYMAIL_CONFIG_FILE
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enable output of snappymail logs
|
||||||
|
if [ "${LOG_TO_STDERR}" = true ]; then
|
||||||
|
sed -z 's/\; Enable logging\nenable = Off/\; Enable logging\nenable = On/' -i $SNAPPYMAIL_CONFIG_FILE
|
||||||
|
sed 's/^filename = .*/filename = "errors.log"/' -i $SNAPPYMAIL_CONFIG_FILE
|
||||||
|
sed 's/^write_on_error_only = .*/write_on_error_only = Off/' -i $SNAPPYMAIL_CONFIG_FILE
|
||||||
|
sed 's/^write_on_php_error_only = .*/write_on_php_error_only = On/' -i $SNAPPYMAIL_CONFIG_FILE
|
||||||
|
else
|
||||||
|
sed -z 's/\; Enable logging\nenable = On/\; Enable logging\nenable = Off/' -i $SNAPPYMAIL_CONFIG_FILE
|
||||||
|
fi
|
||||||
|
# Always enable snappymail Auth logging
|
||||||
|
sed 's/^auth_logging = .*/auth_logging = On/' -i $SNAPPYMAIL_CONFIG_FILE
|
||||||
|
sed 's/^auth_logging_filename = .*/auth_logging_filename = "auth.log"/' -i $SNAPPYMAIL_CONFIG_FILE
|
||||||
|
sed 's/^auth_logging_format = .*/auth_logging_format = "[{date:Y-m-d H:i:s}] Auth failed: ip={request:ip} user={imap:login} host={imap:host} port={imap:port}"/' -i $SNAPPYMAIL_CONFIG_FILE
|
||||||
|
# Redirect snappymail logs to stderr /stdout
|
||||||
|
mkdir -p /snappymail/data/_data_/_default_/logs/
|
||||||
|
# empty logs
|
||||||
|
cp /dev/null /snappymail/data/_data_/_default_/logs/errors.log
|
||||||
|
cp /dev/null /snappymail/data/_data_/_default_/logs/auth.log
|
||||||
|
chown -R php-cli:php-cli /snappymail/data/
|
||||||
|
|
||||||
|
# Fix permissions
|
||||||
|
chown -R $UID:$GID /snappymail/data /var/log /var/lib/nginx
|
||||||
|
chmod o+w /dev/stdout
|
||||||
|
chmod o+w /dev/stderr
|
||||||
|
|
||||||
|
|
||||||
|
# Touch supervisord PID file in order to fix permissions
|
||||||
|
touch /run/supervisord.pid
|
||||||
|
chown php-cli:php-cli /run/supervisord.pid
|
||||||
|
|
||||||
|
# RUN !
|
||||||
|
exec sudo -u php-cli -g php-cli /usr/bin/supervisord -c '/supervisor.conf' --pidfile '/run/supervisord.pid'
|
5
.docker/release/files/etc/logrotate.d/snappymail
Normal file
5
.docker/release/files/etc/logrotate.d/snappymail
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/snappymail/data/_data_/_default_/logs/* {
|
||||||
|
size 10M
|
||||||
|
rotate 0
|
||||||
|
missingok
|
||||||
|
}
|
106
.docker/release/files/etc/nginx/nginx.conf
Normal file
106
.docker/release/files/etc/nginx/nginx.conf
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
worker_processes auto;
|
||||||
|
pid /tmp/nginx.pid;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
use epoll;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
access_log off;
|
||||||
|
error_log /tmp/ngx_error.log error;
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
keepalive_timeout 15;
|
||||||
|
keepalive_disable msie6;
|
||||||
|
keepalive_requests 100;
|
||||||
|
tcp_nopush on;
|
||||||
|
tcp_nodelay on;
|
||||||
|
server_tokens off;
|
||||||
|
|
||||||
|
fastcgi_temp_path /tmp/fastcgi 1 2;
|
||||||
|
client_body_temp_path /tmp/client_body 1 2;
|
||||||
|
proxy_temp_path /tmp/proxy 1 2;
|
||||||
|
uwsgi_temp_path /tmp/uwsgi 1 2;
|
||||||
|
scgi_temp_path /tmp/scgi 1 2;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_comp_level 5;
|
||||||
|
gzip_min_length 512;
|
||||||
|
gzip_buffers 4 8k;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_disable "msie6";
|
||||||
|
gzip_types
|
||||||
|
text/css
|
||||||
|
text/javascript
|
||||||
|
text/xml
|
||||||
|
text/plain
|
||||||
|
text/x-component
|
||||||
|
application/javascript
|
||||||
|
application/x-javascript
|
||||||
|
application/json
|
||||||
|
application/xml
|
||||||
|
application/rss+xml
|
||||||
|
application/vnd.ms-fontobject
|
||||||
|
font/truetype
|
||||||
|
font/opentype
|
||||||
|
image/svg+xml;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 8888;
|
||||||
|
root /snappymail;
|
||||||
|
index index.php;
|
||||||
|
charset utf-8;
|
||||||
|
|
||||||
|
client_max_body_size <UPLOAD_MAX_SIZE>;
|
||||||
|
|
||||||
|
location ^~ /data {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ index.php;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Assets cache control
|
||||||
|
# --------------------------------------
|
||||||
|
location ~* \.(?:html|xml|json)$ {
|
||||||
|
expires -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(?:css|js)$ {
|
||||||
|
expires 7d;
|
||||||
|
add_header Pragma public;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(?:gif|jpe?g|png|ico|otf|eot|svg|ttf|woff|woff2)$ {
|
||||||
|
expires 30d;
|
||||||
|
log_not_found off;
|
||||||
|
add_header Pragma public;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
}
|
||||||
|
|
||||||
|
# PHP Backend
|
||||||
|
# --------------------------------------
|
||||||
|
location ~* \.php$ {
|
||||||
|
try_files $uri =404;
|
||||||
|
include fastcgi_params;
|
||||||
|
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||||
|
fastcgi_param HTTP_PROXY "";
|
||||||
|
fastcgi_index index.php;
|
||||||
|
fastcgi_pass unix:/tmp/php-fpm.sock;
|
||||||
|
fastcgi_intercept_errors on;
|
||||||
|
fastcgi_request_buffering off;
|
||||||
|
fastcgi_param REMOTE_ADDR $http_x_real_ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
.docker/release/files/listener.php
Normal file
23
.docker/release/files/listener.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
$stdIn = STDIN;
|
||||||
|
$stdOut = STDOUT;
|
||||||
|
|
||||||
|
fwrite($stdOut, "READY\n");
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
if (false == $line = trim(fgets($stdIn))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$match = null;
|
||||||
|
if (preg_match('/eventname:(.*?) /', $line, $match)) {
|
||||||
|
if (in_array($match[1], ['PROCESS_STATE_EXITED', 'PROCESS_STATE_STOPPED', 'PROCESS_STATE_FATAL'])) {
|
||||||
|
exec('kill -15 '.file_get_contents('/run/supervisord.pid'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($stdOut, "RESULT 2\nOK");
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
fwrite($stdOut, "READY\n");
|
||||||
|
}
|
113
.docker/release/files/logrotate-loop.sh
Normal file
113
.docker/release/files/logrotate-loop.sh
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# Simple script to invoke logrotate at regular intervals
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
# from https://github.com/misho-kr/docker-appliances/blob/master/nginx-nodejs/logrotate-loop.sh
|
||||||
|
|
||||||
|
LOGROTATE_BIN="logrotate"
|
||||||
|
|
||||||
|
STATE="$HOME/logrotate.state"
|
||||||
|
CONF="/etc/logrotate.d/snappymail"
|
||||||
|
|
||||||
|
export LOGROTATE_BIN STATE CONF
|
||||||
|
|
||||||
|
RUN_INTERVAL="3600" # every hour
|
||||||
|
|
||||||
|
# helper functions for logging
|
||||||
|
export FMT="%a %b %d %Y %H:%M:%S GMT%z (%Z)"
|
||||||
|
|
||||||
|
function log_date() {
|
||||||
|
echo "$(date +"$FMT"): $*"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# Main loop of the logrotate service:
|
||||||
|
#
|
||||||
|
# while True:
|
||||||
|
# sleep N seconds
|
||||||
|
# run logrotate
|
||||||
|
#
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
function logrotate_loop() {
|
||||||
|
|
||||||
|
trap on_terminate TERM INT
|
||||||
|
|
||||||
|
local interval="${1}"
|
||||||
|
|
||||||
|
log_date "===================================================="
|
||||||
|
log_date
|
||||||
|
log_date "logrotate service starting (pid=$$)"
|
||||||
|
log_date "logrotate process will run every ${interval} seconds"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
|
||||||
|
current_time=$(date "+%s")
|
||||||
|
next_run_time=$(( current_time + interval ))
|
||||||
|
|
||||||
|
while (( current_time < next_run_time ))
|
||||||
|
do
|
||||||
|
logrotate_sleep $(( next_run_time - current_time ))
|
||||||
|
current_time=$(date "+%s")
|
||||||
|
done
|
||||||
|
|
||||||
|
logrotate_run
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# helper function to execute logrotate and pass it the right parameters
|
||||||
|
function logrotate_run() {
|
||||||
|
|
||||||
|
log_date "logrotate will run now"
|
||||||
|
${LOGROTATE_BIN} -s ${STATE} ${CONF}
|
||||||
|
}
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# Procedure to idle the execution for a number of seconds
|
||||||
|
#
|
||||||
|
# There are two requirements:
|
||||||
|
#
|
||||||
|
# - export the PID of the sleep command so that it can be terminated
|
||||||
|
# in case the logrotate service is being shutdown
|
||||||
|
# - keep this (bash) process responsive to SIGTERM while in sleep
|
||||||
|
# mode (normally the signal will be masked and will not be delivered
|
||||||
|
# until the subprocess completes)
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
proc_sleep_pid=""
|
||||||
|
|
||||||
|
function logrotate_sleep() {
|
||||||
|
|
||||||
|
local sleep_interval=${1}
|
||||||
|
|
||||||
|
log_date "logrotate will sleep for ${sleep_interval} seconds"
|
||||||
|
|
||||||
|
( exec -a "logrotate: sleep" sleep ${sleep_interval} )&
|
||||||
|
|
||||||
|
proc_sleep_pid=$!
|
||||||
|
wait ${proc_sleep_pid}
|
||||||
|
}
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# Signal handler for logrotate service to make sure the process exits:
|
||||||
|
#
|
||||||
|
# - properly by terminating the sleep process that is used to idle
|
||||||
|
# the service
|
||||||
|
# - gracefully by writing a message in the log
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
function on_terminate() {
|
||||||
|
|
||||||
|
log_date "logrotate will terminate"
|
||||||
|
log_date
|
||||||
|
|
||||||
|
kill -TERM ${proc_sleep_pid}
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# main
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
logrotate_loop ${1:-RUN_INTERVAL}
|
60
.docker/release/files/supervisor.conf
Normal file
60
.docker/release/files/supervisor.conf
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
[supervisord]
|
||||||
|
nodaemon=true
|
||||||
|
|
||||||
|
[program:nginx]
|
||||||
|
command=nginx -c /etc/nginx/nginx.conf -g 'daemon off;'
|
||||||
|
process_name=%(program_name)s_%(process_num)02d
|
||||||
|
user=php-cli
|
||||||
|
numprocs=1
|
||||||
|
autostart=true
|
||||||
|
autorestart=false
|
||||||
|
startsecs=0
|
||||||
|
stdout_logfile=/dev/stdout
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/stderr
|
||||||
|
stderr_logfile_maxbytes=0
|
||||||
|
|
||||||
|
[program:php-fpm]
|
||||||
|
command=php-fpm -F
|
||||||
|
process_name=%(program_name)s_%(process_num)02d
|
||||||
|
user=php-cli
|
||||||
|
numprocs=1
|
||||||
|
autostart=true
|
||||||
|
autorestart=false
|
||||||
|
startsecs=0
|
||||||
|
stdout_logfile=/dev/stdout
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/stderr
|
||||||
|
stderr_logfile_maxbytes=0
|
||||||
|
|
||||||
|
; reads snappymail logs
|
||||||
|
[program:snappymail-auth]
|
||||||
|
command=tail -f /snappymail/data/_data_/_default_/logs/auth.log
|
||||||
|
stdout_logfile=/dev/stdout
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/stderr
|
||||||
|
stderr_logfile_maxbytes=0
|
||||||
|
|
||||||
|
[program:snappymail-errors]
|
||||||
|
command=tail -f /snappymail/data/_data_/_default_/logs/errors.log
|
||||||
|
# everything is an error
|
||||||
|
stdout_logfile=/dev/stderr
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
redirect_stderr=true
|
||||||
|
|
||||||
|
[program:logrotate]
|
||||||
|
command=/logrotate-loop.sh
|
||||||
|
autorestart=true
|
||||||
|
stdout_logfile=/dev/stdout
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/stderr
|
||||||
|
stderr_logfile_maxbytes=0
|
||||||
|
|
||||||
|
[eventlistener:subprocess-stopped]
|
||||||
|
command=php /listener.php
|
||||||
|
process_name=%(program_name)s_%(process_num)02d
|
||||||
|
user=php-cli
|
||||||
|
numprocs=1
|
||||||
|
events=PROCESS_STATE_EXITED,PROCESS_STATE_STOPPED,PROCESS_STATE_FATAL
|
||||||
|
autostart=true
|
||||||
|
autorestart=unexpected
|
19
.docker/release/files/usr/local/etc/php-fpm.d/php-fpm.conf
Normal file
19
.docker/release/files/usr/local/etc/php-fpm.d/php-fpm.conf
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
[global]
|
||||||
|
daemonize = no
|
||||||
|
|
||||||
|
[default]
|
||||||
|
listen = /tmp/php-fpm.sock
|
||||||
|
pm = ondemand
|
||||||
|
pm.max_children = 30
|
||||||
|
pm.process_idle_timeout = 10s
|
||||||
|
pm.max_requests = 500
|
||||||
|
catch_workers_output = yes
|
||||||
|
chdir = /
|
||||||
|
php_admin_value[error_log] = /tmp/php_error.log
|
||||||
|
php_admin_value[log_errors] = On
|
||||||
|
php_admin_value[expose_php] = Off
|
||||||
|
php_admin_value[display_errors] = Off
|
||||||
|
php_admin_value[date.timezone] = UTC
|
||||||
|
php_admin_value[post_max_size] = <UPLOAD_MAX_SIZE>
|
||||||
|
php_admin_value[upload_max_filesize] = <UPLOAD_MAX_SIZE>
|
||||||
|
php_admin_value[memory_limit] = <MEMORY_LIMIT>
|
359
.docker/release/files/usr/local/include/application.ini
Normal file
359
.docker/release/files/usr/local/include/application.ini
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
; SnappyMail Webmail configuration file
|
||||||
|
; Please don't add custom parameters here, those will be overwritten
|
||||||
|
|
||||||
|
[webmail]
|
||||||
|
; Text displayed as page title
|
||||||
|
title = "SnappyMail Webmail"
|
||||||
|
|
||||||
|
; Text displayed on startup
|
||||||
|
loading_description = "SnappyMail"
|
||||||
|
favicon_url = ""
|
||||||
|
|
||||||
|
; Theme used by default
|
||||||
|
theme = "Default"
|
||||||
|
|
||||||
|
; Allow theme selection on settings screen
|
||||||
|
allow_themes = On
|
||||||
|
allow_user_background = Off
|
||||||
|
|
||||||
|
; Language used by default
|
||||||
|
language = "en"
|
||||||
|
|
||||||
|
; Admin Panel interface language
|
||||||
|
language_admin = "en"
|
||||||
|
|
||||||
|
; Allow language selection on settings screen
|
||||||
|
allow_languages_on_settings = On
|
||||||
|
allow_additional_accounts = On
|
||||||
|
allow_additional_identities = On
|
||||||
|
|
||||||
|
; Number of messages displayed on page by default
|
||||||
|
messages_per_page = 20
|
||||||
|
|
||||||
|
; File size limit (MB) for file upload on compose screen
|
||||||
|
; 0 for unlimited.
|
||||||
|
attachment_size_limit = 25
|
||||||
|
|
||||||
|
[interface]
|
||||||
|
show_attachment_thumbnail = On
|
||||||
|
use_native_scrollbars = Off
|
||||||
|
new_move_to_folder_button = On
|
||||||
|
|
||||||
|
[branding]
|
||||||
|
login_logo = ""
|
||||||
|
login_background = ""
|
||||||
|
login_desc = ""
|
||||||
|
login_css = ""
|
||||||
|
user_css = ""
|
||||||
|
user_logo = ""
|
||||||
|
user_logo_title = ""
|
||||||
|
user_logo_message = ""
|
||||||
|
user_iframe_message = ""
|
||||||
|
welcome_page_url = ""
|
||||||
|
welcome_page_display = "none"
|
||||||
|
|
||||||
|
[contacts]
|
||||||
|
; Enable contacts
|
||||||
|
enable = Off
|
||||||
|
allow_sync = On
|
||||||
|
sync_interval = 20
|
||||||
|
type = "sqlite"
|
||||||
|
pdo_dsn = "mysql:host=127.0.0.1;port=3306;dbname=snappymail"
|
||||||
|
pdo_user = "root"
|
||||||
|
pdo_password = ""
|
||||||
|
suggestions_limit = 30
|
||||||
|
|
||||||
|
[security]
|
||||||
|
; Enable CSRF protection (http://en.wikipedia.org/wiki/Cross-site_request_forgery)
|
||||||
|
csrf_protection = On
|
||||||
|
custom_server_signature = "SnappyMail"
|
||||||
|
x_frame_options_header = ""
|
||||||
|
x_xss_protection_header = "1; mode=block"
|
||||||
|
openpgp = Off
|
||||||
|
|
||||||
|
; Login and password for web admin panel
|
||||||
|
admin_login = "admin"
|
||||||
|
admin_password = "12345"
|
||||||
|
|
||||||
|
; Access settings
|
||||||
|
allow_admin_panel = On
|
||||||
|
allow_two_factor_auth = Off
|
||||||
|
force_two_factor_auth = Off
|
||||||
|
hide_x_mailer_header = Off
|
||||||
|
admin_panel_host = ""
|
||||||
|
admin_panel_key = "admin"
|
||||||
|
content_security_policy = ""
|
||||||
|
core_install_access_domain = ""
|
||||||
|
|
||||||
|
[ssl]
|
||||||
|
; Require verification of SSL certificate used.
|
||||||
|
verify_certificate = Off
|
||||||
|
|
||||||
|
; Allow self-signed certificates. Requires verify_certificate.
|
||||||
|
allow_self_signed = On
|
||||||
|
|
||||||
|
; Location of Certificate Authority file on local filesystem (/etc/ssl/certs/ca-certificates.crt)
|
||||||
|
cafile = ""
|
||||||
|
|
||||||
|
; capath must be a correctly hashed certificate directory. (/etc/ssl/certs/)
|
||||||
|
capath = ""
|
||||||
|
|
||||||
|
; Location of client certificate file (pem format with private key) on local filesystem
|
||||||
|
client_cert = ""
|
||||||
|
|
||||||
|
[capa]
|
||||||
|
folders = On
|
||||||
|
composer = On
|
||||||
|
contacts = On
|
||||||
|
settings = On
|
||||||
|
quota = On
|
||||||
|
help = On
|
||||||
|
reload = On
|
||||||
|
search = On
|
||||||
|
search_adv = On
|
||||||
|
filters = On
|
||||||
|
x-templates = Off
|
||||||
|
dangerous_actions = On
|
||||||
|
message_actions = On
|
||||||
|
messagelist_actions = On
|
||||||
|
attachments_actions = On
|
||||||
|
|
||||||
|
[login]
|
||||||
|
default_domain = ""
|
||||||
|
|
||||||
|
; Allow language selection on webmail login screen
|
||||||
|
allow_languages_on_login = On
|
||||||
|
determine_user_language = On
|
||||||
|
determine_user_domain = Off
|
||||||
|
welcome_page = Off
|
||||||
|
hide_submit_button = On
|
||||||
|
forgot_password_link_url = ""
|
||||||
|
registration_link_url = ""
|
||||||
|
login_lowercase = On
|
||||||
|
|
||||||
|
; This option allows webmail to remember the logged in user
|
||||||
|
; once they closed the browser window.
|
||||||
|
;
|
||||||
|
; Values:
|
||||||
|
; "DefaultOff" - can be used, disabled by default;
|
||||||
|
; "DefaultOn" - can be used, enabled by default;
|
||||||
|
; "Unused" - cannot be used
|
||||||
|
sign_me_auto = "DefaultOff"
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
; Enable plugin support
|
||||||
|
enable = Off
|
||||||
|
|
||||||
|
; List of enabled plugins
|
||||||
|
enabled_list = ""
|
||||||
|
|
||||||
|
[defaults]
|
||||||
|
; Editor mode used by default (Plain, Html, HtmlForced or PlainForced)
|
||||||
|
view_editor_type = "Html"
|
||||||
|
|
||||||
|
; layout: 0 - no preview, 1 - side preview, 2 - bottom preview
|
||||||
|
view_layout = 1
|
||||||
|
view_use_checkboxes = On
|
||||||
|
autologout = 30
|
||||||
|
show_images = Off
|
||||||
|
contacts_autosave = On
|
||||||
|
mail_use_threads = Off
|
||||||
|
allow_draft_autosave = On
|
||||||
|
mail_reply_same_folder = Off
|
||||||
|
|
||||||
|
[logs]
|
||||||
|
; Enable logging
|
||||||
|
enable = Off
|
||||||
|
|
||||||
|
; Logs entire request only if error occured (php requred)
|
||||||
|
write_on_error_only = Off
|
||||||
|
|
||||||
|
; Logs entire request only if php error occured
|
||||||
|
write_on_php_error_only = Off
|
||||||
|
|
||||||
|
; Logs entire request only if request timeout (in seconds) occured.
|
||||||
|
write_on_timeout_only = 0
|
||||||
|
|
||||||
|
; Required for development purposes only.
|
||||||
|
; Disabling this option is not recommended.
|
||||||
|
hide_passwords = On
|
||||||
|
time_offset = "0"
|
||||||
|
session_filter = ""
|
||||||
|
sentry_dsn = ""
|
||||||
|
|
||||||
|
; Log filename.
|
||||||
|
; For security reasons, some characters are removed from filename.
|
||||||
|
; Allows for pattern-based folder creation (see examples below).
|
||||||
|
;
|
||||||
|
; Patterns:
|
||||||
|
; {date:Y-m-d} - Replaced by pattern-based date
|
||||||
|
; Detailed info: http://www.php.net/manual/en/function.date.php
|
||||||
|
; {user:email} - Replaced by user's email address
|
||||||
|
; If user is not logged in, value is set to "unknown"
|
||||||
|
; {user:login} - Replaced by user's login (the user part of an email)
|
||||||
|
; If user is not logged in, value is set to "unknown"
|
||||||
|
; {user:domain} - Replaced by user's domain name (the domain part of an email)
|
||||||
|
; If user is not logged in, value is set to "unknown"
|
||||||
|
; {user:uid} - Replaced by user's UID regardless of account currently used
|
||||||
|
;
|
||||||
|
; {user:ip}
|
||||||
|
; {request:ip} - Replaced by user's IP address
|
||||||
|
;
|
||||||
|
; Others:
|
||||||
|
; {imap:login} {imap:host} {imap:port}
|
||||||
|
; {smtp:login} {smtp:host} {smtp:port}
|
||||||
|
;
|
||||||
|
; Examples:
|
||||||
|
; filename = "log-{date:Y-m-d}.txt"
|
||||||
|
; filename = "{date:Y-m-d}/{user:domain}/{user:email}_{user:uid}.log"
|
||||||
|
; filename = "{user:email}-{date:Y-m-d}.txt"
|
||||||
|
filename = "log-{date:Y-m-d}.txt"
|
||||||
|
|
||||||
|
; Enable auth logging in a separate file (for fail2ban)
|
||||||
|
auth_logging = Off
|
||||||
|
auth_logging_filename = "fail2ban/auth-{date:Y-m-d}.txt"
|
||||||
|
auth_logging_format = "[{date:Y-m-d H:i:s}] Auth failed: ip={request:ip} user={imap:login} host={imap:host} port={imap:port}"
|
||||||
|
|
||||||
|
[debug]
|
||||||
|
; Special option required for development purposes
|
||||||
|
enable = Off
|
||||||
|
|
||||||
|
[social]
|
||||||
|
; Google
|
||||||
|
google_enable = Off
|
||||||
|
google_enable_auth = Off
|
||||||
|
google_enable_auth_gmail = Off
|
||||||
|
google_enable_drive = Off
|
||||||
|
google_enable_preview = Off
|
||||||
|
google_client_id = ""
|
||||||
|
google_client_secret = ""
|
||||||
|
google_api_key = ""
|
||||||
|
|
||||||
|
; Facebook
|
||||||
|
fb_enable = Off
|
||||||
|
fb_app_id = ""
|
||||||
|
fb_app_secret = ""
|
||||||
|
|
||||||
|
; Twitter
|
||||||
|
twitter_enable = Off
|
||||||
|
twitter_consumer_key = ""
|
||||||
|
twitter_consumer_secret = ""
|
||||||
|
|
||||||
|
; Dropbox
|
||||||
|
dropbox_enable = Off
|
||||||
|
dropbox_api_key = ""
|
||||||
|
|
||||||
|
[cache]
|
||||||
|
; The section controls caching of the entire application.
|
||||||
|
;
|
||||||
|
; Enables caching in the system
|
||||||
|
enable = On
|
||||||
|
|
||||||
|
; Additional caching key. If changed, cache is purged
|
||||||
|
index = "v1"
|
||||||
|
|
||||||
|
; Can be: files, APC, memcache, redis (beta)
|
||||||
|
fast_cache_driver = "files"
|
||||||
|
|
||||||
|
; Additional caching key. If changed, fast cache is purged
|
||||||
|
fast_cache_index = "v1"
|
||||||
|
|
||||||
|
; Browser-level cache. If enabled, caching is maintainted without using files
|
||||||
|
http = On
|
||||||
|
|
||||||
|
; Browser-level cache time (seconds, Expires header)
|
||||||
|
http_expires = 3600
|
||||||
|
|
||||||
|
; Caching message UIDs when searching and sorting (threading)
|
||||||
|
server_uids = On
|
||||||
|
|
||||||
|
[labs]
|
||||||
|
; Experimental settings. Handle with care.
|
||||||
|
;
|
||||||
|
allow_mobile_version = On
|
||||||
|
ignore_folders_subscription = Off
|
||||||
|
check_new_password_strength = On
|
||||||
|
update_channel = "stable"
|
||||||
|
allow_gravatar = On
|
||||||
|
allow_prefetch = On
|
||||||
|
allow_smart_html_links = On
|
||||||
|
cache_system_data = On
|
||||||
|
date_from_headers = On
|
||||||
|
autocreate_system_folders = On
|
||||||
|
allow_message_append = Off
|
||||||
|
disable_iconv_if_mbstring_supported = Off
|
||||||
|
login_fault_delay = 1
|
||||||
|
log_ajax_response_write_limit = 300
|
||||||
|
allow_html_editor_source_button = Off
|
||||||
|
allow_html_editor_biti_buttons = Off
|
||||||
|
allow_ctrl_enter_on_compose = On
|
||||||
|
try_to_detect_hidden_images = Off
|
||||||
|
hide_dangerous_actions = Off
|
||||||
|
use_app_debug_js = Off
|
||||||
|
use_mobile_version_for_tablets = Off
|
||||||
|
use_app_debug_css = Off
|
||||||
|
use_imap_sort = On
|
||||||
|
use_imap_force_selection = Off
|
||||||
|
use_imap_list_subscribe = On
|
||||||
|
use_imap_thread = On
|
||||||
|
use_imap_move = Off
|
||||||
|
use_imap_expunge_all_on_delete = Off
|
||||||
|
imap_forwarded_flag = "$Forwarded"
|
||||||
|
imap_read_receipt_flag = "$ReadReceipt"
|
||||||
|
imap_body_text_limit = 555000
|
||||||
|
imap_message_list_fast_simple_search = On
|
||||||
|
imap_message_list_count_limit_trigger = 0
|
||||||
|
imap_message_list_date_filter = 0
|
||||||
|
imap_message_list_permanent_filter = ""
|
||||||
|
imap_message_all_headers = Off
|
||||||
|
imap_large_thread_limit = 50
|
||||||
|
imap_folder_list_limit = 200
|
||||||
|
imap_show_login_alert = On
|
||||||
|
imap_use_auth_plain = On
|
||||||
|
imap_use_auth_cram_md5 = Off
|
||||||
|
smtp_show_server_errors = Off
|
||||||
|
smtp_use_auth_plain = On
|
||||||
|
smtp_use_auth_cram_md5 = Off
|
||||||
|
sieve_allow_raw_script = Off
|
||||||
|
sieve_utf8_folder_name = On
|
||||||
|
sieve_auth_plain_initial = On
|
||||||
|
sieve_allow_fileinto_inbox = Off
|
||||||
|
imap_timeout = 300
|
||||||
|
smtp_timeout = 60
|
||||||
|
sieve_timeout = 10
|
||||||
|
domain_list_limit = 99
|
||||||
|
mail_func_clear_headers = On
|
||||||
|
mail_func_additional_parameters = Off
|
||||||
|
favicon_status = On
|
||||||
|
folders_spec_limit = 50
|
||||||
|
owncloud_save_folder = "Attachments"
|
||||||
|
owncloud_suggestions = On
|
||||||
|
curl_proxy = ""
|
||||||
|
curl_proxy_auth = ""
|
||||||
|
in_iframe = Off
|
||||||
|
force_https = Off
|
||||||
|
custom_login_link = ""
|
||||||
|
custom_logout_link = ""
|
||||||
|
allow_external_login = Off
|
||||||
|
allow_external_sso = Off
|
||||||
|
external_sso_key = ""
|
||||||
|
http_client_ip_check_proxy = Off
|
||||||
|
fast_cache_memcache_host = "127.0.0.1"
|
||||||
|
fast_cache_memcache_port = 11211
|
||||||
|
fast_cache_redis_host = "127.0.0.1"
|
||||||
|
fast_cache_redis_port = 6379
|
||||||
|
use_local_proxy_for_external_images = Off
|
||||||
|
detect_image_exif_orientation = On
|
||||||
|
cookie_default_path = ""
|
||||||
|
cookie_default_secure = Off
|
||||||
|
check_new_messages = On
|
||||||
|
replace_env_in_configuration = ""
|
||||||
|
startup_url = ""
|
||||||
|
strict_html_parser = Off
|
||||||
|
allow_cmd = Off
|
||||||
|
dev_email = ""
|
||||||
|
dev_password = ""
|
||||||
|
|
||||||
|
[version]
|
||||||
|
current = "1.14.0"
|
||||||
|
saved = "Wed, 08 Apr 2020 16:37:27 +0000"
|
|
@ -0,0 +1,342 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class ChangePasswordPostfixAdminDriver implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sEngine = 'MySQL';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sHost = '127.0.0.1';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $iPort = 3306;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sDatabase = 'postfixadmin';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sTable = 'mailbox';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sUsercol = 'username';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sPasscol = 'password';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sUser = 'postfixadmin';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sPassword = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sEncrypt = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $sAllowedEmails = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \MailSo\Log\Logger
|
||||||
|
*/
|
||||||
|
private $oLogger = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sEngine
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetEngine($sEngine)
|
||||||
|
{
|
||||||
|
$this->sEngine = $sEngine;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sHost
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetHost($sHost)
|
||||||
|
{
|
||||||
|
$this->sHost = $sHost;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $iPort
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetPort($iPort)
|
||||||
|
{
|
||||||
|
$this->iPort = (int) $iPort;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sDatabase
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetDatabase($sDatabase)
|
||||||
|
{
|
||||||
|
$this->sDatabase = $sDatabase;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sTable
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetTable($sTable)
|
||||||
|
{
|
||||||
|
$this->sTable = $sTable;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sUsercol
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetUserColumn($sUsercol)
|
||||||
|
{
|
||||||
|
$this->sUsercol = $sUsercol;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sPasscol
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetPasswordColumn($sPasscol)
|
||||||
|
{
|
||||||
|
$this->sPasscol = $sPasscol;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sUser
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetUser($sUser)
|
||||||
|
{
|
||||||
|
$this->sUser = $sUser;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sPassword
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetPassword($sPassword)
|
||||||
|
{
|
||||||
|
$this->sPassword = $sPassword;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sEncrypt
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetEncrypt($sEncrypt)
|
||||||
|
{
|
||||||
|
$this->sEncrypt = $sEncrypt;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sAllowedEmails
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetAllowedEmails($sAllowedEmails)
|
||||||
|
{
|
||||||
|
$this->sAllowedEmails = $sAllowedEmails;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \MailSo\Log\Logger $oLogger
|
||||||
|
*
|
||||||
|
* @return \ChangePasswordPostfixAdminDriver
|
||||||
|
*/
|
||||||
|
public function SetLogger($oLogger)
|
||||||
|
{
|
||||||
|
if ($oLogger instanceof \MailSo\Log\Logger)
|
||||||
|
{
|
||||||
|
$this->oLogger = $oLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \RainLoop\Model\Account $oAccount
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function PasswordChangePossibility($oAccount)
|
||||||
|
{
|
||||||
|
return $oAccount && $oAccount->Email() &&
|
||||||
|
\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->sAllowedEmails);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \RainLoop\Model\Account $oAccount
|
||||||
|
* @param string $sPrevPassword
|
||||||
|
* @param string $sNewPassword
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
|
||||||
|
{
|
||||||
|
if ($this->oLogger)
|
||||||
|
{
|
||||||
|
$this->oLogger->Write('Postfix: Try to change password for '.$oAccount->Email());
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($sPrevPassword);
|
||||||
|
|
||||||
|
$bResult = false;
|
||||||
|
|
||||||
|
if (0 < \strlen($sNewPassword))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$sDsn = '';
|
||||||
|
switch($this->sEngine){
|
||||||
|
case 'MySQL':
|
||||||
|
$sDsn = 'mysql:host='.$this->sHost.';port='.$this->iPort.';dbname='.$this->sDatabase;
|
||||||
|
break;
|
||||||
|
case 'PostgreSQL':
|
||||||
|
$sDsn = 'pgsql:host='.$this->sHost.';port='.$this->iPort.';dbname='.$this->sDatabase;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$sDsn = 'mysql:host='.$this->sHost.';port='.$this->iPort.';dbname='.$this->sDatabase;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$oPdo = new \PDO($sDsn, $this->sUser, $this->sPassword);
|
||||||
|
$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||||
|
|
||||||
|
$sUpdatePassword = $this->cryptPassword($sNewPassword, $oPdo);
|
||||||
|
if (0 < \strlen($sUpdatePassword))
|
||||||
|
{
|
||||||
|
$oStmt = $oPdo->prepare("UPDATE {$this->sTable} SET {$this->sPasscol} = ? WHERE {$this->sUsercol} = ?");
|
||||||
|
$bResult = (bool) $oStmt->execute(array($sUpdatePassword, $oAccount->Email()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($this->oLogger)
|
||||||
|
{
|
||||||
|
$this->oLogger->Write('Postfix: Encrypted password is empty',
|
||||||
|
\MailSo\Log\Enumerations\Type::ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$oPdo = null;
|
||||||
|
}
|
||||||
|
catch (\Exception $oException)
|
||||||
|
{
|
||||||
|
if ($this->oLogger)
|
||||||
|
{
|
||||||
|
$this->oLogger->WriteException($oException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sPassword
|
||||||
|
* @param \PDO $oPdo
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function cryptPassword($sPassword, $oPdo)
|
||||||
|
{
|
||||||
|
$sResult = '';
|
||||||
|
if (function_exists('random_bytes')) {
|
||||||
|
$sSalt = substr(base64_encode(random_bytes(32)), 0, 16);
|
||||||
|
} else {
|
||||||
|
$sSalt = substr(str_shuffle('./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'), 0, 16);
|
||||||
|
}
|
||||||
|
switch (strtolower($this->sEncrypt))
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case 'plain':
|
||||||
|
case 'cleartext':
|
||||||
|
$sResult = '{PLAIN}' . $sPassword;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'md5crypt':
|
||||||
|
include_once __DIR__.'/md5crypt.php';
|
||||||
|
$sResult = '{MD5-CRYPT}' . md5crypt($sPassword);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'md5':
|
||||||
|
$sResult = '{PLAIN-MD5}' . md5($sPassword);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'system':
|
||||||
|
$sResult = '{CRYPT}' . crypt($sPassword);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'sha256-crypt':
|
||||||
|
$sResult = '{SHA256-CRYPT}' . crypt($sPassword,'$5$'.$sSalt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'sha512-crypt':
|
||||||
|
$sResult = '{SHA512-CRYPT}' . crypt($sPassword,'$6$'.$sSalt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'mysql_encrypt':
|
||||||
|
if($this->sEngine == 'MySQL'){
|
||||||
|
$oStmt = $oPdo->prepare('SELECT ENCRYPT(?) AS encpass');
|
||||||
|
if ($oStmt->execute(array($sPassword)))
|
||||||
|
{
|
||||||
|
$aFetchResult = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
if (\is_array($aFetchResult) && isset($aFetchResult[0]['encpass']))
|
||||||
|
{
|
||||||
|
$sResult = $aFetchResult[0]['encpass'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CouldNotSaveNewPassword);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sResult;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 RainLoop Team, @zaffkea
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1 @@
|
||||||
|
Plugin that adds functionality to change the email account password (PostfixAdmin).
|
|
@ -0,0 +1 @@
|
||||||
|
1.3
|
|
@ -0,0 +1,100 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class PostfixadminChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
|
{
|
||||||
|
public function Init()
|
||||||
|
{
|
||||||
|
$this->addHook('main.fabrica', 'MainFabrica');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function Supported()
|
||||||
|
{
|
||||||
|
if (!extension_loaded('pdo') || !class_exists('PDO'))
|
||||||
|
{
|
||||||
|
return 'The PHP extension PDO must be installed to use this plugin';
|
||||||
|
}
|
||||||
|
|
||||||
|
$aDrivers = \PDO::getAvailableDrivers();
|
||||||
|
if (!is_array($aDrivers) || (!in_array('mysql', $aDrivers) && !in_array('pgsql', $aDrivers)))
|
||||||
|
{
|
||||||
|
return 'The PHP extension PDO (mysql or pgsql) must be installed to use this plugin';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sName
|
||||||
|
* @param mixed $oProvider
|
||||||
|
*/
|
||||||
|
public function MainFabrica($sName, &$oProvider)
|
||||||
|
{
|
||||||
|
switch ($sName)
|
||||||
|
{
|
||||||
|
case 'change-password':
|
||||||
|
|
||||||
|
include_once __DIR__.'/ChangePasswordPostfixAdminDriver.php';
|
||||||
|
|
||||||
|
$oProvider = new ChangePasswordPostfixAdminDriver();
|
||||||
|
|
||||||
|
$oProvider
|
||||||
|
->SetEngine($this->Config()->Get('plugin', 'engine',''))
|
||||||
|
->SetHost($this->Config()->Get('plugin', 'host', ''))
|
||||||
|
->SetPort((int) $this->Config()->Get('plugin', 'port', 3306))
|
||||||
|
->SetDatabase($this->Config()->Get('plugin', 'database', ''))
|
||||||
|
->SetTable($this->Config()->Get('plugin', 'table', ''))
|
||||||
|
->SetUserColumn($this->Config()->Get('plugin', 'usercol', ''))
|
||||||
|
->SetPasswordColumn($this->Config()->Get('plugin', 'passcol', ''))
|
||||||
|
->SetUser($this->Config()->Get('plugin', 'user', ''))
|
||||||
|
->SetPassword($this->Config()->Get('plugin', 'password', ''))
|
||||||
|
->SetEncrypt($this->Config()->Get('plugin', 'encrypt', ''))
|
||||||
|
->SetAllowedEmails(\strtolower(\trim($this->Config()->Get('plugin', 'allowed_emails', ''))))
|
||||||
|
->SetLogger($this->Manager()->Actions()->Logger())
|
||||||
|
;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function configMapping()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('engine')->SetLabel('Engine')
|
||||||
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
|
||||||
|
->SetDefaultValue(array('MySQL', 'PostgreSQL'))
|
||||||
|
->SetDescription('Database Engine'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('host')->SetLabel('Host')
|
||||||
|
->SetDefaultValue('127.0.0.1'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('port')->SetLabel('Port')
|
||||||
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::INT)
|
||||||
|
->SetDefaultValue(3306),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('database')->SetLabel('Database')
|
||||||
|
->SetDefaultValue('postfixadmin'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('table')->SetLabel('table')
|
||||||
|
->SetDefaultValue('mailbox'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('usercol')->SetLabel('username column')
|
||||||
|
->SetDefaultValue('username'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('passcol')->SetLabel('password column')
|
||||||
|
->SetDefaultValue('password'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('user')->SetLabel('User')
|
||||||
|
->SetDefaultValue('postfixadmin'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('password')->SetLabel('Password')
|
||||||
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::PASSWORD)
|
||||||
|
->SetDefaultValue(''),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('encrypt')->SetLabel('Encrypt')
|
||||||
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
|
||||||
|
->SetDefaultValue(array('md5crypt', 'md5', 'system', 'cleartext', 'mysql_encrypt', 'SHA256-CRYPT', 'SHA512-CRYPT'))
|
||||||
|
->SetDescription('In what way do you want the passwords to be crypted ?'),
|
||||||
|
\RainLoop\Plugins\Property::NewInstance('allowed_emails')->SetLabel('Allowed emails')
|
||||||
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT)
|
||||||
|
->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@domain1.net user2@domain1.net *@domain2.net')
|
||||||
|
->SetDefaultValue('*')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// md5crypt
|
||||||
|
// Action: Creates MD5 encrypted password
|
||||||
|
// Call: md5crypt (string cleartextpassword)
|
||||||
|
|
||||||
|
function md5crypt($pw, $salt = "", $magic = "")
|
||||||
|
{
|
||||||
|
$MAGIC = "$1$";
|
||||||
|
|
||||||
|
if ($magic == "")
|
||||||
|
{
|
||||||
|
$magic = $MAGIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($salt == "")
|
||||||
|
{
|
||||||
|
$salt = create_salt();
|
||||||
|
}
|
||||||
|
|
||||||
|
$slist = explode("$", $salt);
|
||||||
|
if (isset($slist[0]) && $slist[0] == "1")
|
||||||
|
{
|
||||||
|
$salt = $slist[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$salt = substr($salt, 0, 8);
|
||||||
|
$ctx = $pw.$magic.$salt;
|
||||||
|
$final = hex2bin(md5($pw.$salt.$pw));
|
||||||
|
|
||||||
|
for ($i = strlen($pw); $i > 0; $i -= 16)
|
||||||
|
{
|
||||||
|
if ($i > 16)
|
||||||
|
{
|
||||||
|
$ctx .= substr($final,0,16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ctx .= substr($final,0,$i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$i = strlen($pw);
|
||||||
|
|
||||||
|
while ($i > 0)
|
||||||
|
{
|
||||||
|
if ($i & 1)
|
||||||
|
{
|
||||||
|
$ctx .= chr(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ctx .= $pw[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$i = $i >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$final = hex2bin(md5($ctx));
|
||||||
|
|
||||||
|
for ($i=0; $i<1000; $i++)
|
||||||
|
{
|
||||||
|
$ctx1 = "";
|
||||||
|
if ($i & 1)
|
||||||
|
{
|
||||||
|
$ctx1 .= $pw;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ctx1 .= substr($final,0,16);
|
||||||
|
}
|
||||||
|
if ($i % 3)
|
||||||
|
{
|
||||||
|
$ctx1 .= $salt;
|
||||||
|
}
|
||||||
|
if ($i % 7)
|
||||||
|
{
|
||||||
|
$ctx1 .= $pw;
|
||||||
|
}
|
||||||
|
if ($i & 1)
|
||||||
|
{
|
||||||
|
$ctx1 .= substr($final, 0, 16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$ctx1 .= $pw;
|
||||||
|
}
|
||||||
|
|
||||||
|
$final = hex2bin(md5($ctx1));
|
||||||
|
}
|
||||||
|
|
||||||
|
$passwd = "";
|
||||||
|
$passwd .= to64(((ord($final[0]) << 16) | (ord($final[6]) << 8) | (ord($final[12]))), 4);
|
||||||
|
$passwd .= to64(((ord($final[1]) << 16) | (ord($final[7]) << 8) | (ord($final[13]))), 4);
|
||||||
|
$passwd .= to64(((ord($final[2]) << 16) | (ord($final[8]) << 8) | (ord($final[14]))), 4);
|
||||||
|
$passwd .= to64(((ord($final[3]) << 16) | (ord($final[9]) << 8) | (ord($final[15]))), 4);
|
||||||
|
$passwd .= to64(((ord($final[4]) << 16) | (ord($final[10]) << 8) | (ord($final[5]))), 4);
|
||||||
|
$passwd .= to64(ord($final[11]), 2);
|
||||||
|
|
||||||
|
return $magic.$salt.'$'.$passwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_salt()
|
||||||
|
{
|
||||||
|
srand((double) microtime() * 1000000);
|
||||||
|
return substr(md5(rand(0,9999999)), 0, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PHP around 5.3.8 includes hex2bin as native function - http://php.net/hex2bin
|
||||||
|
if (!function_exists('hex2bin'))
|
||||||
|
{
|
||||||
|
function hex2bin($str)
|
||||||
|
{
|
||||||
|
$len = strlen($str);
|
||||||
|
$nstr = "";
|
||||||
|
for ($i = 0; $i < $len; $i += 2)
|
||||||
|
{
|
||||||
|
$num = sscanf(substr($str, $i, 2), "%x");
|
||||||
|
$nstr .= chr($num[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $nstr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function to64($v, $n)
|
||||||
|
{
|
||||||
|
$ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
$ret = "";
|
||||||
|
|
||||||
|
while (($n - 1) >= 0)
|
||||||
|
{
|
||||||
|
$n--;
|
||||||
|
$ret .= $ITOA64[$v & 0x3f];
|
||||||
|
$v = $v >> 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
FROM python:3.6-alpine
|
|
||||||
|
|
||||||
RUN pip install transifex-client
|
|
||||||
|
|
||||||
CMD ["tx", "--version"]
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -16,3 +16,4 @@
|
||||||
/MULTIPLY
|
/MULTIPLY
|
||||||
/include.php
|
/include.php
|
||||||
.idea/
|
.idea/
|
||||||
|
.env
|
|
@ -1,18 +1,16 @@
|
||||||
version: '2'
|
version: '3.0'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
|
# Mail server running on separate image
|
||||||
mail:
|
mail:
|
||||||
image: tvial/docker-mailserver:latest
|
image: tvial/docker-mailserver:latest
|
||||||
hostname: mail
|
|
||||||
container_name: rl.mail
|
|
||||||
domainname: domain.com
|
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
domainname: example.com
|
||||||
- 25:25
|
|
||||||
- 143:143
|
|
||||||
volumes:
|
volumes:
|
||||||
- maildata:/var/mail
|
- maildata:/var/mail
|
||||||
- mailstate:/var/mail-state
|
- mailstate:/var/mail-state
|
||||||
- ./.docker/mail/config/:/tmp/docker-mailserver/
|
- ./.docker/dev/mail/config/:/tmp/docker-mailserver/
|
||||||
environment:
|
environment:
|
||||||
- ENABLE_SPAMASSASSIN=0
|
- ENABLE_SPAMASSASSIN=0
|
||||||
- ENABLE_CLAMAV=0
|
- ENABLE_CLAMAV=0
|
||||||
|
@ -24,70 +22,44 @@ services:
|
||||||
cap_add:
|
cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
- SYS_PTRACE
|
- SYS_PTRACE
|
||||||
|
|
||||||
|
# MySQL database
|
||||||
db:
|
db:
|
||||||
image: mysql:5.7
|
image: mysql:5.7
|
||||||
hostname: db
|
hostname: db
|
||||||
container_name: rl.db
|
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
MYSQL_ROOT_PASSWORD: root
|
- MYSQL_ROOT_PASSWORD=root
|
||||||
MYSQL_USER: snappymail
|
- MYSQL_USER=snappymail
|
||||||
MYSQL_PASSWORD: snappymail
|
- MYSQL_PASSWORD=snappymail
|
||||||
MYSQL_DATABASE: snappymail
|
- MYSQL_DATABASE=snappymail
|
||||||
volumes:
|
volumes:
|
||||||
- mysql:/var/lib/mysql
|
- mysql:/var/lib/mysql
|
||||||
- tmp:/tmp
|
|
||||||
|
# PHP FPM Server
|
||||||
php:
|
php:
|
||||||
build:
|
build:
|
||||||
context: ./.docker/php
|
context: ./.docker/dev/php
|
||||||
hostname: php
|
|
||||||
container_name: rl.php
|
|
||||||
expose:
|
|
||||||
- 9000
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
- mail
|
- mail
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/var/www
|
- ./:/var/www
|
||||||
# - ./build/local/:/var/www
|
- ./.docker/dev/php/snappymail.ini:/usr/local/etc/php/conf.d/snappymail.ini
|
||||||
- ./.docker/php/snappymail.ini:/usr/local/etc/php/conf.d/snappymail.ini
|
|
||||||
- tmp:/tmp
|
# Nginx load balancer translating to PHP FPM
|
||||||
node:
|
|
||||||
build:
|
|
||||||
context: ./.docker/node
|
|
||||||
hostname: node
|
|
||||||
container_name: rl.node
|
|
||||||
working_dir: /var/www
|
|
||||||
command: sh -c 'yarn --version'
|
|
||||||
volumes:
|
|
||||||
- ./:/var/www
|
|
||||||
- tmp:/tmp
|
|
||||||
nginx:
|
nginx:
|
||||||
image: nginx:latest
|
image: nginx:latest
|
||||||
hostname: nginx
|
hostname: nginx
|
||||||
container_name: rl.nginx
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- php
|
- php
|
||||||
ports:
|
ports:
|
||||||
- 443:443
|
- "${HTTPS_PORT}:443"
|
||||||
- 80:80
|
- "${HTTP_PORT}:80"
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/var/www
|
- ./:/var/www
|
||||||
# - ./build/local/:/var/www
|
- ./.docker/dev/nginx/ssl:/etc/nginx/ssl
|
||||||
- ./.docker/nginx/ssl:/etc/nginx/ssl
|
- ./.docker/dev/nginx/default.conf:/etc/nginx/conf.d/default.conf
|
||||||
- ./.docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
|
|
||||||
- tmp:/tmp
|
|
||||||
tx:
|
|
||||||
build:
|
|
||||||
context: ./.docker/tx
|
|
||||||
hostname: tx
|
|
||||||
container_name: rl.tx
|
|
||||||
working_dir: /var/www
|
|
||||||
command: sh -c 'tx --version'
|
|
||||||
volumes:
|
|
||||||
- ./:/var/www
|
|
||||||
- ./.docker/.cache/tx/root:/root
|
|
||||||
- tmp:/tmp
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
mysql:
|
mysql:
|
||||||
|
@ -96,5 +68,3 @@ volumes:
|
||||||
driver: local
|
driver: local
|
||||||
mailstate:
|
mailstate:
|
||||||
driver: local
|
driver: local
|
||||||
tmp:
|
|
||||||
driver: local
|
|
||||||
|
|
13
release.php
13
release.php
|
@ -11,6 +11,7 @@ $package = json_decode(file_get_contents('package.json'));
|
||||||
|
|
||||||
$zip_destination = "snappymail-{$package->version}.zip";
|
$zip_destination = "snappymail-{$package->version}.zip";
|
||||||
$tar_destination = "snappymail-{$package->version}.tar";
|
$tar_destination = "snappymail-{$package->version}.tar";
|
||||||
|
$docker_zip = "./.docker/release/snappymail-{$package->version}.zip";
|
||||||
|
|
||||||
@unlink($zip_destination);
|
@unlink($zip_destination);
|
||||||
@unlink($tar_destination);
|
@unlink($tar_destination);
|
||||||
|
@ -110,3 +111,15 @@ $tar->compress(Phar::GZ);
|
||||||
unlink($tar_destination);
|
unlink($tar_destination);
|
||||||
|
|
||||||
echo "\n{$zip_destination} created\n{$tar_destination}.gz created\n";
|
echo "\n{$zip_destination} created\n{$tar_destination}.gz created\n";
|
||||||
|
|
||||||
|
// Docker build
|
||||||
|
if(readline("Build Docker image? (Y/N): ") === "Y") {
|
||||||
|
copy($zip_destination, $docker_zip);
|
||||||
|
|
||||||
|
$docker = trim(`which docker`);
|
||||||
|
if(!$docker) {
|
||||||
|
exit("Docker not installed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
passthru("{$docker} build " . __DIR__ . "/.docker/release/ --build-arg FILES_ZIP={$zip_destination} -t snappymail:{$package->version}");
|
||||||
|
}
|
2
template.env
Normal file
2
template.env
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
HTTP_PORT=8080
|
||||||
|
HTTPS_PORT=8443
|
Loading…
Reference in a new issue