feat(issue-17): add Tailscale VPN setup for container remote access #21
@@ -284,6 +284,90 @@ scp -P 2222 ./local-file <username>@<host-ip>:/path/in/container
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Remote Access via Tailscale (Optional)
|
||||||
|
|
||||||
|
Tailscale provides VPN access without requiring a public IP on the host. Each container gets its own unique Tailscale IP and can be accessed from any device on your Tailscale network.
|
||||||
|
|
||||||
|
### Why Tailscale?
|
||||||
|
|
||||||
|
| | Port Forwarding | Tailscale |
|
||||||
|
|--|-----------------|-----------|
|
||||||
|
| Public IP required | Yes | No |
|
||||||
|
| Firewall config | Needed | Not needed |
|
||||||
|
| Cross-network access | Limited | Full |
|
||||||
|
| Setup complexity | Higher | Lower |
|
||||||
|
|
||||||
|
### Automated Setup
|
||||||
|
|
||||||
|
Run the Tailscale setup script inside your container:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x skills/kugetsu/scripts/tailscale-setup.sh
|
||||||
|
bash skills/kugetsu/scripts/tailscale-setup.sh <username> <device-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
- `<username>`: SSH user that will be created (defaults to current user)
|
||||||
|
- `<device-name>`: Tailscale hostname (defaults to current hostname)
|
||||||
|
|
||||||
|
### Authentication Methods
|
||||||
|
|
||||||
|
The script will prompt you to choose:
|
||||||
|
|
||||||
|
**1. AUTHKEY (Recommended for automation)**
|
||||||
|
- Pre-generate an auth key from: https://login.tailscale.com/admin/settings/keys
|
||||||
|
- Click "Generate auth key", copy the key (starts with `tskey-auth-`)
|
||||||
|
- Paste it when prompted
|
||||||
|
|
||||||
|
**2. Headless (Browser-based)**
|
||||||
|
- Script will show a login URL
|
||||||
|
- Open the URL in your browser and authenticate
|
||||||
|
- Return to complete setup
|
||||||
|
|
||||||
|
### After Setup
|
||||||
|
|
||||||
|
1. Install Tailscale on your other devices: https://tailscale.com/download
|
||||||
|
2. Log in with the same Tailscale account
|
||||||
|
3. Connect via SSH using your device name:
|
||||||
|
```bash
|
||||||
|
ssh <username>@<device-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use the Tailscale IP directly:
|
||||||
|
```bash
|
||||||
|
ssh <username>@<tailscale-ip>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verify Connection
|
||||||
|
|
||||||
|
Inside the container:
|
||||||
|
```bash
|
||||||
|
tailscale status
|
||||||
|
tailscale ip -4
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tailscale + SSH
|
||||||
|
|
||||||
|
Tailscale handles the network connection. Once connected via Tailscale, you can SSH normally and use kugetsu:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh <username>@<device-name>
|
||||||
|
kugetsu list
|
||||||
|
kugetsu start github.com/shoko/kugetsu#11 "Fix bug"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uninstall Tailscale
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl stop tailscaled
|
||||||
|
sudo systemctl disable tailscaled
|
||||||
|
sudo dnf remove tailscale # Fedora
|
||||||
|
# or
|
||||||
|
sudo apt remove tailscale # Debian/Ubuntu
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Security Notes
|
## Security Notes
|
||||||
|
|
||||||
- **Key-only authentication**: Password authentication is disabled
|
- **Key-only authentication**: Password authentication is disabled
|
||||||
|
|||||||
@@ -235,6 +235,35 @@ kugetsu continue github.com/shoko/kugetsu#14
|
|||||||
|
|
||||||
See [docs/kugetsu-setup.md](../../docs/kugetsu-setup.md) for full remote access setup including host-side port forwarding and firewall configuration.
|
See [docs/kugetsu-setup.md](../../docs/kugetsu-setup.md) for full remote access setup including host-side port forwarding and firewall configuration.
|
||||||
|
|
||||||
|
### Tailscale VPN (Alternative)
|
||||||
|
|
||||||
|
If your host does not have a public IP or you need access across different networks, Tailscale provides a VPN solution.
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- No public IP required
|
||||||
|
- Each container gets its own unique Tailscale IP
|
||||||
|
- Access from anywhere via Tailscale network
|
||||||
|
- Normal internet access still works
|
||||||
|
|
||||||
|
**Setup:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x skills/kugetsu/scripts/tailscale-setup.sh
|
||||||
|
bash skills/kugetsu/scripts/tailscale-setup.sh <username> <device-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
The script will:
|
||||||
|
1. Install Tailscale (supports Debian/Ubuntu, Fedora)
|
||||||
|
2. Start the tailscaled daemon
|
||||||
|
3. Prompt for AUTHKEY or browser-based login
|
||||||
|
4. Configure device name (defaults to current hostname)
|
||||||
|
|
||||||
|
**After Setup:**
|
||||||
|
- From any Tailscale device: `ssh <username>@<device-name>`
|
||||||
|
- Works across different networks without port forwarding
|
||||||
|
|
||||||
|
See [docs/kugetsu-setup.md](../../docs/kugetsu-setup.md) for full Tailscale setup documentation.
|
||||||
|
|
||||||
## Without kugetsu
|
## Without kugetsu
|
||||||
|
|
||||||
If kugetsu is not available, use opencode directly:
|
If kugetsu is not available, use opencode directly:
|
||||||
|
|||||||
164
skills/kugetsu/scripts/tailscale-setup.sh
Normal file
164
skills/kugetsu/scripts/tailscale-setup.sh
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
USERNAME="${1:-$(whoami)}"
|
||||||
|
HOSTNAME="${2:-$(hostname)}"
|
||||||
|
|
||||||
|
echo "=== kugetsu Tailscale Setup ==="
|
||||||
|
echo "Target user: $USERNAME"
|
||||||
|
echo "Device name: $HOSTNAME"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
detect_os() {
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
. /etc/os-release
|
||||||
|
case "$ID" in
|
||||||
|
debian|ubuntu|"noble"|"jammy"|"focal"|"bionic"|"bullseye"|"bookworm"|"trixie"|"sid")
|
||||||
|
echo "debian"
|
||||||
|
;;
|
||||||
|
fedora|rhel|centos|rocky|alma)
|
||||||
|
echo "fedora"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unknown"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
echo "unknown"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
OS_TYPE=$(detect_os)
|
||||||
|
echo "Detected OS: $OS_TYPE"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Step 1: Installing Tailscale ==="
|
||||||
|
|
||||||
|
install_tailscale() {
|
||||||
|
case "$OS_TYPE" in
|
||||||
|
debian)
|
||||||
|
echo "Installing Tailscale via apt (Debian/Ubuntu)..."
|
||||||
|
curl -fsSL https://tailscale.com/install.sh | sh
|
||||||
|
;;
|
||||||
|
fedora)
|
||||||
|
echo "Installing Tailscale via dnf (Fedora/RHEL)..."
|
||||||
|
# Add Tailscale repo
|
||||||
|
dnf config-manager --add-repo https://pkgs.tailscale.com/stable/tailscale.repo
|
||||||
|
dnf install -y tailscale
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: Unsupported OS. Please install Tailscale manually."
|
||||||
|
echo "See: https://tailscale.com/download"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
if command -v tailscale &> /dev/null; then
|
||||||
|
echo "Tailscale is already installed: $(tailscale --version)"
|
||||||
|
else
|
||||||
|
install_tailscale
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Step 2: Verify Tailscale installation ==="
|
||||||
|
if ! command -v tailscale &> /dev/null; then
|
||||||
|
echo "ERROR: Tailscale installation failed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Tailscale binary: $(which tailscale)"
|
||||||
|
echo "Tailscale version: $(tailscale --version)"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Step 3: Start tailscaled daemon ==="
|
||||||
|
systemctl enable --now tailscaled
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
if systemctl is-active --quiet tailscaled; then
|
||||||
|
echo "SUCCESS: tailscaled is running."
|
||||||
|
else
|
||||||
|
echo "ERROR: tailscaled failed to start."
|
||||||
|
echo "Debug: systemctl status tailscaled"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Step 4: Authentication ==="
|
||||||
|
|
||||||
|
auth_method() {
|
||||||
|
echo "Choose authentication method:"
|
||||||
|
echo " 1) AUTHKEY - Use a pre-generated auth key (headless/scripted)"
|
||||||
|
echo " 2) Headless - Get a login URL to click in browser"
|
||||||
|
echo ""
|
||||||
|
read -p "Enter choice [1/2]: " choice
|
||||||
|
|
||||||
|
case "$choice" in
|
||||||
|
1)
|
||||||
|
echo ""
|
||||||
|
echo "To generate an AUTHKEY:"
|
||||||
|
echo " 1. Go to: https://login.tailscale.com/admin/settings/keys"
|
||||||
|
echo " 2. Click 'Generate auth key'"
|
||||||
|
echo " 3. Copy the key (starts with 'tskey-auth-')"
|
||||||
|
echo ""
|
||||||
|
read -p "Paste your AUTHKEY (or press Enter to cancel): " AUTHKEY
|
||||||
|
|
||||||
|
if [ -z "$AUTHKEY" ]; then
|
||||||
|
echo "Cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! "$AUTHKEY" =~ ^tskey-auth ]]; then
|
||||||
|
echo "ERROR: AUTHKEY should start with 'tskey-auth-'. Please check and try again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Connecting with AUTHKEY..."
|
||||||
|
tailscale up --authkey="$AUTHKEY" --hostname="$HOSTNAME" --operator="$USERNAME"
|
||||||
|
;;
|
||||||
|
2|"")
|
||||||
|
echo ""
|
||||||
|
echo "Getting login URL..."
|
||||||
|
echo "After you click the URL and authenticate in browser, this script will continue."
|
||||||
|
echo ""
|
||||||
|
tailscale up --hostname="$HOSTNAME" --operator="$USERNAME"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Invalid choice. Please enter 1 or 2."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
auth_method
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Step 5: Verify Tailscale connection ==="
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
if tailscale status &> /dev/null; then
|
||||||
|
echo "SUCCESS: Connected to Tailscale!"
|
||||||
|
echo ""
|
||||||
|
echo "Your Tailscale IP:"
|
||||||
|
tailscale ip -4
|
||||||
|
echo ""
|
||||||
|
echo "Your Tailscale hostname: $HOSTNAME"
|
||||||
|
echo ""
|
||||||
|
echo "To connect from another Tailscale device:"
|
||||||
|
echo " ssh $USERNAME@$HOSTNAME"
|
||||||
|
echo ""
|
||||||
|
echo "Or directly via IP:"
|
||||||
|
echo " ssh $USERNAME@$(tailscale ip -4)"
|
||||||
|
else
|
||||||
|
echo "WARNING: Tailscale may not be fully connected yet."
|
||||||
|
echo "Check status with: tailscale status"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Setup Complete ==="
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " - Install Tailscale on your other devices: https://tailscale.com/download"
|
||||||
|
echo " - Add this device to your tailnet"
|
||||||
|
echo " - SSH from anywhere using: ssh $USERNAME@$HOSTNAME"
|
||||||
|
echo ""
|
||||||
Reference in New Issue
Block a user