240 lines
7.4 KiB
Bash
240 lines
7.4 KiB
Bash
#!/bin/bash
|
|
#
|
|
# Federated Computer DNS Service
|
|
|
|
PATH=$HOME/.docker/cli-plugins:/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
|
|
config_dns() {
|
|
echo -ne "\n* Configuring /federated/apps/dns container.."
|
|
spin &
|
|
SPINPID=$!
|
|
EXTERNAL_IP_LASTDIGIT=`echo $EXTERNALIP | awk -F . '{ print $4 }'`
|
|
EXTERNALIP_INADDR=`echo $EXTERNALIP | awk -F . '{ print $3"."$2"."$1".in-addr.arpa"}'`
|
|
EXTERNALIP_INADDR_CAPS=`echo $EXTERNALIP | awk -F . '{ print $3"."$2"."$1".IN-ADDR.ARPA"}'`
|
|
mkdir -p /federated/apps/dns/data/root
|
|
mkdir -p /federated/apps/dns/data/etc/bind/zones
|
|
mkdir -p /federated/apps/dns/data/var/log/letsencrypt
|
|
|
|
cat > /federated/apps/dns/docker-compose.yml <<'EOF'
|
|
version: '3.7'
|
|
|
|
services:
|
|
dns:
|
|
image: alpine:latest
|
|
container_name: dns
|
|
hostname: dns
|
|
restart: always
|
|
working_dir: /root
|
|
networks:
|
|
federated:
|
|
ipv4_address: 172.99.0.10
|
|
volumes:
|
|
- ./data/etc/bind:/etc/bind
|
|
- ./data/etc/letsencrypt:/etc/letsencrypt
|
|
- ./data/var/log/letsencrypt:/var/log/letsencrypt
|
|
- ./data/root:/root
|
|
ports:
|
|
- "53:53/udp"
|
|
- "53:53/tcp"
|
|
command: [ "/root/dns-cert.sh" ]
|
|
|
|
networks:
|
|
federated:
|
|
external: true
|
|
EOF
|
|
|
|
cat > /federated/apps/dns/data/root/dns-cert.sh <<'EOF'
|
|
#!/bin/sh -x
|
|
|
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
|
|
if [ ! -e /etc/bind/.firstdone ]; then
|
|
# Install bind and certbot packages
|
|
apk add --no-cache bind
|
|
apk add --no-cache certbot
|
|
|
|
# Install ACME DNS script
|
|
if [ ! -e /root/acme-dns-auth.py ]; then
|
|
wget https://github.com/joohoi/acme-dns-certbot-joohoi/raw/master/acme-dns-auth.py
|
|
chmod +x acme-dns-auth.py
|
|
fi
|
|
[ ! -e /usr/bin/python ] && ln -s /usr/bin/python3 /usr/bin/python
|
|
|
|
# Run rndc to create bind keys for rndc to run
|
|
rndc-confgen -a
|
|
cat /etc/bind/rndc.key >> /etc/bind/named.conf
|
|
|
|
# Run Certbot and insert CNAME record into bind configuration
|
|
DOMAIN=`ls /etc/bind/zones | head -1`
|
|
echo "Trying to certbot for DOMAIN $DOMAIN"
|
|
CNAME_RECORD=`certbot certonly --manual --manual-auth-hook /root/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d \*.$DOMAIN -d $DOMAIN --agree-tos --email hostmaster@$DOMAIN -n 2>1 | grep acme-dns | awk '{ print $3 }'`
|
|
echo "Got CNAME record: $CNAME_RECORD"
|
|
echo "$CNAME_RECORD" > /etc/bind/.cnamerecord
|
|
echo -e "_acme-challenge\tIN\tCNAME\t$CNAME_RECORD" >> /etc/bind/zones/$DOMAIN
|
|
|
|
# Reload Bind configuration without restarting the container or process
|
|
named -f -g &
|
|
crond &
|
|
# rndc reload $DOMAIN
|
|
# rndc reload
|
|
sleep 7
|
|
|
|
# Run Certbot again to generate the certificate
|
|
certbot certonly --manual --manual-auth-hook /root/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d \*.$DOMAIN -d $DOMAIN --agree-tos --email hostmaster@$DOMAIN -n &> /dev/null
|
|
if [ $? -eq 0 ]; then
|
|
echo "[federated]: SUCCESS generating certificates for $DOMAIN!"
|
|
echo "[federated]: Certificates are at /etc/letsencrypt/live/$DOMAIN"
|
|
echo -ne "#!/bin/sh\n\n/usr/bin/certbot renew -q" > /etc/periodic/15min/certbot-renew.sh
|
|
chmod +x /etc/periodic/15min/certbot-renew.sh
|
|
else
|
|
touch /etc/bind/.failedcert
|
|
touch /etc/bind/.firstdone
|
|
echo "[federated]: FAILED generating certificates for $DOMAIN"
|
|
echo "[federated]: Check that you have DNS setup properly"
|
|
exit 2;
|
|
fi
|
|
|
|
touch /etc/bind/.firstdone
|
|
wait -n
|
|
elif [ -e /etc/bind/.firstdone ] && [ -e /etc/bind/.failedcert ]; then
|
|
# Install bind and certbot packages
|
|
apk add --no-cache bind
|
|
apk add --no-cache certbot
|
|
|
|
DOMAIN=`ls /etc/bind/zones | head -1`
|
|
named -f -g &
|
|
crond &
|
|
sleep 7
|
|
|
|
# Run Certbot again to generate the certificate
|
|
certbot certonly --manual --manual-auth-hook /root/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d \*.$DOMAIN -d $DOMAIN --agree-tos --email hostmaster@$DOMAIN -n &> /dev/null
|
|
if [ $? -eq 0 ]; then
|
|
rm /etc/bind/.failedcert
|
|
echo "[federated]: SUCCESS generating certificates for $DOMAIN!"
|
|
echo "[federated]: Certificates are at /etc/letsencrypt/live/$DOMAIN"
|
|
else
|
|
touch /etc/bind/.failedcert
|
|
echo "[federated]: FAILED generating certificates for $DOMAIN"
|
|
echo "[federated]: Check that you have DNS setup properly"
|
|
exit 2;
|
|
fi
|
|
wait -n
|
|
else
|
|
# Install bind and certbot packages
|
|
apk add --no-cache bind
|
|
apk add --no-cache certbot
|
|
[ ! `pgrep -x named` ] && named -f -g && crond
|
|
fi
|
|
EOF
|
|
|
|
chmod +x /federated/apps/dns/data/root/dns-cert.sh
|
|
|
|
cat > /federated/apps/dns/data/etc/bind/named.conf <<EOF
|
|
options {
|
|
directory "/var/bind";
|
|
|
|
listen-on { any; };
|
|
listen-on-v6 { none; };
|
|
allow-transfer { none; };
|
|
allow-recursion { none; };
|
|
recursion no;
|
|
dnssec-validation auto;
|
|
};
|
|
zone "$DOMAIN" {
|
|
type master;
|
|
file "/etc/bind/zones/$DOMAIN";
|
|
};
|
|
zone "$EXTERNALIP_INADDR" {
|
|
type master;
|
|
file "/etc/bind/zones/$DOMAIN.rev";
|
|
};
|
|
controls {
|
|
inet 127.0.0.1 port 953
|
|
allow { 127.0.0.1; } keys { "rndc-key"; };
|
|
};
|
|
EOF
|
|
|
|
cat > /federated/apps/dns/data/etc/bind/zones/$DOMAIN <<EOF
|
|
\$TTL 2d
|
|
\$ORIGIN $DOMAIN.
|
|
$DOMAIN. IN SOA ns1.$DOMAIN. hostmaster.$DOMAIN. (
|
|
18 ; Serial
|
|
12h ; Refresh
|
|
15m ; Retry
|
|
3w ; Expire
|
|
3h ; Negative Cache TTL
|
|
)
|
|
IN NS ns1.$DOMAIN.
|
|
IN NS ns2.$DOMAIN.
|
|
MX 10 mail.$DOMAIN.
|
|
IN TXT "v=spf1 mx a:mail.$DOMAIN ~all"
|
|
ns1 IN A $EXTERNALIP
|
|
ns2 IN A $EXTERNALIP
|
|
mail IN A $EXTERNALIP
|
|
www IN A $EXTERNALIP
|
|
panel IN A $EXTERNALIP
|
|
webmail IN A $EXTERNALIP
|
|
nextcloud IN A $EXTERNALIP
|
|
computer IN A $EXTERNALIP
|
|
collabora IN A $EXTERNALIP
|
|
jitsi IN A $EXTERNALIP
|
|
matrix IN A $EXTERNALIP
|
|
element IN A $EXTERNALIP
|
|
listmonk IN A $EXTERNALIP
|
|
vaultwarden IN A $EXTERNALIP
|
|
$DOMAIN. IN A $EXTERNALIP
|
|
EOF
|
|
|
|
cat > /federated/apps/dns/data/etc/bind/zones/$DOMAIN.rev <<EOF
|
|
\$TTL 2d
|
|
\$ORIGIN $EXTERNALIP_INADDR_CAPS.
|
|
@ IN SOA ns1.$DOMAIN. hostmaster.$DOMAIN. (
|
|
12 ; Serial
|
|
12h ; Refresh
|
|
15m ; Retry
|
|
3w ; Expire
|
|
3h ; Negative Cache TTL
|
|
)
|
|
IN NS ns1.$DOMAIN.
|
|
IN NS ns2.$DOMAIN.
|
|
$EXTERNAL_IP_LASTDIGIT IN PTR computer.$DOMAIN.
|
|
EOF
|
|
|
|
echo -ne "done."
|
|
kill $SPINPID &> /dev/null
|
|
}
|
|
|
|
start_dns() {
|
|
echo -ne "\n* Starting /federated/apps/dns service.."
|
|
spin &
|
|
SPINPID=$!
|
|
|
|
if [ $DEBUG ]; then
|
|
# Start /federated/apps/dns with output to console for debug
|
|
docker-compose -f /federated/apps/dns/docker-compose.yml -p dns up
|
|
[ $? -eq 0 ] && echo -ne "done.\n" || fail "There was a problem starting service /federated/apps/dns"
|
|
else
|
|
# Start /federated/apps/dns with output to /dev/null
|
|
docker-compose -f /federated/apps/dns/docker-compose.yml -p dns up -d &> /dev/null
|
|
|
|
# Keep trying to see that certificates are generated
|
|
RETRY="18"
|
|
while [ $RETRY -gt 0 ]; do
|
|
ls /federated/apps/dns/data/etc/letsencrypt/live/$DOMAIN/*.pem &> /dev/null
|
|
if [ $? -eq 0 ]; then
|
|
kill -9 $SPINPID &> /dev/null
|
|
echo -ne "done."
|
|
# echo -ne "* Certificates at /federated/apps/dns/data/etc/letsencrypt/live/$DOMAIN\n"
|
|
break
|
|
else
|
|
if [ "$RETRY" == 1 ]; then
|
|
docker-compose -f /federated/apps/dns/docker-compose.yml -p dns down &> /dev/null
|
|
fail "There was a problem starting service /federated/apps/dns\nCheck the output of 'docker logs dns' or turn on\ndebug with -d"
|
|
fi
|
|
((RETRY--))
|
|
sleep 9
|
|
fi
|
|
done
|
|
fi
|
|
}
|