diff --git a/webmails/rainloop/Dockerfile b/webmails/rainloop/Dockerfile index 9814413d..f1394d64 100644 --- a/webmails/rainloop/Dockerfile +++ b/webmails/rainloop/Dockerfile @@ -1,51 +1,71 @@ ARG ARCH="" -ARG QEMU=other # NOTE: only add file if building for arm -FROM ${ARCH}php:7.4-apache as build_arm +FROM ${ARCH}alpine:3.14 ONBUILD COPY --from=balenalib/rpi-alpine:3.14 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static -FROM ${ARCH}php:7.4-apache as build_other +# 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 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 +# 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 \ + nginx \ + php7 php7-fpm php7-curl php7-iconv php7-json php7-xml php7-dom php7-openssl php7-pdo php7-pdo_sqlite \ + && rm /etc/nginx/http.d/default.conf \ + && rm /etc/php7/php-fpm.d/www.conf \ + && mkdir -p /run/nginx \ + && mkdir -p /var/www/rainloop -# Shared layer between nginx, dovecot, postfix, postgresql, rspamd, unbound, rainloop, roundcube -RUN pip3 install socrate +# nginx / PHP config files +COPY config/nginx-rainloop.conf /etc/nginx/http.d/rainloop.conf +COPY config/php-rainloop.conf /etc/php7/php-fpm.d/rainloop.conf +# 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 \ + curl unzip \ + && 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 +CMD php-fpm7 && /start.py HEALTHCHECK CMD curl -f -L http://localhost/ || exit 1 diff --git a/webmails/rainloop/config/nginx-rainloop.conf b/webmails/rainloop/config/nginx-rainloop.conf new file mode 100644 index 00000000..dfdbf8f7 --- /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 warn; + + index index.php; + + location / { + try_files $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..e9906505 --- /dev/null +++ b/webmails/rainloop/config/php-rainloop.conf @@ -0,0 +1,101 @@ +; 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] + +; Redirect worker stdout and stderr into main error log. If not set, stdout and +; stderr will be redirected to /dev/null according to FastCGI specs. +; Default value: no. +catch_workers_output = 1 + +; 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 = ondemand + +; 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 + +; This sets the maximum time in seconds a script is allowed to run before it is +; terminated by the parser. This helps prevent poorly written scripts from tying up +; the server. The default setting is 30s. +; Note: Used only when pm is set to 'ondemand' +pm.process_idle_timeout = 10s + +; The number of requests each child process should execute before respawning. +; This can be useful to work around memory leaks in 3rd party libraries. For endless +; request processing specify '0'. +; Equivalent to PHP_FCGI_MAX_REQUESTS. Default value: 0. +; Noted: Used only when pm is set to 'ondemand' +pm.max_requests = 200 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;"])