Untitled

 avatar
unknown
batchfile
7 days ago
8.2 kB
31
No Index
#!/bin/bash

# --- Configuration Variables (USER MUST EDIT THESE) ---
# !!! WARNING: HARDCODED PASSWORD!  CHANGE THIS! !!!
# It's MUCH better to use SSH key-based authentication and remove
# the --password option from pct create. See instructions below.
LXC_ID="123"  # Choose a unique container ID
LXC_TEMPLATE="local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst" # Path to your Ubuntu template
LXC_STORAGE="local-lvm"  # Your Proxmox storage name (e.g., local-lvm, local, etc.)
LXC_DISK_SIZE="8"      # Root filesystem size in GB
LXC_BRIDGE="vmbr0"     # Your Proxmox network bridge
LXC_IP="10.0.50.166/24" # Static IP address for the container
LXC_GATEWAY="10.0.50.1" # Gateway IP address
LXC_HOSTNAME="dns1"      # Hostname for the container
LXC_MEMORY="2048"      # RAM in MB
LXC_SWAP="512"       # Swap space in MB
LXC_CORES="4"        # Number of CPU cores
USERNAME="daniel"    # Non-root username
USERPASS="daniel" # Non-root user password  (CHANGE THIS!!!)
PIHOLE_IP="10.0.50.166" #Pi-hole static IP address.  Must match LXC_IP
TAILSCALE_AUTHKEY="YOUR_TAILSCALE_AUTH_KEY"  # Your Tailscale auth key (reusable, tagged)
CLOUDFLARE_API_TOKEN="YOUR_CLOUDFLARE_API_TOKEN"  # Your Cloudflare API token
DOH_DOMAIN="doh.example.com"  # Your DoH subdomain (e.g., doh.example.com)
EMAIL="your_email@example.com"  # Your email address for Let's Encrypt
UNBOUND_PORT="5335"
# --- End of User Configuration ---

# --- Input Validation ---
if [[ -z "$LXC_IP" ]]; then
    echo "ERROR: LXC_IP is not set."
    exit 1
fi

if ! [[ "$LXC_IP" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$ ]]; then
  echo "ERROR: Invalid LXC_IP format"
  exit 1
fi

if [[ -z "$LXC_GATEWAY" ]]; then
    echo "ERROR: LXC_GATEWAY is not set."
    exit 1
fi

