Skip to content

Instantly share code, notes, and snippets.

@pcbulai
Last active October 17, 2025 07:13
Show Gist options
  • Save pcbulai/ec73e22959af9a8b469aeef2828d5614 to your computer and use it in GitHub Desktop.
Save pcbulai/ec73e22959af9a8b469aeef2828d5614 to your computer and use it in GitHub Desktop.
Mullvad Helper Script
#!/usr/bin/env bash
DRY_RUN=true # Set to false for real run
# Then wrap all pct commands:
if [ "$DRY_RUN" = false ]; then
pct create $CTID ...
else
echo "[DRY RUN] Would create: pct create $CTID ..."
fi
# Mullvad Exit Node LXC - Main Setup Script
# Run on Proxmox host: bash -c "$(curl -fsSL https://gist.githubusercontent.com/YOUR_USERNAME/GIST_ID/raw/mullvad-exit.sh)"
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
APP="Mullvad-Exit"
var_tags="vpn;mullvad;tailscale"
var_cpu="1"
var_ram="512"
var_disk="2"
var_os="debian"
var_version="12"
var_unprivileged="1"
var_tun="yes"
# URL to the install script (Gist 2)
INSTALL_SCRIPT_URL="https://gist.githubusercontent.com/pcbulai/a105d93782655135d16075519c98239c/raw/4273fa841f6ba03947e47dc01df61d32c08f8a7c/mullvad-vpn.sh"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/wireguard/mullvad.conf ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating ${APP} LXC"
apt-get update &>/dev/null
apt-get -y upgrade &>/dev/null
msg_ok "Updated ${APP} LXC"
msg_info "Updating Tailscale"
apt-get install -y tailscale &>/dev/null
msg_ok "Updated Tailscale"
exit
}
# Custom installation function
custom_install() {
msg_info "Downloading and executing installation script"
# Download and execute the install script in the container
pct exec $CTID -- bash -c "curl -fsSL $INSTALL_SCRIPT_URL | bash"
msg_ok "${APP} Installation Complete"
}
start
build_container
# Run custom installation
custom_install
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} LXC has been created!${CL}"
echo -e "\n${YW}═══════════════════════════════════════${CL}"
echo -e "${YW}Container Details:${CL}"
echo -e "${YW}═══════════════════════════════════════${CL}"
echo -e " ${DGN}CT ID:${CL} ${BL}$CTID${CL}"
echo -e " ${DGN}Hostname:${CL} ${BL}$(pct config $CTID | grep '^hostname:' | awk '{print $2}')${CL}"
echo -e " ${DGN}IP:${CL} ${BL}$(pct exec $CTID -- ip -4 addr show eth0 | grep inet | awk '{print $2}' | cut -d/ -f1)${CL}"
echo -e "\n${YW}═══════════════════════════════════════${CL}"
echo -e "${YW}Next Steps:${CL}"
echo -e "${YW}═══════════════════════════════════════${CL}\n"
echo -e "${BOLD}1.${NC} Enter the container:"
echo -e " ${BL}pct enter $CTID${CL}\n"
echo -e "${BOLD}2.${NC} Configure Mullvad:"
echo -e " ${BL}nano /etc/wireguard/mullvad.conf${CL}"
echo -e " ${DGN}Delete the template and paste your config from:${CL}"
echo -e " ${BL}https://mullvad.net/en/account/#/wireguard-config/${CL}\n"
echo -e "${BOLD}3.${NC} Run the setup:"
echo -e " ${BL}/root/complete-setup.sh${CL}"
echo -e " ${DGN}This will:${CL}"
echo -e " ${DGN}- Start Mullvad VPN${CL}"
echo -e " ${DGN}- Authenticate Tailscale (browser required)${CL}"
echo -e " ${DGN}- Configure routing${CL}\n"
echo -e "${BOLD}4.${NC} Enable exit node:"
echo -e " ${DGN}Go to:${CL} ${BL}https://login.tailscale.com/admin/machines${CL}"
echo -e " ${DGN}Find your container → Edit route settings → Enable 'Use as exit node'${CL}\n"
echo -e "${BOLD}5.${NC} Use from your devices:"
echo -e " ${BL}tailscale up --exit-node=$(pct config $CTID | grep '^hostname:' | awk '{print $2}')${CL}\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment