aboutsummaryrefslogtreecommitdiff
path: root/files/usr
diff options
context:
space:
mode:
authorCullum Smith <cullum@sacredheartsc.com>2024-10-04 21:59:59 -0400
committerCullum Smith <cullum@sacredheartsc.com>2024-10-04 21:59:59 -0400
commit1e088983f6a80b6fd47543d0b4989e9ddb3234d5 (patch)
tree16af4205d84c9194257887e5e54653f79e96f987 /files/usr
parenta1bddcb1de1053994fb445267ca5d1ffaecb0fb5 (diff)
downloadinfrastructure-1e088983f6a80b6fd47543d0b4989e9ddb3234d5.tar.gz
add imap stuff
Diffstat (limited to 'files/usr')
-rw-r--r--files/usr/local/etc/dovecot/conf.d/10-auth.conf.imap_server7
-rw-r--r--files/usr/local/etc/dovecot/conf.d/10-mail.conf.imap_server23
-rw-r--r--files/usr/local/etc/dovecot/conf.d/10-master.conf.imap_server32
-rw-r--r--files/usr/local/etc/dovecot/conf.d/10-ssl.conf.imap_server8
-rw-r--r--files/usr/local/etc/dovecot/conf.d/15-lda.conf.imap_server8
-rw-r--r--files/usr/local/etc/dovecot/conf.d/15-mailboxes.conf.imap_server31
-rw-r--r--files/usr/local/etc/dovecot/conf.d/20-imap.conf.imap_server3
-rw-r--r--files/usr/local/etc/dovecot/conf.d/20-lmtp.conf.imap_server3
-rw-r--r--files/usr/local/etc/dovecot/conf.d/20-managesieve.conf.imap_server11
-rw-r--r--files/usr/local/etc/dovecot/conf.d/90-fts.conf.imap_server6
-rw-r--r--files/usr/local/etc/dovecot/conf.d/90-quota.conf.imap_server32
-rw-r--r--files/usr/local/etc/dovecot/conf.d/90-sieve-extprograms.conf.imap_server3
-rw-r--r--files/usr/local/etc/dovecot/conf.d/90-sieve.conf.imap_server28
-rw-r--r--files/usr/local/etc/dovecot/conf.d/auth-ldap.conf.ext.imap_server8
-rw-r--r--files/usr/local/etc/dovecot/dovecot-ldap-passdb.conf.ext.imap_server11
-rw-r--r--files/usr/local/etc/dovecot/dovecot-ldap-userdb.conf.ext.imap_server17
-rw-r--r--files/usr/local/etc/dovecot/dovecot.conf.imap_server5
-rw-r--r--files/usr/local/etc/dovecot/report-ham.sieve.imap_server15
-rw-r--r--files/usr/local/etc/dovecot/report-spam.sieve.imap_server7
-rw-r--r--files/usr/local/etc/dovecot/sieve-before.d/10-rspamd.sieve.imap_server5
-rw-r--r--files/usr/local/etc/nginx/nginx.conf.common2
-rw-r--r--files/usr/local/etc/poudriere.d/make.conf.pkg_repository1
-rw-r--r--files/usr/local/etc/poudriere.d/pkglist.pkg_repository4
-rw-r--r--files/usr/local/etc/rc.d/solr.imap_server76
-rw-r--r--files/usr/local/etc/rc.d/tika.imap_server55
-rw-r--r--files/usr/local/etc/solr/log4j2.xml.imap_server17
-rw-r--r--files/usr/local/etc/solr/solrconfig.xml.imap_server280
-rw-r--r--files/usr/local/etc/sudoers.d/acme.smtp_server1
-rw-r--r--files/usr/local/etc/tika/config.xml.imap_server21
-rw-r--r--files/usr/local/etc/tika/log4j2.xml.imap_server17
-rw-r--r--files/usr/local/libexec/dovecot/quota-warning.sh.imap_server20
-rw-r--r--files/usr/local/libexec/dovecot/sieve-pipe/report-ham.sh.imap_server7
-rw-r--r--files/usr/local/libexec/dovecot/sieve-pipe/report-spam.sh.imap_server7
33 files changed, 766 insertions, 5 deletions
diff --git a/files/usr/local/etc/dovecot/conf.d/10-auth.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/10-auth.conf.imap_server
new file mode 100644
index 0000000..7a908e6
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/10-auth.conf.imap_server
@@ -0,0 +1,7 @@
+auth_default_realm = ${realm}
+auth_gssapi_hostname = "\$ALL"
+auth_username_format = %Ln
+auth_mechanisms = gssapi plain login
+auth_cache_size = 10M
+
+!include auth-ldap.conf.ext
diff --git a/files/usr/local/etc/dovecot/conf.d/10-mail.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/10-mail.conf.imap_server
new file mode 100644
index 0000000..0fa15ea
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/10-mail.conf.imap_server
@@ -0,0 +1,23 @@
+mail_location = mdbox:~/mdbox
+
+namespace inbox {
+ type = private
+ separator = /
+ inbox = yes
+ subscriptions = yes
+}
+
+mail_plugins = \$mail_plugins quota virtual fts fts_solr
+
+mail_privileged_group = ${dovecot_vmail_user}
+
+first_valid_uid = ${dovecot_vmail_uid}
+last_valid_uid = ${dovecot_vmail_uid}
+
+first_valid_gid = ${dovecot_vmail_uid}
+last_valid_gid = ${dovecot_vmail_uid}
+
+# recommended configuration for quota:count
+protocol !indexer-worker {
+ mail_vsize_bg_after_count = 100
+}
diff --git a/files/usr/local/etc/dovecot/conf.d/10-master.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/10-master.conf.imap_server
new file mode 100644
index 0000000..1445cb6
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/10-master.conf.imap_server
@@ -0,0 +1,32 @@
+service imap-login {
+ inet_listener imap {
+ port = 0
+ }
+
+ inet_listener imaps {
+ port = 993
+ ssl = yes
+ }
+}
+
+service lmtp {
+ user = ${dovecot_vmail_user}
+ inet_listener lmtp {
+ port = ${lmtp_port}
+ ssl = yes
+ }
+}
+
+service auth-worker {
+ user = \$default_internal_user
+}
+
+# Allow the vmail user to write to stats. This isn't strictly necessary, but
+# prevents dovecot-lda from spamming the mail log with errors.
+service stats {
+ unix_listener stats-writer {
+ user = dovecot
+ group = ${dovecot_vmail_user}
+ mode = 0660
+ }
+}
diff --git a/files/usr/local/etc/dovecot/conf.d/10-ssl.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/10-ssl.conf.imap_server
new file mode 100644
index 0000000..9f90a47
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/10-ssl.conf.imap_server
@@ -0,0 +1,8 @@
+ssl = required
+
+ssl_cert = <${dovecot_tls_cert}
+ssl_key = <${dovecot_tls_key}
+
+ssl_min_protocol = TLSv1.2
+ssl_cipher_list = ${dovecot_cipherlist}
+ssl_prefer_server_ciphers = no
diff --git a/files/usr/local/etc/dovecot/conf.d/15-lda.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/15-lda.conf.imap_server
new file mode 100644
index 0000000..557594b
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/15-lda.conf.imap_server
@@ -0,0 +1,8 @@
+recipient_delimiter = ${dovecot_recipient_delimiter}
+lda_original_recipient_header = X-Original-To
+
+lda_mailbox_autocreate = yes
+
+protocol lda {
+ mail_plugins = \$mail_plugins sieve
+}
diff --git a/files/usr/local/etc/dovecot/conf.d/15-mailboxes.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/15-mailboxes.conf.imap_server
new file mode 100644
index 0000000..540947c
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/15-mailboxes.conf.imap_server
@@ -0,0 +1,31 @@
+namespace inbox {
+
+ mailbox INBOX {
+ auto = subscribe
+ }
+
+ mailbox Drafts {
+ auto = subscribe
+ special_use = \Drafts
+ }
+
+ mailbox Junk {
+ auto = subscribe
+ special_use = \Junk
+ }
+
+ mailbox Trash {
+ auto = subscribe
+ special_use = \Trash
+ }
+
+ mailbox Sent {
+ auto = subscribe
+ special_use = \Sent
+ }
+
+ mailbox Archive {
+ auto = subscribe
+ special_use = \Archive
+ }
+}
diff --git a/files/usr/local/etc/dovecot/conf.d/20-imap.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/20-imap.conf.imap_server
new file mode 100644
index 0000000..ae67bae
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/20-imap.conf.imap_server
@@ -0,0 +1,3 @@
+protocol imap {
+ mail_plugins = $mail_plugins imap_quota imap_sieve
+}
diff --git a/files/usr/local/etc/dovecot/conf.d/20-lmtp.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/20-lmtp.conf.imap_server
new file mode 100644
index 0000000..2619ce5
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/20-lmtp.conf.imap_server
@@ -0,0 +1,3 @@
+protocol lmtp {
+ mail_plugins = $mail_plugins sieve
+}
diff --git a/files/usr/local/etc/dovecot/conf.d/20-managesieve.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/20-managesieve.conf.imap_server
new file mode 100644
index 0000000..f4adea9
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/20-managesieve.conf.imap_server
@@ -0,0 +1,11 @@
+protocols = $protocols sieve
+
+service managesieve-login {
+ inet_listener sieve {
+ port = 4190
+ }
+
+ inet_listener sieve_deprecated {
+ port = 0
+ }
+}
diff --git a/files/usr/local/etc/dovecot/conf.d/90-fts.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/90-fts.conf.imap_server
new file mode 100644
index 0000000..fbe7e0f
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/90-fts.conf.imap_server
@@ -0,0 +1,6 @@
+plugin {
+ fts_autoindex = yes
+ fts = solr
+ fts_solr = url=http://127.0.0.1:${solr_port}/solr/dovecot/
+ fts_tika = http://127.0.0.1:${tika_port}/tika/
+}
diff --git a/files/usr/local/etc/dovecot/conf.d/90-quota.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/90-quota.conf.imap_server
new file mode 100644
index 0000000..7bffe9f
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/90-quota.conf.imap_server
@@ -0,0 +1,32 @@
+plugin {
+ quota = count:User quota
+ quota_vsizes = yes
+ quota_rule = *:storage=${dovecot_default_quota}
+ quota_grace = ${dovecot_quota_grace_percent}%%
+
+ quota_status_success = DUNNO
+ quota_status_nouser = DUNNO
+ quota_status_overquota = "552 5.2.2 Mailbox is full"
+
+ quota_warning = storage=95%% quota-warning 95 %u ${dovecot_quota_mail_from}
+ quota_warning2 = storage=90%% quota-warning 90 %u ${dovecot_quota_mail_from}
+ quota_warning3 = storage=80%% quota-warning 80 %u ${dovecot_quota_mail_from}
+}
+
+service quota-warning {
+ executable = script ${dovecot_script_dir}/quota-warning.sh
+ user = ${dovecot_vmail_user}
+ unix_listener quota-warning {
+ user = dovecot
+ group = ${dovecot_vmail_user}
+ mode = 0660
+ }
+}
+
+service quota-status {
+ executable = quota-status -p postfix
+ inet_listener {
+ port = ${quota_status_port}
+ }
+ client_limit = 5
+}
diff --git a/files/usr/local/etc/dovecot/conf.d/90-sieve-extprograms.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/90-sieve-extprograms.conf.imap_server
new file mode 100644
index 0000000..06250e9
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/90-sieve-extprograms.conf.imap_server
@@ -0,0 +1,3 @@
+plugin {
+ sieve_pipe_bin_dir = ${dovecot_sieve_pipe_bin_dir}
+}
diff --git a/files/usr/local/etc/dovecot/conf.d/90-sieve.conf.imap_server b/files/usr/local/etc/dovecot/conf.d/90-sieve.conf.imap_server
new file mode 100644
index 0000000..cd67671
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/90-sieve.conf.imap_server
@@ -0,0 +1,28 @@
+plugin {
+ sieve = file:~/sieve;active=~/.dovecot.sieve
+
+ sieve_before = ${dovecot_sieve_before_dir}
+
+ sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute
+
+ sieve_plugins = sieve_extprograms sieve_imapsieve
+
+ sieve_quota_max_scripts = 10
+ sieve_quota_max_storage = 2M
+
+ # The default value for this is "sender", but that will totally break SPF
+ sieve_redirect_envelope_from = orig_recipient
+
+ # From elsewhere to Junk folder
+ imapsieve_mailbox1_name = Junk
+ imapsieve_mailbox1_causes = COPY
+ imapsieve_mailbox1_before = file:${dovecot_conf_dir}/report-spam.sieve
+
+ # From Junk folder to elsewhere
+ imapsieve_mailbox2_name = *
+ imapsieve_mailbox2_from = Junk
+ imapsieve_mailbox2_causes = COPY
+ imapsieve_mailbox2_before = file:${dovecot_conf_dir}/report-ham.sieve
+
+ sieve_global_extensions = +vnd.dovecot.pipe
+}
diff --git a/files/usr/local/etc/dovecot/conf.d/auth-ldap.conf.ext.imap_server b/files/usr/local/etc/dovecot/conf.d/auth-ldap.conf.ext.imap_server
new file mode 100644
index 0000000..9237f1f
--- /dev/null
+++ b/files/usr/local/etc/dovecot/conf.d/auth-ldap.conf.ext.imap_server
@@ -0,0 +1,8 @@
+passdb {
+ driver = ldap
+ args = ${dovecot_conf_dir}/dovecot-ldap-passdb.conf.ext
+}
+userdb {
+ driver = ldap
+ args = ${dovecot_conf_dir}/dovecot-ldap-userdb.conf.ext
+}
diff --git a/files/usr/local/etc/dovecot/dovecot-ldap-passdb.conf.ext.imap_server b/files/usr/local/etc/dovecot/dovecot-ldap-passdb.conf.ext.imap_server
new file mode 100644
index 0000000..5158954
--- /dev/null
+++ b/files/usr/local/etc/dovecot/dovecot-ldap-passdb.conf.ext.imap_server
@@ -0,0 +1,11 @@
+uris = ${ldap_uri}
+
+sasl_bind = yes
+sasl_mech = gssapi
+sasl_realm = ${realm}
+
+base = ${users_basedn}
+
+auth_bind = yes
+pass_attrs = uid=user
+user_filter = (uid=%u)
diff --git a/files/usr/local/etc/dovecot/dovecot-ldap-userdb.conf.ext.imap_server b/files/usr/local/etc/dovecot/dovecot-ldap-userdb.conf.ext.imap_server
new file mode 100644
index 0000000..fc939a6
--- /dev/null
+++ b/files/usr/local/etc/dovecot/dovecot-ldap-userdb.conf.ext.imap_server
@@ -0,0 +1,17 @@
+uris = ${ldap_uri}
+
+sasl_bind = yes
+sasl_mech = gssapi
+sasl_realm = ${realm}
+
+base = ${users_basedn}
+user_filter = (|(mailAddress=%u)(uid=%u))
+user_attrs = \
+ =user=%{ldap:uid}, \
+ =uid=${dovecot_vmail_uid}, \
+ =gid=${dovecot_vmail_uid}, \
+ =home=${dovecot_vmail_dir}/%{ldap:uid} \
+ mailQuota=quota_rule=\*:storage=%{ldap:mailQuota}
+
+iterate_attrs = uid=user
+iterate_filter = (mailAddress=*)
diff --git a/files/usr/local/etc/dovecot/dovecot.conf.imap_server b/files/usr/local/etc/dovecot/dovecot.conf.imap_server
new file mode 100644
index 0000000..2045e76
--- /dev/null
+++ b/files/usr/local/etc/dovecot/dovecot.conf.imap_server
@@ -0,0 +1,5 @@
+protocols = imap lmtp
+
+import_environment = \$import_environment KRB5_KTNAME=${dovecot_keytab} KRB5_CLIENT_KTNAME=${dovecot_keytab}
+
+!include conf.d/*.conf
diff --git a/files/usr/local/etc/dovecot/report-ham.sieve.imap_server b/files/usr/local/etc/dovecot/report-ham.sieve.imap_server
new file mode 100644
index 0000000..578e7b2
--- /dev/null
+++ b/files/usr/local/etc/dovecot/report-ham.sieve.imap_server
@@ -0,0 +1,15 @@
+require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
+
+if environment :matches "imap.mailbox" "*" {
+ set "mailbox" "${1}";
+}
+
+if string "${mailbox}" "Trash" {
+ stop;
+}
+
+if environment :matches "imap.email" "*" {
+ set "email" "${1}";
+}
+
+pipe :copy "report-ham.sh" [ "${email}" ];
diff --git a/files/usr/local/etc/dovecot/report-spam.sieve.imap_server b/files/usr/local/etc/dovecot/report-spam.sieve.imap_server
new file mode 100644
index 0000000..d34c71b
--- /dev/null
+++ b/files/usr/local/etc/dovecot/report-spam.sieve.imap_server
@@ -0,0 +1,7 @@
+require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
+
+if environment :matches "imap.email" "*" {
+ set "email" "${1}";
+}
+
+pipe :copy "report-spam.sh" [ "${email}" ];
diff --git a/files/usr/local/etc/dovecot/sieve-before.d/10-rspamd.sieve.imap_server b/files/usr/local/etc/dovecot/sieve-before.d/10-rspamd.sieve.imap_server
new file mode 100644
index 0000000..7931a71
--- /dev/null
+++ b/files/usr/local/etc/dovecot/sieve-before.d/10-rspamd.sieve.imap_server
@@ -0,0 +1,5 @@
+require ["fileinto"];
+
+if header :is "X-Spam" "Yes" {
+ fileinto "Junk";
+}
diff --git a/files/usr/local/etc/nginx/nginx.conf.common b/files/usr/local/etc/nginx/nginx.conf.common
index 9ab993c..1da7c3c 100644
--- a/files/usr/local/etc/nginx/nginx.conf.common
+++ b/files/usr/local/etc/nginx/nginx.conf.common
@@ -47,7 +47,7 @@ $([ "${nginx_gssapi:-}" = true ] && cat <<EOF
EOF
)
-$([ "${nginx_acme:-}" = true ] && cat <<EOF
+$([ "${acme:-}" = true ] && [ "${acme_standalone:-}" != true ] && cat <<EOF
server {
listen 0.0.0.0:80 default_server;
listen [::]:80 default_server;
diff --git a/files/usr/local/etc/poudriere.d/make.conf.pkg_repository b/files/usr/local/etc/poudriere.d/make.conf.pkg_repository
index 6dbbafc..fd35928 100644
--- a/files/usr/local/etc/poudriere.d/make.conf.pkg_repository
+++ b/files/usr/local/etc/poudriere.d/make.conf.pkg_repository
@@ -74,7 +74,6 @@ sysutils_htop_SET=LSOF
sysutils_k3b_UNSET=EMOVIX VCDIMAGER
sysutils_rsyslog8_SET=GSSAPI RELP OPENSSL
sysutils_rsyslog8_UNSET=GCRYPT
-www_apache${apache_version}_SET=AUTHNZ_LDAP LDAP SUEXEC SUEXEC_SYSLOG
www_chromium_SET=WIDEVINE
www_firefox_UNSET=PROFILE JACK
www_nginx_SET=HTTPV3 HTTPV3_QTLS HTTP_AUTH_KRB5 HTTP_AUTH_LDAP
diff --git a/files/usr/local/etc/poudriere.d/pkglist.pkg_repository b/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
index 5e95f8c..d24ce06 100644
--- a/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
+++ b/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
@@ -14,6 +14,7 @@ dns/unbound
editors/vim@console
editors/vim@tiny
ftp/php${php_version}-curl
+java/openjdk21
lang/python
lang/php${php_version}
mail/dovecot
@@ -50,9 +51,6 @@ sysutils/stow
sysutils/tmux
sysutils/tree
textproc/php${php_version}-xml
-www/apache${apache_version}
-www/mod_auth_gssapi
-www/mod_php${php_version}
www/nginx
www/php${php_version}-opcache
www/php${php_version}-session
diff --git a/files/usr/local/etc/rc.d/solr.imap_server b/files/usr/local/etc/rc.d/solr.imap_server
new file mode 100644
index 0000000..70cc324
--- /dev/null
+++ b/files/usr/local/etc/rc.d/solr.imap_server
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+# PROVIDE: solr
+# REQUIRE: LOGIN
+# BEFORE: dovecot
+# KEYWORD: shutdown
+
+. /etc/rc.subr
+
+name=solr
+rcvar=solr_enable
+
+load_rc_config "$name"
+
+: ${solr_enable:='NO'}
+: ${solr_host:='127.0.0.1'}
+: ${solr_port:='8983'}
+: ${solr_syslog_priority:='info'}
+: ${solr_syslog_facility:='daemon'}
+: ${solr_heap_size:='512m'}
+: ${solr_softcommit_ms:='60000'}
+
+solr_java_home=/usr/local/openjdk21
+solr_syslog_tag=solr
+solr_data_dir=/var/db/solr
+solr_install_dir=/usr/local/solr
+solr_conf_dir=/usr/local/etc/solr
+solr_config_file="${solr_conf_dir}/solrconfig.xml"
+solr_log4j_config_file="${solr_conf_dir}/log4j2.xml"
+solr_jar="${solr_install_dir}/server/start.jar"
+
+solr_user=solr
+solr_chdir="${solr_install_dir}/server"
+
+pidfile=/var/run/solr/solr.pid
+command=/usr/sbin/daemon
+
+command_args="-f \
+-s ${solr_syslog_priority} \
+-l ${solr_syslog_facility} \
+-T ${solr_syslog_tag} \
+-p ${pidfile} \
+-t solr \
+${solr_java_home}/bin/java \
+-server \
+-Xmx${solr_heap_size} \
+-XX:+UseG1GC \
+-XX:+PerfDisableSharedMem \
+-XX:+ParallelRefProcEnabled \
+-XX:MaxGCPauseMillis=250 \
+-XX:+AlwaysPreTouch \
+-XX:+ExplicitGCInvokesConcurrent \
+-XX:+CrashOnOutOfMemoryError \
+-Djava.awt.headless=true \
+-Dlog4j.configurationFile=${solr_log4j_config_file} \
+-Djetty.host=${solr_host} \
+-Djetty.port=${solr_port} \
+-Djetty.home=${solr_install_dir}/server \
+-Dsolr.autoSoftCommit.maxTime=${solr_softcommit_ms} \
+-Dsolr.solr.home=${solr_data_dir} \
+-Dsolr.data.home= \
+-Dsolr.install.dir=${solr_install_dir} \
+-Dsolr.default.confdir=${solr_conf_dir} \
+-jar ${solr_jar} \
+--module=http \
+--module=gzip"
+
+required_files="${solr_config_file} ${solr_log4j_config_file} ${solr_jar}"
+procname="${solr_java_home}/bin/java"
+start_precmd=solr_prestart
+
+solr_prestart(){
+ install -d -m 0755 -o ${solr_user} /var/run/solr
+}
+
+run_rc_command "$1"
diff --git a/files/usr/local/etc/rc.d/tika.imap_server b/files/usr/local/etc/rc.d/tika.imap_server
new file mode 100644
index 0000000..95f1c88
--- /dev/null
+++ b/files/usr/local/etc/rc.d/tika.imap_server
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+# PROVIDE: tika
+# REQUIRE: LOGIN
+# BEFORE: dovecot
+# KEYWORD: shutdown
+
+. /etc/rc.subr
+
+name=tika
+rcvar=tika_enable
+
+load_rc_config "$name"
+
+: ${tika_enable:='NO'}
+: ${tika_host:='127.0.0.1'}
+: ${tika_port:='9998'}
+: ${tika_syslog_priority:='info'}
+: ${tika_syslog_facility:='daemon'}
+
+tika_user=tika
+tika_java_home=/usr/local/openjdk21
+tika_syslog_tag=tika
+tika_jar=/usr/local/tika/tika.jar
+tika_config_file=/usr/local/etc/tika/config.xml
+tika_log4j_config_file=/usr/local/etc/tika/log4j2.xml
+
+pidfile=/var/run/tika/tika.pid
+command=/usr/sbin/daemon
+
+command_args="-f \
+-s ${tika_syslog_priority} \
+-l ${tika_syslog_facility} \
+-T ${tika_syslog_tag} \
+-p ${pidfile} \
+-t tika \
+${tika_java_home}/bin/java \
+-server \
+-Xmx64m \
+-Djava.awt.headless=true \
+-Dlog4j.configurationFile=${tika_log4j_config_file} \
+-jar ${tika_jar} \
+-c ${tika_config_file} \
+-h ${tika_host} \
+-p ${tika_port}"
+
+required_files="${tika_config_file} ${tika_log4j_config_file} ${tika_jar}"
+procname="${tika_java_home}/bin/java"
+start_precmd=tika_prestart
+
+tika_prestart(){
+ install -d -m 0755 -o ${tika_user} /var/run/tika
+}
+
+run_rc_command "$1"
diff --git a/files/usr/local/etc/solr/log4j2.xml.imap_server b/files/usr/local/etc/solr/log4j2.xml.imap_server
new file mode 100644
index 0000000..cabde07
--- /dev/null
+++ b/files/usr/local/etc/solr/log4j2.xml.imap_server
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration>
+ <Appenders>
+ <Console name="STDOUT" target="SYSTEM_OUT">
+ <PatternLayout>
+ <Pattern>
+ %maxLen{%-5p %c %m%notEmpty{ =>%ex{short}}}{10240}%n
+ </Pattern>
+ </PatternLayout>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <Root level="INFO">
+ <AppenderRef ref="STDOUT"/>
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/files/usr/local/etc/solr/solrconfig.xml.imap_server b/files/usr/local/etc/solr/solrconfig.xml.imap_server
new file mode 100644
index 0000000..f7a9d7b
--- /dev/null
+++ b/files/usr/local/etc/solr/solrconfig.xml.imap_server
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<config>
+ <luceneMatchVersion>9.3.0</luceneMatchVersion>
+ <!-- the rest of this file is unchanged from the defaults -->
+ <dataDir>${solr.data.dir:}</dataDir>
+ <directoryFactory name="DirectoryFactory"
+ class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
+ <codecFactory class="solr.SchemaCodecFactory"/>
+ <indexConfig>
+ <lockType>${solr.lock.type:native}</lockType>
+ </indexConfig>
+ <jmx />
+ <updateHandler class="solr.DirectUpdateHandler2">
+ <updateLog>
+ <str name="dir">${solr.ulog.dir:}</str>
+ <int name="numVersionBuckets">${solr.ulog.numVersionBuckets:65536}</int>
+ </updateLog>
+ <autoCommit>
+ <maxTime>${solr.autoCommit.maxTime:15000}</maxTime>
+ <openSearcher>false</openSearcher>
+ </autoCommit>
+ <autoSoftCommit>
+ <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime>
+ </autoSoftCommit>
+ </updateHandler>
+
+ <query>
+ <maxBooleanClauses>${solr.max.booleanClauses:1024}</maxBooleanClauses>
+ <filterCache size="512"
+ initialSize="512"
+ autowarmCount="0"/>
+ <queryResultCache size="512"
+ initialSize="512"
+ autowarmCount="0"/>
+
+ <documentCache size="512"
+ initialSize="512"
+ autowarmCount="0"/>
+
+ <cache name="perSegFilter"
+ size="10"
+ initialSize="0"
+ autowarmCount="10"
+ regenerator="solr.NoOpRegenerator" />
+
+ <enableLazyFieldLoading>true</enableLazyFieldLoading>
+
+ <queryResultWindowSize>20</queryResultWindowSize>
+
+ <queryResultMaxDocsCached>200</queryResultMaxDocsCached>
+
+ <listener event="newSearcher" class="solr.QuerySenderListener">
+ <arr name="queries">
+ </arr>
+ </listener>
+ <listener event="firstSearcher" class="solr.QuerySenderListener">
+ <arr name="queries">
+ </arr>
+ </listener>
+
+ <useColdSearcher>false</useColdSearcher>
+ </query>
+
+ <circuitBreakers enabled="true">
+ </circuitBreakers>
+
+
+ <requestDispatcher>
+ <httpCaching never304="true" />
+ </requestDispatcher>
+
+ <requestHandler name="/select" class="solr.SearchHandler">
+ <lst name="defaults">
+ <str name="echoParams">explicit</str>
+ <int name="rows">10</int>
+ <str name="df">hdr</str>
+ </lst>
+ </requestHandler>
+
+ <requestHandler name="/query" class="solr.SearchHandler">
+ <lst name="defaults">
+ <str name="echoParams">explicit</str>
+ <str name="wt">json</str>
+ <str name="indent">true</str>
+ </lst>
+ </requestHandler>
+
+ <initParams path="/update/**,/query,/select,/spell">
+ <lst name="defaults">
+ <str name="df">_text_</str>
+ </lst>
+ </initParams>
+
+ <searchComponent name="spellcheck" class="solr.SpellCheckComponent">
+
+ <str name="queryAnalyzerFieldType">text_general</str>
+
+ <lst name="spellchecker">
+ <str name="name">default</str>
+ <str name="field">_text_</str>
+ <str name="classname">solr.DirectSolrSpellChecker</str>
+ <str name="distanceMeasure">internal</str>
+ <float name="accuracy">0.5</float>
+ <int name="maxEdits">2</int>
+ <int name="minPrefix">1</int>
+ <int name="maxInspections">5</int>
+ <int name="minQueryLength">4</int>
+ <float name="maxQueryFrequency">0.01</float>
+ </lst>
+ </searchComponent>
+
+ <requestHandler name="/spell" class="solr.SearchHandler" startup="lazy">
+ <lst name="defaults">
+ <str name="spellcheck.dictionary">default</str>
+ <str name="spellcheck">on</str>
+ <str name="spellcheck.extendedResults">true</str>
+ <str name="spellcheck.count">10</str>
+ <str name="spellcheck.alternativeTermCount">5</str>
+ <str name="spellcheck.maxResultsForSuggest">5</str>
+ <str name="spellcheck.collate">true</str>
+ <str name="spellcheck.collateExtendedResults">true</str>
+ <str name="spellcheck.maxCollationTries">10</str>
+ <str name="spellcheck.maxCollations">5</str>
+ </lst>
+ <arr name="last-components">
+ <str>spellcheck</str>
+ </arr>
+ </requestHandler>
+
+ <searchComponent name="terms" class="solr.TermsComponent"/>
+
+ <requestHandler name="/terms" class="solr.SearchHandler" startup="lazy">
+ <lst name="defaults">
+ <bool name="terms">true</bool>
+ <bool name="distrib">false</bool>
+ </lst>
+ <arr name="components">
+ <str>terms</str>
+ </arr>
+ </requestHandler>
+
+ <searchComponent class="solr.HighlightComponent" name="highlight">
+ <highlighting>
+ <fragmenter name="gap"
+ default="true"
+ class="solr.highlight.GapFragmenter">
+ <lst name="defaults">
+ <int name="hl.fragsize">100</int>
+ </lst>
+ </fragmenter>
+
+ <fragmenter name="regex"
+ class="solr.highlight.RegexFragmenter">
+ <lst name="defaults">
+ <int name="hl.fragsize">70</int>
+ <float name="hl.regex.slop">0.5</float>
+ <str name="hl.regex.pattern">[-\w ,/\n\&quot;&apos;]{20,200}</str>
+ </lst>
+ </fragmenter>
+
+ <formatter name="html"
+ default="true"
+ class="solr.highlight.HtmlFormatter">
+ <lst name="defaults">
+ <str name="hl.simple.pre"><![CDATA[<em>]]></str>
+ <str name="hl.simple.post"><![CDATA[</em>]]></str>
+ </lst>
+ </formatter>
+
+ <encoder name="html"
+ class="solr.highlight.HtmlEncoder" />
+
+ <fragListBuilder name="simple"
+ class="solr.highlight.SimpleFragListBuilder"/>
+
+ <fragListBuilder name="single"
+ class="solr.highlight.SingleFragListBuilder"/>
+
+ <fragListBuilder name="weighted"
+ default="true"
+ class="solr.highlight.WeightedFragListBuilder"/>
+
+ <fragmentsBuilder name="default"
+ default="true"
+ class="solr.highlight.ScoreOrderFragmentsBuilder">
+ </fragmentsBuilder>
+
+ <fragmentsBuilder name="colored"
+ class="solr.highlight.ScoreOrderFragmentsBuilder">
+ <lst name="defaults">
+ <str name="hl.tag.pre"><![CDATA[
+ <b style="background:yellow">,<b style="background:lawgreen">,
+ <b style="background:aquamarine">,<b style="background:magenta">,
+ <b style="background:palegreen">,<b style="background:coral">,
+ <b style="background:wheat">,<b style="background:khaki">,
+ <b style="background:lime">,<b style="background:deepskyblue">]]></str>
+ <str name="hl.tag.post"><![CDATA[</b>]]></str>
+ </lst>
+ </fragmentsBuilder>
+
+ <boundaryScanner name="default"
+ default="true"
+ class="solr.highlight.SimpleBoundaryScanner">
+ <lst name="defaults">
+ <str name="hl.bs.maxScan">10</str>
+ <str name="hl.bs.chars">.,!? &#9;&#10;&#13;</str>
+ </lst>
+ </boundaryScanner>
+
+ <boundaryScanner name="breakIterator"
+ class="solr.highlight.BreakIteratorBoundaryScanner">
+ <lst name="defaults">
+ <str name="hl.bs.type">WORD</str>
+ <str name="hl.bs.language">en</str>
+ <str name="hl.bs.country">US</str>
+ </lst>
+ </boundaryScanner>
+ </highlighting>
+ </searchComponent>
+
+ <updateProcessor class="solr.UUIDUpdateProcessorFactory" name="uuid"/>
+ <updateProcessor class="solr.RemoveBlankFieldUpdateProcessorFactory" name="remove-blank"/>
+ <updateProcessor class="solr.FieldNameMutatingUpdateProcessorFactory" name="field-name-mutating">
+ <str name="pattern">[^\w-\.]</str>
+ <str name="replacement">_</str>
+ </updateProcessor>
+ <updateProcessor class="solr.ParseBooleanFieldUpdateProcessorFactory" name="parse-boolean"/>
+ <updateProcessor class="solr.ParseLongFieldUpdateProcessorFactory" name="parse-long"/>
+ <updateProcessor class="solr.ParseDoubleFieldUpdateProcessorFactory" name="parse-double"/>
+ <updateProcessor class="solr.ParseDateFieldUpdateProcessorFactory" name="parse-date">
+ <arr name="format">
+ <str>yyyy-MM-dd['T'[HH:mm[:ss[.SSS]][z</str>
+ <str>yyyy-MM-dd['T'[HH:mm[:ss[,SSS]][z</str>
+ <str>yyyy-MM-dd HH:mm[:ss[.SSS]][z</str>
+ <str>yyyy-MM-dd HH:mm[:ss[,SSS]][z</str>
+ <str>[EEE, ]dd MMM yyyy HH:mm[:ss] z</str>
+ <str>EEEE, dd-MMM-yy HH:mm:ss z</str>
+ <str>EEE MMM ppd HH:mm:ss [z ]yyyy</str>
+ </arr>
+ </updateProcessor>
+ <updateProcessor class="solr.AddSchemaFieldsUpdateProcessorFactory" name="add-schema-fields">
+ <lst name="typeMapping">
+ <str name="valueClass">java.lang.String</str>
+ <str name="fieldType">text_general</str>
+ <lst name="copyField">
+ <str name="dest">*_str</str>
+ <int name="maxChars">256</int>
+ </lst>
+ <bool name="default">true</bool>
+ </lst>
+ <lst name="typeMapping">
+ <str name="valueClass">java.lang.Boolean</str>
+ <str name="fieldType">booleans</str>
+ </lst>
+ <lst name="typeMapping">
+ <str name="valueClass">java.util.Date</str>
+ <str name="fieldType">pdates</str>
+ </lst>
+ <lst name="typeMapping">
+ <str name="valueClass">java.lang.Long</str>
+ <str name="valueClass">java.lang.Integer</str>
+ <str name="fieldType">plongs</str>
+ </lst>
+ <lst name="typeMapping">
+ <str name="valueClass">java.lang.Number</str>
+ <str name="fieldType">pdoubles</str>
+ </lst>
+ </updateProcessor>
+
+ <updateRequestProcessorChain name="add-unknown-fields-to-the-schema" default="${update.autoCreateFields:true}"
+ processor="uuid,remove-blank,field-name-mutating,parse-boolean,parse-long,parse-double,parse-date,add-schema-fields">
+ <processor class="solr.LogUpdateProcessorFactory"/>
+ <processor class="solr.DistributedUpdateProcessorFactory"/>
+ <processor class="solr.RunUpdateProcessorFactory"/>
+ </updateRequestProcessorChain>
+
+ <queryResponseWriter name="json" class="solr.JSONResponseWriter">
+ <str name="content-type">text/plain; charset=UTF-8</str>
+ </queryResponseWriter>
+</config>
diff --git a/files/usr/local/etc/sudoers.d/acme.smtp_server b/files/usr/local/etc/sudoers.d/acme.smtp_server
new file mode 100644
index 0000000..5180fdc
--- /dev/null
+++ b/files/usr/local/etc/sudoers.d/acme.smtp_server
@@ -0,0 +1 @@
+acme ALL=(root) NOPASSWD: /usr/sbin/service postfix reload
diff --git a/files/usr/local/etc/tika/config.xml.imap_server b/files/usr/local/etc/tika/config.xml.imap_server
new file mode 100644
index 0000000..22fe638
--- /dev/null
+++ b/files/usr/local/etc/tika/config.xml.imap_server
@@ -0,0 +1,21 @@
+<properties>
+ <server>
+ <params>
+ <javaPath>/usr/local/bin/java</javaPath>
+ <returnStackTrace>false</returnStackTrace>
+ <forkedJvmArgs>
+ <arg>-Xmx${tika_heap_size}</arg>
+ <arg>-XX:+UseG1GC</arg>
+ <arg>-XX:+PerfDisableSharedMem</arg>
+ <arg>-XX:+ParallelRefProcEnabled</arg>
+ <arg>-XX:MaxGCPauseMillis=250</arg>
+ <arg>-XX:+AlwaysPreTouch</arg>
+ <arg>-Dlog4j.configurationFile=${tika_conf_dir}/log4j2.xml</arg>
+ </forkedJvmArgs>
+ <endpoints>
+ <endpoint>tika</endpoint>
+ <endpoint>status</endpoint>
+ </endpoints>
+ </params>
+ </server>
+</properties>
diff --git a/files/usr/local/etc/tika/log4j2.xml.imap_server b/files/usr/local/etc/tika/log4j2.xml.imap_server
new file mode 100644
index 0000000..cabde07
--- /dev/null
+++ b/files/usr/local/etc/tika/log4j2.xml.imap_server
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration>
+ <Appenders>
+ <Console name="STDOUT" target="SYSTEM_OUT">
+ <PatternLayout>
+ <Pattern>
+ %maxLen{%-5p %c %m%notEmpty{ =>%ex{short}}}{10240}%n
+ </Pattern>
+ </PatternLayout>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <Root level="INFO">
+ <AppenderRef ref="STDOUT"/>
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/files/usr/local/libexec/dovecot/quota-warning.sh.imap_server b/files/usr/local/libexec/dovecot/quota-warning.sh.imap_server
new file mode 100644
index 0000000..96419f5
--- /dev/null
+++ b/files/usr/local/libexec/dovecot/quota-warning.sh.imap_server
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+set -eu -o pipefail
+
+PERCENT=$1
+USER=$2
+FROM=$3
+
+cat << EOF | /usr/libexec/dovecot/dovecot-lda -d "$USER" -o "plugin/quota=count:User quota:noenforcing"
+From: ${FROM}
+Subject: Mailbox quota warning
+
+This is an automatically generated message.
+
+Your mailbox is now ${PERCENT}% full.
+
+When your mailbox exceeds its quota, you will no longer receive new mail.
+
+Please delete some messages to free up space.
+EOF
diff --git a/files/usr/local/libexec/dovecot/sieve-pipe/report-ham.sh.imap_server b/files/usr/local/libexec/dovecot/sieve-pipe/report-ham.sh.imap_server
new file mode 100644
index 0000000..e09674a
--- /dev/null
+++ b/files/usr/local/libexec/dovecot/sieve-pipe/report-ham.sh.imap_server
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+exec /usr/local/bin/rspamc \\
+ --connect="${rspamd_host}.${domain}" \\
+ --password="${rspamd_rw_password}" \\
+ --key="${rspamd_pubkey}" \\
+ learn_ham
diff --git a/files/usr/local/libexec/dovecot/sieve-pipe/report-spam.sh.imap_server b/files/usr/local/libexec/dovecot/sieve-pipe/report-spam.sh.imap_server
new file mode 100644
index 0000000..825113f
--- /dev/null
+++ b/files/usr/local/libexec/dovecot/sieve-pipe/report-spam.sh.imap_server
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+exec /usr/local/bin/rspamc \\
+ --connect="${rspamd_host}.${domain}" \\
+ --password="${rspamd_rw_password}" \\
+ --key="${rspamd_pubkey}" \\
+ learn_spam