Setup PowerDNS Admin Part 2: Trisquel 12

#!/bin/bash
# =============================================================================
# PowerDNS Admin DB Setup + TLS Certificate
# Targets: Ubuntu 22.04/24.04/26.04, Trisquel 11/12/13
# =============================================================================

set -euo pipefail

# --- Configuration ---
ROOT_MYSQL_PASSWORD="penguin"
POWERUSER_MYSQL_PASSWORD="penguin"
POWERDNS_ADMIN_PASSWORD_PLAIN_TEXT="penguin"
domain_name="tuxmail.io"
user1_email_address="user1"
MAX_DNS_RETRIES=30
DNS_RETRY_INTERVAL=5

# --- Debugging helpers ---
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a /var/log/powerdns-install.log
}

die() {
log "FATAL: $*" >&2
exit 1
}

# =============================================================================
# Section 0: OS Detection
# =============================================================================
detect_os() {
log "=== SECTION: OS Detection ==="
if [ -f /etc/os-release ]; then
. /etc/os-release
OS_ID="$ID"
OS_VERSION="$VERSION_ID"
else
die "Cannot detect OS"
fi
log "Detected OS: $OS_ID $OS_VERSION"
}

# =============================================================================
# Section 1: PowerDNS Admin Database Setup
# =============================================================================
section_pda_database() {
log "=== SECTION: PowerDNS Admin Database ==="

# Ensure htpasswd is available
apt-get install -y apache2-utils

local schema="/var/www/powerdns/sql/poweradmin-mysql-db-structure.sql"
if [ ! -f "$schema" ]; then
die "PowerDNS Admin schema not found at $schema (was section_powerdns_admin run?)"
fi

# Dynamically drop all tables defined in the schema (idempotent re-runs)
local tables
tables=$(grep -oP '(?<=CREATE TABLE `)[^`]+' "$schema")
for t in $tables; do
mysql -u root -p"$ROOT_MYSQL_PASSWORD" powerdns -e "DROP TABLE IF EXISTS \`$t\`;"
done
log "PDA tables dropped (if existed)"

# Import PowerDNS Admin schema structure
mysql -u root -p"$ROOT_MYSQL_PASSWORD" powerdns < "$schema"
log "PowerDNS Admin schema imported"

# Create poweruser with privileges (idempotent)
mysql -u root -p"$ROOT_MYSQL_PASSWORD" -e "
CREATE USER IF NOT EXISTS 'poweruser'@'%' IDENTIFIED BY '$POWERUSER_MYSQL_PASSWORD';"
mysql -u root -p"$ROOT_MYSQL_PASSWORD" powerdns < "/var/www/powerdns/inc/config.inc.php" << EOF
<?php
\$db_host = 'localhost';
\$db_name = 'powerdns';
\$db_user = 'poweruser';
\$db_pass = '$POWERUSER_MYSQL_PASSWORD';
\$db_type = 'mysql';

\$session_key = '$SESSION_ID';

\$iface_lang = 'en_EN';

\$dns_hostmaster = 'hostmaster.$domain_name';
\$dns_ns1 = 'ns1.$domain_name';
\$dns_ns2 = 'ns1.$domain_name';

\$ignore_install_dir = true;
EOF
log "config.inc.php written"

# Remove install directory for security
rm -rf /var/www/powerdns/install
log "Install directory removed"

# Set admin password
local s
s=$(htpasswd -nbBC 12 "" "$POWERDNS_ADMIN_PASSWORD_PLAIN_TEXT")
local POWERDNS_ADMIN_PASSWORD=${s:1}

mysql -u root -p"$ROOT_MYSQL_PASSWORD" powerdns </dev/null; then
log "DNS lookup for powerdns.$domain_name succeeded"
break
fi
attempt=$((attempt + 1))
log "DNS lookup failed (attempt $attempt/$MAX_DNS_RETRIES). Sleeping ${DNS_RETRY_INTERVAL}s..."
sleep $DNS_RETRY_INTERVAL
done

if [ $attempt -ge $MAX_DNS_RETRIES ]; then
die "DNS lookup for powerdns.$domain_name failed after $MAX_DNS_RETRIES attempts. Is PowerDNS running and the zone configured?"
fi

# Obtain Let's Encrypt certificate
log "Requesting Let's Encrypt certificate for powerdns.$domain_name"
certbot --non-interactive --apache --agree-tos --redirect --hsts --staple-ocsp \
--email "${user1_email_address}@${domain_name}" \
-d "powerdns.$domain_name"
log "Certificate obtained"
}

# =============================================================================
# Main: Run all sections or a specific one
# =============================================================================
ALL_SECTIONS=(
detect_os
section_pda_database
section_certbot
)

if [ $# -gt 0 ]; then
for section in "$@"; do
case "$section" in
detect_os|section_*)
log "Running: $section"
"$section"
;;
all)
for s in "${ALL_SECTIONS[@]}"; do
log "Running: $s"
"$s"
done
;;
*)
die "Unknown section: $section"
;;
esac
done
else
for s in "${ALL_SECTIONS[@]}"; do
log "Running: $s"
"$s"
done
fi

log "=== PowerDNS Admin setup complete ==="