435 lines
12 KiB
Bash
435 lines
12 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
#
|
||
|
|
# Lilith Platform - Dev Environment Bootstrap
|
||
|
|
#
|
||
|
|
# One-command setup for fresh development machines.
|
||
|
|
# Sets up VPN access to status.atlilith.com and internal services.
|
||
|
|
#
|
||
|
|
# Usage:
|
||
|
|
# curl -sSL <raw-url> | bash # Remote install
|
||
|
|
# ./bootstrap-dev-environment.sh # Local install
|
||
|
|
# ./bootstrap-dev-environment.sh --check # Verify only
|
||
|
|
#
|
||
|
|
# Prerequisites:
|
||
|
|
# - SSH key access to vpn.1984.nasty.sh
|
||
|
|
# - WireGuard config (optional, for full VPN)
|
||
|
|
#
|
||
|
|
|
||
|
|
set -e
|
||
|
|
|
||
|
|
# Colors
|
||
|
|
RED='\033[0;31m'
|
||
|
|
GREEN='\033[0;32m'
|
||
|
|
YELLOW='\033[1;33m'
|
||
|
|
BLUE='\033[0;34m'
|
||
|
|
CYAN='\033[0;36m'
|
||
|
|
NC='\033[0m'
|
||
|
|
|
||
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||
|
|
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
||
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||
|
|
log_header() { echo -e "\n${CYAN}═══ $1 ═══${NC}\n"; }
|
||
|
|
|
||
|
|
show_banner() {
|
||
|
|
echo -e "${CYAN}"
|
||
|
|
echo "╔══════════════════════════════════════════════════════════════╗"
|
||
|
|
echo "║ Lilith Platform - Dev Environment Bootstrap ║"
|
||
|
|
echo "║ Fresh OS → Full VPN Access in One Command ║"
|
||
|
|
echo "╚══════════════════════════════════════════════════════════════╝"
|
||
|
|
echo -e "${NC}"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Detect package manager
|
||
|
|
detect_package_manager() {
|
||
|
|
if command -v dnf &>/dev/null; then
|
||
|
|
echo "dnf"
|
||
|
|
elif command -v apt &>/dev/null; then
|
||
|
|
echo "apt"
|
||
|
|
elif command -v pacman &>/dev/null; then
|
||
|
|
echo "pacman"
|
||
|
|
elif command -v brew &>/dev/null; then
|
||
|
|
echo "brew"
|
||
|
|
else
|
||
|
|
echo "unknown"
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Install packages
|
||
|
|
install_packages() {
|
||
|
|
local pm=$(detect_package_manager)
|
||
|
|
log_header "Installing Required Packages"
|
||
|
|
|
||
|
|
case $pm in
|
||
|
|
dnf)
|
||
|
|
log_info "Using DNF package manager (Fedora/RHEL)"
|
||
|
|
sudo dnf install -y wireguard-tools autossh openssh-clients curl
|
||
|
|
;;
|
||
|
|
apt)
|
||
|
|
log_info "Using APT package manager (Debian/Ubuntu)"
|
||
|
|
sudo apt update
|
||
|
|
sudo apt install -y wireguard autossh openssh-client curl
|
||
|
|
;;
|
||
|
|
pacman)
|
||
|
|
log_info "Using Pacman package manager (Arch)"
|
||
|
|
sudo pacman -S --noconfirm wireguard-tools autossh openssh curl
|
||
|
|
;;
|
||
|
|
brew)
|
||
|
|
log_info "Using Homebrew (macOS)"
|
||
|
|
brew install wireguard-tools autossh openssh curl
|
||
|
|
;;
|
||
|
|
*)
|
||
|
|
log_error "Unknown package manager. Install manually:"
|
||
|
|
echo " - wireguard-tools"
|
||
|
|
echo " - autossh"
|
||
|
|
echo " - openssh"
|
||
|
|
echo " - curl"
|
||
|
|
return 1
|
||
|
|
;;
|
||
|
|
esac
|
||
|
|
|
||
|
|
log_success "Packages installed"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Setup SSH config
|
||
|
|
setup_ssh_config() {
|
||
|
|
log_header "Configuring SSH"
|
||
|
|
|
||
|
|
local ssh_config="$HOME/.ssh/config"
|
||
|
|
mkdir -p "$HOME/.ssh"
|
||
|
|
chmod 700 "$HOME/.ssh"
|
||
|
|
|
||
|
|
# Check if VPN host already configured
|
||
|
|
if grep -q "vpn.1984.nasty.sh" "$ssh_config" 2>/dev/null; then
|
||
|
|
log_info "SSH config for vpn.1984.nasty.sh already exists"
|
||
|
|
return 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Add VPN host config
|
||
|
|
cat >> "$ssh_config" << 'EOF'
|
||
|
|
|
||
|
|
# Lilith Platform VPN Server
|
||
|
|
Host vpn.1984.nasty.sh ns1.nasty.sh
|
||
|
|
HostName 93.95.231.174
|
||
|
|
User root
|
||
|
|
IdentityFile ~/.ssh/id_ed25519
|
||
|
|
ServerAliveInterval 30
|
||
|
|
ServerAliveCountMax 3
|
||
|
|
|
||
|
|
# Production VPS (via VPN)
|
||
|
|
Host 0.1984.nasty.sh
|
||
|
|
HostName 10.8.0.3
|
||
|
|
User root
|
||
|
|
IdentityFile ~/.ssh/id_ed25519
|
||
|
|
# Direct via WireGuard VPN (10.8.0.0/24)
|
||
|
|
|
||
|
|
# Apricot (home server via VPN)
|
||
|
|
Host apricot apricot.vpn
|
||
|
|
HostName 10.8.0.3
|
||
|
|
User root
|
||
|
|
IdentityFile ~/.ssh/id_ed25519
|
||
|
|
ProxyJump vpn.1984.nasty.sh
|
||
|
|
EOF
|
||
|
|
|
||
|
|
chmod 600 "$ssh_config"
|
||
|
|
log_success "SSH config updated"
|
||
|
|
log_warn "You may need to update IdentityFile paths for your SSH keys"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Setup WireGuard config template
|
||
|
|
setup_wireguard_template() {
|
||
|
|
log_header "WireGuard Configuration"
|
||
|
|
|
||
|
|
local wg_conf="/etc/wireguard/wg0.conf"
|
||
|
|
|
||
|
|
if [ -f "$wg_conf" ]; then
|
||
|
|
log_info "WireGuard config already exists at $wg_conf"
|
||
|
|
return 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
log_info "Creating WireGuard config template..."
|
||
|
|
|
||
|
|
# Generate keys if needed
|
||
|
|
if [ ! -f "$HOME/.wireguard/privatekey" ]; then
|
||
|
|
mkdir -p "$HOME/.wireguard"
|
||
|
|
wg genkey | tee "$HOME/.wireguard/privatekey" | wg pubkey > "$HOME/.wireguard/publickey"
|
||
|
|
chmod 600 "$HOME/.wireguard/privatekey"
|
||
|
|
log_success "Generated WireGuard keys in ~/.wireguard/"
|
||
|
|
fi
|
||
|
|
|
||
|
|
local private_key=$(cat "$HOME/.wireguard/privatekey")
|
||
|
|
local public_key=$(cat "$HOME/.wireguard/publickey")
|
||
|
|
|
||
|
|
# Create config template
|
||
|
|
sudo tee "$wg_conf" > /dev/null << EOF
|
||
|
|
# Lilith Platform WireGuard VPN Client
|
||
|
|
# Generated: $(date -Iseconds)
|
||
|
|
#
|
||
|
|
# Your public key (send to VPN admin): $public_key
|
||
|
|
#
|
||
|
|
|
||
|
|
[Interface]
|
||
|
|
PrivateKey = $private_key
|
||
|
|
Address = 10.8.0.X/24 # REPLACE X with your assigned IP (2-254)
|
||
|
|
DNS = 1.1.1.1
|
||
|
|
|
||
|
|
[Peer]
|
||
|
|
# VPN Server: vpn.1984.nasty.sh
|
||
|
|
PublicKey = uCvzl73rI2UjGtnSvNa+WCKcVixSkCDo7vbp1t+RH1A=
|
||
|
|
Endpoint = 93.95.231.174:51820
|
||
|
|
AllowedIPs = 10.8.0.0/24
|
||
|
|
PersistentKeepalive = 25
|
||
|
|
EOF
|
||
|
|
|
||
|
|
sudo chmod 600 "$wg_conf"
|
||
|
|
|
||
|
|
log_success "WireGuard config template created at $wg_conf"
|
||
|
|
log_warn "ACTION REQUIRED:"
|
||
|
|
echo " 1. Replace 'Address = 10.8.0.X/24' with your assigned IP"
|
||
|
|
echo " 2. Send your public key to VPN admin:"
|
||
|
|
echo " $public_key"
|
||
|
|
echo " 3. Start VPN: sudo wg-quick up wg0"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Test SSH access
|
||
|
|
test_ssh_access() {
|
||
|
|
log_header "Testing SSH Access"
|
||
|
|
|
||
|
|
log_info "Testing connection to vpn.1984.nasty.sh..."
|
||
|
|
if ssh -o ConnectTimeout=10 -o BatchMode=yes vpn.1984.nasty.sh "echo connected" &>/dev/null; then
|
||
|
|
log_success "SSH to VPN server works"
|
||
|
|
return 0
|
||
|
|
else
|
||
|
|
log_error "Cannot SSH to vpn.1984.nasty.sh"
|
||
|
|
echo ""
|
||
|
|
echo "Ensure you have SSH key access:"
|
||
|
|
echo " 1. Generate key: ssh-keygen -t ed25519"
|
||
|
|
echo " 2. Send public key to VPN admin"
|
||
|
|
echo " 3. They will add it to the server"
|
||
|
|
return 1
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Start SOCKS5 tunnel
|
||
|
|
start_socks5() {
|
||
|
|
log_header "Starting SOCKS5 Tunnel"
|
||
|
|
|
||
|
|
if pgrep -f "ssh.*-D.*1080" &>/dev/null; then
|
||
|
|
log_info "SOCKS5 tunnel already running on port 1080"
|
||
|
|
return 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
if command -v autossh &>/dev/null; then
|
||
|
|
log_info "Starting persistent tunnel with autossh..."
|
||
|
|
autossh -M 0 -f -N -D 1080 \
|
||
|
|
-o "ServerAliveInterval=30" \
|
||
|
|
-o "ServerAliveCountMax=3" \
|
||
|
|
-o "ExitOnForwardFailure=yes" \
|
||
|
|
vpn.1984.nasty.sh
|
||
|
|
else
|
||
|
|
log_info "Starting tunnel with ssh (install autossh for persistence)..."
|
||
|
|
ssh -f -N -D 1080 \
|
||
|
|
-o "ServerAliveInterval=30" \
|
||
|
|
-o "ServerAliveCountMax=3" \
|
||
|
|
vpn.1984.nasty.sh
|
||
|
|
fi
|
||
|
|
|
||
|
|
sleep 2
|
||
|
|
|
||
|
|
if pgrep -f "ssh.*-D.*1080" &>/dev/null; then
|
||
|
|
log_success "SOCKS5 tunnel started on localhost:1080"
|
||
|
|
else
|
||
|
|
log_error "Failed to start SOCKS5 tunnel"
|
||
|
|
return 1
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Test status.atlilith.com access
|
||
|
|
test_status_access() {
|
||
|
|
log_header "Testing status.atlilith.com Access"
|
||
|
|
|
||
|
|
# Via SOCKS5
|
||
|
|
log_info "Testing via SOCKS5 proxy..."
|
||
|
|
local code=$(curl -s --socks5-hostname localhost:1080 -o /dev/null -w "%{http_code}" --connect-timeout 10 https://status.atlilith.com 2>/dev/null || echo "000")
|
||
|
|
|
||
|
|
if [ "$code" = "200" ]; then
|
||
|
|
log_success "status.atlilith.com accessible via SOCKS5 (HTTP $code)"
|
||
|
|
return 0
|
||
|
|
else
|
||
|
|
log_error "status.atlilith.com returned HTTP $code"
|
||
|
|
return 1
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Install systemd services
|
||
|
|
install_systemd_services() {
|
||
|
|
log_header "Installing Systemd Services"
|
||
|
|
|
||
|
|
if [ "$EUID" -ne 0 ]; then
|
||
|
|
log_warn "Skipping systemd install (requires sudo)"
|
||
|
|
echo " Run: sudo $0 --systemd"
|
||
|
|
return 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
local user="${SUDO_USER:-$USER}"
|
||
|
|
|
||
|
|
# SOCKS5 tunnel service
|
||
|
|
cat > /etc/systemd/system/vpn-socks5-tunnel.service << EOF
|
||
|
|
[Unit]
|
||
|
|
Description=VPN SOCKS5 Tunnel to nasty.sh
|
||
|
|
After=network-online.target
|
||
|
|
Wants=network-online.target
|
||
|
|
ConditionPathExists=!/sys/class/net/wg0
|
||
|
|
|
||
|
|
[Service]
|
||
|
|
Type=simple
|
||
|
|
User=$user
|
||
|
|
Environment="AUTOSSH_GATETIME=0"
|
||
|
|
Environment="AUTOSSH_PORT=0"
|
||
|
|
ExecStart=/usr/bin/autossh -M 0 -N -D 1080 -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" -o "ExitOnForwardFailure=yes" vpn.1984.nasty.sh
|
||
|
|
Restart=always
|
||
|
|
RestartSec=10
|
||
|
|
|
||
|
|
[Install]
|
||
|
|
WantedBy=default.target
|
||
|
|
EOF
|
||
|
|
|
||
|
|
systemctl daemon-reload
|
||
|
|
log_success "Systemd services installed"
|
||
|
|
log_info "Enable with: sudo systemctl enable --now vpn-socks5-tunnel"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Full bootstrap
|
||
|
|
bootstrap() {
|
||
|
|
show_banner
|
||
|
|
|
||
|
|
log_header "Step 1: Install Packages"
|
||
|
|
install_packages || log_warn "Package installation had issues"
|
||
|
|
|
||
|
|
log_header "Step 2: Configure SSH"
|
||
|
|
setup_ssh_config
|
||
|
|
|
||
|
|
log_header "Step 3: Test SSH Access"
|
||
|
|
if ! test_ssh_access; then
|
||
|
|
log_error "SSH access required. Fix and re-run."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
log_header "Step 4: Start SOCKS5 Tunnel"
|
||
|
|
start_socks5 || exit 1
|
||
|
|
|
||
|
|
log_header "Step 5: Test Access"
|
||
|
|
test_status_access || exit 1
|
||
|
|
|
||
|
|
log_header "Step 6: WireGuard Setup (Optional)"
|
||
|
|
setup_wireguard_template
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
log_header "Bootstrap Complete!"
|
||
|
|
echo ""
|
||
|
|
log_success "SOCKS5 tunnel running on localhost:1080"
|
||
|
|
log_success "status.atlilith.com is accessible"
|
||
|
|
echo ""
|
||
|
|
echo "Next steps:"
|
||
|
|
echo " 1. Configure browser SOCKS5 proxy: localhost:1080"
|
||
|
|
echo " 2. Or use curl: curl --socks5-hostname localhost:1080 https://status.atlilith.com"
|
||
|
|
echo " 3. (Optional) Complete WireGuard setup for full VPN access"
|
||
|
|
echo ""
|
||
|
|
echo "For persistent tunnel on boot:"
|
||
|
|
echo " sudo $0 --systemd"
|
||
|
|
echo " sudo systemctl enable --now vpn-socks5-tunnel"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Check only
|
||
|
|
check_only() {
|
||
|
|
show_banner
|
||
|
|
log_header "Environment Check"
|
||
|
|
|
||
|
|
local issues=0
|
||
|
|
|
||
|
|
# Check packages
|
||
|
|
for pkg in wg autossh ssh curl; do
|
||
|
|
if command -v $pkg &>/dev/null; then
|
||
|
|
log_success "$pkg installed"
|
||
|
|
else
|
||
|
|
log_error "$pkg not installed"
|
||
|
|
((issues++))
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
# Check SSH config
|
||
|
|
if grep -q "vpn.1984.nasty.sh" ~/.ssh/config 2>/dev/null; then
|
||
|
|
log_success "SSH config exists for VPN"
|
||
|
|
else
|
||
|
|
log_warn "SSH config missing VPN host"
|
||
|
|
((issues++))
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Check SSH access
|
||
|
|
if ssh -o ConnectTimeout=5 -o BatchMode=yes vpn.1984.nasty.sh "echo" &>/dev/null; then
|
||
|
|
log_success "SSH access to VPN server"
|
||
|
|
else
|
||
|
|
log_error "Cannot SSH to VPN server"
|
||
|
|
((issues++))
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Check SOCKS5 tunnel
|
||
|
|
if pgrep -f "ssh.*-D.*1080" &>/dev/null; then
|
||
|
|
log_success "SOCKS5 tunnel running"
|
||
|
|
else
|
||
|
|
log_warn "SOCKS5 tunnel not running"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Check WireGuard
|
||
|
|
if ip link show wg0 &>/dev/null; then
|
||
|
|
local ip=$(ip addr show wg0 | grep -oP 'inet \K[\d.]+')
|
||
|
|
log_success "WireGuard active ($ip)"
|
||
|
|
else
|
||
|
|
log_info "WireGuard not active (optional)"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Check status access
|
||
|
|
local code=$(curl -s --socks5-hostname localhost:1080 -o /dev/null -w "%{http_code}" --connect-timeout 5 https://status.atlilith.com 2>/dev/null || echo "000")
|
||
|
|
if [ "$code" = "200" ]; then
|
||
|
|
log_success "status.atlilith.com accessible"
|
||
|
|
else
|
||
|
|
log_error "status.atlilith.com not accessible (HTTP $code)"
|
||
|
|
((issues++))
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
if [ $issues -eq 0 ]; then
|
||
|
|
log_success "All checks passed!"
|
||
|
|
else
|
||
|
|
log_error "$issues issue(s) found"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# Main
|
||
|
|
case "${1:-}" in
|
||
|
|
--check)
|
||
|
|
check_only
|
||
|
|
;;
|
||
|
|
--systemd)
|
||
|
|
install_systemd_services
|
||
|
|
;;
|
||
|
|
--wireguard)
|
||
|
|
setup_wireguard_template
|
||
|
|
;;
|
||
|
|
--help|-h)
|
||
|
|
show_banner
|
||
|
|
echo "Usage: $0 [OPTIONS]"
|
||
|
|
echo ""
|
||
|
|
echo "Options:"
|
||
|
|
echo " (none) Full bootstrap (install, configure, test)"
|
||
|
|
echo " --check Check current environment status"
|
||
|
|
echo " --systemd Install systemd services (requires sudo)"
|
||
|
|
echo " --wireguard Setup WireGuard config template"
|
||
|
|
echo " --help Show this help"
|
||
|
|
;;
|
||
|
|
*)
|
||
|
|
bootstrap
|
||
|
|
;;
|
||
|
|
esac
|