Commit
+255 -60 +/-11 browse
1 | diff --git a/containers/multiuser-mail/Containerfile b/containers/multiuser-mail/Containerfile |
2 | index d6a8692..5c21597 100644 |
3 | --- a/containers/multiuser-mail/Containerfile |
4 | +++ b/containers/multiuser-mail/Containerfile |
5 | @@ -12,12 +12,17 @@ RUN cargo install --locked spf-milter@"$SPF_MILTER" |
6 | |
7 | RUN mkdir /build && mv -v /root/.cargo/bin/* /build |
8 | |
9 | - ARG BASE_IMAGE |
10 | - FROM $BASE_IMAGE |
11 | + ARG MULTIUSER_IMAGE |
12 | + FROM $MULTIUSER_IMAGE |
13 | |
14 | USER root |
15 | |
16 | - RUN apk add --no-cache mutt postfix |
17 | + RUN apk add --no-cache neomutt postfix |
18 | + |
19 | + # un-privilaged user to run various milter software |
20 | + RUN adduser -D -s /bin/sh -H milter |
21 | + |
22 | + RUN addgroup postfix milter |
23 | |
24 | COPY --from=build --chown=0:0 /build/dkimdo /usr/bin/ |
25 | COPY --from=build --chown=0:0 /build/dkim-milter /usr/bin/ |
26 | @@ -26,3 +31,4 @@ COPY --from=build --chown=0:0 /build/spf-milter /usr/bin/ |
27 | COPY containers/multiuser-mail/templates /etc/templates/ |
28 | COPY containers/multiuser-mail/service /etc/service |
29 | COPY containers/multiuser-mail/cron.d /etc/cron.d/ |
30 | + COPY containers/multiuser-mail/init/ /etc/ayllu-init/ |
31 | diff --git a/containers/multiuser-mail/init/ayllu-mail.sh b/containers/multiuser-mail/init/ayllu-mail.sh |
32 | new file mode 100755 |
33 | index 0000000..1a24852 |
34 | --- /dev/null |
35 | +++ b/containers/multiuser-mail/init/ayllu-mail.sh |
36 | @@ -0,0 +1 @@ |
37 | + #!/bin/sh |
38 | diff --git a/containers/multiuser-mail/init/dkim-milter.sh b/containers/multiuser-mail/init/dkim-milter.sh |
39 | new file mode 100755 |
40 | index 0000000..91edb41 |
41 | --- /dev/null |
42 | +++ b/containers/multiuser-mail/init/dkim-milter.sh |
43 | @@ -0,0 +1,20 @@ |
44 | + #!/bin/sh |
45 | + set -ex |
46 | + |
47 | + TEMPLATE_PATH="/etc/templates/dkim-milter/dkim-milter.conf" |
48 | + CONFIG_PATH="/etc/dkim-milter/dkim-milter.conf" |
49 | + SIGNING_KEY="/etc/dkim-milter/ed25519.key" |
50 | + |
51 | + mkdir -p /etc/dkim-milter |
52 | + |
53 | + if [ ! -f "$SIGNING_KEY" ] ; then |
54 | + echo "DKIM signing key not detected, generating it now" |
55 | + dkimdo genkey -O "$SIGNING_KEY" ed25519 |
56 | + dkimdo keyinfo "$SIGNING_KEY" |
57 | + chown milter:milter "$SIGNING_KEY" |
58 | + fi |
59 | + |
60 | + envsubst < "$TEMPLATE_PATH" > "$CONFIG_PATH" |
61 | + |
62 | + echo "ed25519 <$SIGNING_KEY" > /etc/dkim-milter/signing-keys |
63 | + echo ".$AYLLU_MAIL_HOSTNAME $AYLLU_MAIL_HOSTNAME ed25519 ed25519" > /etc/dkim-milter/signing-senders |
64 | diff --git a/containers/multiuser-mail/init/mail.sh b/containers/multiuser-mail/init/mail.sh |
65 | deleted file mode 100755 |
66 | index d37118b..0000000 |
67 | --- a/containers/multiuser-mail/init/mail.sh |
68 | +++ /dev/null |
69 | @@ -1,2 +0,0 @@ |
70 | - #!/bin/sh |
71 | - set -e |
72 | diff --git a/containers/multiuser-mail/init/postfix.sh b/containers/multiuser-mail/init/postfix.sh |
73 | new file mode 100755 |
74 | index 0000000..795e55e |
75 | --- /dev/null |
76 | +++ b/containers/multiuser-mail/init/postfix.sh |
77 | @@ -0,0 +1,55 @@ |
78 | + #!/bin/sh |
79 | + |
80 | + AYLLU_MAIL="/usr/bin/ayllu-mail" |
81 | + AYLLU_CONFIG="${AYLLU_CONFIG-/etc/ayllu/config.toml}" |
82 | + AYLLU_DB_PATH="${AYLLU_DB_PATH-/home/ayllu/.local/share/ayllu/mail.db}" |
83 | + |
84 | + # FIXME: Mailpot's master-cf generation seems to be broken but it may also be |
85 | + # due to my own ignorance so manually specifying it for now. |
86 | + |
87 | + AYLLU_SMTP_TLS_SECURITY_LEVEL="${AYLLU_SMTP_TLS_SECURITY_LEVEL:-none}" |
88 | + |
89 | + [ -n "${AYLLU_ROOT_MAIL_USER}" ] && { |
90 | + echo "# AYLLU: DO NOT EDIT" > /etc/postfix/aliases |
91 | + AYLLU_ROOT_MAIL_USER="$(echo "$AYLLU_ROOT_MAIL_USER" | tr '[:upper:]' '[:lower:]')" |
92 | + AYLLU_ROOT_MAIL_USER="$AYLLU_ROOT_MAIL_USER" envsubst < /etc/templates/postfix/aliases >> /etc/postfix/aliases |
93 | + newaliases |
94 | + } |
95 | + |
96 | + # hide sender's IP address / User Agent |
97 | + # See https://wiki.archlinux.org/title/Postfix#Hide_the_sender's_IP_and_user_agent_in_the_Received_header |
98 | + cp /etc/templates/postfix/smtp_header_checks /etc/postfix/ |
99 | + postconf -e smtp_header_checks="regexp:/etc/postfix/smtp_header_checks" |
100 | + postconf -e smtpd_helo_required=yes |
101 | + |
102 | + # attachments are entirely disallowed |
103 | + cp /etc/templates/postfix/mime_header_checks /etc/postfix/ |
104 | + postconf -e mime_header_checks="regexp:/etc/postfix/mime_header_checks" |
105 | + |
106 | + postconf -e smtp_tls_security_level="$AYLLU_SMTP_TLS_SECURITY_LEVEL" |
107 | + postconf -e maillog_file="/dev/stdout" |
108 | + |
109 | + AYLLU_MAIL_HOSTNAME="${AYLLU_MAIL_HOSTNAME:-localhost}" |
110 | + postconf -e myhostname="${AYLLU_MAIL_HOSTNAME}" |
111 | + |
112 | + # disallow relay from anywhere but localhost |
113 | + postconf -e inet_interfaces="loopback-only" |
114 | + postconf -e mynetworks="127.0.0.0/8" |
115 | + postconf -e local_transport="local" |
116 | + postconf -e transport_maps="lmdb:/etc/postfix/transport" |
117 | + |
118 | + # SPF |
119 | + postconf -e smtpd_milters="unix:/run/spf-milter/spf-milter.sock" |
120 | + postconf -e policyd-spf_time_limit="3600" |
121 | + |
122 | + postconf -e smtpd_recipient_restrictions="permit_mynetworks,reject_unauth_destination,check_policy_service unix:private/policyd-spf" |
123 | + |
124 | + # setup master.cf |
125 | + AYLLU_CONFIG="$AYLLU_CONFIG" AYLLU_DB_PATH="$AYLLU_DB_PATH" envsubst \ |
126 | + < /etc/templates/postfix/master.cf > /etc/postfix/master.cf |
127 | + |
128 | + su ayllu -c "$AYLLU_MAIL --config $AYLLU_CONFIG --database $AYLLU_DB_PATH postfix maps" |tee /etc/postfix/transport |
129 | + |
130 | + chown -R ayllu:ayllu /home/ayllu/.local/share/ayllu |
131 | + |
132 | + postmap /etc/postfix/transport |
133 | diff --git a/containers/multiuser-mail/init/spf-milter.sh b/containers/multiuser-mail/init/spf-milter.sh |
134 | new file mode 100755 |
135 | index 0000000..8d2403c |
136 | --- /dev/null |
137 | +++ b/containers/multiuser-mail/init/spf-milter.sh |
138 | @@ -0,0 +1,7 @@ |
139 | + #!/bin/sh |
140 | + set -e |
141 | + |
142 | + TEMPLATE_PATH="/etc/templates/spf-milter/spf-milter.conf" |
143 | + CONFIG_PATH="/etc/spf-milter.conf" |
144 | + |
145 | + envsubst < "$TEMPLATE_PATH" > "$CONFIG_PATH" |
146 | diff --git a/containers/multiuser-mail/service/dkim-milter/run b/containers/multiuser-mail/service/dkim-milter/run |
147 | new file mode 100755 |
148 | index 0000000..f09b180 |
149 | --- /dev/null |
150 | +++ b/containers/multiuser-mail/service/dkim-milter/run |
151 | @@ -0,0 +1,10 @@ |
152 | + #!/bin/sh |
153 | + set -e |
154 | + |
155 | + RUN_DIR="/run/dkim-milter" |
156 | + |
157 | + mkdir -p "$RUN_DIR" |
158 | + chown milter:milter "$RUN_DIR" |
159 | + |
160 | + umask 0007 |
161 | + exec su milter -c /usr/bin/dkim-milter |
162 | diff --git a/containers/multiuser-mail/service/postfix/run b/containers/multiuser-mail/service/postfix/run |
163 | index 218c9ea..6fd52e1 100755 |
164 | --- a/containers/multiuser-mail/service/postfix/run |
165 | +++ b/containers/multiuser-mail/service/postfix/run |
166 | @@ -1,59 +1,4 @@ |
167 | #!/bin/sh |
168 | set -e |
169 | |
170 | - AYLLU_MAIL="/usr/bin/ayllu-mail" |
171 | - AYLLU_CONFIG="${AYLLU_CONFIG-/etc/ayllu/config.toml}" |
172 | - AYLLU_DB_PATH="${AYLLU_DB_PATH-/home/ayllu/.local/share/ayllu/mail.db}" |
173 | - |
174 | - # FIXME: Mailpot's master-cf generation seems to be broken but it may also be |
175 | - # due to my own ignorance so manually specifying it for now. |
176 | - |
177 | - AYLLU_SMTP_TLS_SECURITY_LEVEL="${AYLLU_SMTP_TLS_SECURITY_LEVEL:-none}" |
178 | - |
179 | - [ -n "${AYLLU_ROOT_MAIL_USER}" ] && { |
180 | - echo "# AYLLU: DO NOT EDIT" > /etc/postfix/aliases |
181 | - AYLLU_ROOT_MAIL_USER="$(echo "$AYLLU_ROOT_MAIL_USER" | tr '[:upper:]' '[:lower:]')" |
182 | - AYLLU_ROOT_MAIL_USER="$AYLLU_ROOT_MAIL_USER" envsubst < /etc/templates/postfix/aliases >> /etc/postfix/aliases |
183 | - newaliases |
184 | - } |
185 | - |
186 | - # hide sender's IP address / User Agent |
187 | - # See https://wiki.archlinux.org/title/Postfix#Hide_the_sender's_IP_and_user_agent_in_the_Received_header |
188 | - cp /etc/templates/postfix/smtp_header_checks /etc/postfix/ |
189 | - postconf -e smtp_header_checks="regexp:/etc/postfix/smtp_header_checks" |
190 | - postconf -e smtpd_helo_required=yes |
191 | - |
192 | - # attachments are entirely disallowed |
193 | - cp /etc/templates/postfix/mime_header_checks /etc/postfix/ |
194 | - postconf -e mime_header_checks="regexp:/etc/postfix/mime_header_checks" |
195 | - |
196 | - postconf -e smtp_tls_security_level="$AYLLU_SMTP_TLS_SECURITY_LEVEL" |
197 | - postconf -e maillog_file="/dev/stdout" |
198 | - |
199 | - AYLLU_MAIL_HOSTNAME="${AYLLU_MAIL_HOSTNAME:-localhost}" |
200 | - postconf -e myhostname="${AYLLU_MAIL_HOSTNAME}" |
201 | - |
202 | - # disallow relay from anywhere but localhost |
203 | - postconf -e inet_interfaces="loopback-only" |
204 | - postconf -e mynetworks="127.0.0.0/8" |
205 | - postconf -e local_transport="local" |
206 | - postconf -e transport_maps="lmdb:/etc/postfix/transport" |
207 | - |
208 | - # DKIM |
209 | - postconf -e non_smtpd_milters="unix:/run/opendkim/opendkim.sock" |
210 | - postconf -e smtpd_milters="unix:/run/opendkim/opendkim.sock" |
211 | - |
212 | - # SPF |
213 | - postconf -e policyd-spf_time_limit="3600" |
214 | - postconf -e smtpd_recipient_restrictions="permit_mynetworks,reject_unauth_destination,check_policy_service unix:private/policyd-spf" |
215 | - |
216 | - # setup master.cf |
217 | - AYLLU_CONFIG="$AYLLU_CONFIG" AYLLU_DB_PATH="$AYLLU_DB_PATH" envsubst \ |
218 | - < /etc/templates/postfix/master.cf > /etc/postfix/master.cf |
219 | - |
220 | - "$AYLLU_MAIL" --config "$AYLLU_CONFIG" --database "$AYLLU_DB_PATH" \ |
221 | - postfix maps > /etc/postfix/transport |
222 | - |
223 | - postmap /etc/postfix/transport |
224 | - |
225 | exec postfix -c /etc/postfix start-fg |
226 | diff --git a/containers/multiuser-mail/service/spf-milter/run b/containers/multiuser-mail/service/spf-milter/run |
227 | new file mode 100755 |
228 | index 0000000..ddef30d |
229 | --- /dev/null |
230 | +++ b/containers/multiuser-mail/service/spf-milter/run |
231 | @@ -0,0 +1,10 @@ |
232 | + #!/bin/sh |
233 | + set -e |
234 | + |
235 | + RUN_DIR="/run/spf-milter" |
236 | + |
237 | + mkdir -p "$RUN_DIR" |
238 | + chown milter:milter "$RUN_DIR" |
239 | + |
240 | + umask 0007 |
241 | + exec su milter -c /usr/bin/spf-milter |
242 | diff --git a/containers/multiuser-mail/templates/dkim-milter/dkim-milter.conf b/containers/multiuser-mail/templates/dkim-milter/dkim-milter.conf |
243 | new file mode 100644 |
244 | index 0000000..e81678c |
245 | --- /dev/null |
246 | +++ b/containers/multiuser-mail/templates/dkim-milter/dkim-milter.conf |
247 | @@ -0,0 +1,135 @@ |
248 | + # DKIM Milter sample configuration file |
249 | + # See the manual page dkim-milter.conf(5) for reference documentation. |
250 | + |
251 | + # |
252 | + # General |
253 | + # |
254 | + |
255 | + # Start the milter listening on port 3000: |
256 | + # socket = inet:localhost:3000 |
257 | + socket = unix:/run/dkim-milter/dkim-milter.sock |
258 | + |
259 | + # Whether to only "sign", only "verify", or make this decision "auto"matically: |
260 | + mode = auto |
261 | + #mode = sign |
262 | + |
263 | + # Read signing keys and signing senders from the following files: |
264 | + signing_senders = /etc/dkim-milter/signing-senders |
265 | + # signing_keys = <sample-conf/signing-keys |
266 | + signing_keys = /etc/dkim-milter/signing-keys |
267 | + #signing_keys = sqlite://mail-config.db |
268 | + #signing_keys = sqlite://mail-config.db#dkim_signing_keys |
269 | + |
270 | + # Read connection-specific configuration overrides from this file: |
271 | + # connection_overrides = <sample-conf/connection-overrides |
272 | + # |
273 | + # # Read recipient-specific configuration overrides from this file: |
274 | + # recipient_overrides = <sample-conf/recipient-overrides |
275 | + |
276 | + # Treat message transactions from these networks as eligible for signing: |
277 | + # trusted_networks = loopback |
278 | + # #trusted_networks = 12.3.4.56/28, 2001:1600:2:3::4cde |
279 | + # |
280 | + # # Whether to treat messages from authenticated senders as eligible for signing: |
281 | + # trust_authenticated_senders = yes |
282 | + # |
283 | + # # Use this authserv-id in generated Authentication-Results headers: |
284 | + # authserv_id = mail.example.com |
285 | + # |
286 | + # # Whether to delete forged Authentication-Results headers |
287 | + # # ("forged" means *incoming* authserv-id equals *our* authserv-id). |
288 | + # # Important: If you use an earlier milter that adds such headers and takes care |
289 | + # # of deletion itself (eg, SPF Milter), you must disable this setting, else those |
290 | + # # legitimate headers will be deleted by DKIM Milter. |
291 | + # delete_incoming_authentication_results = yes |
292 | + # |
293 | + # # Whether to only accept signing senders (in Sender or From header) that match |
294 | + # # the envelope sender (in MAIL FROM) for signing. |
295 | + # require_envelope_sender_match = no |
296 | + |
297 | + # Log destination (syslog, stderr) and log level (error, warn, info, debug). |
298 | + log_destination = stderr |
299 | + log_level = info |
300 | + |
301 | + # Maximum time to allow when querying for DKIM public key records. |
302 | + lookup_timeout = 10s |
303 | + |
304 | + # Whether to operate without applying changes to messages or rejecting messages. |
305 | + dry_run = no |
306 | + |
307 | + # |
308 | + # Signing |
309 | + # |
310 | + |
311 | + # When signing, include the following headers in the signature. Value "default" |
312 | + # selects the default set of headers plus additional colon-separated headers |
313 | + # after a semicolon. Value "all" selects all headers present. |
314 | + sign_headers = default |
315 | + #sign_headers = default; Message-ID |
316 | + #sign_headers = all |
317 | + #sign_headers = From:To:Cc:Date:Subject |
318 | + |
319 | + # Value "default" in parameter sign_headers refers to this set of headers: |
320 | + default_signed_headers = From:Reply-To:Subject:Date:To:Cc:Resent-Date:Resent-From:Resent-To:Resent-Cc:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive |
321 | + |
322 | + # When value "all" is used in parameter sign_headers, exclude these headers: |
323 | + default_unsigned_headers = Return-Path:Received:Comments:Keywords |
324 | + |
325 | + # When signing, oversign these headers, that is include them in h= once more |
326 | + # than actually present. Value "signed" oversigns all headers included in the |
327 | + # h= tag, value "signed-extended" additionally oversigns all headers in the |
328 | + # default set even if not present in the message. |
329 | + oversign_headers = |
330 | + #oversign_headers = From:To |
331 | + #oversign_headers = signed |
332 | + #oversign_headers = signed-extended |
333 | + |
334 | + # When signing, canonicalize using the following algorithm: |
335 | + canonicalization = relaxed/simple |
336 | + |
337 | + # When signing, set the valid duration in the x= tag to this value: |
338 | + expiration = 5d |
339 | + #expiration = never |
340 | + |
341 | + # Whether to record the length of the signed body in the l= tag: |
342 | + limit_body_length = no |
343 | + |
344 | + # Whether to record the original headers in the z= tag: |
345 | + copy_headers = no |
346 | + |
347 | + # Whether to include tag r=y in signatures (RFC 6651, DKIM Failure Reporting): |
348 | + request_reports = no |
349 | + |
350 | + # |
351 | + # Verification |
352 | + # |
353 | + |
354 | + # Whether to accept expired signatures. |
355 | + allow_expired = no |
356 | + |
357 | + # Whether to accept signatures with a timestamp in the future. |
358 | + allow_timestamp_in_future = no |
359 | + |
360 | + # Whether to accept signatures using the SHA-1 hash algorithm. |
361 | + # (This setting is only effective if DKIM Milter was compiled with feature |
362 | + # "pre-rfc8301".) |
363 | + allow_sha1 = no |
364 | + |
365 | + # Minimum acceptable RSA public key size. |
366 | + min_rsa_key_bits = 1024 |
367 | + |
368 | + # When verifying, require these headers to be signed. |
369 | + required_signed_headers = From* |
370 | + #required_signed_headers = From:To:Subject |
371 | + |
372 | + # When verifying, whether to accept messages whose body is only partially |
373 | + # included in a signature through an l= tag limit. |
374 | + forbid_unsigned_content = no |
375 | + |
376 | + # The set of signature verification results to reject with an SMTP error reply: |
377 | + # "missing": reject messages without DKIM signature |
378 | + # "no-pass": reject messages without a passing DKIM signature |
379 | + # "author-mismatch": reject messages that don’t have a passing DKIM signature |
380 | + # where d= matches the From header domain |
381 | + reject_failures = |
382 | + #reject_failures = missing, no-pass, author-mismatch |
383 | diff --git a/containers/multiuser-mail/templates/spf-milter/spf-milter.conf b/containers/multiuser-mail/templates/spf-milter/spf-milter.conf |
384 | new file mode 100644 |
385 | index 0000000..d97eb8c |
386 | --- /dev/null |
387 | +++ b/containers/multiuser-mail/templates/spf-milter/spf-milter.conf |
388 | @@ -0,0 +1,8 @@ |
389 | + # spf-milter.conf |
390 | + |
391 | + socket = unix:/run/spf-milter/spf-milter.sock |
392 | + log_level = debug |
393 | + log_destination = stderr |
394 | + |
395 | + # Also verify HELO before MAIL FROM: |
396 | + verify_helo = yes |