mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-12-25 07:47:05 +00:00
remove extra features from master branch
This commit is contained in:
parent
473d4616f2
commit
e04f358cc4
@ -1 +0,0 @@
|
||||
/usr/bin/doveadm fts rescan -A
|
@ -1,2 +0,0 @@
|
||||
*/1 * * * * root /usr/bin/curl http://127.0.0.1:8080/solr/update?commit=true &>/dev/null
|
||||
30 3 * * * root /usr/bin/curl http://127.0.0.1:8080/solr/update?optimize=true &>/dev/null
|
@ -1,6 +1,5 @@
|
||||
## $HOSTNAME
|
||||
|
||||
#BEGIN_HTTP
|
||||
# Redirect all HTTP to HTTPS *except* the ACME challenges (Let's Encrypt TLS certificate
|
||||
# domain validation challenges) path, which must be served over HTTP per the ACME spec
|
||||
# (due to some Apache vulnerability).
|
||||
@ -29,12 +28,11 @@ server {
|
||||
alias $STORAGE_ROOT/ssl/lets_encrypt/webroot/.well-known/acme-challenge/;
|
||||
}
|
||||
}
|
||||
#END_HTTP
|
||||
|
||||
# The secure HTTPS server.
|
||||
server {
|
||||
listen $HTTP_SSL_PORT ssl http2;
|
||||
listen [::]:$HTTP_SSL_PORT ssl http2;
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
|
||||
server_name $HOSTNAME;
|
||||
|
||||
|
@ -59,7 +59,7 @@ class KeyAuthService:
|
||||
|
||||
credentials = decode(credentials)
|
||||
if ":" not in credentials:
|
||||
return credentials, None
|
||||
return None, None
|
||||
username, password = credentials.split(':', maxsplit=1)
|
||||
return username, password
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
import os, os.path, re, json, time
|
||||
import subprocess
|
||||
import base64
|
||||
import sys
|
||||
|
||||
from functools import wraps
|
||||
|
||||
@ -349,34 +347,6 @@ def dns_get_dump():
|
||||
from dns_update import build_recommended_dns
|
||||
return json_response(build_recommended_dns(env))
|
||||
|
||||
@app.route('/letsencrypt/dns-auth/<domain>/<token>', methods=['GET'])
|
||||
@authorized_personnel_only
|
||||
def letsencrypt_dns_auth(domain, token):
|
||||
from dns_update import do_dns_update, set_custom_dns_record
|
||||
try:
|
||||
qname = '_acme-challenge.' + domain
|
||||
if set_custom_dns_record(qname, 'TXT', token, 'add', env):
|
||||
if not do_dns_update(env):
|
||||
return ("Error updating DNS", 400)
|
||||
return "OK"
|
||||
|
||||
except ValueError as e:
|
||||
return (str(e), 400)
|
||||
|
||||
@app.route('/letsencrypt/dns-cleanup/<domain>', methods=['GET'])
|
||||
@authorized_personnel_only
|
||||
def letsencrypt_dns_cleanup(domain):
|
||||
from dns_update import do_dns_update, set_custom_dns_record
|
||||
try:
|
||||
qname = '_acme-challenge.' + domain
|
||||
if set_custom_dns_record(qname, 'TXT', None, 'remove', env):
|
||||
if not do_dns_update(env):
|
||||
return ("Error updating DNS", 400)
|
||||
return "OK"
|
||||
|
||||
except ValueError as e:
|
||||
return (str(e), 400)
|
||||
|
||||
# SSL
|
||||
|
||||
@app.route('/ssl/status')
|
||||
@ -573,9 +543,6 @@ def privacy_status_set():
|
||||
utils.write_settings(config, env)
|
||||
return "OK"
|
||||
|
||||
|
||||
# Quotas
|
||||
|
||||
@app.route('/system/default-quota', methods=["GET"])
|
||||
@authorized_personnel_only
|
||||
def default_quota_get():
|
||||
@ -599,37 +566,6 @@ def default_quota_set():
|
||||
|
||||
return "OK"
|
||||
|
||||
|
||||
# Mailgraph
|
||||
|
||||
@app.route('/mailgraph/image.cgi', methods=['GET'])
|
||||
@authorized_personnel_only
|
||||
def mailgraph():
|
||||
if request.query_string:
|
||||
query = request.query_string.decode('utf-8', 'ignore')
|
||||
if '&' in query:
|
||||
query = query.split('&')[0]
|
||||
|
||||
print("QUERY_STRING=%s" % query, file=sys.stderr)
|
||||
|
||||
code, bin_out = utils.shell(
|
||||
"check_output",
|
||||
["/usr/share/mailgraph/mailgraph.cgi"],
|
||||
env={"QUERY_STRING": query},
|
||||
return_bytes=True,
|
||||
trap=True
|
||||
)
|
||||
|
||||
if code != 0:
|
||||
return ('Error generating mailgraph image: %s' % query, 500)
|
||||
|
||||
headers, image_bytes = bin_out.split(b'\n\n', 1)
|
||||
|
||||
return base64.b64encode(image_bytes)
|
||||
|
||||
return ('Mailgraph: no image requested', 500)
|
||||
|
||||
|
||||
# MUNIN
|
||||
|
||||
@app.route('/munin/')
|
||||
|
@ -313,7 +313,6 @@ def provision_certificates(env, limit_domains):
|
||||
webroot = os.path.join(account_path, 'webroot')
|
||||
os.makedirs(webroot, exist_ok=True)
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
miab_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
cert_file = os.path.join(d, 'cert_and_chain.pem')
|
||||
print("Provisioning TLS certificates for " + ", ".join(domain_list) + ".")
|
||||
certbotret = subprocess.check_output([
|
||||
@ -329,10 +328,7 @@ def provision_certificates(env, limit_domains):
|
||||
"--chain-path", os.path.join(d, 'chain'), # we only use the full chain
|
||||
"--fullchain-path", cert_file,
|
||||
|
||||
"--manual",
|
||||
"--preferred-challenge", "dns",
|
||||
"--manual-auth-hook", os.path.join(miab_dir, "tools/dns-auth.sh"),
|
||||
"--manual-cleanup-hook", os.path.join(miab_dir, "tools/dns-cleanup.sh"),
|
||||
"--webroot", "--webroot-path", webroot,
|
||||
|
||||
"--config-dir", account_path,
|
||||
#"--staging",
|
||||
|
@ -26,7 +26,6 @@ def get_services():
|
||||
{ "name": "Dovecot LMTP LDA", "port": 10026, "public": False, },
|
||||
{ "name": "Postgrey", "port": 10023, "public": False, },
|
||||
{ "name": "Spamassassin", "port": 10025, "public": False, },
|
||||
{ "name": "IMAP Quota", "port": 12340, "public": False },
|
||||
{ "name": "OpenDKIM", "port": 8891, "public": False, },
|
||||
{ "name": "OpenDMARC", "port": 8893, "public": False, },
|
||||
{ "name": "Mail-in-a-Box Management Daemon", "port": 10222, "public": False, },
|
||||
@ -39,7 +38,6 @@ def get_services():
|
||||
{ "name": "Mail Filters (Sieve/dovecot)", "port": 4190, "public": True, },
|
||||
{ "name": "HTTP Web (nginx)", "port": 80, "public": True, },
|
||||
{ "name": "HTTPS Web (nginx)", "port": 443, "public": True, },
|
||||
{ "name": "Solr Full Text Search (tomcat)", "port": 8080, "public": False, },
|
||||
]
|
||||
|
||||
def run_checks(rounded_values, env, output, pool):
|
||||
|
@ -102,7 +102,6 @@
|
||||
<li><a href="#mail-guide" onclick="return show_panel(this);">Instructions</a></li>
|
||||
<li><a href="#users" onclick="return show_panel(this);">Users</a></li>
|
||||
<li><a href="#aliases" onclick="return show_panel(this);">Aliases</a></li>
|
||||
<li><a href="#mailgraph" onclick="return show_panel(this);">Mailgraph</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#sync_guide" onclick="return show_panel(this);">Contacts/Calendar</a></li>
|
||||
@ -152,10 +151,6 @@
|
||||
{% include "sync-guide.html" %}
|
||||
</div>
|
||||
|
||||
<div id="panel_mailgraph" class="admin_panel">
|
||||
{% include "mailgraph.html" %}
|
||||
</div>
|
||||
|
||||
<div id="panel_web" class="admin_panel">
|
||||
{% include "web.html" %}
|
||||
</div>
|
||||
|
@ -1,48 +0,0 @@
|
||||
<h2>Mail statistics</h2>
|
||||
<ul id="jump">
|
||||
<li><a href="#G0">Day</a> </li>
|
||||
<li><a href="#G1">Week</a> </li>
|
||||
<li><a href="#G2">Month</a> </li>
|
||||
<li><a href="#G3">Year</a> </li>
|
||||
</ul>
|
||||
|
||||
<h3 id="G0">Last Day</h3>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?0-n" alt="mailgraph"/></p>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?0-e" alt="mailgraph"/></p>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?0-g" alt="mailgraph"/></p>
|
||||
|
||||
<h3 id="G1">Last Week</h3>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?1-n" alt="mailgraph"/></p>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?1-e" alt="mailgraph"/></p>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?1-g" alt="mailgraph"/></p>
|
||||
|
||||
<h3 id="G2">Last Month</h3>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?2-n" alt="mailgraph"/></p>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?2-e" alt="mailgraph"/></p>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?2-g" alt="mailgraph"/></p>
|
||||
|
||||
<h3 id="G3">Last Year</h3>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?3-n" alt="mailgraph"/></p>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?3-e" alt="mailgraph"/></p>
|
||||
<p><img src="" data-src="/mailgraph/image.cgi?3-g" alt="mailgraph"/></p>
|
||||
|
||||
<hr/>
|
||||
|
||||
<p><a href="http://mailgraph.schweikert.ch/">Mailgraph</a> 1.14 by <a href="http://david.schweikert.ch/">David Schweikert</a>
|
||||
(built on Tobi Oetiker's <a href="http://oss.oetiker.ch/rrdtool/">RRDtool</a>)</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
function show_mailgraph() {
|
||||
$('[data-src]').each(function() {
|
||||
var that = this;
|
||||
api(
|
||||
$(that).attr('data-src'),
|
||||
'GET',
|
||||
'',
|
||||
function(data) {
|
||||
$(that).attr('src', 'data:image/gif;base64,' + data);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
</script>
|
@ -100,20 +100,6 @@ def do_web_update(env):
|
||||
# Add default 'www.' redirect.
|
||||
nginx_conf += make_domain_config(domain, [template0, template3], ssl_certificates, env)
|
||||
|
||||
if str(env['HTTP_SSL_PORT']) != "443":
|
||||
in_http = False
|
||||
new_conf = ''
|
||||
for line in nginx_conf.split('\n'):
|
||||
if line.strip() == '#BEGIN_HTTP':
|
||||
in_http = True
|
||||
elif line.strip() == '#END_HTTP':
|
||||
in_http = False
|
||||
|
||||
if not in_http:
|
||||
new_conf += line + '\n'
|
||||
|
||||
nginx_conf = new_conf
|
||||
|
||||
# Did the file change? If not, don't bother writing & restarting nginx.
|
||||
nginx_conf_fn = "/etc/nginx/conf.d/local.conf"
|
||||
if os.path.exists(nginx_conf_fn):
|
||||
@ -198,12 +184,8 @@ def make_domain_config(domain, templates, ssl_certificates, env):
|
||||
nginx_conf = re.sub("[ \t]*# ADDITIONAL DIRECTIVES HERE *\n", t, nginx_conf)
|
||||
|
||||
# Replace substitution strings in the template & return.
|
||||
if int(env['HTTP_SSL_PORT']) != 443:
|
||||
# disable the regular HTTP server
|
||||
nginx_conf = re.sub(r'#BEGIN_HTTP.*?#END_HTTP', repl='', string=nginx_conf, flags=re.MULTILINE)
|
||||
nginx_conf = nginx_conf.replace("$STORAGE_ROOT", env['STORAGE_ROOT'])
|
||||
nginx_conf = nginx_conf.replace("$HOSTNAME", domain)
|
||||
nginx_conf = nginx_conf.replace("$HTTP_SSL_PORT", env['HTTP_SSL_PORT'])
|
||||
nginx_conf = nginx_conf.replace("$ROOT", root)
|
||||
nginx_conf = nginx_conf.replace("$SSL_KEY", tls_cert["private-key"])
|
||||
nginx_conf = nginx_conf.replace("$SSL_CERTIFICATE", tls_cert["certificate"])
|
||||
|
@ -1,11 +0,0 @@
|
||||
rtyaml
|
||||
email_validator>=1.0.0
|
||||
exclusiveprocess
|
||||
flask
|
||||
dnspython
|
||||
python-dateutil
|
||||
idna>=2.0.0
|
||||
cryptography==2.2.2
|
||||
boto
|
||||
psutil
|
||||
npyscreen
|
@ -42,8 +42,7 @@ source /etc/mailinabox.conf # load global vars
|
||||
# * `ca-certificates`: A trust store used to squelch postfix warnings about
|
||||
# untrusted opportunistically-encrypted connections.
|
||||
echo "Installing Postfix (SMTP server)..."
|
||||
apt_install postfix postfix-sqlite postfix-pcre postgrey ca-certificates \
|
||||
postfix-policyd-spf-python postsrsd
|
||||
apt_install postfix postfix-sqlite postfix-pcre postgrey ca-certificates
|
||||
|
||||
# ### Basic Settings
|
||||
|
||||
@ -98,9 +97,7 @@ tools/editconf.py /etc/postfix/master.cf -s -w \
|
||||
-o cleanup_service_name=authclean" \
|
||||
"authclean=unix n - - - 0 cleanup
|
||||
-o header_checks=pcre:/etc/postfix/outgoing_mail_header_filters
|
||||
-o nested_header_checks=" \
|
||||
"policy-spf=unix - n n - - spawn
|
||||
user=nobody argv=/usr/bin/policyd-spf"
|
||||
-o nested_header_checks="
|
||||
|
||||
# Install the `outgoing_mail_header_filters` file required by the new 'authclean' service.
|
||||
cp conf/postfix_outgoing_mail_header_filters /etc/postfix/outgoing_mail_header_filters
|
||||
@ -199,23 +196,9 @@ tools/editconf.py /etc/postfix/main.cf lmtp_destination_recipient_limit=1
|
||||
# so these IPs get mail delivered quickly. But when an IP is not listed in the permit_dnswl_client list (i.e. it is not #NODOC
|
||||
# whitelisted) then postfix does a DEFER_IF_REJECT, which results in all "unknown user" sorts of messages turning into #NODOC
|
||||
# "450 4.7.1 Client host rejected: Service unavailable". This is a retry code, so the mail doesn't properly bounce. #NODOC
|
||||
|
||||
postconf -e smtpd_sender_restrictions="reject_non_fqdn_sender,reject_unknown_sender_domain,reject_authenticated_sender_login_mismatch,reject_rhsbl_sender dbl.spamhaus.org"
|
||||
|
||||
RECIPIENT_RESTRICTIONS="permit_sasl_authenticated,permit_mynetworks,reject_rbl_client zen.spamhaus.org,reject_unlisted_recipient"
|
||||
|
||||
if [ $POSTGREY == 1 ]; then
|
||||
RECIPIENT_RESTRICTIONS="${RECIPIENT_RESTRICTIONS},check_policy_service inet:127.0.0.1:10023"
|
||||
fi
|
||||
|
||||
if [ $POLICY_SPF == 1 ]; then
|
||||
RECIPIENT_RESTRICTIONS="${RECIPIENT_RESTRICTIONS},check_policy_service unix:private/policy-spf"
|
||||
fi
|
||||
|
||||
# Add quota check
|
||||
RECIPIENT_RESTRICTIONS="${RECIPIENT_RESTRICTIONS},check_policy_service inet:127.0.0.1:12340"
|
||||
|
||||
postconf -e smtpd_recipient_restrictions="$RECIPIENT_RESTRICTIONS"
|
||||
tools/editconf.py /etc/postfix/main.cf \
|
||||
smtpd_sender_restrictions="reject_non_fqdn_sender,reject_unknown_sender_domain,reject_authenticated_sender_login_mismatch,reject_rhsbl_sender dbl.spamhaus.org" \
|
||||
smtpd_recipient_restrictions=permit_sasl_authenticated,permit_mynetworks,"reject_rbl_client zen.spamhaus.org",reject_unlisted_recipient,"check_policy_service inet:127.0.0.1:10023","check_policy_service inet:127.0.0.1:12340"
|
||||
|
||||
# Postfix connects to Postgrey on the 127.0.0.1 interface specifically. Ensure that
|
||||
# Postgrey listens on the same interface (and not IPv6, for instance).
|
||||
@ -259,29 +242,6 @@ chmod +x /etc/cron.daily/mailinabox-postgrey-whitelist
|
||||
tools/editconf.py /etc/postfix/main.cf \
|
||||
message_size_limit=134217728
|
||||
|
||||
if [ $POSTSRSD == 1 ]; then
|
||||
# Setup SRS
|
||||
postconf -e \
|
||||
sender_canonical_maps=tcp:localhost:10001 \
|
||||
sender_canonical_classes=envelope_sender \
|
||||
recipient_canonical_maps=tcp:localhost:10002 \
|
||||
recipient_canonical_classes=envelope_recipient,header_recipient
|
||||
|
||||
hide_output systemctl enable postsrsd
|
||||
hide_output systemctl restart postsrsd
|
||||
|
||||
else
|
||||
postconf -e \
|
||||
sender_canonical_maps= \
|
||||
sender_canonical_classes= \
|
||||
recipient_canonical_maps= \
|
||||
recipient_canonical_classes=
|
||||
|
||||
hide_output systemctl disable postsrsd
|
||||
hide_output systemctl stop postsrsd
|
||||
fi
|
||||
|
||||
|
||||
# Allow the two SMTP ports in the firewall.
|
||||
|
||||
ufw_allow smtp
|
||||
@ -290,11 +250,4 @@ ufw_allow submission
|
||||
# Restart services
|
||||
|
||||
restart_service postfix
|
||||
|
||||
if [ $POSTGREY == 1 ]; then
|
||||
hide_output systemctl enable postgrey
|
||||
hide_output systemctl restart postgrey
|
||||
else
|
||||
hide_output systemctl disable postgrey
|
||||
hide_output systemctl stop postgrey
|
||||
fi
|
||||
restart_service postgrey
|
||||
|
@ -1,93 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
import npyscreen
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
class OptionsApp(npyscreen.NPSApp):
|
||||
def main(self):
|
||||
# These lines create the form and populate it with widgets.
|
||||
# A fairly complex screen in only 8 or so lines of code - a line for each control.
|
||||
npyscreen.setTheme(npyscreen.Themes.BlackOnWhiteTheme)
|
||||
|
||||
form = npyscreen.Form(name = "Mail-in-a-Box Options",)
|
||||
form.add(
|
||||
npyscreen.TitleFixedText,
|
||||
name="POSTGREY",
|
||||
value="",
|
||||
editable=False
|
||||
)
|
||||
form.add(
|
||||
npyscreen.MultiLineEdit,
|
||||
value="The Postgrey service greylists incoming messages from unknown senders.\n"
|
||||
"It can be useful for fighting spam but often causes message delivery\n"
|
||||
"delays of several minutes.",
|
||||
max_height=4,
|
||||
editable=False
|
||||
)
|
||||
|
||||
form.add(
|
||||
npyscreen.TitleFixedText,
|
||||
name="POSTSRSD",
|
||||
value="",
|
||||
editable=False
|
||||
)
|
||||
form.add(
|
||||
npyscreen.MultiLineEdit,
|
||||
value="The PostSRSd daemon performs return path rewriting using the SRS protocol.\n"
|
||||
"Not that all messages, including locally delivered mail will have their return\n"
|
||||
"paths rewritten",
|
||||
max_height=4,
|
||||
editable=False
|
||||
)
|
||||
|
||||
form.add(
|
||||
npyscreen.TitleFixedText,
|
||||
name="POLICY_SPF",
|
||||
value="",
|
||||
editable=False
|
||||
)
|
||||
form.add(
|
||||
npyscreen.MultiLineEdit,
|
||||
value=""
|
||||
"The policy SPF service checks the SPF of incoming mails and rejects those\n"
|
||||
"that do not qualify. This helps to prevent spoofing, but if valid mail does\n"
|
||||
"not have SPF configured properly it will be rejected.",
|
||||
max_height=4,
|
||||
editable=False
|
||||
)
|
||||
|
||||
init_values = []
|
||||
if int(os.getenv('POSTGREY', 1)) == 1:
|
||||
init_values.append(0)
|
||||
|
||||
if int(os.getenv('POSTSRSD', 0)) == 1:
|
||||
init_values.append(1)
|
||||
|
||||
if int(os.getenv('POLICY_SPF', 0)) == 1:
|
||||
init_values.append(2)
|
||||
|
||||
options = form.add(
|
||||
npyscreen.TitleMultiSelect,
|
||||
max_height=-2,
|
||||
value=init_values,
|
||||
name="Options",
|
||||
values= ["POSTGREY","POSTSRSD","POLICY_SPF"],
|
||||
scroll_exit=True
|
||||
)
|
||||
|
||||
# This lets the user interact with the Form.
|
||||
form.edit()
|
||||
|
||||
with open('_options.sh', 'w') as output:
|
||||
print('POSTGREY=%i' % (1 if 0 in options.value else 0), file=output)
|
||||
print('POSTSRSD=%i' % (1 if 1 in options.value else 0), file=output)
|
||||
print('POLICY_SPF=%i' % (1 if 2 in options.value else 0), file=output)
|
||||
# print(npyscreen.ThemeManager.default_colors, file=output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
App = OptionsApp()
|
||||
App.run()
|
@ -16,7 +16,6 @@ if [ -z "${NONINTERACTIVE:-}" ]; then
|
||||
# we install it inside a virtualenv. In this script, we don't have the virtualenv yet
|
||||
# so we install the python package globally.
|
||||
hide_output pip3 install "email_validator>=1.0.0" || exit 1
|
||||
hide_output pip3 install npyscreen || exit 1
|
||||
|
||||
message_box "Mail-in-a-Box Installation" \
|
||||
"Hello and thanks for deploying a Mail-in-a-Box!
|
||||
@ -194,16 +193,6 @@ if [ -z "${STORAGE_ROOT:-}" ]; then
|
||||
STORAGE_ROOT=$([[ -z "${DEFAULT_STORAGE_ROOT:-}" ]] && echo "/home/$STORAGE_USER" || echo "$DEFAULT_STORAGE_ROOT")
|
||||
fi
|
||||
|
||||
# export options variables so they are visible to the options program
|
||||
export POSTGREY
|
||||
export POSTSRSD
|
||||
export POLICY_SPF
|
||||
|
||||
python3 setup/options-dialog.py
|
||||
source ./_options.sh
|
||||
rm _options.sh
|
||||
|
||||
|
||||
# Show the configuration, since the user may have not entered it manually.
|
||||
echo
|
||||
echo "Primary Hostname: $PRIMARY_HOSTNAME"
|
||||
|
@ -1,85 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Inspired by the solr.sh from jkaberg (https://github.com/jkaberg/mailinabox-sogo)
|
||||
# with some modifications
|
||||
#
|
||||
# IMAP search with lucene via solr
|
||||
# --------------------------------
|
||||
#
|
||||
# By default dovecot uses its own Squat search index that has awful performance
|
||||
# on large mailboxes. Dovecot 2.1+ has support for using Lucene internally but
|
||||
# this didn't make it into the Ubuntu packages, so we use Solr instead to run
|
||||
# Lucene for us.
|
||||
#
|
||||
# Solr runs as a tomcat process. The dovecot solr plugin talks to solr via its
|
||||
# HTTP interface, causing mail to be indexed when searches occur, and getting
|
||||
# results back.
|
||||
|
||||
source setup/functions.sh # load our functions
|
||||
source /etc/mailinabox.conf # load global vars
|
||||
|
||||
# Install packages and basic configuation
|
||||
# ---------------------------------------
|
||||
|
||||
echo "Installing Solr..."
|
||||
|
||||
# Install packages
|
||||
apt_install solr-tomcat dovecot-solr
|
||||
|
||||
# Solr requires a schema to tell it how to index data, this is provided by dovecot
|
||||
cp /usr/share/dovecot/solr-schema.xml /etc/solr/conf/schema.xml
|
||||
|
||||
# Update the dovecot plugin configuration
|
||||
#
|
||||
# Break-imap-search makes search work the way users expect, rather than the way
|
||||
# the IMAP specification expects
|
||||
tools/editconf.py /etc/dovecot/conf.d/10-mail.conf \
|
||||
mail_plugins="fts fts_solr"
|
||||
|
||||
cat > /etc/dovecot/conf.d/90-plugin-fts.conf << EOF;
|
||||
plugin {
|
||||
fts = solr
|
||||
fts_autoindex = yes
|
||||
fts_solr = break-imap-search url=http://127.0.0.1:8080/solr/
|
||||
}
|
||||
EOF
|
||||
|
||||
# Bump memory allocation for Solr.
|
||||
# Not needed? I'll let it sit here for a while.
|
||||
#echo 'export JAVA_OPTS=-Xms512M -Xmx1024M' > /usr/share/tomcat7/bin/setenv.sh
|
||||
|
||||
# Install cronjobs to keep FTS up to date
|
||||
hide_output install -m 755 conf/cronjob/dovecot /etc/cron.daily/
|
||||
hide_output install -m 644 conf/cronjob/solr /etc/cron.d/
|
||||
|
||||
# PERMISSIONS
|
||||
|
||||
# Ensure configuration files are owned by dovecot and not world readable.
|
||||
chown -R mail:dovecot /etc/dovecot
|
||||
chmod -R o-rwx /etc/dovecot
|
||||
|
||||
mkdir -p /etc/systemd/system/tomcat9.service.d
|
||||
cat > /etc/systemd/system/tomcat9.service.d/solr-permissions.conf << EOF
|
||||
[Service]
|
||||
ReadWritePaths=/var/lib/solr/
|
||||
ReadWritePaths=/var/lib/solr/data/
|
||||
EOF
|
||||
|
||||
# Restart services to reload solr schema & dovecot plugins
|
||||
restart_service tomcat9
|
||||
restart_service dovecot
|
||||
|
||||
|
||||
# Kickoff building the index
|
||||
|
||||
# Per doveadm-fts manpage: Scan what mails exist in the full text search index
|
||||
# and compare those to what actually exist in mailboxes.
|
||||
# This removes mails from the index that have already been expunged and makes
|
||||
# sure that the next doveadm index will index all the missing mails (if any).
|
||||
doveadm fts rescan -A
|
||||
|
||||
# Adds unindexed files to the fts database
|
||||
# * `-q`: Queues the indexing to be run by indexer process. (will background the indexing)
|
||||
# * `-A`: All users
|
||||
# * `'*'`: All folders
|
||||
doveadm index -q -A '*'
|
@ -42,22 +42,6 @@ else
|
||||
FIRST_TIME_SETUP=1
|
||||
fi
|
||||
|
||||
if [ -z "${HTTP_SSL_PORT:-}" ]; then
|
||||
HTTP_SSL_PORT=$([[ -z "${DEFAULT_HTTP_SSL_PORT:-}" ]] && echo "443" || echo "$DEFAULT_HTTP_SSL_PORT")
|
||||
fi
|
||||
|
||||
if [ -z "${POSTGREY:-}" ]; then
|
||||
POSTGREY=$([[ -z "${DEFAULT_POSTGREY:-}" ]] && echo "1" || echo "$DEFAULT_POSTGREY")
|
||||
fi
|
||||
|
||||
if [ -z "${POSTSRSD:-}" ]; then
|
||||
POSTSRSD=$([[ -z "${DEFAULT_POSTSRSD:-}" ]] && echo "0" || echo "$DEFAULT_POSTSRSD")
|
||||
fi
|
||||
|
||||
if [ -z "${POLICY_SPF:-}" ]; then
|
||||
POLICY_SPF=$([[ -z "${DEFAULT_POLICY_SPF:-}" ]] && echo "0" || echo "$DEFAULT_POLICY_SPF")
|
||||
fi
|
||||
|
||||
# Put a start script in a global location. We tell the user to run 'mailinabox'
|
||||
# in the first dialog prompt, so we should do this before that starts.
|
||||
cat > /usr/local/bin/mailinabox << EOF;
|
||||
@ -109,10 +93,6 @@ PUBLIC_IP=$PUBLIC_IP
|
||||
PUBLIC_IPV6=$PUBLIC_IPV6
|
||||
PRIVATE_IP=$PRIVATE_IP
|
||||
PRIVATE_IPV6=$PRIVATE_IPV6
|
||||
HTTP_SSL_PORT=$HTTP_SSL_PORT
|
||||
POSTGREY=$POSTGREY
|
||||
POSTSRSD=$POSTSRSD
|
||||
POLICY_SPF=$POLICY_SPF
|
||||
EOF
|
||||
|
||||
# Start service configuration.
|
||||
@ -122,7 +102,6 @@ source setup/dns.sh
|
||||
source setup/mail-postfix.sh
|
||||
source setup/mail-dovecot.sh
|
||||
source setup/mail-users.sh
|
||||
source setup/solr.sh
|
||||
source setup/dkim.sh
|
||||
source setup/spamassassin.sh
|
||||
source setup/web.sh
|
||||
|
17
setup/web.sh
17
setup/web.sh
@ -19,7 +19,7 @@ fi
|
||||
|
||||
echo "Installing Nginx (web server)..."
|
||||
|
||||
apt_install nginx php-cli php-fpm fcgiwrap mailgraph
|
||||
apt_install nginx php-cli php-fpm
|
||||
|
||||
rm -f /etc/nginx/sites-enabled/default
|
||||
|
||||
@ -48,12 +48,6 @@ tools/editconf.py /etc/php/7.2/fpm/php.ini -c ';' \
|
||||
tools/editconf.py /etc/php/7.2/fpm/php.ini -c ';' \
|
||||
default_charset="UTF-8"
|
||||
|
||||
# Set higher timeout since searches with Roundcube and Solr may take longer
|
||||
# than the default 60 seconds. We will also match Roundcube's timeout to the
|
||||
# same value
|
||||
tools/editconf.py /etc/php/7.2/fpm/php.ini -c ';' \
|
||||
default_socket_timeout=180
|
||||
|
||||
# Switch from the dynamic process manager to the ondemand manager see #1216
|
||||
tools/editconf.py /etc/php/7.2/fpm/pool.d/www.conf -c ';' \
|
||||
pm=ondemand
|
||||
@ -102,9 +96,6 @@ restart_service nginx
|
||||
restart_service php7.2-fpm
|
||||
|
||||
# Open ports.
|
||||
if [ $HTTP_SSL_PORT == 443 ]; then
|
||||
ufw_allow http
|
||||
ufw_allow https
|
||||
else
|
||||
ufw_allow $HTTP_SSL_PORT
|
||||
fi
|
||||
ufw_allow http
|
||||
ufw_allow https
|
||||
|
||||
|
@ -108,7 +108,7 @@ cat > $RCM_CONFIG <<EOF;
|
||||
'verify_peer_name' => false,
|
||||
),
|
||||
);
|
||||
\$config['imap_timeout'] = 180;
|
||||
\$config['imap_timeout'] = 15;
|
||||
\$config['smtp_server'] = 'tls://127.0.0.1';
|
||||
\$config['smtp_port'] = 587;
|
||||
\$config['smtp_user'] = '%u';
|
||||
|
@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# TODO: Make work with port other than 443
|
||||
|
||||
API_KEY=`cat /var/lib/mailinabox/api.key`
|
||||
HOSTNAME=`hostname`
|
||||
|
||||
curl -s -X PUT -d "$CERTBOT_VALIDATION" --user "$API_KEY:" https://$HOSTNAME/admin/dns/custom/_acme-challenge.$CERTBOT_DOMAIN/TXT
|
||||
|
||||
sleep 15
|
@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# TODO: Make work with port other than 443
|
||||
|
||||
API_KEY=`cat /var/lib/mailinabox/api.key`
|
||||
HOSTNAME=`hostname`
|
||||
|
||||
curl -s -X DELETE --user "$API_KEY:" https://$HOSTNAME/admin/dns/custom/_acme-challenge.$CERTBOT_DOMAIN/TXT
|
Loading…
Reference in New Issue
Block a user