-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Expand file tree
/
Copy pathalgo
More file actions
executable file
·211 lines (193 loc) · 8.26 KB
/
algo
File metadata and controls
executable file
·211 lines (193 loc) · 8.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#!/usr/bin/env bash
set -e
# Track which installation method succeeded
UV_INSTALL_METHOD=""
# Function to install uv via package managers (most secure)
install_uv_via_package_manager() {
echo "Attempting to install uv via system package manager..."
if command -v brew &> /dev/null; then
echo "Using Homebrew..."
brew install uv && UV_INSTALL_METHOD="Homebrew" && return 0
elif command -v apt &> /dev/null && apt list uv 2>/dev/null | grep -q uv; then
echo "Using apt..."
sudo apt update && sudo apt install -y uv && UV_INSTALL_METHOD="apt" && return 0
elif command -v dnf &> /dev/null; then
echo "Using dnf..."
sudo dnf install -y uv 2>/dev/null && UV_INSTALL_METHOD="dnf" && return 0
elif command -v pacman &> /dev/null; then
echo "Using pacman..."
sudo pacman -S --noconfirm uv 2>/dev/null && UV_INSTALL_METHOD="pacman" && return 0
elif command -v zypper &> /dev/null; then
echo "Using zypper..."
sudo zypper install -y uv 2>/dev/null && UV_INSTALL_METHOD="zypper" && return 0
elif command -v winget &> /dev/null; then
echo "Using winget..."
winget install --id=astral-sh.uv -e && UV_INSTALL_METHOD="winget" && return 0
elif command -v scoop &> /dev/null; then
echo "Using scoop..."
scoop install uv && UV_INSTALL_METHOD="scoop" && return 0
fi
return 1
}
# Function to handle Ubuntu-specific installation alternatives
install_uv_ubuntu_alternatives() {
# Check if we're on Ubuntu
if ! command -v lsb_release &> /dev/null || [[ "$(lsb_release -si)" != "Ubuntu" ]]; then
return 1 # Not Ubuntu, skip these options
fi
echo ""
echo "Ubuntu detected. Additional trusted installation options available:"
echo ""
echo "1. pipx (official PyPI, installs ~9 packages)"
echo " Command: sudo apt install pipx && pipx install uv"
echo ""
echo "2. snap (community-maintained by Canonical employee)"
echo " Command: sudo snap install astral-uv --classic"
echo " Source: https://github.com/lengau/uv-snap"
echo ""
echo "3. Continue to official installer script download"
echo ""
while true; do
read -r -p "Choose installation method (1/2/3): " choice
case $choice in
1)
echo "Installing uv via pipx..."
if sudo apt update && sudo apt install -y pipx; then
if pipx install uv; then
# Add pipx bin directory to PATH
export PATH="$HOME/.local/bin:$PATH"
UV_INSTALL_METHOD="pipx"
return 0
fi
fi
echo "pipx installation failed, trying next option..."
;;
2)
echo "Installing uv via snap..."
if sudo snap install astral-uv --classic; then
# Snap binaries should be automatically in PATH via /snap/bin
UV_INSTALL_METHOD="snap"
return 0
fi
echo "snap installation failed, trying next option..."
;;
3)
return 1 # Continue to official installer download
;;
*)
echo "Invalid option. Please choose 1, 2, or 3."
;;
esac
done
}
# Function to install uv via download (with user consent)
install_uv_via_download() {
echo ""
echo "⚠️ SECURITY NOTICE ⚠️"
echo "uv is not available via system package managers on this system."
echo "To continue, we need to download and execute an installation script from:"
echo " https://astral.sh/uv/install.sh (Linux/macOS)"
echo " https://astral.sh/uv/install.ps1 (Windows)"
echo ""
echo "For maximum security, you can install uv manually instead:"
echo " 1. Visit: https://docs.astral.sh/uv/getting-started/installation/"
echo " 2. Download the binary for your platform from GitHub releases"
echo " 3. Verify checksums and install manually"
echo " 4. Then run: ./algo"
echo ""
read -p "Continue with script download? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Installation cancelled. Please install uv manually and retry."
exit 1
fi
echo "Downloading uv installation script..."
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "linux-gnu" && -n "${WSL_DISTRO_NAME:-}" ]] || uname -s | grep -q "MINGW\|MSYS"; then
# Windows (Git Bash/WSL/MINGW) - use versioned installer
powershell -ExecutionPolicy ByPass -c "irm https://github.com/astral-sh/uv/releases/download/0.8.5/uv-installer.ps1 | iex"
UV_INSTALL_METHOD="official installer (Windows)"
else
# macOS/Linux - use the versioned script for consistency
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/uv/releases/download/0.8.5/uv-installer.sh | sh
UV_INSTALL_METHOD="official installer"
fi
}
# Check if uv is installed, if not, install it securely
if ! command -v uv &> /dev/null; then
echo "uv (Python package manager) not found. Installing..."
# Try package managers first (most secure)
if ! install_uv_via_package_manager; then
# Try Ubuntu-specific alternatives if available
if ! install_uv_ubuntu_alternatives; then
# Fall back to download with user consent
install_uv_via_download
fi
fi
# Reload PATH to find uv (includes pipx, cargo, and snap paths)
# Note: This PATH change only affects the current shell session.
# Users may need to restart their terminal for subsequent runs.
export PATH="$HOME/.local/bin:$HOME/.cargo/bin:/snap/bin:$PATH"
# Verify installation worked
if ! command -v uv &> /dev/null; then
echo "Error: uv installation failed. Please restart your terminal and try again."
echo "Or install manually from: https://docs.astral.sh/uv/getting-started/installation/"
exit 1
fi
echo "✓ uv installed successfully via ${UV_INSTALL_METHOD}!"
fi
# Install Ansible Galaxy collections if requirements.yml exists
# This is needed for cloud providers that use collection modules (Linode, DigitalOcean, Azure, etc.)
if [ -f "requirements.yml" ]; then
uv run ansible-galaxy collection install -r requirements.yml > /dev/null 2>&1 || true
fi
# Run the appropriate playbook
case "$1" in
help|-h|--help)
echo "Usage: ./algo [COMMAND] [ANSIBLE_OPTIONS]"
echo ""
echo "Set up a personal VPN in the cloud."
echo ""
echo "Commands:"
echo " (default) Deploy a new VPN server"
echo " update-users Add or remove users on an existing server"
echo " destroy Destroy a deployed server and clean up configs"
echo " list-servers List deployed servers (JSON output)"
echo ""
echo "Configuration:"
echo " Edit config.cfg to set users, DNS, and VPN options before deploying."
echo ""
echo "Non-interactive deployment:"
echo " ./algo -e 'provider=digitalocean server_name=algo region=nyc3 do_token=TOKEN'"
echo ""
echo "Common Ansible options (passed through):"
echo " -e KEY=VALUE Set variable (bypass interactive prompts)"
echo " -v, -vvv Increase output verbosity"
echo " --skip-tags TAG Skip specific components"
echo " -t, --tags TAG Run only specific components"
echo ""
echo "Docs: https://trailofbits.github.io/algo/"
exit 0
;;
update-users)
uv run ansible-playbook users.yml "${@:2}" -t update-users ;;
destroy)
if [ -z "${2:-}" ] || [[ "$2" == -* ]]; then
echo "Usage: ./algo destroy <server-ip> [ANSIBLE_OPTIONS]"
echo ""
echo "Destroy a deployed Algo VPN server and remove local configs."
echo ""
echo "Arguments:"
echo " server-ip IP address of the server to destroy"
echo ""
echo "Examples:"
echo " ./algo destroy 188.166.66.185"
echo " ./algo destroy 52.1.2.3 -e \"region=us-east-1\""
echo " ./algo destroy 188.166.66.185 -e \"confirm_destroy=true\""
exit 1
fi
uv run ansible-playbook destroy.yml -e "server_ip=$2" "${@:3}" ;;
list-servers)
uv run python3 scripts/list_servers.py "${@:2}" ;;
*)
uv run ansible-playbook main.yml "${@}" ;;
esac