-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinstall-tailscale.sh
More file actions
266 lines (232 loc) · 8.88 KB
/
Copy pathinstall-tailscale.sh
File metadata and controls
266 lines (232 loc) · 8.88 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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
#!/bin/sh
set -eu
# All the code is wrapped in a main function that gets called at the
# bottom of the file, so that a truncated partial download doesn't end
# up executing half a script.
main() {
TAILSCALE_STABLE="$(echo $(curl -fsSL "https://pkgs.tailscale.com/stable/?mode=json&os=linux") | sed -ne 's/.*"TarballsVersion":[ ]*"\([^"]*\)".*/\1/p')"
TAILSCALE_FALLBACK_VERSION="1.96.4"
TAILSCALE_BLOCKED_ISSUE="https://github.com/jetkvm/kvm/issues/1461"
REQUESTED_VERSION=""
JETKVM_IP=""
AUTO_YES=false
CLEAN_INSTALL=false
TAILSCALE_UP_ARGS=""
# Parse command line arguments
while [ $# -gt 0 ]; do
case $1 in
-v | --version)
REQUESTED_VERSION="$2"
shift 2
;;
-y | --yes)
AUTO_YES=true
shift
;;
-c | --clean)
CLEAN_INSTALL=true
shift
;;
--)
shift
TAILSCALE_UP_ARGS="$*"
break
;;
*)
JETKVM_IP="$1"
shift
;;
esac
done
if [ -z "$JETKVM_IP" ]; then
echo "ERROR: JetKVM IP address is required"
echo ""
echo "Usage: $0 [-v|--version <TAILSCALE_VERSION>] [-y|--yes] [-c|--clean] <JETKVM_IP> [-- <tailscale_up_args>...]"
echo ""
echo "Options:"
echo " -v, --version Specify Tailscale version (defaults to current stable release)"
echo " -y, --yes Automatically answer yes to confirmation prompt"
echo " -c, --clean Delete any existing tailscale data (will cause a new machine to be created)"
echo ""
echo "Any arguments after '--' are passed directly to 'tailscale up'."
echo "See https://tailscale.com/docs/reference/tailscale-cli/up for available flags."
echo ""
echo "Examples:"
echo " $0 192.168.1.64"
echo " $0 -v 1.88.1 -y 192.168.1.64"
echo " $0 --version 1.88.1 192.168.1.64"
echo ""
echo " # Use a custom coordination server (e.g. Headscale):"
echo " $0 192.168.1.64 -- --login-server=https://headscale.example.com"
echo ""
echo " # Pass multiple tailscale up flags:"
echo " $0 192.168.1.64 -- --login-server=https://headscale.example.com --advertise-tags=tag:kvm"
echo ""
echo "Current Tailscale stable release: $TAILSCALE_STABLE"
exit 1
fi
export TAILSCALE_VERSION="${REQUESTED_VERSION:-$TAILSCALE_STABLE}"
case "$TAILSCALE_VERSION" in
1.98.*)
if [ -n "$REQUESTED_VERSION" ]; then
echo "ERROR: Tailscale $TAILSCALE_VERSION is temporarily blocked on JetKVM."
echo " See $TAILSCALE_BLOCKED_ISSUE for details."
echo " Use Tailscale $TAILSCALE_FALLBACK_VERSION or another known-good version."
exit 1
fi
echo "WARNING: Tailscale $TAILSCALE_VERSION is temporarily blocked on JetKVM."
echo " See $TAILSCALE_BLOCKED_ISSUE for details."
echo " Falling back to Tailscale $TAILSCALE_FALLBACK_VERSION."
export TAILSCALE_VERSION="$TAILSCALE_FALLBACK_VERSION"
;;
esac
# Confirmation prompt (unless auto-yes is enabled)
if [ "$AUTO_YES" = false ]; then
echo "───────────────────────────────────────────────────────────"
echo " JetKVM Tailscale Installation"
echo "───────────────────────────────────────────────────────────"
echo ""
echo " JetKVM IP: $JETKVM_IP"
echo " Tailscale Version: $TAILSCALE_VERSION"
if [ -n "$TAILSCALE_UP_ARGS" ]; then
echo " Tailscale Up Args: $TAILSCALE_UP_ARGS"
fi
echo ""
echo " Note: The device will be rebooted during installation"
echo ""
if [ "$CLEAN_INSTALL" = "true" ]; then
echo " Note: New tailscale machine will be created (clean install)"
echo ""
fi
if [ -t 0 ]; then
# stdin is a TTY
printf "Continue? [y/N]: "
read -r response
else
# stdin is NOT a TTY (e.g., curl | sh). Read from the terminal.
printf "Continue? [y/N]: " >/dev/tty
read -r response </dev/tty
fi
case "$response" in
[yY] | [yY][eE][sS])
echo ""
;;
*)
echo "Installation cancelled"
exit 0
;;
esac
else
echo "Auto-confirmation enabled, proceeding with installation..."
echo ""
fi
# Check if the JetKVM device is reachable
echo "[1/7] Checking if JetKVM device is reachable..."
if ! ping -c 3 -W 5 "$JETKVM_IP" >/dev/null 2>&1; then
echo "ERROR: JetKVM device at $JETKVM_IP is not reachable"
echo " Please verify the IP address and ensure the device is powered on and connected to the network"
exit 1
fi
echo " Device is reachable"
# Check if SSH access is available (Developer Mode enabled)
echo " Checking SSH access (Developer Mode)..."
# First, test SSH connectivity without BatchMode to get proper error messages
SSH_TEST_OUTPUT=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-o PreferredAuthentications=publickey -o PubkeyAuthentication=yes -o PasswordAuthentication=no \
root@"$JETKVM_IP" 'echo "SSH OK"' 2>&1) || SSH_EXIT_CODE=$?
if [ "${SSH_EXIT_CODE:-0}" -ne 0 ]; then
echo ""
# Check if it's a connection refused (port 22 not open - Developer Mode not enabled)
if echo "$SSH_TEST_OUTPUT" | grep -qi "connection refused\|connection timed out"; then
echo "ERROR: SSH connection refused"
echo " Most likely cause: Developer Mode is not enabled on the JetKVM device."
echo ""
echo " Follow the guide at:"
echo " https://jetkvm.com/docs/advanced-usage/developing#developer-mode"
echo ""
# Check if it's a permission denied (SSH enabled but no key configured)
elif echo "$SSH_TEST_OUTPUT" | grep -qi "permission denied\|authentication failed"; then
echo "ERROR: SSH authentication failed"
echo " Most likely cause: Developer Mode is enabled, but your SSH public key is not added."
echo ""
echo " Follow the guide at:"
echo " https://jetkvm.com/docs/advanced-usage/developing#developer-mode"
echo ""
else
echo "ERROR: SSH connection failed - unknown cause"
echo " Error details: $SSH_TEST_OUTPUT"
echo ""
echo " This may indicate Developer Mode issues. Please check the guide at:"
echo " https://jetkvm.com/docs/advanced-usage/developing#developer-mode"
echo ""
fi
exit 1
fi
echo " SSH access confirmed"
echo "[2/7] Downloading Tailscale $TAILSCALE_VERSION checksum..."
HASH=$(curl -fsSL https://pkgs.tailscale.com/stable/tailscale_"${TAILSCALE_VERSION}"_arm.tgz.sha256)
echo "[3/7] Downloading Tailscale $TAILSCALE_VERSION package..."
TMP_FILE=$(mktemp -t tailscale.XXXXXX.tgz)
curl -fSL https://pkgs.tailscale.com/stable/tailscale_"${TAILSCALE_VERSION}"_arm.tgz -o "$TMP_FILE" >/dev/null 2>&1
echo "[4/7] Verifying package integrity..."
LOCAL_HASH=$(sha256sum "$TMP_FILE" | awk '{print $1}')
if [ "$HASH" != "$LOCAL_HASH" ]; then
rm -f "$TMP_FILE"
echo "ERROR: Package verification failed!"
echo " Expected: $HASH"
echo " Got: $LOCAL_HASH"
exit 1
fi
echo " Package verification successful"
echo "[5/7] Transferring Tailscale package to JetKVM..."
ssh root@"${JETKVM_IP}" "cat > /userdata/tailscale.tgz" <"$TMP_FILE"
echo "[6/7] Installing and configuring Tailscale on JetKVM..."
ssh -o ServerAliveInterval=1 -o ServerAliveCountMax=1 \
root@"$JETKVM_IP" \
"export TAILSCALE_VERSION=$TAILSCALE_VERSION CLEAN_INSTALL=$CLEAN_INSTALL; ash -s" 2>/dev/null <<'EOF' || true
set -e
cd /userdata
if [ "$CLEAN_INSTALL" = "true" ]; then
echo " Removing old tailscale directory..."
rm -rf ./tailscale
fi
mkdir -p ./tailscale
echo " Extracting package..."
tar xf ./tailscale.tgz
# copy new tailscale files to the correct location (tailscale configure assumes this path)
cp -r ./tailscale_${TAILSCALE_VERSION}_arm/* ./tailscale/
rm -r ./tailscale_${TAILSCALE_VERSION}_arm ./tailscale.tgz
echo " Configuring Tailscale for JetKVM..."
cd ./tailscale
./tailscale configure jetkvm 2>&1 >/dev/null
sync
echo " Rebooting JetKVM device..."
# Fire the reboot asynchronously, then keep the session open
( sleep 1; reboot ) &
# Block until the kernel kills this session (i.e., only returns once SSH drops)
exec tail -f /dev/null
EOF
echo " Waiting for JetKVM to reboot and come back online..."
i=1
while [ "$i" -le 120 ]; do
echo " Checking device status... ($i/120s)"
if ssh -q -o ConnectTimeout=2 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
root@"$JETKVM_IP" 'tailscale version' >/dev/null 2>&1; then
echo " JetKVM is back online with Tailscale installed!"
break
fi
if [ "$i" -eq 120 ]; then
echo "ERROR: Timeout - JetKVM did not come back online within 2 minutes"
echo " Please check the device status manually"
exit 1
fi
i=$((i + 1))
sleep 1
done
echo "[7/7] Starting Tailscale service..."
ssh root@"$JETKVM_IP" "tailscale up $TAILSCALE_UP_ARGS"
echo ""
echo "SUCCESS: Tailscale installation completed!"
echo " Your JetKVM device is now ready to connect to your Tailscale network."
}
main "$@"