2018-12-29 05:10:36 +00:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
|
|
# === Patches for poste.io free version to be a properly isolated service ===
|
|
|
|
#
|
|
|
|
# - Restricts all public listening ports to the IP(s) associated with the
|
|
|
|
# container's hostname
|
|
|
|
#
|
|
|
|
# - Replaces all localhost listening ports with unix-domain sockets inside
|
|
|
|
# the container
|
|
|
|
#
|
|
|
|
# With these changes, multiple poste.io instances can be run on the same
|
|
|
|
# machine (as long as each container has its own public IP), and no internal
|
2020-02-29 18:53:15 +00:00
|
|
|
# services (such as quota, websockets, etc.) are exposed to the host's
|
2018-12-29 05:10:36 +00:00
|
|
|
# loopback interface.
|
|
|
|
|
|
|
|
set -eu # fail on any errors or undefined variables
|
2022-02-05 01:28:41 +00:00
|
|
|
shopt -s nullglob
|
2018-12-29 05:10:36 +00:00
|
|
|
|
|
|
|
# A tiny DSL for editing files with sed: `~ edit files...; {{ commands }}`
|
2022-02-05 01:28:41 +00:00
|
|
|
edit() { local sed; ::block sed-dsl; if (($#)); then sed -i -e "$sed" "$@"; fi; }
|
2018-12-29 05:10:36 +00:00
|
|
|
sed-dsl() { sed."$@"; }
|
|
|
|
sed.sub() { sed+="s~$1~$2~${3-}"$'\n'; }
|
2020-02-29 06:22:11 +00:00
|
|
|
sed.del() { sed+="${1+/$1/}d"$'\n'; }
|
2018-12-29 05:10:36 +00:00
|
|
|
sed.append() { sed+='$a'; ((!$#))||__sedline "$@"; ::block __sedline; sed+=$'\n'; }
|
|
|
|
sed.after() { sed+='/'"$1"'/a'; (($#<2))||__sedline "${@:2}"; ::block __sedline; sed+=$'\n'; }
|
2020-02-29 06:22:11 +00:00
|
|
|
sed.range() { sed+="/$1/,/$2/ {"$'\n'; ::block sed-dsl; sed+=$'}\n'; }
|
2018-12-29 05:10:36 +00:00
|
|
|
__sedline() { sed+="${*/#/\\$'\n'}"; }
|
|
|
|
|
|
|
|
# DSL syntax macros: minified runtime copied from https://github.com/bashup/scale-dsl
|
|
|
|
shopt -q expand_aliases||{ unalias -a;shopt -s expand_aliases;};builtin alias +='{ ::__;::(){ ((!$#))||{ shift;"${__dsl__[@]-::no-dsl}" ' ~='{ ::__;::(){ ((!$#))||{ shift; ' -='"${__dsl__[@]-::no-dsl}" ' '{{=return;return;};__blk__=;set -- "${__blarg__[@]:1}"; ' '}}=};__:: 0 "$@";}';::block(){ ((!$#))||local __dsl__=("$@");${__blk__:+::};};__bsp__=0;::__(){ __bstk__[__bsp__++]="${__blk__:+__blk__=1;$(declare -f ::)}";};__::(){ local __blarg__=("$@");__blk__=1;:: "$@"||set -- $?;__blk__=;local REPLY;${__bstk__[--__bsp__]:+eval "${__bstk__[__bsp__]}"}||:;return $1;}
|
|
|
|
|
|
|
|
|
2021-05-02 15:38:33 +00:00
|
|
|
# === Upstream bug fixes ===
|
2020-04-15 21:18:28 +00:00
|
|
|
|
2022-02-05 01:28:41 +00:00
|
|
|
# Remove this when 2.3.x is stable
|
|
|
|
~ edit opt/admin/src/AppBundle/Resources/views/Box/edit.html[.]twig; {{
|
2021-05-02 15:38:33 +00:00
|
|
|
# Fix typo
|
|
|
|
- sub "refereneId" "referenceId"
|
2020-04-15 21:18:28 +00:00
|
|
|
}}
|
|
|
|
|
|
|
|
|
2018-12-29 05:10:36 +00:00
|
|
|
# === Restrict public ports to the container hostname IP ===
|
|
|
|
|
|
|
|
~ edit /opt/www/webmail/config/config.inc.php; {{
|
|
|
|
# Make webmail connect to the public hostname, instead of localhost
|
|
|
|
+ append ""; {{
|
|
|
|
- "\$config['default_host'] = 'ssl://' . gethostname();"
|
|
|
|
- "\$config['smtp_server'] = 'tls://' . gethostname() . ':587';"
|
2020-04-06 07:28:33 +00:00
|
|
|
- "\$config['managesieve_port'] = 4190;"
|
|
|
|
- "\$config['managesieve_host'] = gethostname();"
|
|
|
|
- "\$config['managesieve_usetls'] = true;"
|
2018-12-29 05:10:36 +00:00
|
|
|
}}
|
|
|
|
}}
|
|
|
|
|
2020-04-26 21:11:58 +00:00
|
|
|
~ edit /healthcheck/nginx.sh; {{
|
|
|
|
- sub "http://127.0.0.1" '"http://$(hostname)"'
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
2022-02-05 01:28:41 +00:00
|
|
|
~ edit \
|
|
|
|
/opt/admin/src/AppBundle/CommandInternal/DeliverQuarantineCommand[.]php \
|
|
|
|
/opt/admin/src/Base/CommandInternal/DeliverQuarantineCommand[.]php ;
|
|
|
|
{{
|
2020-03-23 02:17:15 +00:00
|
|
|
# Quarantine "deliver" / deliver:quarantine should send to host, not localhost
|
|
|
|
- sub "\['msmtp', '-f'.*" "['msmtp', '--host', gethostname(), '-f', \$meta['from']];"
|
|
|
|
}}
|
|
|
|
|
2018-12-29 05:10:36 +00:00
|
|
|
~ edit /etc/nginx/sites-enabled.templates/{no-,}https; {{
|
|
|
|
# Remove the listen lines that lack an address
|
|
|
|
- del 'listen __HTTP_PORT__;'
|
|
|
|
- del 'listen __HTTPS_PORT__ ssl;'
|
|
|
|
|
|
|
|
# Replace the IPv6 wildcard and any localhost references w/explicit host
|
|
|
|
- sub 'listen \[::\]:' 'listen __HOST__:'
|
|
|
|
- sub localhost '$hostname'
|
|
|
|
}}
|
|
|
|
|
2020-03-06 03:08:46 +00:00
|
|
|
~ edit /opt/haraka-{smtp,submission}/config/plugins; {{
|
2020-04-16 00:24:48 +00:00
|
|
|
# Fake remote IP to 127.0.0.1 when connection is from localhost
|
|
|
|
- after "status_http" \
|
|
|
|
"inbound_ips"
|
2020-03-06 03:08:46 +00:00
|
|
|
# Add our outbound IP routing plugin
|
|
|
|
- append 'outbound_ips'
|
2018-12-29 05:10:36 +00:00
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
|
|
# === Replace localhost ports with unix sockets ====
|
|
|
|
|
|
|
|
# Note: if you change any of these socket names or locations, they must also be
|
|
|
|
# changed in the corresponding files, as applicable:
|
|
|
|
#
|
|
|
|
# - files/etc/dovecot/local.conf
|
|
|
|
# - files/etc/rspamd/override.d/worker-*.inc
|
|
|
|
# - files/opt/haraka-smtp/config/redis.ini
|
|
|
|
|
|
|
|
sockdir=/var/run
|
|
|
|
rspam_web=$sockdir/rspamd-web.sock
|
|
|
|
rspam=$sockdir/rspamd-normal.sock
|
|
|
|
quota=$sockdir/dovecot-quota.sock
|
|
|
|
|
|
|
|
# redis and haraka run unprivileged and so need directories of their own
|
|
|
|
mkdir -p "$sockdir"/redis "$sockdir"/haraka
|
|
|
|
chown redis "$sockdir"/redis
|
|
|
|
chown delivery "$sockdir"/haraka
|
|
|
|
|
|
|
|
redis="$sockdir"/redis/redis.sock
|
2020-02-29 06:23:39 +00:00
|
|
|
haraka_smtp_web=$sockdir/haraka/web-11380.sock
|
|
|
|
haraka_sub_web=$sockdir/haraka/web-11381.sock
|
2018-12-29 05:10:36 +00:00
|
|
|
|
2020-02-29 06:26:16 +00:00
|
|
|
|
2018-12-29 05:10:36 +00:00
|
|
|
# Change nginx proxy settings to use unix sockets
|
|
|
|
|
|
|
|
~ edit /etc/nginx/sites-enabled.templates/{no-,}https; {{
|
|
|
|
- sub 127.0.0.1:11334 unix:"$rspam_web":
|
2020-02-29 06:23:39 +00:00
|
|
|
- sub 'proxy_pass http://127.0.0.1:\$1/' "proxy_pass http://unix:$sockdir/haraka/web-\$1.sock:/"
|
2018-12-29 05:10:36 +00:00
|
|
|
}}
|
|
|
|
|
|
|
|
# The rspamc command needs to reference the web socket explicitly
|
|
|
|
|
2022-02-05 01:28:41 +00:00
|
|
|
~ edit /opt/admin/src/AppBundle/Server/System[.]php /opt/admin/src/Base/Server/System[.]php; {{
|
2018-12-29 05:10:36 +00:00
|
|
|
- sub "rspamc stat" \
|
|
|
|
"rspamc -h $rspam_web stat"
|
|
|
|
}}
|
|
|
|
~ edit /etc/dovecot/sieve/report-{spam,ham}.sieve; {{
|
|
|
|
- sub '"rspamc" \[' \
|
2021-05-31 19:46:42 +00:00
|
|
|
'"rspamc" ["--connect='"$rspam_web"'", '
|
2018-12-29 05:10:36 +00:00
|
|
|
}}
|
|
|
|
|
2020-02-29 06:22:11 +00:00
|
|
|
# Disable dovecot quota service on localhost
|
|
|
|
|
|
|
|
~ edit /etc/dovecot/conf.d/90-quota.conf; {{
|
|
|
|
+ range 'inet_listener' '}'; {{
|
|
|
|
- del
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
|
2020-02-29 06:26:16 +00:00
|
|
|
# Haraka plugins need to use sockets for quota instead of ports
|
2018-12-29 05:10:36 +00:00
|
|
|
|
|
|
|
~ edit /opt/haraka-smtp/plugins/dovecot_quota.js; {{
|
|
|
|
- sub "socket\\.connect(13001, '127.0.0.1');" \
|
|
|
|
"socket.connect('$quota');"
|
|
|
|
}}
|
|
|
|
|
2021-08-04 21:12:30 +00:00
|
|
|
# Haraka logs should show the redis socket
|
|
|
|
~ edit /usr/lib/node_modules/Haraka/node_modules/haraka-plugin-redis/index.js; {{
|
|
|
|
- sub 'redis://\${opts.host}:\${opts.port}' \
|
|
|
|
'redis://${opts.path}'
|
|
|
|
}}
|
|
|
|
|
2020-02-29 06:23:39 +00:00
|
|
|
# Haraka web servers need to listen on unix sockets
|
2018-12-29 05:10:36 +00:00
|
|
|
|
2020-02-29 06:23:39 +00:00
|
|
|
~ edit /opt/haraka-smtp/config/http.ini; {{
|
2020-04-15 21:18:28 +00:00
|
|
|
- sub 'listen=127.0.0.1:11380' "listen=$haraka_smtp_web:777"
|
2018-12-29 05:10:36 +00:00
|
|
|
}}
|
|
|
|
|
2020-02-29 06:23:39 +00:00
|
|
|
~ edit /opt/haraka-submission/config/http.ini; {{
|
2020-04-15 21:18:28 +00:00
|
|
|
- sub 'listen=127.0.0.1:11381' "listen=$haraka_sub_web:777"
|
2020-02-29 06:23:39 +00:00
|
|
|
}}
|
|
|
|
|
2018-12-29 05:10:36 +00:00
|
|
|
# Have haraka talk to rspamd via unix socket
|
|
|
|
|
2020-04-15 21:18:28 +00:00
|
|
|
~ edit /opt/haraka-{smtp,submission}/config/rspamd.ini; {{
|
|
|
|
- sub '^host.*=.*$' "unix_socket = $rspam"
|
2018-12-29 05:10:36 +00:00
|
|
|
}}
|
|
|
|
|
2018-12-29 06:00:50 +00:00
|
|
|
# Configure redis to listen on a unix socket, and rspamd+admin to connect there
|
2018-12-29 05:10:36 +00:00
|
|
|
|
|
|
|
~ edit /etc/redis/redis.conf; {{
|
|
|
|
- sub "^port 6379" "port 0" # disable the localhost port
|
2023-01-22 09:39:31 +00:00
|
|
|
- append "" "unixsocket $redis" "unixsocketperm 777" # can be removed as of 2.3.7
|
2018-12-29 05:10:36 +00:00
|
|
|
}}
|
|
|
|
|
|
|
|
~ edit /etc/rspamd/local.d/{redis,statistic}.conf; {{
|
|
|
|
- sub 'servers = "127.*;$' \
|
|
|
|
'servers = "'"$redis"'";'
|
|
|
|
}}
|
2018-12-29 06:00:50 +00:00
|
|
|
|
2020-04-26 21:11:58 +00:00
|
|
|
~ edit /healthcheck/redis.sh; {{
|
|
|
|
- sub '-h "127.0.0.1"' "-s '$redis'";
|
|
|
|
}}
|
|
|
|
|
2023-01-22 09:39:31 +00:00
|
|
|
~ edit /bin/clear[-]idle-connections; {{ # can be removed as of 2.3.7
|
2021-05-02 15:03:09 +00:00
|
|
|
- sub "redis-cli'" "redis-cli', '-s', '$redis'"
|
|
|
|
}}
|
|
|
|
|
|
|
|
~ edit /bin/poste-redis-statistics; {{
|
|
|
|
- sub "redis-cli" "redis-cli -s '$redis'"
|
|
|
|
}}
|
|
|
|
|
2022-02-05 01:28:41 +00:00
|
|
|
~ edit /opt/admin/src/AppBundle/Resources/config/services[.]yml /opt/admin/config/services_base[.]yaml; {{
|
2020-02-29 18:53:15 +00:00
|
|
|
- sub '^ Predis\\Client: .*$' \
|
|
|
|
' Predis\\Client: { arguments: [ "unix:'"$redis"'" ] }'
|
|
|
|
|
|
|
|
# The above change won't take effect unless the service cache is cleared:
|
|
|
|
rm -rf /opt/admin/var/cache/prod
|
2018-12-29 05:10:36 +00:00
|
|
|
}}
|
2020-04-03 23:38:05 +00:00
|
|
|
|
|
|
|
# === Support Roundcube plugins and persistent encryption key
|
|
|
|
|
|
|
|
# Load 48-digit hex des_key from DES_KEY
|
2022-02-05 01:28:41 +00:00
|
|
|
~ edit /etc/cont-init.d/{20-apply-server-config,97[-]randoms}; {{
|
|
|
|
+ range 'roundcube' 'preg_replace'; {{
|
|
|
|
- sub '[$]key = bin2hex' '$key = getenv("DES_KEY") ?: bin2hex'
|
|
|
|
}}
|
2020-04-03 23:38:05 +00:00
|
|
|
}}
|
|
|
|
|
|
|
|
# Autoload roundcube plugins from /data/roundcube/installed-plugins
|
|
|
|
|
|
|
|
~ edit /opt/www/webmail/config/config.inc.php; {{
|
|
|
|
+ append ""; {{
|
|
|
|
- 'foreach ( explode("\\n", file_get_contents("/data/roundcube/installed-plugins")) as $line ) {'
|
|
|
|
- ' $line = trim($line);'
|
|
|
|
- ' if ( "" === $line || substr($line,0,1) === "#" || ! is_dir("plugins/$line")) continue;'
|
|
|
|
- ' $config["plugins"][] = $line;'
|
|
|
|
- '}'
|
|
|
|
}}
|
|
|
|
}}
|