Skip to content

Commit eb905f8

Browse files
committed
feat: add curl|sh installer script for OpenWrt
Detects the target architecture from OPENWRT_ARCH (falling back to uname -m plus a hexdump ELF endianness probe for MIPS), downloads the latest release binary, and installs a procd init script and a sample config.yaml.example defaulting to the builtin opendht plugin. Defaults to the -ca variant since OpenWrt images usually ship without a CA bundle. sh -s -- uninstall reverses everything but keeps the live config unless STUNMESH_PURGE=1. Signed-off-by: Date Huang <tjjh89017@hotmail.com>
1 parent b9dfdc4 commit eb905f8

1 file changed

Lines changed: 186 additions & 0 deletions

File tree

scripts/openwrt-install.sh

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
#!/bin/sh
2+
# stunmesh-go installer for OpenWrt.
3+
#
4+
# Usage (on the router):
5+
# wget -qO- https://raw.githubusercontent.com/tjjh89017/stunmesh-go/main/scripts/openwrt-install.sh | sh
6+
# curl -fsSL https://raw.githubusercontent.com/tjjh89017/stunmesh-go/main/scripts/openwrt-install.sh | sh
7+
#
8+
# Uninstall:
9+
# wget -qO- https://raw.githubusercontent.com/tjjh89017/stunmesh-go/main/scripts/openwrt-install.sh | sh -s -- uninstall
10+
#
11+
# Overrides via environment:
12+
# STUNMESH_VERSION=v1.2.3 install a specific release tag (default: latest)
13+
# STUNMESH_ARCH=mipsle skip architecture detection
14+
# STUNMESH_NO_CA=1 install the plain binary instead of the -ca one
15+
# (the -ca variant embeds the Mozilla CA bundle, so
16+
# TLS works without the ca-bundle package)
17+
# STUNMESH_BIN_DIR=/usr/bin install directory for the binary
18+
# STUNMESH_PURGE=1 uninstall only: also delete /etc/stunmesh
19+
# including the live config
20+
21+
set -eu
22+
23+
REPO="tjjh89017/stunmesh-go"
24+
BIN_DIR="${STUNMESH_BIN_DIR:-/usr/bin}"
25+
BIN_PATH="$BIN_DIR/stunmesh-go"
26+
INIT_PATH="/etc/init.d/stunmesh"
27+
CONFIG_DIR="/etc/stunmesh"
28+
29+
log() { echo "stunmesh-install: $*"; }
30+
die() { echo "stunmesh-install: error: $*" >&2; exit 1; }
31+
32+
# curl if available, otherwise wget (uclient-fetch on OpenWrt).
33+
if command -v curl >/dev/null 2>&1; then
34+
fetch() { curl -fsSL -o "$2" "$1"; }
35+
elif command -v wget >/dev/null 2>&1; then
36+
fetch() { wget -q -O "$2" "$1"; }
37+
else
38+
die "neither curl nor wget found"
39+
fi
40+
41+
detect_arch() {
42+
# OPENWRT_ARCH (e.g. mips_24kc, mipsel_24kc, aarch64_cortex-a53,
43+
# arm_cortex-a7_neon-vfpv4, x86_64) distinguishes MIPS endianness,
44+
# which uname -m does not.
45+
openwrt_arch=""
46+
[ -r /etc/os-release ] && openwrt_arch="$(. /etc/os-release 2>/dev/null; echo "${OPENWRT_ARCH:-}")"
47+
[ -n "$openwrt_arch" ] || openwrt_arch="$(uname -m)"
48+
49+
case "$openwrt_arch" in
50+
x86_64*) echo amd64 ;;
51+
aarch64*) echo arm64 ;;
52+
arm*) echo arm ;;
53+
mips64*) die "unsupported architecture: $openwrt_arch" ;;
54+
mipsel*) echo mipsle ;;
55+
mips*)
56+
# uname -m fallback says just "mips" for both endiannesses;
57+
# EI_DATA (byte 5) of any ELF binary settles it: 1=LE, 2=BE.
58+
# OpenWrt busybox ships hexdump but usually not od.
59+
if command -v hexdump >/dev/null 2>&1; then
60+
ei_data="$(hexdump -v -s5 -n1 -e '1/1 "%u"' /bin/sh)"
61+
elif command -v od >/dev/null 2>&1; then
62+
ei_data="$(od -An -j5 -N1 -tu1 /bin/sh | tr -d ' ')"
63+
else
64+
die "cannot probe MIPS endianness (no hexdump or od); set STUNMESH_ARCH=mips or STUNMESH_ARCH=mipsle"
65+
fi
66+
if [ "$ei_data" = "1" ]; then
67+
echo mipsle
68+
else
69+
echo mips
70+
fi
71+
;;
72+
i386|i686|x86) die "32-bit x86 is not supported by stunmesh-go releases" ;;
73+
*) die "unrecognized architecture: $openwrt_arch (set STUNMESH_ARCH to override)" ;;
74+
esac
75+
}
76+
77+
do_install() {
78+
ARCH="${STUNMESH_ARCH:-$(detect_arch)}"
79+
80+
TMP_DIR="$(mktemp -d)"
81+
trap 'rm -rf "$TMP_DIR"' EXIT INT TERM
82+
83+
VERSION="${STUNMESH_VERSION:-}"
84+
if [ -z "$VERSION" ]; then
85+
fetch "https://api.github.com/repos/$REPO/releases/latest" "$TMP_DIR/release.json" \
86+
|| die "failed to query the latest release (TLS missing? opkg install ca-bundle libustream-mbedtls, or set STUNMESH_VERSION)"
87+
VERSION="$(sed -n 's/.*"tag_name"[^"]*"\([^"]*\)".*/\1/p' "$TMP_DIR/release.json" | head -n1)"
88+
[ -n "$VERSION" ] || die "could not determine the latest release tag"
89+
fi
90+
91+
ASSET="stunmesh-linux-$ARCH"
92+
[ "${STUNMESH_NO_CA:-0}" != "0" ] || ASSET="$ASSET-ca"
93+
ASSET="$ASSET-$VERSION"
94+
URL="https://github.com/$REPO/releases/download/$VERSION/$ASSET"
95+
96+
log "installing stunmesh-go $VERSION for linux/$ARCH"
97+
log "downloading $URL"
98+
fetch "$URL" "$TMP_DIR/stunmesh-go" || die "download failed: $URL"
99+
[ -s "$TMP_DIR/stunmesh-go" ] || die "downloaded file is empty: $URL"
100+
101+
chmod 755 "$TMP_DIR/stunmesh-go"
102+
mv "$TMP_DIR/stunmesh-go" "$BIN_PATH"
103+
log "installed $BIN_PATH"
104+
105+
if [ ! -e "$INIT_PATH" ]; then
106+
cat > "$INIT_PATH" <<EOF
107+
#!/bin/sh /etc/rc.common
108+
109+
START=99
110+
USE_PROCD=1
111+
112+
start_service() {
113+
procd_open_instance
114+
procd_set_param command $BIN_PATH
115+
procd_set_param respawn
116+
procd_set_param stderr 1
117+
procd_close_instance
118+
}
119+
EOF
120+
chmod 755 "$INIT_PATH"
121+
log "installed procd init script $INIT_PATH"
122+
else
123+
log "keeping existing $INIT_PATH"
124+
fi
125+
126+
mkdir -p "$CONFIG_DIR"
127+
cat > "$CONFIG_DIR/config.yaml.example" <<'EOF'
128+
---
129+
refresh_interval: "1m"
130+
log:
131+
level: "info"
132+
interfaces:
133+
wg0:
134+
peers:
135+
"PEER_B":
136+
public_key: "<PEER_B_PUBLIC_KEY_BASE64>"
137+
plugin: dht
138+
stun:
139+
addresses: ["stun.l.google.com:19302"]
140+
plugins:
141+
dht:
142+
type: builtin
143+
name: opendht
144+
endpoints:
145+
- "https://dhtproxy2.jami.net"
146+
- "https://dhtproxy3.jami.net"
147+
EOF
148+
log "wrote sample config to $CONFIG_DIR/config.yaml.example"
149+
150+
log "done. next steps:"
151+
log " 1. cp $CONFIG_DIR/config.yaml.example $CONFIG_DIR/config.yaml and edit it"
152+
log " 2. $INIT_PATH enable"
153+
log " 3. $INIT_PATH start"
154+
}
155+
156+
do_uninstall() {
157+
if [ -e "$INIT_PATH" ]; then
158+
"$INIT_PATH" stop 2>/dev/null || true
159+
"$INIT_PATH" disable 2>/dev/null || true
160+
rm -f "$INIT_PATH"
161+
log "stopped service and removed $INIT_PATH"
162+
fi
163+
164+
if [ -e "$BIN_PATH" ]; then
165+
rm -f "$BIN_PATH"
166+
log "removed $BIN_PATH"
167+
fi
168+
169+
rm -f "$CONFIG_DIR/config.yaml.example"
170+
171+
if [ "${STUNMESH_PURGE:-0}" != "0" ]; then
172+
rm -rf "$CONFIG_DIR"
173+
log "removed $CONFIG_DIR"
174+
elif [ -d "$CONFIG_DIR" ]; then
175+
rmdir "$CONFIG_DIR" 2>/dev/null \
176+
|| log "kept $CONFIG_DIR (your config; set STUNMESH_PURGE=1 to delete it too)"
177+
fi
178+
179+
log "uninstalled"
180+
}
181+
182+
case "${1:-install}" in
183+
install) do_install ;;
184+
uninstall) do_uninstall ;;
185+
*) die "unknown command: $1 (expected install or uninstall)" ;;
186+
esac

0 commit comments

Comments
 (0)