Merge branch 'miab-config' into extended
This commit is contained in:
commit
bb96ee8269
13 changed files with 208 additions and 12 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,3 +5,4 @@ tools/__pycache__/
|
||||||
externals/
|
externals/
|
||||||
.env
|
.env
|
||||||
.vagrant
|
.vagrant
|
||||||
|
.idea/
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
## $HOSTNAME
|
## $HOSTNAME
|
||||||
|
|
||||||
|
#BEGIN_HTTP
|
||||||
# Redirect all HTTP to HTTPS *except* the ACME challenges (Let's Encrypt TLS certificate
|
# 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
|
# domain validation challenges) path, which must be served over HTTP per the ACME spec
|
||||||
# (due to some Apache vulnerability).
|
# (due to some Apache vulnerability).
|
||||||
|
@ -28,11 +29,12 @@ server {
|
||||||
alias $STORAGE_ROOT/ssl/lets_encrypt/webroot/.well-known/acme-challenge/;
|
alias $STORAGE_ROOT/ssl/lets_encrypt/webroot/.well-known/acme-challenge/;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#END_HTTP
|
||||||
|
|
||||||
# The secure HTTPS server.
|
# The secure HTTPS server.
|
||||||
server {
|
server {
|
||||||
listen 443 ssl http2;
|
listen $HTTP_SSL_PORT ssl http2;
|
||||||
listen [::]:443 ssl http2;
|
listen [::]:$HTTP_SSL_PORT ssl http2;
|
||||||
|
|
||||||
server_name $HOSTNAME;
|
server_name $HOSTNAME;
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ class KeyAuthService:
|
||||||
|
|
||||||
credentials = decode(credentials)
|
credentials = decode(credentials)
|
||||||
if ":" not in credentials:
|
if ":" not in credentials:
|
||||||
return None, None
|
return credentials, None
|
||||||
username, password = credentials.split(':', maxsplit=1)
|
username, password = credentials.split(':', maxsplit=1)
|
||||||
return username, password
|
return username, password
|
||||||
|
|
||||||
|
|
|
@ -349,6 +349,34 @@ def dns_get_dump():
|
||||||
from dns_update import build_recommended_dns
|
from dns_update import build_recommended_dns
|
||||||
return json_response(build_recommended_dns(env))
|
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
|
# SSL
|
||||||
|
|
||||||
@app.route('/ssl/status')
|
@app.route('/ssl/status')
|
||||||
|
|
|
@ -313,6 +313,7 @@ def provision_certificates(env, limit_domains):
|
||||||
webroot = os.path.join(account_path, 'webroot')
|
webroot = os.path.join(account_path, 'webroot')
|
||||||
os.makedirs(webroot, exist_ok=True)
|
os.makedirs(webroot, exist_ok=True)
|
||||||
with tempfile.TemporaryDirectory() as d:
|
with tempfile.TemporaryDirectory() as d:
|
||||||
|
miab_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
cert_file = os.path.join(d, 'cert_and_chain.pem')
|
cert_file = os.path.join(d, 'cert_and_chain.pem')
|
||||||
print("Provisioning TLS certificates for " + ", ".join(domain_list) + ".")
|
print("Provisioning TLS certificates for " + ", ".join(domain_list) + ".")
|
||||||
certbotret = subprocess.check_output([
|
certbotret = subprocess.check_output([
|
||||||
|
@ -328,7 +329,10 @@ def provision_certificates(env, limit_domains):
|
||||||
"--chain-path", os.path.join(d, 'chain'), # we only use the full chain
|
"--chain-path", os.path.join(d, 'chain'), # we only use the full chain
|
||||||
"--fullchain-path", cert_file,
|
"--fullchain-path", cert_file,
|
||||||
|
|
||||||
"--webroot", "--webroot-path", webroot,
|
"--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"),
|
||||||
|
|
||||||
"--config-dir", account_path,
|
"--config-dir", account_path,
|
||||||
#"--staging",
|
#"--staging",
|
||||||
|
|
|
@ -94,6 +94,20 @@ def do_web_update(env):
|
||||||
# Add default 'www.' redirect.
|
# Add default 'www.' redirect.
|
||||||
nginx_conf += make_domain_config(domain, [template0, template3], ssl_certificates, env)
|
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.
|
# Did the file change? If not, don't bother writing & restarting nginx.
|
||||||
nginx_conf_fn = "/etc/nginx/conf.d/local.conf"
|
nginx_conf_fn = "/etc/nginx/conf.d/local.conf"
|
||||||
if os.path.exists(nginx_conf_fn):
|
if os.path.exists(nginx_conf_fn):
|
||||||
|
@ -178,8 +192,12 @@ def make_domain_config(domain, templates, ssl_certificates, env):
|
||||||
nginx_conf = re.sub("[ \t]*# ADDITIONAL DIRECTIVES HERE *\n", t, nginx_conf)
|
nginx_conf = re.sub("[ \t]*# ADDITIONAL DIRECTIVES HERE *\n", t, nginx_conf)
|
||||||
|
|
||||||
# Replace substitution strings in the template & return.
|
# 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("$STORAGE_ROOT", env['STORAGE_ROOT'])
|
||||||
nginx_conf = nginx_conf.replace("$HOSTNAME", domain)
|
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("$ROOT", root)
|
||||||
nginx_conf = nginx_conf.replace("$SSL_KEY", tls_cert["private-key"])
|
nginx_conf = nginx_conf.replace("$SSL_KEY", tls_cert["private-key"])
|
||||||
nginx_conf = nginx_conf.replace("$SSL_CERTIFICATE", tls_cert["certificate"])
|
nginx_conf = nginx_conf.replace("$SSL_CERTIFICATE", tls_cert["certificate"])
|
||||||
|
|
|
@ -42,7 +42,8 @@ source /etc/mailinabox.conf # load global vars
|
||||||
# * `ca-certificates`: A trust store used to squelch postfix warnings about
|
# * `ca-certificates`: A trust store used to squelch postfix warnings about
|
||||||
# untrusted opportunistically-encrypted connections.
|
# untrusted opportunistically-encrypted connections.
|
||||||
echo "Installing Postfix (SMTP server)..."
|
echo "Installing Postfix (SMTP server)..."
|
||||||
apt_install postfix postfix-sqlite postfix-pcre postgrey ca-certificates
|
apt_install postfix postfix-sqlite postfix-pcre postgrey ca-certificates \
|
||||||
|
postfix-policyd-spf-python postsrsd
|
||||||
|
|
||||||
# ### Basic Settings
|
# ### Basic Settings
|
||||||
|
|
||||||
|
@ -97,7 +98,9 @@ tools/editconf.py /etc/postfix/master.cf -s -w \
|
||||||
-o cleanup_service_name=authclean" \
|
-o cleanup_service_name=authclean" \
|
||||||
"authclean=unix n - - - 0 cleanup
|
"authclean=unix n - - - 0 cleanup
|
||||||
-o header_checks=pcre:/etc/postfix/outgoing_mail_header_filters
|
-o header_checks=pcre:/etc/postfix/outgoing_mail_header_filters
|
||||||
-o nested_header_checks="
|
-o nested_header_checks=" \
|
||||||
|
"policy-spf=unix - n n - - spawn
|
||||||
|
user=nobody argv=/usr/bin/policyd-spf"
|
||||||
|
|
||||||
# Install the `outgoing_mail_header_filters` file required by the new 'authclean' service.
|
# 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
|
cp conf/postfix_outgoing_mail_header_filters /etc/postfix/outgoing_mail_header_filters
|
||||||
|
@ -196,9 +199,22 @@ 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
|
# 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
|
# 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
|
# "450 4.7.1 Client host rejected: Service unavailable". This is a retry code, so the mail doesn't properly bounce. #NODOC
|
||||||
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" \
|
postconf -e 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"
|
|
||||||
|
RECIPIENT_RESTRICTIONS="permit_sasl_authenticated,permit_mynetworks,reject_rbl_client zen.spamhaus.org,reject_unlisted_recipient"
|
||||||
|
|
||||||
|
if [ $GREYLISTING != 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
|
||||||
|
|
||||||
|
RECIPIENT_RESTRICTIONS="${RECIPIENT_RESTRICTIONS},check_policy_service inet:127.0.0.1:12340"
|
||||||
|
|
||||||
|
postconf -e smtpd_recipient_restrictions="$RECIPIENT_RESTRICTIONS"
|
||||||
|
|
||||||
# Postfix connects to Postgrey on the 127.0.0.1 interface specifically. Ensure that
|
# 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).
|
# Postgrey listens on the same interface (and not IPv6, for instance).
|
||||||
|
@ -215,6 +231,29 @@ tools/editconf.py /etc/default/postgrey \
|
||||||
tools/editconf.py /etc/postfix/main.cf \
|
tools/editconf.py /etc/postfix/main.cf \
|
||||||
message_size_limit=134217728
|
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.
|
# Allow the two SMTP ports in the firewall.
|
||||||
|
|
||||||
ufw_allow smtp
|
ufw_allow smtp
|
||||||
|
|
60
setup/options-dialog.py
Normal file
60
setup/options-dialog.py
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
import npyscreen
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class TestApp(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",)
|
||||||
|
postgrey_text = form.add(
|
||||||
|
npyscreen.TitleFixedText,
|
||||||
|
name="POSTGREY",
|
||||||
|
value="Should Postgrey be used to greylist messages?",
|
||||||
|
editable=False
|
||||||
|
)
|
||||||
|
form.add(npyscreen.FixedText)
|
||||||
|
|
||||||
|
postgrey_text = form.add(
|
||||||
|
npyscreen.MultiLineEditable,
|
||||||
|
name="POSTSRSD",
|
||||||
|
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.FixedText)
|
||||||
|
|
||||||
|
options = form.add(
|
||||||
|
npyscreen.TitleMultiSelect,
|
||||||
|
max_height=-2,
|
||||||
|
value = [
|
||||||
|
int(os.getenv('POSTGREY', 1)),
|
||||||
|
int(os.getenv('POSTSRSD', 0)),
|
||||||
|
int(os.getenv('POLICY_SPF', 0))
|
||||||
|
],
|
||||||
|
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 = TestApp()
|
||||||
|
App.run()
|
|
@ -16,6 +16,7 @@ if [ -z "${NONINTERACTIVE:-}" ]; then
|
||||||
# we install it inside a virtualenv. In this script, we don't have the virtualenv yet
|
# we install it inside a virtualenv. In this script, we don't have the virtualenv yet
|
||||||
# so we install the python package globally.
|
# so we install the python package globally.
|
||||||
hide_output pip3 install "email_validator>=1.0.0" || exit 1
|
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" \
|
message_box "Mail-in-a-Box Installation" \
|
||||||
"Hello and thanks for deploying a Mail-in-a-Box!
|
"Hello and thanks for deploying a Mail-in-a-Box!
|
||||||
|
@ -193,6 +194,8 @@ if [ -z "${STORAGE_ROOT:-}" ]; then
|
||||||
STORAGE_ROOT=$([[ -z "${DEFAULT_STORAGE_ROOT:-}" ]] && echo "/home/$STORAGE_USER" || echo "$DEFAULT_STORAGE_ROOT")
|
STORAGE_ROOT=$([[ -z "${DEFAULT_STORAGE_ROOT:-}" ]] && echo "/home/$STORAGE_USER" || echo "$DEFAULT_STORAGE_ROOT")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
python3 setup/options-dialog.py
|
||||||
|
|
||||||
# Show the configuration, since the user may have not entered it manually.
|
# Show the configuration, since the user may have not entered it manually.
|
||||||
echo
|
echo
|
||||||
echo "Primary Hostname: $PRIMARY_HOSTNAME"
|
echo "Primary Hostname: $PRIMARY_HOSTNAME"
|
||||||
|
|
|
@ -42,6 +42,22 @@ else
|
||||||
FIRST_TIME_SETUP=1
|
FIRST_TIME_SETUP=1
|
||||||
fi
|
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 "${GREYLISTING:-}" ]; then
|
||||||
|
GREYLISTING=$([[ -z "${DEFAULT_GREYLISTING:-}" ]] && echo "1" || echo "$DEFAULT_GREYLISTING")
|
||||||
|
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'
|
# 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.
|
# in the first dialog prompt, so we should do this before that starts.
|
||||||
cat > /usr/local/bin/mailinabox << EOF;
|
cat > /usr/local/bin/mailinabox << EOF;
|
||||||
|
@ -93,6 +109,10 @@ PUBLIC_IP=$PUBLIC_IP
|
||||||
PUBLIC_IPV6=$PUBLIC_IPV6
|
PUBLIC_IPV6=$PUBLIC_IPV6
|
||||||
PRIVATE_IP=$PRIVATE_IP
|
PRIVATE_IP=$PRIVATE_IP
|
||||||
PRIVATE_IPV6=$PRIVATE_IPV6
|
PRIVATE_IPV6=$PRIVATE_IPV6
|
||||||
|
HTTP_SSL_PORT=$HTTP_SSL_PORT
|
||||||
|
GREYLISTING=$GREYLISTING
|
||||||
|
POSTSRSD=$POSTSRSD
|
||||||
|
POLICY_SPF=$POLICY_SPF
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Start service configuration.
|
# Start service configuration.
|
||||||
|
|
|
@ -96,6 +96,9 @@ restart_service nginx
|
||||||
restart_service php7.2-fpm
|
restart_service php7.2-fpm
|
||||||
|
|
||||||
# Open ports.
|
# Open ports.
|
||||||
ufw_allow http
|
if [ $HTTP_SSL_PORT == 443 ]; then
|
||||||
ufw_allow https
|
ufw_allow http
|
||||||
|
ufw_allow https
|
||||||
|
else
|
||||||
|
ufw_allow $HTTP_SSL_PORT
|
||||||
|
fi
|
||||||
|
|
10
tools/dns-auth.sh
Executable file
10
tools/dns-auth.sh
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/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
|
8
tools/dns-cleanup.sh
Executable file
8
tools/dns-cleanup.sh
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#!/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 a new issue