You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FreeDMR/docker-configs/docker-compose_install.sh

313 lines
10 KiB

#!/bin/bash
#
###############################################################################
# Copyright (C) 2020 Simon Adlem, G7RZU <g7rzu@gb7fr.org.uk>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
###############################################################################
set -e
BASE_URL='https://gitlab.hacknix.net/hacknix/FreeDMR/-/raw/master'
prompt_value()
{
prompt_text="$1"
default_value="$2"
if [ ! -r /dev/tty ]
then
echo "Interactive input is required unless installer values are supplied as environment variables." >&2
exit 2
fi
if [ -n "$default_value" ]
then
printf '%s [%s]: ' "$prompt_text" "$default_value" >/dev/tty
else
printf '%s: ' "$prompt_text" >/dev/tty
fi
read -r entered_value </dev/tty
if [ -z "$entered_value" ]
then
printf '%s' "$default_value"
else
printf '%s' "$entered_value"
fi
}
is_unsigned_integer()
{
case "$1" in
''|*[!0-9]*) return 1 ;;
*) return 0 ;;
esac
}
validate_server_id()
{
description="$1"
value="$2"
if ! is_unsigned_integer "$value" || [ "$value" -lt 1 ] || [ "$value" -gt 4294967295 ]
then
echo "$description must be an unsigned non-zero DMR/server ID." >&2
exit 2
fi
}
build_data_gateway_relationships()
{
count="$1"
base_id="$2"
key="$3"
relationships='['
number=1
while [ "$number" -le "$count" ]
do
if [ "$count" -eq 1 ]
then
server_id="$base_id"
else
server_id=$((base_id + number))
fi
bind_port=$((62030 + number))
peer_port=$((62040 + number))
if [ "$number" -gt 1 ]
then
relationships="${relationships},"
fi
relationships="${relationships}{\"link_id\":\"hdstack-${number}\",\"bind_host\":\"0.0.0.0\",\"bind_port\":${bind_port},\"peer_host\":\"freedmr\",\"peer_port\":${peer_port},\"peer_network_id\":${server_id},\"direct_source_server_id\":${server_id},\"key\":\"${key}\"}"
number=$((number + 1))
done
printf '%s]' "$relationships"
}
CPU_COUNT=$(getconf _NPROCESSORS_ONLN 2>/dev/null) || CPU_COUNT=2
if ! is_unsigned_integer "$CPU_COUNT" || [ "$CPU_COUNT" -lt 1 ]
then
CPU_COUNT=2
fi
DEFAULT_HDSTACK=$((CPU_COUNT - 1))
if [ "$DEFAULT_HDSTACK" -lt 1 ]
then
DEFAULT_HDSTACK=1
elif [ "$DEFAULT_HDSTACK" -gt 5 ]
then
DEFAULT_HDSTACK=5
fi
echo 'FreeDMR Docker installer'
echo
echo 'Assigned Server ID, or your own DMR ID if you do not have one.'
HDSTACK_BASEID="${HDSTACK_BASEID:-}"
if [ -z "$HDSTACK_BASEID" ]
then
HDSTACK_BASEID=$(prompt_value 'Main/aggregator server ID' '')
fi
validate_server_id 'Main/aggregator server ID' "$HDSTACK_BASEID"
echo
echo 'Enabling HDStack allows FreeDMR to use more than one CPU core and support more than 100 HBP connections.'
HDSTACK_COUNT="${HDSTACK:-}"
if [ -z "$HDSTACK_COUNT" ]
then
HDSTACK_COUNT=$(prompt_value 'Number of HDStack workers (1-5)' "$DEFAULT_HDSTACK")
fi
if ! is_unsigned_integer "$HDSTACK_COUNT" || [ "$HDSTACK_COUNT" -lt 1 ] || [ "$HDSTACK_COUNT" -gt 5 ]
then
echo 'HDSTACK must be an integer from 1 to 5.' >&2
exit 2
fi
if [ $((HDSTACK_BASEID + HDSTACK_COUNT)) -gt 4294967295 ]
then
echo 'Main/aggregator ID plus worker IDs exceed the supported ID range.' >&2
exit 2
fi
HDSTACK_BRIDGE_VALUE="${HDSTACK_BRIDGE:-}"
if [ -z "$HDSTACK_BRIDGE_VALUE" ]
then
HDSTACK_BRIDGE_VALUE=$(prompt_value 'Enable the separate bridge server? (y/N)' 'N')
fi
case "$HDSTACK_BRIDGE_VALUE" in
1|y|Y|yes|YES) HDSTACK_BRIDGE_VALUE=1 ;;
0|n|N|no|NO) HDSTACK_BRIDGE_VALUE=0 ;;
*)
echo 'HDSTACK_BRIDGE must be 0 or 1 (or yes/no).' >&2
exit 2
;;
esac
HDSTACK_BRIDGE_ID="${HDSTACK_BRIDGE_ID:-0}"
if [ "$HDSTACK_BRIDGE_VALUE" -eq 1 ]
then
if [ "$HDSTACK_COUNT" -eq 1 ]
then
echo 'The separate bridge process requires HDSTACK to be 2..5.' >&2
exit 2
fi
if [ "$HDSTACK_BRIDGE_ID" -eq 0 ] 2>/dev/null
then
echo
echo 'The bridge server requires its own assigned server ID.'
HDSTACK_BRIDGE_ID=$(prompt_value 'Bridge server ID' '')
fi
validate_server_id 'Bridge server ID' "$HDSTACK_BRIDGE_ID"
if [ "$HDSTACK_BRIDGE_ID" -ge "$HDSTACK_BASEID" ] &&
[ "$HDSTACK_BRIDGE_ID" -le $((HDSTACK_BASEID + HDSTACK_COUNT)) ]
then
echo 'Bridge server ID must not duplicate the aggregator or a worker ID.' >&2
exit 2
fi
fi
echo
echo 'The separate Data Gateway provides D-APRS and future packet-data services.'
FREEDMR_GATEWAY_APRS_LOGIN_CALL="${FREEDMR_GATEWAY_APRS_LOGIN_CALL:-}"
if [ -z "$FREEDMR_GATEWAY_APRS_LOGIN_CALL" ]
then
FREEDMR_GATEWAY_APRS_LOGIN_CALL=$(prompt_value 'APRS-IS login callsign' '')
fi
case "$FREEDMR_GATEWAY_APRS_LOGIN_CALL" in
''|*[!A-Za-z0-9-]*)
echo 'APRS-IS login callsign may contain only letters, digits and a hyphen.' >&2
exit 2
;;
esac
if [ "${#FREEDMR_GATEWAY_APRS_LOGIN_CALL}" -gt 9 ]
then
echo 'APRS-IS login callsign must not exceed 9 characters.' >&2
exit 2
fi
FREEDMR_GATEWAY_APRS_PASSCODE="${FREEDMR_GATEWAY_APRS_PASSCODE:-}"
if [ -z "$FREEDMR_GATEWAY_APRS_PASSCODE" ]
then
FREEDMR_GATEWAY_APRS_PASSCODE=$(prompt_value 'APRS-IS passcode' '')
fi
if ! is_unsigned_integer "$FREEDMR_GATEWAY_APRS_PASSCODE"
then
echo 'APRS-IS passcode must be numeric.' >&2
exit 2
fi
FREEDMR_GATEWAY_FBP_KEY="${FREEDMR_GATEWAY_FBP_KEY:-}"
if [ -z "$FREEDMR_GATEWAY_FBP_KEY" ]
then
FREEDMR_GATEWAY_FBP_KEY=$(od -An -N10 -tx1 /dev/urandom | tr -d ' \n')
fi
case "$FREEDMR_GATEWAY_FBP_KEY" in
''|*[!A-Za-z0-9._-]*)
echo 'Data Gateway FBP key may contain only letters, digits, dot, underscore and hyphen.' >&2
exit 2
;;
esac
if [ "${#FREEDMR_GATEWAY_FBP_KEY}" -gt 20 ]
then
echo 'Data Gateway FBP key must not exceed 20 characters.' >&2
exit 2
fi
FREEDMR_GATEWAY_FBP_RELATIONSHIPS=$(build_data_gateway_relationships \
"$HDSTACK_COUNT" "$HDSTACK_BASEID" "$FREEDMR_GATEWAY_FBP_KEY")
echo
echo 'Installing required packages and Docker Community Edition...'
apt-get -y remove docker docker-engine docker.io
apt-get -y update
apt-get -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
ARCH=$(/usr/bin/arch)
echo "System architecture is $ARCH"
if [ "$ARCH" = "x86_64" ]
then
ARCH="amd64"
fi
add-apt-repository \
"deb [arch=$ARCH] https://download.docker.com/linux/debian \
$(lsb_release -cs) \
stable"
apt-get -y update
apt-get -y install docker-ce docker-compose
echo 'Configuring Docker...'
cat <<EOF > /etc/docker/daemon.json
{
"userland-proxy": false,
"experimental": true,
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
EOF
systemctl restart docker
echo 'Installing FreeDMR configuration...'
mkdir -p /etc/freedmr/acme.sh /etc/freedmr/certs /etc/freedmr/json
chmod -R 755 /etc/freedmr
chown 54000:54000 /etc/freedmr/json
curl -fsSL "$BASE_URL/FreeDMR.cfg" -o /etc/freedmr/freedmr.cfg
sed -i "0,/^SERVER_ID:/s/^SERVER_ID:.*/SERVER_ID: $HDSTACK_BASEID/" /etc/freedmr/freedmr.cfg
sed -i '/^\[GLOBAL\]/,/^\[/ s/^DATA_GATEWAY:.*/DATA_GATEWAY: True/' /etc/freedmr/freedmr.cfg
sed -i '/^\[DATA-GATEWAY\]/,/^\[/ s/^ENABLED:.*/ENABLED: True/' /etc/freedmr/freedmr.cfg
sed -i "/^\[DATA-GATEWAY\]/,/^\[/ s|^PASSPHRASE:.*|PASSPHRASE: $FREEDMR_GATEWAY_FBP_KEY|" /etc/freedmr/freedmr.cfg
sed -i '/^\[DATA-GATEWAY\]/,/^\[/ s/^TARGET_IP:.*/TARGET_IP: freedmr-data-gateway/' /etc/freedmr/freedmr.cfg
if [ ! -e /etc/freedmr/freedmr-bridge.cfg ]
then
curl -fsSL "$BASE_URL/docker-configs/freedmr-bridge.cfg" -o /etc/freedmr/freedmr-bridge.cfg
fi
if [ "$HDSTACK_BRIDGE_VALUE" -eq 1 ]
then
sed -i "0,/^SERVER_ID:/s/^SERVER_ID:.*/SERVER_ID: $HDSTACK_BRIDGE_ID/" /etc/freedmr/freedmr-bridge.cfg
fi
if [ ! -e /etc/freedmr/rules-bridge.py ]
then
curl -fsSL "$BASE_URL/docker-configs/rules-bridge.py" -o /etc/freedmr/rules-bridge.py
fi
curl -fsSL "$BASE_URL/docker-configs/docker-compose.yml" -o /etc/freedmr/docker-compose.yml
sed -i "s|^[[:space:]]*#*- HDSTACK=.*| - HDSTACK=$HDSTACK_COUNT|" /etc/freedmr/docker-compose.yml
sed -i "s|^[[:space:]]*#*- HDSTACK_BASEID=.*| - HDSTACK_BASEID=$HDSTACK_BASEID|" /etc/freedmr/docker-compose.yml
sed -i "s|^[[:space:]]*- HDSTACK_BRIDGE=.*| - HDSTACK_BRIDGE=$HDSTACK_BRIDGE_VALUE|" /etc/freedmr/docker-compose.yml
sed -i "s|__FREEDMR_GATEWAY_FBP_RELATIONSHIPS__|$FREEDMR_GATEWAY_FBP_RELATIONSHIPS|" /etc/freedmr/docker-compose.yml
sed -i "s|__FREEDMR_GATEWAY_APRS_LOGIN_CALL__|$FREEDMR_GATEWAY_APRS_LOGIN_CALL|" /etc/freedmr/docker-compose.yml
sed -i "s|__FREEDMR_GATEWAY_APRS_PASSCODE__|$FREEDMR_GATEWAY_APRS_PASSCODE|" /etc/freedmr/docker-compose.yml
chown -R 54000:54000 /etc/freedmr
if [ -e /etc/cron.daily/lastheard ]
then
chmod 755 /etc/cron.daily/lastheard
fi
echo 'Tuning network stack...'
cat <<EOF > /etc/sysctl.conf
net.core.rmem_default=134217728
net.core.rmem_max=134217728
net.core.wmem_max=134217728
net.core.netdev_max_backlog=250000
net.netfilter.nf_conntrack_udp_timeout=15
net.netfilter.nf_conntrack_udp_timeout_stream=35
EOF
/usr/sbin/sysctl -p
echo 'Starting the FreeDMR release-candidate container...'
cd /etc/freedmr
docker-compose up -d
echo 'Read /etc/freedmr/docker-compose.yml and docs/hdstack.md before adding optional services or custom links.'
echo 'FreeDMR setup complete.'

Powered by TurnKey Linux.