-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathpackages.sh
More file actions
278 lines (230 loc) · 10 KB
/
packages.sh
File metadata and controls
278 lines (230 loc) · 10 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#!/bin/bash
# -e :: exit on error (do this in functions as well)
# -E :: inherit the ERR trap to functions, command substitutions and sub-shells
# -u :: show (and exit) when using unset variables
# -o pipefail :: exit on error in pipes
set -eE -u -o pipefail
VERSION_CODENAME='bookworm'
# shellcheck source=../helpers/log.sh
source /usr/local/bin/helpers/log.sh
_log_level_is 'trace' && QUIET='-y' || QUIET='-qq'
function _pre_installation_steps() {
_log 'info' 'Starting package installation'
_log 'debug' 'Running pre-installation steps'
_log 'trace' 'Updating package signatures'
apt-get "${QUIET}" update
_log 'trace' 'Upgrading packages'
apt-get "${QUIET}" upgrade
_log 'trace' 'Installing packages that are needed early'
# Add packages usually required by apt to:
local EARLY_PACKAGES=(
# Avoid logging unnecessary warnings:
apt-utils
# Required for adding third-party repos (/etc/apt/sources.list.d) as alternative package sources (eg: Dovecot CE and Rspamd):
apt-transport-https ca-certificates curl gnupg
# Avoid problems with SA / Amavis (https://github.com/docker-mailserver/docker-mailserver/pull/3403#pullrequestreview-1596689953):
systemd-standalone-sysusers
)
apt-get "${QUIET}" install --no-install-recommends "${EARLY_PACKAGES[@]}" 2>/dev/null
}
# Install third-party commands to /usr/local/bin
function _install_utils() {
local ARCH_A
ARCH_A=$(uname --machine)
# Alternate naming convention support: x86_64 (amd64) / aarch64 (arm64)
# https://en.wikipedia.org/wiki/X86-64#Industry_naming_conventions
local ARCH_B
case "${ARCH_A}" in
( 'x86_64' ) ARCH_B='amd64' ;;
( 'aarch64' ) ARCH_B='arm64' ;;
( * )
_log 'error' "Unsupported arch: '${ARCH_A}'"
return 1
;;
esac
# TIP: `*.tar.gz` releases tend to forget to reset UID/GID ownership when archiving.
# When extracting with `tar` as `root` the archived UID/GID is kept, unless using `--no-same-owner`.
# Likewise when the binary is in a nested location the full archived path
# must be provided + `--strip-components` to extract the file to the target directory.
# Doing this avoids the need for (`mv` + `rm`) or (`--to-stdout` + `chmod +x`)
_log 'debug' 'Installing utils sourced from Github'
_log 'trace' 'Installing jaq'
local JAQ_VERSION='v3.0.0'
curl -sSfL -o /usr/local/bin/jaq \
"https://github.com/01mf02/jaq/releases/download/${JAQ_VERSION}/jaq-${ARCH_A}-unknown-linux-gnu"
chmod +x /usr/local/bin/jaq
_log 'trace' 'Installing step'
local STEP_CLI_VERSION='0.30.2'
curl -sSfL -o /tmp/step-cli.deb \
"https://github.com/smallstep/cli/releases/download/v${STEP_CLI_VERSION}/step-cli_${ARCH_B}.deb"
dpkg -i /tmp/step-cli.deb
rm /tmp/step-cli.deb
_log 'trace' 'Installing swaks'
# `perl-doc` is required for `swaks --help` to work:
apt-get "${QUIET}" install --no-install-recommends perl-doc
local SWAKS_VERSION='20240103.0'
local SWAKS_RELEASE="swaks-${SWAKS_VERSION}"
curl -sSfL \
"https://github.com/jetmore/swaks/releases/download/v${SWAKS_VERSION}/${SWAKS_RELEASE}.tar.gz" \
| tar -xz --directory /usr/local/bin --no-same-owner --strip-components=1 "${SWAKS_RELEASE}/swaks"
}
function _install_packages() {
_log 'debug' 'Installing all packages now'
local ANTI_VIRUS_SPAM_PACKAGES=(
clamav clamav-daemon
# spamassassin is used only with amavisd-new
amavisd-new spamassassin
)
# predominantly for Amavis support
local CODECS_PACKAGES=(
altermime arj bzip2
cabextract cpio file
gzip lhasa liblz4-tool
lrzip lzop nomarch
p7zip-full pax rpm2cpio
unrar-free unzip xz-utils
)
local MISCELLANEOUS_PACKAGES=(
binutils bsd-mailx
dbconfig-no-thanks dumb-init iproute2
libdate-manip-perl libldap-common libmail-spf-perl libnet-dns-perl
locales logwatch netcat-openbsd
nftables # primarily for Fail2Ban
rsyslog supervisor
uuid # used for file-locking
whois
)
local POSTFIX_PACKAGES=(
pflogsumm postgrey postfix postfix-ldap postfix-mta-sts-resolver
postfix-pcre postfix-policyd-spf-python postsrsd
)
local MAIL_PROGRAMS_PACKAGES=(
opendkim opendkim-tools
opendmarc libsasl2-modules sasl2-bin
)
# These packages support community contributed features.
# If they cause too much maintenance burden in future, they are liable for removal.
local COMMUNITY_PACKAGES=(
fetchmail getmail6
)
# `bind9-dnsutils` provides the `dig` command
# `iputils-ping` provides the `ping` command
DEBUG_PACKAGES=(
bind9-dnsutils iputils-ping less nano
)
apt-get "${QUIET}" install --no-install-recommends \
"${ANTI_VIRUS_SPAM_PACKAGES[@]}" \
"${CODECS_PACKAGES[@]}" \
"${MISCELLANEOUS_PACKAGES[@]}" \
"${POSTFIX_PACKAGES[@]}" \
"${MAIL_PROGRAMS_PACKAGES[@]}" \
"${DEBUG_PACKAGES[@]}" \
"${COMMUNITY_PACKAGES[@]}"
}
function _install_dovecot() {
local DOVECOT_PACKAGES=(
dovecot-core dovecot-imapd
dovecot-ldap dovecot-lmtpd dovecot-managesieved
dovecot-pop3d dovecot-sieve
)
# Additional Dovecot packages for supporting the DMS community (docs-only guide contributions).
DOVECOT_PACKAGES+=(dovecot-auth-lua)
# (Opt-in via ENV) Change repo source for dovecot packages to a third-party repo maintained by Dovecot.
# NOTE: AMD64 / x86_64 is the only supported arch from the Dovecot CE repo (thus noDMS built for ARM64 / aarch64)
# Repo: https://repo.dovecot.org/ce-2.4-latest/debian/bookworm/dists/bookworm/main/
# Docs: https://repo.dovecot.org/#debian
if [[ ${DOVECOT_COMMUNITY_REPO} -eq 1 ]] && [[ "$(uname --machine)" == "x86_64" ]]; then
# WARNING: Repo only provides Debian Bookworm package support for Dovecot CE 2.4+.
# As Debian Bookworm only packages Dovecot 2.3.x, building DMS with this alternative package repo may not yet be compatible with DMS:
# - 2.3.19: https://salsa.debian.org/debian/dovecot/-/tree/stable/bookworm
# - 2.3.21: https://salsa.debian.org/debian/dovecot/-/tree/stable/bookworm-backports
_log 'trace' 'Adding third-party package repository (Dovecot)'
curl -fsSL https://repo.dovecot.org/DOVECOT-REPO-GPG-2.4 \
| gpg --dearmor >/usr/share/keyrings/upstream-dovecot.gpg
cat >/etc/apt/sources.list.d/upstream-dovecot.sources <<EOF
Types: deb
URIs: https://repo.dovecot.org/ce-2.4-latest/debian/${VERSION_CODENAME}
Suites: ${VERSION_CODENAME}
Components: main
Signed-By: /usr/share/keyrings/upstream-dovecot.gpg
EOF
# Refresh package index:
apt-get "${QUIET}" update
# This repo instead provides `dovecot-auth-lua` as a transitional package to `dovecot-lua`,
# thus this extra package is required to retain lua support:
DOVECOT_PACKAGES+=(dovecot-lua)
fi
_log 'debug' 'Installing Dovecot'
apt-get "${QUIET}" install --no-install-recommends "${DOVECOT_PACKAGES[@]}"
# Runtime dependency for fts_xapian (built via `compile.sh`):
apt-get "${QUIET}" install --no-install-recommends libxapian30
}
function _install_rspamd() {
# NOTE: DMS only supports the rspamd package via using the third-party repo maintained by Rspamd (AMD64 + ARM64):
# Repo: https://rspamd.com/apt-stable/dists/bookworm/main/
# Docs: https://rspamd.com/downloads.html#debian-and-ubuntu-linux
# NOTE: Debian 12 provides Rspamd 3.4 (too old) and Rspamd discourages it's use
_log 'trace' 'Adding third-party package repository (Rspamd)'
curl -fsSL https://rspamd.com/apt-stable/gpg.key \
| gpg --dearmor >/usr/share/keyrings/upstream-rspamd.gpg
cat >/etc/apt/sources.list.d/upstream-rspamd.sources <<EOF
Types: deb
URIs: https://rspamd.com/apt-stable/
Suites: ${VERSION_CODENAME}
Components: main
Signed-By: /usr/share/keyrings/upstream-rspamd.gpg
EOF
# Refresh package index:
apt-get "${QUIET}" update
_log 'debug' 'Installing Rspamd'
apt-get "${QUIET}" install rspamd redis-server
}
function _install_fail2ban() {
local FAIL2BAN_VERSION=1.1.0
local FAIL2BAN_DEB_URL="https://github.com/fail2ban/fail2ban/releases/download/${FAIL2BAN_VERSION}/fail2ban_${FAIL2BAN_VERSION}-1.upstream1_all.deb"
local FAIL2BAN_DEB_ASC_URL="${FAIL2BAN_DEB_URL}.asc"
local FAIL2BAN_GPG_FINGERPRINT='8738 559E 26F6 71DF 9E2C 6D9E 683B F1BE BD0A 882C'
local FAIL2BAN_GPG_PUBLIC_KEY_ID='0x683BF1BEBD0A882C'
local FAIL2BAN_GPG_PUBLIC_KEY_SERVER='hkps://keyserver.ubuntu.com'
_log 'debug' 'Installing Fail2ban'
# Dependencies (https://github.com/docker-mailserver/docker-mailserver/pull/3403#discussion_r1306581431)
apt-get "${QUIET}" install --no-install-recommends python3-pyinotify python3-dnspython python3-systemd
gpg --keyserver "${FAIL2BAN_GPG_PUBLIC_KEY_SERVER}" --recv-keys "${FAIL2BAN_GPG_PUBLIC_KEY_ID}" 2>&1
curl -fsSLo fail2ban.deb "${FAIL2BAN_DEB_URL}"
curl -fsSLo fail2ban.deb.asc "${FAIL2BAN_DEB_ASC_URL}"
FINGERPRINT=$(LANG=C gpg --verify fail2ban.deb.asc fail2ban.deb |& sed -n 's#Primary key fingerprint: \(.*\)#\1#p')
if [[ -z ${FINGERPRINT} ]]; then
echo 'ERROR: Invalid GPG signature!' >&2
exit 1
fi
if [[ ${FINGERPRINT} != "${FAIL2BAN_GPG_FINGERPRINT}" ]]; then
echo "ERROR: Wrong GPG fingerprint!" >&2
exit 1
fi
dpkg -i fail2ban.deb 2>&1
rm fail2ban.deb fail2ban.deb.asc
_log 'debug' 'Patching Fail2ban to enable network bans'
# Enable network bans
# https://github.com/docker-mailserver/docker-mailserver/issues/2669
# https://github.com/fail2ban/fail2ban/issues/3125
sedfile -i -r 's/^_nft_add_set = .+/_nft_add_set = <nftables> add set <table_family> <table> <addr_set> \\{ type <addr_type>\\; flags interval\\; \\}/' /etc/fail2ban/action.d/nftables.conf
}
function _post_installation_steps() {
_log 'debug' 'Running post-installation steps (cleanup)'
_log 'debug' 'Deleting sensitive files (secrets)'
rm /etc/postsrsd.secret
_log 'debug' 'Deleting default logwatch cronjob'
rm /etc/cron.daily/00logwatch
_log 'trace' 'Removing leftovers from APT'
apt-get "${QUIET}" clean
rm -rf /var/lib/apt/lists/*
# Irrelevant - Debian's default `chroot` jail config for Postfix needed a separate syslog socket:
rm /etc/rsyslog.d/postfix.conf
}
_pre_installation_steps
_install_utils
_install_packages
_install_dovecot
_install_rspamd
_install_fail2ban
_post_installation_steps