Skip to content

Instantly share code, notes, and snippets.

@Agnishom
Last active September 7, 2026 07:22
Show Gist options
  • Select an option

  • Save Agnishom/22ff62bdd56d3d5b87febf08dae752b4 to your computer and use it in GitHub Desktop.

Select an option

Save Agnishom/22ff62bdd56d3d5b87febf08dae752b4 to your computer and use it in GitHub Desktop.
Install Rathole
#!/bin/bash
set -euo pipefail
# --- Configuration ---
RATHOLE_VERSION="v0.5.0"
# ---------------------
echo "=== Rathole VPS Installation Script (Dumb Proxy Mode) ==="
if [ "$EUID" -ne 0 ]; then
echo "Error: Please run this script as root (e.g., sudo ./install-rathole.sh)"
exit 1
fi
TEMP_DIR=$(mktemp -d)
trap 'echo "Cleaning up..."; rm -rf "$TEMP_DIR"' EXIT
for cmd in wget unzip systemctl openssl awk grep useradd; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "Error: Required command '$cmd' is missing. Please install it and try again."
exit 1
fi
done
ARCH=$(uname -m)
case "$ARCH" in
x86_64) RATHOLE_ARCH="x86_64-unknown-linux-gnu" ;;
aarch64) RATHOLE_ARCH="aarch64-unknown-linux-gnu" ;;
*) echo "Error: Unsupported architecture ($ARCH)."; exit 1 ;;
esac
echo "[1/7] Downloading and extracting Rathole binary ($RATHOLE_VERSION for $ARCH)..."
DOWNLOAD_URL="https://github.com/rapiz1/rathole/releases/download/${RATHOLE_VERSION}/rathole-${RATHOLE_ARCH}.zip"
ZIP_PATH="$TEMP_DIR/rathole.zip"
if ! wget -q --show-progress -O "$ZIP_PATH" "$DOWNLOAD_URL"; then
echo "Error: Failed to download the rathole binary. Check your network or the URL."
exit 1
fi
if ! unzip -q "$ZIP_PATH" -d "$TEMP_DIR/extracted"; then
echo "Error: Failed to extract the zip file. It may be corrupted."
exit 1
fi
mv "$TEMP_DIR/extracted/rathole" /usr/local/bin/
chmod +x /usr/local/bin/rathole
echo "[2/7] Creating a dedicated unprivileged system user..."
if ! id -u rathole >/dev/null 2>&1; then
useradd --system --no-create-home --shell /usr/sbin/nologin rathole
fi
echo "[3/7] Setting up the configuration directory..."
mkdir -p /etc/rathole
chown -R rathole:rathole /etc/rathole
if [ -f /etc/rathole/server.toml ]; then
echo "[4/7] Existing configuration found. Skipping key generation to preserve client access."
else
echo "[4/7] Generating cryptographic keys and passphrase..."
KEYS=$(/usr/local/bin/rathole --genkey)
PRIVATE_KEY=$(echo "$KEYS" | grep "Private Key:" | awk '{print $3}')
PUBLIC_KEY=$(echo "$KEYS" | grep "Public Key:" | awk '{print $3}')
PASSPHRASE=$(openssl rand -hex 16)
echo "[5/7] Creating server.toml configuration..."
cat <<EOF > /etc/rathole/server.toml
[server]
bind_addr = "[::]:2333" # control channel, rathole client dials in here
default_token = "${PASSPHRASE}"
[server.transport]
type = "noise"
[server.transport.noise]
pattern = "Noise_NK_25519_ChaChaPoly_BLAKE2s"
local_private_key = "${PRIVATE_KEY}"
[server.services.caddy_http]
bind_addr = "[::]:80"
[server.services.caddy_https]
bind_addr = "[::]:443"
EOF
chown rathole:rathole /etc/rathole/server.toml
chmod 600 /etc/rathole/server.toml
echo "$PUBLIC_KEY" > /etc/rathole/public_key.txt
chown rathole:rathole /etc/rathole/public_key.txt
fi
echo "[6/7] Creating the systemd service file..."
cat <<EOF > /etc/systemd/system/rathole.service
[Unit]
Description=Rathole Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/rathole --server /etc/rathole/server.toml
User=rathole
Group=rathole
NoNewPrivileges=yes
AmbientCapabilities=CAP_NET_BIND_SERVICE
Restart=always
RestartSec=5
StartLimitIntervalSec=0
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
EOF
echo "[7/7] Reloading systemd and starting the Rathole service..."
systemctl daemon-reload
systemctl enable --now rathole
sleep 2
if systemctl is-active --quiet rathole; then
echo ""
echo "=========================================================="
echo "=== SUCCESS: Rathole is running as a Dumb Proxy! ==="
echo "=========================================================="
if [ -n "${PASSPHRASE:-}" ]; then
echo "Your VPS is now silently forwarding ports 80 and 443."
echo "Remember to open ports 80, 443, and 2333 in your VPS firewall!"
echo ""
echo "!!! IMPORTANT: SAVE THESE CLIENT CREDENTIALS !!!"
echo "Copy these into your local node's client.toml file:"
echo ""
echo "default_token = \"${PASSPHRASE}\""
echo "remote_public_key = \"${PUBLIC_KEY}\""
else
echo "Service updated successfully. Your existing client credentials"
echo "remain valid."
fi
echo "=========================================================="
echo ""
else
echo "Warning: The installation completed, but the service failed to start..."
exit 1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment