Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into merge-upstream
Browse files Browse the repository at this point in the history
# Conflicts:
#	setup/firstuser.sh
#	setup/functions.sh
#	setup/mail-users.sh
#	setup/management.sh
#	setup/network-checks.sh
#	setup/nextcloud.sh
#	setup/questions.sh
#	setup/ssl.sh
#	setup/start.sh
#	setup/system.sh
#	setup/webmail.sh
#	tools/archive_conf_files.sh
#	tools/web_update
  • Loading branch information
downtownallday committed Apr 3, 2024
2 parents 21b01aa + a332be6 commit 11e69f5
Show file tree
Hide file tree
Showing 27 changed files with 315 additions and 310 deletions.
2 changes: 1 addition & 1 deletion management/daily_tasks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export LC_TYPE=en_US.UTF-8

# On Mondays, i.e. once a week, send the administrator a report of total emails
# sent and received so the admin might notice server abuse.
if [ `date "+%u"` -eq 1 ]; then
if [ "$(date "+%u")" -eq 1 ]; then
management/mail_log.py -t week | management/email_administrator.py "Mail-in-a-Box Usage Report"
fi

Expand Down
24 changes: 12 additions & 12 deletions setup/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ if [[ $EUID -ne 0 ]]; then
fi

# Clone the Mail-in-a-Box repository if it doesn't exist.
if [ ! -d $HOME/mailinabox ]; then
if [ ! -d "$HOME/mailinabox" ]; then
if [ ! -f /usr/bin/git ]; then
echo Installing git . . .
echo "Installing git . . ."
apt-get -q -q update
DEBIAN_FRONTEND=noninteractive apt-get -q -q install -y git < /dev/null
echo
Expand All @@ -91,25 +91,25 @@ if [ ! -d $HOME/mailinabox ]; then
SOURCE=https://github.com/downtownallday/mailinabox-ldap.git
fi

echo Downloading Mail-in-a-Box $TAG. . .
echo "Downloading Mail-in-a-Box $TAG. . ."
git clone \
-b $TAG --depth 1 \
$SOURCE \
$HOME/mailinabox \
-b "$TAG" --depth 1 \
"$SOURCE" \
"$HOME/mailinabox" \
< /dev/null 2> /dev/null

echo
fi

# Change directory to it.
cd $HOME/mailinabox
cd "$HOME/mailinabox" || exit

# Update it.
if [ "$TAG" != $(git describe --always) ]; then
echo Updating Mail-in-a-Box to $TAG . . .
git fetch --depth 1 --force --prune origin tag $TAG
if ! git checkout -q $TAG; then
echo "Update failed. Did you modify something in $(pwd)?"
if [ "$TAG" != "$(git describe --always)" ]; then
echo "Updating Mail-in-a-Box to $TAG . . ."
git fetch --depth 1 --force --prune origin tag "$TAG"
if ! git checkout -q "$TAG"; then
echo "Update failed. Did you modify something in $PWD?"
exit 1
fi
echo
Expand Down
10 changes: 5 additions & 5 deletions setup/dkim.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ source setup/functions.sh # load our functions
source /etc/mailinabox.conf # load global vars

# Install DKIM...
echo Installing OpenDKIM/OpenDMARC...
echo "Installing OpenDKIM/OpenDMARC..."
apt_install opendkim opendkim-tools opendmarc

# Make sure configuration directories exist.
mkdir -p /etc/opendkim;
mkdir -p $STORAGE_ROOT/mail/dkim
mkdir -p "$STORAGE_ROOT/mail/dkim"

# Used in InternalHosts and ExternalIgnoreList configuration directives.
# Not quite sure why.
Expand Down Expand Up @@ -62,12 +62,12 @@ fi
# such as Google. But they and others use a 2048 bit key, so we'll
# do the same. Keys beyond 2048 bits may exceed DNS record limits.
if [ ! -f "$STORAGE_ROOT/mail/dkim/mail.private" ]; then
opendkim-genkey -b 2048 -r -s mail -D $STORAGE_ROOT/mail/dkim
opendkim-genkey -b 2048 -r -s mail -D "$STORAGE_ROOT/mail/dkim"
fi

# Ensure files are owned by the opendkim user and are private otherwise.
chown -R opendkim:opendkim $STORAGE_ROOT/mail/dkim
chmod go-rwx $STORAGE_ROOT/mail/dkim
chown -R opendkim:opendkim "$STORAGE_ROOT/mail/dkim"
chmod go-rwx "$STORAGE_ROOT/mail/dkim"

tools/editconf.py /etc/opendmarc.conf -s \
"Syslog=true" \
Expand Down
8 changes: 4 additions & 4 deletions setup/dns.sh
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,15 @@ if [ ! -f "$STORAGE_ROOT/dns/dnssec/$algo.conf" ]; then
# (This previously used -b 2048 but it's unclear if this setting makes sense
# for non-RSA keys, so it's removed. The RSA-based keys are not recommended
# anymore anyway.)
KSK=$(umask 077; cd $STORAGE_ROOT/dns/dnssec; ldns-keygen -r /dev/urandom -a $algo -k _domain_);
KSK=$(umask 077; cd "$STORAGE_ROOT/dns/dnssec"; ldns-keygen -r /dev/urandom -a $algo -k _domain_);

# Now create a Zone-Signing Key (ZSK) which is expected to be
# rotated more often than a KSK, although we have no plans to
# rotate it (and doing so would be difficult to do without
# disturbing DNS availability.) Omit `-k`.
# (This previously used -b 1024 but it's unclear if this setting makes sense
# for non-RSA keys, so it's removed.)
ZSK=$(umask 077; cd $STORAGE_ROOT/dns/dnssec; ldns-keygen -r /dev/urandom -a $algo _domain_);
ZSK=$(umask 077; cd "$STORAGE_ROOT/dns/dnssec"; ldns-keygen -r /dev/urandom -a $algo _domain_);

# These generate two sets of files like:
#
Expand All @@ -162,7 +162,7 @@ if [ ! -f "$STORAGE_ROOT/dns/dnssec/$algo.conf" ]; then
# options. So we'll store the names of the files we just generated.
# We might have multiple keys down the road. This will identify
# what keys are the current keys.
cat > $STORAGE_ROOT/dns/dnssec/$algo.conf << EOF;
cat > "$STORAGE_ROOT/dns/dnssec/$algo.conf" << EOF;
KSK=$KSK
ZSK=$ZSK
EOF
Expand All @@ -178,7 +178,7 @@ cat > /etc/cron.daily/mailinabox-dnssec << EOF;
#!/bin/bash
# Mail-in-a-Box
# Re-sign any DNS zones with DNSSEC because the signatures expire periodically.
$(pwd)/tools/dns_update
$PWD/tools/dns_update
EOF
chmod +x /etc/cron.daily/mailinabox-dnssec

Expand Down
11 changes: 6 additions & 5 deletions setup/firstuser.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/bin/bash
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
Expand All @@ -19,7 +20,7 @@ if [ -z "$(management/cli.py user)" ]; then
input_box "Mail Account" \
"Let's create your first mail account.
\n\nWhat email address do you want?" \
me@$(get_default_hostname) \
"me@$(get_default_hostname)" \
EMAIL_ADDR

if [ -z "$EMAIL_ADDR" ]; then
Expand All @@ -31,7 +32,7 @@ if [ -z "$(management/cli.py user)" ]; then
input_box "Mail Account" \
"That's not a valid email address.
\n\nWhat email address do you want?" \
$EMAIL_ADDR \
"$EMAIL_ADDR" \
EMAIL_ADDR
if [ -z "$EMAIL_ADDR" ]; then
# user hit ESC/cancel
Expand All @@ -56,11 +57,11 @@ if [ -z "$(management/cli.py user)" ]; then
fi

# Create the user's mail account. This will ask for a password if none was given above.
management/cli.py user add $EMAIL_ADDR ${EMAIL_PW:-}
management/cli.py user add "$EMAIL_ADDR" "${EMAIL_PW:-}"

# Make it an admin.
hide_output management/cli.py user make-admin $EMAIL_ADDR
hide_output management/cli.py user make-admin "$EMAIL_ADDR"

# Create an alias to which we'll direct all automatically-created administrative aliases.
management/cli.py alias add administrator@$PRIMARY_HOSTNAME $EMAIL_ADDR > /dev/null
management/cli.py alias add "administrator@$PRIMARY_HOSTNAME" "$EMAIL_ADDR" > /dev/null
fi
52 changes: 26 additions & 26 deletions setup/functions.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/bin/bash
# -*- indent-tabs-mode: t; tab-width: 4; -*-
#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
Expand Down Expand Up @@ -32,23 +33,23 @@ function hide_output {
# Execute command, redirecting stderr/stdout to the temporary file. Since we
# check the return code ourselves, disable 'set -e' temporarily.
set +e
"$@" &> $OUTPUT
"$@" &> "$OUTPUT"
E=$?
set -e

# If the command failed, show the output that was captured in the temporary file.
if [ $E != 0 ]; then
# Something failed.
echo
echo FAILED: "$@"
echo "FAILED: $*"
echo -----------------------------------------
cat $OUTPUT
cat "$OUTPUT"
echo -----------------------------------------
exit $E
fi

# Remove temporary file.
rm -f $OUTPUT
rm -f "$OUTPUT"
}

function wait_for_apt_lock {
Expand Down Expand Up @@ -97,9 +98,9 @@ function get_default_hostname {
# Guess the machine's hostname. It should be a fully qualified
# domain name suitable for DNS. None of these calls may provide
# the right value, but it's the best guess we can make.
set -- $(hostname --fqdn 2>/dev/null ||
set -- "$(hostname --fqdn 2>/dev/null ||
hostname --all-fqdns 2>/dev/null ||
hostname 2>/dev/null)
hostname 2>/dev/null)"
printf '%s\n' "$1" # return this value
}

Expand All @@ -111,7 +112,7 @@ function get_publicip_from_web_service {
#
# Pass '4' or '6' as an argument to this function to specify
# what type of address to get (IPv4, IPv6).
curl -$1 --fail --silent --max-time 15 icanhazip.com 2>/dev/null || /bin/true
curl -"$1" --fail --silent --max-time 15 icanhazip.com 2>/dev/null || /bin/true
}

function get_default_privateip {
Expand Down Expand Up @@ -154,19 +155,19 @@ function get_default_privateip {
if [ "$1" == "6" ]; then target=2001:4860:4860::8888; fi

# Get the route information.
route=$(ip -$1 -o route get $target 2>/dev/null | grep -v unreachable)
route=$(ip -"$1" -o route get $target 2>/dev/null | grep -v unreachable)

# Parse the address out of the route information.
address=$(echo $route | sed "s/.* src \([^ ]*\).*/\1/")
address=$(echo "$route" | sed "s/.* src \([^ ]*\).*/\1/")

if [[ "$1" == "6" && $address == fe80:* ]]; then
# For IPv6 link-local addresses, parse the interface out
# of the route information and append it with a '%'.
interface=$(echo $route | sed "s/.* dev \([^ ]*\).*/\1/")
interface=$(echo "$route" | sed "s/.* dev \([^ ]*\).*/\1/")
address=$address%$interface
fi

echo $address
echo "$address"
}

function ufw_allow {
Expand All @@ -184,7 +185,7 @@ function ufw_limit {
}

function restart_service {
hide_output service $1 restart
hide_output service "$1" restart
}

## Dialog Functions ##
Expand Down Expand Up @@ -213,7 +214,7 @@ function input_menu {
declare -n result_code=$4_EXITCODE
local IFS=^$'\n'
set +e
result=$(dialog --stdout --title "$1" --menu "$2" 0 0 0 $3)
result=$(dialog --stdout --title "$1" --menu "$2" 0 0 0 "$3")
result_code=$?
set -e
}
Expand All @@ -225,17 +226,17 @@ function wget_verify {
HASH=$2
DEST=$3
CHECKSUM="$HASH $DEST"
rm -f $DEST
hide_output wget --compression=auto -O $DEST $URL
rm -f "$DEST"
hide_output wget --compression=auto -O "$DEST" "$URL"
if ! echo "$CHECKSUM" | sha1sum --check --strict > /dev/null; then
echo "------------------------------------------------------------"
echo "Download of $URL did not match expected checksum."
echo "Found:"
sha1sum $DEST
sha1sum "$DEST"
echo
echo "Expected:"
echo "$CHECKSUM"
rm -f $DEST
rm -f "$DEST"
exit 1
fi
}
Expand All @@ -251,10 +252,10 @@ function git_clone {
SUBDIR=$3
TARGETPATH=$4
TMPPATH=/tmp/git-clone-$$
rm -rf $TMPPATH $TARGETPATH
git clone -q $REPO $TMPPATH || exit 1
(cd $TMPPATH; git checkout -q $TREEISH;) || exit 1
mv $TMPPATH/$SUBDIR $TARGETPATH
rm -rf $TMPPATH "$TARGETPATH"
git clone -q "$REPO" $TMPPATH || exit 1
(cd $TMPPATH; git checkout -q "$TREEISH";) || exit 1
mv $TMPPATH/"$SUBDIR" "$TARGETPATH"
rm -rf $TMPPATH
}

Expand Down Expand Up @@ -326,14 +327,14 @@ say() {
wait_for_management_daemon() {
local progress="${1:-progress}" # show progress? "progress"/"no-progress"
local max_wait="${2:-60}" # seconds, 0=forever
local start=$(date +%s)
local start="$(date +%s)"
local elapsed=0 now
[ "$max_wait" = "forever" ] && max_wait=0

# Wait for the management daemon to start...
until nc -z -w 4 127.0.0.1 10222
do
now=$(date +%s)
now="$(date +%s)"
# let returns 1 if the equasion evaluates to zero, which will
# cause the script to exit because of set -e. add one.
[ $now -eq $start ] && let now+=1
Expand All @@ -343,7 +344,7 @@ wait_for_management_daemon() {
return 1
fi
if [ "$progress" = "progress" ]; then
echo Waiting for the Mail-in-a-Box management daemon to start...
echo "Waiting for the Mail-in-a-Box management daemon to start..."
fi
sleep 2
done
Expand Down Expand Up @@ -383,4 +384,3 @@ remove_hook_handler() {
fi
fi
}

20 changes: 10 additions & 10 deletions setup/mail-dovecot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ apt_install \
# - https://www.dovecot.org/list/dovecot/2012-August/137569.html
# - https://www.dovecot.org/list/dovecot/2011-December/132455.html
tools/editconf.py /etc/dovecot/conf.d/10-master.conf \
default_process_limit=$(echo "$(nproc) * 250" | bc) \
default_vsz_limit=$(echo "$(free -tm | tail -1 | awk '{print $2}') / 3" | bc)M \
default_process_limit="$(($(nproc) * 250))" \
default_vsz_limit="$(($(free -tm | tail -1 | awk '{print $2}') / 3))M" \
log_path=/var/log/mail.log

# The inotify `max_user_instances` default is 128, which constrains
Expand All @@ -70,7 +70,7 @@ tools/editconf.py /etc/sysctl.conf \
# username part of the user's email address. We'll ensure that no bad domains or email addresses
# are created within the management daemon.
tools/editconf.py /etc/dovecot/conf.d/10-mail.conf \
mail_location=maildir:$STORAGE_ROOT/mail/mailboxes/%d/%n \
mail_location="maildir:$STORAGE_ROOT/mail/mailboxes/%d/%n" \
mail_privileged_group=mail \
first_valid_uid=0

Expand Down Expand Up @@ -161,7 +161,7 @@ EOF
# Setting a `postmaster_address` is required or LMTP won't start. An alias
# will be created automatically by our management daemon.
tools/editconf.py /etc/dovecot/conf.d/15-lda.conf \
postmaster_address=postmaster@$PRIMARY_HOSTNAME
"postmaster_address=postmaster@$PRIMARY_HOSTNAME"

# ### Sieve

Expand Down Expand Up @@ -210,14 +210,14 @@ chown -R mail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot

# Ensure mailbox files have a directory that exists and are owned by the mail user.
mkdir -p $STORAGE_ROOT/mail/mailboxes
chown -R mail:mail $STORAGE_ROOT/mail/mailboxes
mkdir -p "$STORAGE_ROOT/mail/mailboxes"
chown -R mail:mail "$STORAGE_ROOT/mail/mailboxes"

# Same for the sieve scripts.
mkdir -p $STORAGE_ROOT/mail/sieve
mkdir -p $STORAGE_ROOT/mail/sieve/global_before
mkdir -p $STORAGE_ROOT/mail/sieve/global_after
chown -R mail:mail $STORAGE_ROOT/mail/sieve
mkdir -p "$STORAGE_ROOT/mail/sieve"
mkdir -p "$STORAGE_ROOT/mail/sieve/global_before"
mkdir -p "$STORAGE_ROOT/mail/sieve/global_after"
chown -R mail:mail "$STORAGE_ROOT/mail/sieve"

# Allow the IMAP/POP ports in the firewall.
ufw_allow imaps
Expand Down
Loading

0 comments on commit 11e69f5

Please sign in to comment.