Untitled
unknown
batchfile
8 months ago
8.2 kB
279
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