From d472900efa5a81cf59b2b91d506b58fe7a1b3d57 Mon Sep 17 00:00:00 2001 From: Erriez Date: Tue, 10 Aug 2021 21:47:14 +0200 Subject: [PATCH] Optimize Rainloop to NGINX - Reduce build time. - Reduce image size. - Faster user response using CGI. --- webmails/rainloop/Dockerfile | 78 ++++++++++------- webmails/rainloop/config/nginx-rainloop.conf | 38 +++++++++ webmails/rainloop/config/php-rainloop.conf | 83 +++++++++++++++++++ .../rainloop/{ => defaults}/application.ini | 0 webmails/rainloop/{ => defaults}/default.ini | 0 webmails/rainloop/{ => defaults}/php.ini | 0 webmails/rainloop/{ => login}/include.php | 0 webmails/rainloop/{ => login}/sso.php | 2 +- webmails/rainloop/start.py | 13 ++- 9 files changed, 174 insertions(+), 40 deletions(-) create mode 100644 webmails/rainloop/config/nginx-rainloop.conf create mode 100644 webmails/rainloop/config/php-rainloop.conf rename webmails/rainloop/{ => defaults}/application.ini (100%) rename webmails/rainloop/{ => defaults}/default.ini (100%) rename webmails/rainloop/{ => defaults}/php.ini (100%) rename webmails/rainloop/{ => login}/include.php (100%) rename webmails/rainloop/{ => login}/sso.php (89%) diff --git a/webmails/rainloop/Dockerfile b/webmails/rainloop/Dockerfile index 9814413d..95cf9b4a 100644 --- a/webmails/rainloop/Dockerfile +++ b/webmails/rainloop/Dockerfile @@ -1,51 +1,65 @@ -ARG ARCH="" -ARG QEMU=other +ARG DISTRO=nginx:1.21-alpine +FROM $DISTRO -# NOTE: only add file if building for arm -FROM ${ARCH}php:7.4-apache as build_arm -ONBUILD COPY --from=balenalib/rpi-alpine:3.14 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static +# Shared later between dovecot postfix nginx rspamd rainloop and roundloop +RUN apk add --no-cache \ + python3 py3-pip \ + && pip3 install socrate==0.2.0 -FROM ${ARCH}php:7.4-apache as build_other +# Shared layer between rainloop and roundcube +# https://www.rainloop.net/docs/system-requirements/ +# Rainloop: +# cURL Builtin +# iconv php7-iconv +# json php7-json +# libxml php7-xml +# dom php7-dom +# openssl php7-openssl +# DateTime Builtin +# PCRE Builtin +# SPL Builtin +# Recommended: +# php7-fpm FastCGI Process Manager +# Optional PHP extension (for contacts): +# php7-pdo Accessing databases in PHP +# php7-pdo_sqlite Access to SQLite 3 databases +RUN apk add --no-cache \ + && apk add php7 php7-fpm php7-curl php7-iconv php7-json php7-xml php7-dom php7-openssl \ + && rm /etc/nginx/conf.d/default.conf \ + && rm /etc/php7/php-fpm.d/www.conf -FROM build_${QEMU} -#Shared layer between rainloop and roundcube -RUN apt-get update && apt-get install -y \ - python3 curl python3-pip git python3-multidict \ - && rm -rf /var/lib/apt/lists \ - && echo "ServerSignature Off" >> /etc/apache2/apache2.conf +# nginx / PHP config files +COPY config/nginx-rainloop.conf /etc/nginx/conf.d/rainloop.conf +COPY config/php-rainloop.conf /etc/php7/php-fpm.d/rainloop.conf -# Shared layer between nginx, dovecot, postfix, postgresql, rspamd, unbound, rainloop, roundcube -RUN pip3 install socrate +# Rainloop login +COPY login/include.php /var/www/rainloop/include.php +COPY login/sso.php /var/www/rainloop/sso.php +# Parsed en moved at startup +COPY defaults/php.ini /defaults/php.ini +COPY defaults/application.ini /defaults/application.ini +COPY defaults/default.ini /defaults/default.ini + +# Install Rainloop from source ENV RAINLOOP_URL https://github.com/RainLoop/rainloop-webmail/releases/download/v1.16.0/rainloop-community-1.16.0.zip -RUN apt-get update && apt-get install -y \ - unzip python3-jinja2 \ - && rm -rf /var/www/html/ \ - && mkdir /var/www/html \ - && cd /var/www/html \ +RUN apk add --no-cache \ + unzip py3-jinja2 \ + && mkdir -p /var/www/rainloop \ + && cd /var/www/rainloop \ && curl -L -O ${RAINLOOP_URL} \ && unzip -q *.zip \ && rm -f *.zip \ && rm -rf data/ \ && find . -type d -exec chmod 755 {} \; \ && find . -type f -exec chmod 644 {} \; \ - && chown -R www-data: * \ - && apt-get purge -y unzip \ - && rm -rf /var/lib/apt/lists - -COPY include.php /var/www/html/include.php -COPY sso.php /var/www/html/sso.php -COPY php.ini /php.ini - -COPY application.ini /application.ini -COPY default.ini /default.ini + && chown -R nginx:nginx /var/www/rainloop \ + && apk del unzip COPY start.py /start.py EXPOSE 80/tcp VOLUME ["/data"] -CMD /start.py - -HEALTHCHECK CMD curl -f -L http://localhost/ || exit 1 +CMD php-fpm7 && /start.py diff --git a/webmails/rainloop/config/nginx-rainloop.conf b/webmails/rainloop/config/nginx-rainloop.conf new file mode 100644 index 00000000..3a0ff7fd --- /dev/null +++ b/webmails/rainloop/config/nginx-rainloop.conf @@ -0,0 +1,38 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + + root /var/www/rainloop; + + # /dev/stdout (Default), , off + access_log off; + + # /dev/stderr (Default), , debug, info, notice, warn, error, crit, alert, emerg + error_log /dev/stderr error; + + index index.php; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_split_path_info ^(.+\.php)(/.*)$; + + fastcgi_intercept_errors on; + fastcgi_index index.php; + + fastcgi_keep_conn on; + include /etc/nginx/fastcgi_params; + fastcgi_pass unix:/var/run/php7-fpm.sock; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + } + + location ~ /\.ht { + deny all; + } + + location ^~ /data { + deny all; + } +} diff --git a/webmails/rainloop/config/php-rainloop.conf b/webmails/rainloop/config/php-rainloop.conf new file mode 100644 index 00000000..bb2534cc --- /dev/null +++ b/webmails/rainloop/config/php-rainloop.conf @@ -0,0 +1,83 @@ +; Start a new pool named 'rainloop'. +; the variable $pool can be used in any directive and will be replaced by the +; pool name ('rainloop' here) +[rainloop] + +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +user = nginx +group = nginx + +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on +; a specific port; +; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses +; (IPv6 and IPv4-mapped) on a specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +listen = /var/run/php7-fpm.sock + +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. Many +; BSD-derived systems allow connections regardless of permissions. +; Default Values: user and group are set as the running user +; mode is set to 0660 +listen.owner = nginx +listen.group = nginx +listen.mode = 0660 + +; Choose how the process manager will control the number of child processes. +; Possible Values: +; static - a fixed number (pm.max_children) of child processes; +; dynamic - the number of child processes are set dynamically based on the +; following directives. With this process management, there will be +; always at least 1 children. +; pm.max_children - the maximum number of children that can +; be alive at the same time. +; pm.start_servers - the number of children created on startup. +; pm.min_spare_servers - the minimum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is less than this +; number then some children will be created. +; pm.max_spare_servers - the maximum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is greater than this +; number then some children will be killed. +; ondemand - no children are created at startup. Children will be forked when +; new requests will connect. The following parameter are used: +; pm.max_children - the maximum number of children that +; can be alive at the same time. +; pm.process_idle_timeout - The number of seconds after which +; an idle process will be killed. +; Note: This value is mandatory. +pm = dynamic + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = 5 + +; The number of child processes created on startup. +; Note: Used only when pm is set to 'dynamic' +; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 +pm.start_servers = 2 + +; The desired minimum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.min_spare_servers = 1 + +; The desired maximum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.max_spare_servers = 3 diff --git a/webmails/rainloop/application.ini b/webmails/rainloop/defaults/application.ini similarity index 100% rename from webmails/rainloop/application.ini rename to webmails/rainloop/defaults/application.ini diff --git a/webmails/rainloop/default.ini b/webmails/rainloop/defaults/default.ini similarity index 100% rename from webmails/rainloop/default.ini rename to webmails/rainloop/defaults/default.ini diff --git a/webmails/rainloop/php.ini b/webmails/rainloop/defaults/php.ini similarity index 100% rename from webmails/rainloop/php.ini rename to webmails/rainloop/defaults/php.ini diff --git a/webmails/rainloop/include.php b/webmails/rainloop/login/include.php similarity index 100% rename from webmails/rainloop/include.php rename to webmails/rainloop/login/include.php diff --git a/webmails/rainloop/sso.php b/webmails/rainloop/login/sso.php similarity index 89% rename from webmails/rainloop/sso.php rename to webmails/rainloop/login/sso.php index 2415f45c..0bfbe263 100644 --- a/webmails/rainloop/sso.php +++ b/webmails/rainloop/login/sso.php @@ -18,7 +18,7 @@ if (file_exists(APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/include.php')) { } // Retrieve email and password -if (in_array('HTTP_X_REMOTE_USER', $_SERVER) && in_array('HTTP_X_REMOTE_USER_TOKEN', $_SERVER)) { +if (isset($_SERVER['HTTP_X_REMOTE_USER']) && isset($_SERVER['HTTP_X_REMOTE_USER_TOKEN'])) { $email = $_SERVER['HTTP_X_REMOTE_USER']; $password = $_SERVER['HTTP_X_REMOTE_USER_TOKEN']; $ssoHash = \RainLoop\Api::GetUserSsoHash($email, $password); diff --git a/webmails/rainloop/start.py b/webmails/rainloop/start.py index 2d537284..a52b70e9 100755 --- a/webmails/rainloop/start.py +++ b/webmails/rainloop/start.py @@ -19,12 +19,11 @@ shutil.rmtree(base + "domains/", ignore_errors=True) os.makedirs(base + "domains", exist_ok=True) os.makedirs(base + "configs", exist_ok=True) -conf.jinja("/default.ini", os.environ, "/data/_data_/_default_/domains/default.ini") -conf.jinja("/application.ini", os.environ, "/data/_data_/_default_/configs/application.ini") -conf.jinja("/php.ini", os.environ, "/usr/local/etc/php/conf.d/rainloop.ini") +conf.jinja("/defaults/default.ini", os.environ, "/data/_data_/_default_/domains/default.ini") +conf.jinja("/defaults/application.ini", os.environ, "/data/_data_/_default_/configs/application.ini") +conf.jinja("/defaults/php.ini", os.environ, "/etc/php7/php.ini") -os.system("chown -R www-data:www-data /data") -os.system("chmod -R a+rX /var/www/html/") - -os.execv("/usr/local/bin/apache2-foreground", ["apache2-foreground"]) +os.system("chown -R nginx:nginx /data") +os.system("chmod -R a+rX /var/www/rainloop/") +os.execv("/usr/sbin/nginx", ["nginx", "-g", "daemon off;"])