if ! [[ "$LXC_GATEWAY" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
  echo "ERROR: Invalid LXC_GATEWAY format"
  exit 1
fi

# --- Exit on Error ---
set -e

# --- Proxmox LXC Creation ---
pct create "$LXC_ID" "$LXC_TEMPLATE" \
    --rootfs "$LXC_STORAGE:$LXC_DISK_SIZE" \
    --net0 name=eth0,bridge="$LXC_BRIDGE",ip="$LXC_IP",gw="$LXC_GATEWAY",ip6=auto \
    --hostname "$LXC_HOSTNAME" \
    --memory "$LXC_MEMORY" \
    --swap "$LXC_SWAP" \
    --cores "$LXC_CORES" \
    --unprivileged 1 \
    --password "$USERPASS"
if [[ $? -ne 0 ]]; then
    echo "ERROR: pct create failed."
    exit 1
fi

pct start "$LXC_ID"

# --- Install expect (needed for automating Pi-hole install) ---
apt-get update
apt-get install -y expect

# --- Helper Function to Run Commands Inside the Container ---
run_in_lxc() {
    pct exec "$LXC_ID" -- bash -c "$@"
    if [[ $? -ne 0 ]]; then
      echo "ERROR: Command failed inside LXC: $@"
      exit 1
    fi
}

# --- Base System Setup (Inside the Container) ---
run_in_lxc "apt update && apt upgrade -y"
run_in_lxc "apt install -y curl wget nano git sudo apt-transport-https ca-certificates"

# Create Non-Root User
run_in_lxc "adduser --disabled-password --gecos '' $USERNAME"
run_in_lxc "echo '$USERNAME:$USERPASS' | chpasswd"
run_in_lxc "usermod -aG sudo $USERNAME"

# Configure SSH (Key-Based Authentication - you still need to copy your key manually)
run_in_lxc "mkdir -p /home/$USERNAME/.ssh"
run_in_lxc "chmod 700 /home/$USERNAME/.ssh"
run_in_lxc "touch /home/$USERNAME/.ssh/authorized_keys"
run_in_lxc "chmod 600 /home/$USERNAME/.ssh/authorized_keys"
run_in_lxc "chown -R $USERNAME:$USERNAME /home/$USERNAME/.ssh"

# SSH Configuration (disable password auth)
run_in_lxc "sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config"
run_in_lxc "sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin no/g' /etc/ssh/sshd_config"
run_in_lxc "sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config"
run_in_lxc "systemctl restart sshd"

# --- Pi-hole Installation (Automated with expect) ---
run_in_lxc "curl -sSL https://install.pi-hole.net | bash"
sleep 5

run_in_lxc << EOF
set timeout 10
expect "Do you want to continue? \[y/N] " { send "y\r" }
expect "Transform your device into a network-wide ad blocker!" { send "\r" }
expect "*static IP address*" { send "\r" }
expect "*Press any key*" { send "\r" }
expect "Choose an upstream DNS provider" { send "\r" }
expect "*Custom*" {send "6\r"}
expect "IPv4 Custom DNS Server*" {send "127.0.0.1#$UNBOUND_PORT\r"}
expect "IPv6 Custom DNS Server*" {send "\r"}
expect "Select Protocols" { send "\r" }
expect "Do you wish to install the web admin interface" {send "\r"}
expect "Do you wish to install the web server" {send "\r"}
expect "Do you want to log queries" {send "\r"}
expect "Select a privacy mode" {send "\r"}
expect "::: Done!"
EOF
sleep 5

# --- Unbound Installation and Configuration ---
run_in_lxc "apt install -y unbound"
run_in_lxc "wget https://www.internic.net/domain/named.root -O /usr/share/dns/root.hints"
run_in_lxc "cat <<EOF | tee /etc/unbound/unbound.conf.d/pi-hole.conf
server:
    verbosity: 1
    interface: 127.0.0.1
    interface: $PIHOLE_IP
    port: $UNBOUND_PORT
    do-ip4: yes
    do-ip6: no
    access-control: 127.0.0.0/8 allow
    access-control: ${LXC_IP%.*}.0/24 allow
    access-control: 0.0.0.0/0 refuse
    root-hints: \"/usr/share/dns/root.hints\"
    harden-glue: yes
    harden-dnssec-stripped: yes
    private-address: 10.0.0.0/8
    private-address: 172.16.0.0/12
    private-address: 192.168.0.0/16
    private-address: 169.254.0.0/16
    prefetch: yes
    num-threads: 2
    so-rcvbuf: 1m
EOF"
run_in_lxc "unbound-checkconf"
run_in_lxc "systemctl start unbound"
run_in_lxc "systemctl enable unbound"

# --- DNSDist Installation and Configuration ---
run_in_lxc "apt install -y dnsdist"
run_in_lxc "cat <<EOF | tee /etc/dnsdist/dnsdist.conf
addLocal('0.0.0.0:53')
addLocal('[::]:53')
addTLSLocal('0.0.0.0:853', '/etc/letsencrypt/live/$DOH_DOMAIN/fullchain.pem', '/etc/letsencrypt/live/$DOH_DOMAIN/privkey.pem')
addDOHLocal('0.0.0.0:443', '/etc/letsencrypt/live/$DOH_DOMAIN/fullchain.pem', '/etc/letsencrypt/live/$DOH_DOMAIN/privkey.pem', '/dns-query')
addConsole('127.0.0.1:5199', 'strongconsolepassword')
newServer({address='127.0.0.1:$UNBOUND_PORT', name='unbound'})
setACL({'0.0.0.0/0', '::/0'})
EOF"
run_in_lxc "systemctl enable dnsdist"
run_in_lxc "systemctl start dnsdist"

# --- Tailscale Installation and Configuration ---
run_in_lxc "curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.noarmor.gpg | tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null"
run_in_lxc "curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.tailscale-keyring.list | tee /etc/apt/sources.list.d/tailscale.list"
run_in_lxc "apt update"
run_in_lxc "apt install -y tailscale"
run_in_lxc "tailscale up --authkey=$TAILSCALE_AUTHKEY --advertise-exit-node=false --advertise-routes= --accept-dns=false"

# --- Let's Encrypt (dns01 Challenge with Cloudflare) ---
run_in_lxc "apt install -y certbot python3-certbot-dns-cloudflare"

# Create Cloudflare credentials file
run_in_lxc "mkdir -p /etc/cloudflare"
run_in_lxc "cat <<EOF | tee /etc/cloudflare/cloudflare.ini
dns_cloudflare_api_token = $CLOUDFLARE_API_TOKEN
EOF"
run_in_lxc "chmod 600 /etc/cloudflare/cloudflare.ini"

# Obtain Certificate
run_in_lxc "certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/cloudflare/cloudflare.ini \
  -d $DOH_DOMAIN \
  --agree-tos \
  -m $EMAIL \
  --non-interactive"

# --- Firewall (UFW) ---
run_in_lxc "apt install -y ufw"
run_in_lxc "ufw default deny incoming"
run_in_lxc "ufw default allow outgoing"
run_in_lxc "ufw allow ssh"
run_in_lxc "ufw allow 53/udp"
run_in_lxc "ufw allow 53/tcp"
run_in_lxc "ufw allow 443/tcp"
run_in_lxc "ufw allow 853/tcp"
run_in_lxc "ufw allow from ${LXC_IP%.*}.0/24"

# Get Tailscale port (dynamically) and allow it
TAILSCALE_PORT=$(run_in_lxc "tailscale status | grep -oP ':[0-9]+' | cut -d':' -f2")
run_in_lxc "ufw allow $TAILSCALE_PORT/udp"

run_in_lxc "ufw enable"
run_in_lxc "ufw status verbose"

echo "Setup complete!  Don't forget to:"
echo "1. Copy your SSH public key to /home/$USERNAME/.ssh/authorized_keys inside the container."
echo "2. Access Pi-hole web interface at http://$PIHOLE_IP/admin or via Tailscale IP."
echo "3. Test DoH/DoT with curl/dog."
echo "4. Check certificate expiry with openssl."
Editor is loading...
Leave a Comment