Files
wild-cloud/bin/setup-systemd-resolved-dns
2025-04-27 14:57:00 -07:00

211 lines
7.1 KiB
Bash
Executable File

#!/bin/bash
# Set up error handling
set -e
# Define colors for better readability
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# Load environment variables
if [ -f "$(dirname "$0")/../load-env.sh" ]; then
echo -e "${YELLOW}Loading environment variables...${NC}"
source "$(dirname "$0")/../load-env.sh"
fi
# Get cluster IP
echo -e "${YELLOW}Getting cluster IP address...${NC}"
CLUSTER_IP=$(kubectl get -n kube-system service traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
if [ -z "$CLUSTER_IP" ]; then
echo -e "${RED}Failed to get cluster IP. Is Traefik running?${NC}"
exit 1
fi
echo -e "${YELLOW}Using cluster IP: ${CLUSTER_IP}${NC}"
# Domain settings
DOMAIN="cloud.payne.io"
INTERNAL_DOMAIN="in.${DOMAIN}"
DASHBOARD_DOMAIN="kubernetes-dashboard.${INTERNAL_DOMAIN}"
echo -e "${BLUE}=== Setting up Split DNS with systemd-resolved ===${NC}"
echo -e "${YELLOW}Internal Domain: ${INTERNAL_DOMAIN}${NC}"
echo -e "${YELLOW}Dashboard Domain: ${DASHBOARD_DOMAIN}${NC}"
echo
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}This script must be run as root to configure systemd-resolved.${NC}"
echo -e "${YELLOW}Please run: sudo $0${NC}"
exit 1
fi
# Create systemd-resolved configuration directory if it doesn't exist
echo -e "${YELLOW}Creating systemd-resolved configuration directory...${NC}"
mkdir -p /etc/systemd/resolved.conf.d/
# Create the configuration file for split DNS
echo -e "${YELLOW}Creating split DNS configuration...${NC}"
cat > /etc/systemd/resolved.conf.d/split-dns.conf << EOF
[Resolve]
# Use Google DNS servers as fallback
FallbackDNS=8.8.8.8 8.8.4.4
# Define our domain for special handling
Domains=~${INTERNAL_DOMAIN}
# Enable split DNS
DNSStubListenerExtra=${CLUSTER_IP}
EOF
# Create a static host entry for the dashboard domain
echo -e "${YELLOW}Creating static address mapping for ${DASHBOARD_DOMAIN}...${NC}"
mkdir -p /etc/systemd/resolved.conf.d/
cat > /etc/systemd/resolved.conf.d/static-domains.conf << EOF
[Resolve]
# Map our dashboard domain to the cluster IP
$(echo "${DASHBOARD_DOMAIN} ${CLUSTER_IP}" | awk '{print "DNS=" $2 "#" $1}')
EOF
# Restart systemd-resolved
echo -e "${YELLOW}Restarting systemd-resolved...${NC}"
systemctl restart systemd-resolved
# Remove immutable flag from resolv.conf if set
if lsattr /etc/resolv.conf 2>/dev/null | grep -q 'i'; then
echo -e "${YELLOW}Removing immutable flag from /etc/resolv.conf...${NC}"
chattr -i /etc/resolv.conf
fi
# Configure resolv.conf to use systemd-resolved
echo -e "${YELLOW}Configuring /etc/resolv.conf to use systemd-resolved...${NC}"
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
# Now for the Kubernetes parts
echo -e "${YELLOW}Setting up Kubernetes components...${NC}"
# Get email for Let's Encrypt
echo -e "${YELLOW}Please enter an email address for Let's Encrypt registration:${NC}"
read -p "Email: " EMAIL_ADDRESS
# Ensure cert-manager namespace exists
kubectl get namespace cert-manager >/dev/null 2>&1 || kubectl create namespace cert-manager
# Install cert-manager if needed
if ! kubectl get deployment -n cert-manager cert-manager >/dev/null 2>&1; then
echo -e "${YELLOW}Installing cert-manager...${NC}"
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm upgrade --install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--set installCRDs=true
# Wait for cert-manager to be ready
echo -e "${YELLOW}Waiting for cert-manager to be ready (this may take a minute)...${NC}"
sleep 30
kubectl wait --for=condition=available --timeout=300s deployment/cert-manager -n cert-manager
kubectl wait --for=condition=available --timeout=300s deployment/cert-manager-webhook -n cert-manager
fi
# Ensure kubernetes-dashboard namespace exists
kubectl get namespace kubernetes-dashboard >/dev/null 2>&1 || kubectl create namespace kubernetes-dashboard
# Install the dashboard if not already installed
if ! kubectl get deployment -n kubernetes-dashboard kubernetes-dashboard >/dev/null 2>&1; then
echo -e "${YELLOW}Installing Kubernetes Dashboard...${NC}"
"$(dirname "$0")/install-simple-dashboard"
fi
# Create a ClusterIssuer for Let's Encrypt
echo -e "${YELLOW}Setting up Let's Encrypt ClusterIssuer...${NC}"
cat << EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ${EMAIL_ADDRESS}
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: traefik
EOF
# Check dashboard service name and port
echo -e "${YELLOW}Checking kubernetes-dashboard service...${NC}"
DASHBOARD_SERVICE=$(kubectl get svc -n kubernetes-dashboard -o name | grep kubernetes-dashboard | grep -v metrics-scraper | grep -v api | grep -v auth | head -1)
if [ -z "$DASHBOARD_SERVICE" ]; then
echo -e "${RED}Kubernetes Dashboard service not found. Please check your installation.${NC}"
exit 1
fi
# Get the service name without the "service/" prefix
DASHBOARD_SERVICE_NAME=$(echo $DASHBOARD_SERVICE | cut -d'/' -f2)
echo -e "${YELLOW}Found dashboard service: ${DASHBOARD_SERVICE_NAME}${NC}"
# Get the service port
DASHBOARD_PORT=$(kubectl get svc $DASHBOARD_SERVICE_NAME -n kubernetes-dashboard -o jsonpath='{.spec.ports[0].port}')
echo -e "${YELLOW}Dashboard port: ${DASHBOARD_PORT}${NC}"
# Create an Ingress with TLS
echo -e "${YELLOW}Creating ingress with TLS for ${DASHBOARD_DOMAIN}...${NC}"
cat << EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubernetes-dashboard
namespace: kubernetes-dashboard
annotations:
kubernetes.io/ingress.class: traefik
cert-manager.io/cluster-issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/service.serversscheme: https
traefik.ingress.kubernetes.io/service.serverstransport.insecureskipverify: "true"
spec:
tls:
- hosts:
- ${DASHBOARD_DOMAIN}
secretName: kubernetes-dashboard-tls
rules:
- host: ${DASHBOARD_DOMAIN}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ${DASHBOARD_SERVICE_NAME}
port:
number: ${DASHBOARD_PORT}
EOF
echo
echo -e "${GREEN}=== Split DNS Setup Complete! ===${NC}"
echo
echo -e "${YELLOW}Your Kubernetes Dashboard will be available at:${NC}"
echo -e "${BLUE}https://${DASHBOARD_DOMAIN}${NC}"
echo
echo -e "${YELLOW}Key points:${NC}"
echo "1. systemd-resolved is now configured to resolve ${INTERNAL_DOMAIN} domains locally"
echo "2. The dashboard domain ${DASHBOARD_DOMAIN} is mapped to ${CLUSTER_IP}"
echo "3. Let's Encrypt will issue a valid certificate for secure HTTPS (may take a few minutes)"
echo "4. External users cannot access these domains (special DNS configuration required)"
echo
echo -e "${YELLOW}To test the DNS resolution:${NC}"
echo -e "${BLUE}nslookup ${DASHBOARD_DOMAIN}${NC}"
echo
echo -e "${YELLOW}To verify systemd-resolved configuration:${NC}"
echo -e "${BLUE}resolvectl status${NC}"
echo
echo -e "${YELLOW}Certificate status:${NC}"
echo -e "${BLUE}kubectl get certificate -n kubernetes-dashboard${NC}"
echo