Compare commits
8 Commits
fac2c33e05
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f26a83da3 | |||
| 6bee92ef4a | |||
| b581561a63 | |||
| 26777dbb89 | |||
| e857bdba67 | |||
| 8c27a7f5d9 | |||
| 096a8275be | |||
| 6f7fdef746 |
2
go.mod
2
go.mod
@@ -1,3 +1,3 @@
|
|||||||
module dragoncore-bridge
|
module dragoncore-bridge
|
||||||
|
|
||||||
go 1.21
|
go 1.13
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ set -euo pipefail
|
|||||||
REPO_URL="${REPO_URL:-}"
|
REPO_URL="${REPO_URL:-}"
|
||||||
BRANCH="${BRANCH:-main}"
|
BRANCH="${BRANCH:-main}"
|
||||||
PORT="${PORT:-6969}"
|
PORT="${PORT:-6969}"
|
||||||
|
PORT_SET=0
|
||||||
OPEN_FIREWALL="${OPEN_FIREWALL:-yes}"
|
OPEN_FIREWALL="${OPEN_FIREWALL:-yes}"
|
||||||
INSTALL_DIR="/opt/dragoncore-bridge"
|
INSTALL_DIR="/opt/dragoncore-bridge"
|
||||||
CONFIG_DIR="/etc/dragoncore-bridge"
|
CONFIG_DIR="/etc/dragoncore-bridge"
|
||||||
@@ -14,7 +15,7 @@ while [ $# -gt 0 ]; do
|
|||||||
case "$1" in
|
case "$1" in
|
||||||
--repo) REPO_URL="$2"; shift 2 ;;
|
--repo) REPO_URL="$2"; shift 2 ;;
|
||||||
--branch) BRANCH="$2"; shift 2 ;;
|
--branch) BRANCH="$2"; shift 2 ;;
|
||||||
--port) PORT="$2"; shift 2 ;;
|
--port) PORT="$2"; PORT_SET=1; shift 2 ;;
|
||||||
--open-firewall) OPEN_FIREWALL="$2"; shift 2 ;;
|
--open-firewall) OPEN_FIREWALL="$2"; shift 2 ;;
|
||||||
*) echo "Unknown option: $1"; exit 1 ;;
|
*) echo "Unknown option: $1"; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
@@ -28,17 +29,120 @@ fi
|
|||||||
need_cmd() { command -v "$1" >/dev/null 2>&1; }
|
need_cmd() { command -v "$1" >/dev/null 2>&1; }
|
||||||
rand_hex() { openssl rand -hex "$1"; }
|
rand_hex() { openssl rand -hex "$1"; }
|
||||||
|
|
||||||
|
extract_listen_port() {
|
||||||
|
cfg="$1"
|
||||||
|
[ -f "$cfg" ] || return 1
|
||||||
|
listen="$(grep -o '"listen"[[:space:]]*:[[:space:]]*"[^"]*"' "$cfg" | head -1 | cut -d '"' -f4 || true)"
|
||||||
|
port="${listen##*:}"
|
||||||
|
case "$port" in
|
||||||
|
''|*[!0-9]*) return 1 ;;
|
||||||
|
*) printf '%s\n' "$port" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
port_in_use() {
|
||||||
|
p="$1"
|
||||||
|
if need_cmd ss; then
|
||||||
|
ss -ltn 2>/dev/null | awk '{print $4}' | grep -Eq "[:.]${p}$"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
if need_cmd netstat; then
|
||||||
|
netstat -ltn 2>/dev/null | awk '{print $4}' | grep -Eq "[:.]${p}$"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
if need_cmd lsof; then
|
||||||
|
lsof -iTCP:"$p" -sTCP:LISTEN -Pn >/dev/null 2>&1
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
choose_free_port() {
|
||||||
|
base="$1"
|
||||||
|
case "$base" in ''|*[!0-9]*) base=6969 ;; esac
|
||||||
|
i=0
|
||||||
|
while [ "$i" -le 100 ]; do
|
||||||
|
cand=$((base + i))
|
||||||
|
if ! port_in_use "$cand"; then
|
||||||
|
printf '%s\n' "$cand"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
echo "No free TCP port found from $base to $((base + 100))." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# The bridge source is intentionally Go 1.13-compatible so old VPS images
|
||||||
|
# such as Ubuntu 20.04 can compile it with their distro package.
|
||||||
|
# If the distro Go is older than 1.13, install a known-good official Go.
|
||||||
|
GO_MIN_MAJOR=1
|
||||||
|
GO_MIN_MINOR=13
|
||||||
|
GO_VERSION="${GO_VERSION:-1.21.13}"
|
||||||
|
GO_BIN=""
|
||||||
|
|
||||||
|
go_version_ok() {
|
||||||
|
if ! need_cmd go; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
ver="$(go version 2>/dev/null | awk '{print $3}' | sed 's/^go//; s/[^0-9.].*$//')"
|
||||||
|
major="$(printf '%s' "$ver" | cut -d. -f1)"
|
||||||
|
minor="$(printf '%s' "$ver" | cut -d. -f2)"
|
||||||
|
case "$major:$minor" in
|
||||||
|
*[!0-9:]*|:*) return 1 ;;
|
||||||
|
esac
|
||||||
|
if [ "$major" -gt "$GO_MIN_MAJOR" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if [ "$major" -eq "$GO_MIN_MAJOR" ] && [ "$minor" -ge "$GO_MIN_MINOR" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
install_official_go() {
|
||||||
|
arch="$(uname -m)"
|
||||||
|
case "$arch" in
|
||||||
|
x86_64|amd64) goarch="amd64" ;;
|
||||||
|
aarch64|arm64) goarch="arm64" ;;
|
||||||
|
armv6l|armv7l) goarch="armv6l" ;;
|
||||||
|
i386|i686) goarch="386" ;;
|
||||||
|
*) echo "Unsupported CPU architecture for automatic Go install: $arch"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
url="https://go.dev/dl/go${GO_VERSION}.linux-${goarch}.tar.gz"
|
||||||
|
tmp="/tmp/go${GO_VERSION}.linux-${goarch}.tar.gz"
|
||||||
|
echo "Installing Go ${GO_VERSION} from ${url} ..."
|
||||||
|
curl -fsSL "$url" -o "$tmp"
|
||||||
|
rm -rf /usr/local/go
|
||||||
|
tar -C /usr/local -xzf "$tmp"
|
||||||
|
ln -sf /usr/local/go/bin/go /usr/local/bin/go
|
||||||
|
ln -sf /usr/local/go/bin/gofmt /usr/local/bin/gofmt
|
||||||
|
GO_BIN="/usr/local/go/bin/go"
|
||||||
|
}
|
||||||
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
if need_cmd apt-get; then
|
if need_cmd apt-get; then
|
||||||
apt-get update -y
|
apt-get update -y
|
||||||
apt-get install -y ca-certificates curl wget git openssl build-essential
|
apt-get install -y ca-certificates curl wget git openssl build-essential sqlite3 lsof iproute2
|
||||||
if ! need_cmd go; then
|
if ! need_cmd go; then
|
||||||
apt-get install -y golang-go
|
apt-get install -y golang-go || true
|
||||||
fi
|
fi
|
||||||
elif need_cmd yum; then
|
elif need_cmd yum; then
|
||||||
yum install -y ca-certificates curl wget git openssl gcc make golang
|
yum install -y ca-certificates curl wget git openssl gcc make golang sqlite lsof iproute || yum install -y ca-certificates curl wget git openssl gcc make sqlite lsof iproute
|
||||||
elif need_cmd dnf; then
|
elif need_cmd dnf; then
|
||||||
dnf install -y ca-certificates curl wget git openssl gcc make golang
|
dnf install -y ca-certificates curl wget git openssl gcc make golang sqlite lsof iproute || dnf install -y ca-certificates curl wget git openssl gcc make sqlite lsof iproute
|
||||||
|
fi
|
||||||
|
|
||||||
|
if go_version_ok; then
|
||||||
|
GO_BIN="$(command -v go)"
|
||||||
|
else
|
||||||
|
install_official_go
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! "$GO_BIN" version >/dev/null 2>&1; then
|
||||||
|
echo "Go installation failed. Cannot build dragoncore-bridge."
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$INSTALL_DIR" "$CONFIG_DIR"
|
mkdir -p "$INSTALL_DIR" "$CONFIG_DIR"
|
||||||
@@ -56,18 +160,37 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$INSTALL_DIR/src"
|
cd "$INSTALL_DIR/src"
|
||||||
go build -trimpath -ldflags "-s -w" -o "$BIN" .
|
if need_cmd systemctl; then systemctl stop dragoncore-bridge 2>/dev/null || true; fi
|
||||||
|
"$GO_BIN" build -trimpath -ldflags "-s -w" -o "$BIN" .
|
||||||
chmod 755 "$BIN"
|
chmod 755 "$BIN"
|
||||||
|
|
||||||
USER_NAME="admin"
|
USER_NAME="admin"
|
||||||
PASSWORD="$(rand_hex 10)"
|
PASSWORD="$(rand_hex 10)"
|
||||||
TOKEN="$(rand_hex 24)"
|
TOKEN="$(rand_hex 24)"
|
||||||
|
PANEL_URL=""
|
||||||
|
PANEL_SERVER_ID="0"
|
||||||
|
PANEL_SERVER_IP=""
|
||||||
|
PANEL_PUSH_INTERVAL="60"
|
||||||
|
|
||||||
if [ -f "$CONFIG_DIR/config.json" ]; then
|
if [ -f "$CONFIG_DIR/config.json" ]; then
|
||||||
echo "Existing config found: $CONFIG_DIR/config.json"
|
echo "Existing config found: $CONFIG_DIR/config.json"
|
||||||
USER_NAME="$(grep -o '"username"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_DIR/config.json" | head -1 | cut -d '"' -f4 || echo admin)"
|
USER_NAME="$(grep -o '"username"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_DIR/config.json" | head -1 | cut -d '"' -f4 || echo admin)"
|
||||||
PASSWORD="$(grep -o '"password"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_DIR/config.json" | head -1 | cut -d '"' -f4 || rand_hex 10)"
|
PASSWORD="$(grep -o '"password"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_DIR/config.json" | head -1 | cut -d '"' -f4 || rand_hex 10)"
|
||||||
TOKEN="$(grep -o '"token"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_DIR/config.json" | head -1 | cut -d '"' -f4 || rand_hex 24)"
|
TOKEN="$(grep -o '"token"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_DIR/config.json" | head -1 | cut -d '"' -f4 || rand_hex 24)"
|
||||||
|
PANEL_URL="$(grep -o '"panel_url"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_DIR/config.json" | head -1 | cut -d '"' -f4 || echo '')"
|
||||||
|
PANEL_SERVER_ID="$(grep -o '"panel_server_id"[[:space:]]*:[[:space:]]*[0-9]*' "$CONFIG_DIR/config.json" | head -1 | grep -o '[0-9]*$' || echo 0)"
|
||||||
|
PANEL_SERVER_IP="$(grep -o '"panel_server_ip"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_DIR/config.json" | head -1 | cut -d '"' -f4 || echo '')"
|
||||||
|
PANEL_PUSH_INTERVAL="$(grep -o '"panel_push_interval_seconds"[[:space:]]*:[[:space:]]*[0-9]*' "$CONFIG_DIR/config.json" | head -1 | grep -o '[0-9]*$' || echo 60)"
|
||||||
|
EXISTING_PORT="$(extract_listen_port "$CONFIG_DIR/config.json" || true)"
|
||||||
|
if [ "$PORT_SET" = "0" ] && [ -n "$EXISTING_PORT" ]; then
|
||||||
|
PORT="$EXISTING_PORT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
REQUESTED_PORT="$PORT"
|
||||||
|
PORT="$(choose_free_port "$PORT")"
|
||||||
|
if [ "$PORT" != "$REQUESTED_PORT" ]; then
|
||||||
|
echo "Port $REQUESTED_PORT is already in use. Using free port $PORT instead."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat > "$CONFIG_DIR/config.json" <<EOF
|
cat > "$CONFIG_DIR/config.json" <<EOF
|
||||||
@@ -76,7 +199,11 @@ cat > "$CONFIG_DIR/config.json" <<EOF
|
|||||||
"username": "$USER_NAME",
|
"username": "$USER_NAME",
|
||||||
"password": "$PASSWORD",
|
"password": "$PASSWORD",
|
||||||
"token": "$TOKEN",
|
"token": "$TOKEN",
|
||||||
"data_dir": "$CONFIG_DIR"
|
"data_dir": "$CONFIG_DIR",
|
||||||
|
"panel_url": "$PANEL_URL",
|
||||||
|
"panel_server_id": $PANEL_SERVER_ID,
|
||||||
|
"panel_server_ip": "$PANEL_SERVER_IP",
|
||||||
|
"panel_push_interval_seconds": $PANEL_PUSH_INTERVAL
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
chmod 600 "$CONFIG_DIR/config.json"
|
chmod 600 "$CONFIG_DIR/config.json"
|
||||||
@@ -101,6 +228,12 @@ EOF
|
|||||||
|
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable --now dragoncore-bridge
|
systemctl enable --now dragoncore-bridge
|
||||||
|
sleep 1
|
||||||
|
if ! systemctl is-active --quiet dragoncore-bridge; then
|
||||||
|
echo "dragoncore-bridge failed to start. Last logs:" >&2
|
||||||
|
journalctl -u dragoncore-bridge -n 40 --no-pager >&2 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$OPEN_FIREWALL" = "yes" ] || [ "$OPEN_FIREWALL" = "true" ] || [ "$OPEN_FIREWALL" = "1" ]; then
|
if [ "$OPEN_FIREWALL" = "yes" ] || [ "$OPEN_FIREWALL" = "true" ] || [ "$OPEN_FIREWALL" = "1" ]; then
|
||||||
if need_cmd ufw && ufw status 2>/dev/null | grep -qi "Status: active"; then
|
if need_cmd ufw && ufw status 2>/dev/null | grep -qi "Status: active"; then
|
||||||
|
|||||||
47
update_bridge.sh
Normal file
47
update_bridge.sh
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_URL="${REPO_URL:-https://git.dr2.site/penguinehis/DragonCore-Modules.git}"
|
||||||
|
BRANCH="${BRANCH:-main}"
|
||||||
|
CONFIG_DIR="/etc/dragoncore-bridge"
|
||||||
|
|
||||||
|
if [ "$(id -u)" != "0" ]; then
|
||||||
|
echo "Run as root."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
need_cmd() { command -v "$1" >/dev/null 2>&1; }
|
||||||
|
|
||||||
|
# If this updater is executed from an extracted repository, use the local files.
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd || true)"
|
||||||
|
if [ -n "$SCRIPT_DIR" ] && [ -f "$SCRIPT_DIR/install_bridge.sh" ] && [ -f "$SCRIPT_DIR/main.go" ]; then
|
||||||
|
echo "Updating DragonCore Bridge from local source..."
|
||||||
|
bash "$SCRIPT_DIR/install_bridge.sh" "$@"
|
||||||
|
exit $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
if need_cmd apt-get; then
|
||||||
|
apt-get update -y
|
||||||
|
apt-get install -y ca-certificates curl git
|
||||||
|
elif need_cmd yum; then
|
||||||
|
yum install -y ca-certificates curl git
|
||||||
|
elif need_cmd dnf; then
|
||||||
|
dnf install -y ca-certificates curl git
|
||||||
|
fi
|
||||||
|
|
||||||
|
TMP_DIR="$(mktemp -d)"
|
||||||
|
cleanup() { rm -rf "$TMP_DIR"; }
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
echo "Updating DragonCore Bridge from ${REPO_URL} (${BRANCH})..."
|
||||||
|
git clone --depth 1 --branch "$BRANCH" "$REPO_URL" "$TMP_DIR/src"
|
||||||
|
|
||||||
|
# install_bridge.sh preserves existing username/password/token and existing port
|
||||||
|
# unless --port is explicitly supplied. It also migrates accounts.json to SQLite.
|
||||||
|
bash "$TMP_DIR/src/install_bridge.sh" "$@"
|
||||||
|
|
||||||
|
if [ -f "$CONFIG_DIR/config.json" ]; then
|
||||||
|
echo
|
||||||
|
echo "Updated config: $CONFIG_DIR/config.json"
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user