Files

147 lines
6.3 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# ROS-DPI Linux 一键部署(debug18):下载二进制 → 安装 systemd 服务 → 自动启动
# 用法:curl -fsSL https://raw.githubusercontent.com/suyijun8182/ros-dpi/main/install.sh | bash
# 可用环境变量:ROS_DPI_PORT(默认 8080)、ROS_DPI_DIR(默认 /opt/ros-dpi)
# 自定义配置(DATABASE_URL、ADMIN_PASSWORD 等)写在 /etc/ros-dpi.env,重装 / 升级都不会覆盖
set -euo pipefail
REPO="suyijun8182/ros-dpi"
PORT="${ROS_DPI_PORT:-8080}"
DIR="${ROS_DPI_DIR:-/opt/ros-dpi}"
BIN="$DIR/bin/ros-dpi" # 放在安装目录下,服务账号可写:一键自更新要原地替换它
LINK="/usr/local/bin/ros-dpi"
ENV_FILE="/etc/ros-dpi.env"
SVC_USER="ros-dpi"
[ "$(id -u)" = 0 ] || { echo "请用 root 运行(sudo curl ... | sudo bash)"; exit 1; }
ARCH="$(uname -m)"
case "$ARCH" in
x86_64) ASSET="ros-dpi-linux-amd64.tar.gz" ;;
aarch64 | arm64) ASSET="ros-dpi-linux-arm64.tar.gz" ;;
*) echo "不支持的架构:$ARCH"; exit 1 ;;
esac
echo "==> 获取最新版本号"
URL="https://api.github.com/repos/${REPO}/releases/latest"
# 不用 grep -P(BusyBox / 部分发行版的 grep 不支持),sed 取 "tag_name": "vX.Y.Z"
TAG=$(curl -fsSL "$URL" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n 1 || true)
[ -n "$TAG" ] || { echo "取不到最新版本(网络问题?)"; exit 1; }
echo " 最新版本 $TAG"
echo "==> 下载 $ASSET ($TAG)"
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT
BASE="https://github.com/${REPO}/releases/download/${TAG}"
curl -fsSL "$BASE/${ASSET}" -o "$TMP/${ASSET}"
echo "==> 校验 SHA256"
curl -fsSL "$BASE/SHA256SUMS" -o "$TMP/SHA256SUMS" || { echo "该版本没有 SHA256SUMS 校验文件,为安全起见停止安装"; exit 1; }
grep -q " [*]\{0,1\}${ASSET}\$" "$TMP/SHA256SUMS" || { echo "SHA256SUMS 里没有 ${ASSET},停止安装"; exit 1; }
(cd "$TMP" && grep " [*]\{0,1\}${ASSET}\$" SHA256SUMS | sha256sum -c -) || { echo "校验失败:下载的文件已损坏或被篡改"; exit 1; }
tar -xzf "$TMP/${ASSET}" -C "$TMP"
echo "==> 安装"
REINSTALL=0
[ -f /etc/systemd/system/ros-dpi.service ] && REINSTALL=1
# 专用系统账号运行服务(0.6.22 及以前是 root):不能登录、没有家目录
if ! id "$SVC_USER" >/dev/null 2>&1; then
NOLOGIN=$(command -v nologin || echo /bin/false)
if command -v useradd >/dev/null 2>&1; then
useradd --system --user-group --no-create-home --home-dir "$DIR" --shell "$NOLOGIN" "$SVC_USER"
else # BusyBox / Alpine
addgroup -S "$SVC_USER" 2>/dev/null || true
adduser -S -D -H -h "$DIR" -s "$NOLOGIN" -G "$SVC_USER" "$SVC_USER"
fi
fi
mkdir -p "$DIR/bin" "$DIR/data"
install -m 755 "$TMP/ros-dpi" "$BIN"
# 旧版把二进制装在 /usr/local/bin(只有 root 可写):换成指向安装目录的软链接,命令行照常可用
rm -f "$LINK.bak"
ln -sfn "$BIN" "$LINK"
# 数据目录里的 SQLite 库存着 JWT 签名密钥和各类密码:只给服务账号读写(旧版装出来的是 root 的 644 文件)
chown -R "$SVC_USER:$SVC_USER" "$DIR/bin" "$DIR/data"
chmod 700 "$DIR/data"
chmod -R go-rwx "$DIR/data"
# 用户配置单独放在 EnvironmentFile:只在不存在时创建(全是注释示例),重装 / 升级都不覆盖
NEW_ENV=0
if [ ! -f "$ENV_FILE" ]; then
NEW_ENV=1
cat > "$ENV_FILE" <<'ENVF'
# ROS-DPI 自定义配置:取消注释并修改后执行 systemctl restart ros-dpi
# 本文件不会被 install.sh 覆盖;端口和数据目录由服务文件给出,这里设置会覆盖它们
#
# 用 MySQL 代替默认 SQLite:
# DATABASE_URL=mysql+pymysql://rosdpi:密码@127.0.0.1:3306/rosdpi?charset=utf8mb4
# 管理员 admin 的初始密码(强烈建议设置;留空则首次打开网页时设置):
# ADMIN_PASSWORD=
# 内网网段(之后也可在 系统设置 → 网络 里改):
# LAN_CIDRS=192.168.88.0/24
# RouterOS 只读 API(可选):
# ROS_URL=https://192.168.88.1
# ROS_USER=
# ROS_PASSWORD=
ENVF
# 0.6.21 及以前的配置写在服务文件里(Environment=DATABASE_URL=…):搬进来,否则重装后会退回 SQLite,看起来像数据全丢了
if [ "$REINSTALL" = 1 ]; then
grep '^Environment=' /etc/systemd/system/ros-dpi.service \
| grep -v -e '^Environment="\{0,1\}HTTP_PORT=' -e '^Environment="\{0,1\}DATA_DIR=' \
| sed -e 's/^Environment=//' -e 's/^"\(.*\)"$/\1/' >> "$ENV_FILE" || true
fi
fi
chmod 600 "$ENV_FILE"
# 以专用账号运行。一键自更新只需要写 $DIR/bin,重启靠进程退出后 Restart=always 拉起,不需要 systemctl 权限;
# 环境文件由 systemd 以 root 读取,服务账号本身读不到(chmod 600 root)
cat > /etc/systemd/system/ros-dpi.service <<UNIT
[Unit]
Description=ROS-DPI 终端流量与应用统计
After=network-online.target
Wants=network-online.target
[Service]
User=$SVC_USER
Group=$SVC_USER
WorkingDirectory=$DIR
Environment=HTTP_PORT=$PORT
Environment=DATA_DIR=$DIR/data
EnvironmentFile=-$ENV_FILE
ExecStart=$BIN
Restart=always
RestartSec=3
UMask=0077
# Web 端口改成 1024 以下(如 80)时需要绑定特权端口的能力;除此之外不给任何能力
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectHome=yes
ProtectSystem=strict
ReadWritePaths=$DIR/bin $DIR/data
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictSUIDSGID=yes
LockPersonality=yes
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload
systemctl enable ros-dpi >/dev/null 2>&1
# 重装 / 升级:restart 让新二进制和新服务文件立即生效(enable --now 对已运行的服务不会重启)
if [ "$REINSTALL" = 1 ]; then systemctl restart ros-dpi; else systemctl start ros-dpi; fi
sleep 2
systemctl is-active ros-dpi >/dev/null && STATE="运行中" || STATE="启动失败(journalctl -u ros-dpi 查看)"
IP=$(hostname -I 2>/dev/null | awk '{print $1}')
echo
echo "==> 完成:$STATE"
echo " 浏览器打开 http://${IP:-本机IP}:$PORT"
echo " 数据目录 $DIR/data(默认 SQLite,想用 MySQL 在 $ENV_FILE 里设 DATABASE_URL 后 systemctl restart ros-dpi)"
echo " 建议在 $ENV_FILE 里设置 ADMIN_PASSWORD,或立即打开网页设置管理员密码"
echo " 流量采集:RouterOS 的 Traffic-Flow(udp/2055) 与 TZSP(udp/37008) 指到本机地址"