diff --git a/.github/workflows/agent.yml b/.github/workflows/agent.yml new file mode 100644 index 0000000..2174294 --- /dev/null +++ b/.github/workflows/agent.yml @@ -0,0 +1,27 @@ +name: Agent release + +on: + push: + paths-ignore: + - "script/**" + - ".gitignore" + - "README.md" + - "cmd/dashboard/**" + - ".github/dashboard.yaml" + tags: + - "v*" + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v2 + if: startsWith(github.ref, 'refs/tags/') + with: + version: latest + args: release --rm-dist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/build.yml b/.github/workflows/dashboard.yml similarity index 65% rename from .github/workflows/build.yml rename to .github/workflows/dashboard.yml index 44a72c0..7c64f5a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/dashboard.yml @@ -1,6 +1,13 @@ -name: Build Docker Image +name: Build Dashboard Image -on: [push] +on: + push: + paths-ignore: + - "script/**" + - ".gitignore" + - "README.md" + - "cmd/agent/**" + - ".github/agent.yaml" jobs: deploy: @@ -11,9 +18,7 @@ jobs: - name: Log into registry run: echo "${{ secrets.CR_PAT }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin - - name: docker + - name: Build and push dasbboard image run: | - docker build -t ghcr.io/${{ github.repository_owner }}/nezha-agent -f Dockerfile.agent . docker build -t ghcr.io/${{ github.repository_owner }}/nezha-dashboard -f Dockerfile.dashboard . - docker push ghcr.io/${{ github.repository_owner }}/nezha-agent docker push ghcr.io/${{ github.repository_owner }}/nezha-dashboard diff --git a/.gitignore b/.gitignore index bb99604..0f175e8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,6 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out -.DS_Store /data -/release \ No newline at end of file +/dist +.DS_Store diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..1c1fb16 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,22 @@ +before: + hooks: + - go mod tidy -v +builds: + - id: nezha-agent + env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin + main: ./cmd/agent +checksum: + name_template: "checksums.txt" +snapshot: + name_template: "{{ .Tag }}-next" +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" diff --git a/Dockerfile.agent b/Dockerfile.agent deleted file mode 100644 index e14dc88..0000000 --- a/Dockerfile.agent +++ /dev/null @@ -1,27 +0,0 @@ -FROM golang:alpine AS binarybuilder -RUN apk --no-cache --no-progress add \ - gcc git musl-dev -WORKDIR /agent -COPY . . -RUN cd cmd/agent && go build -o app -ldflags="-s -w -X github.com/naiba/nezha/service/dao.Version=$(git rev-parse HEAD)" - -FROM alpine:latest -RUN apk --no-cache --no-progress add \ - ca-certificates \ - tzdata -WORKDIR /agent -COPY --from=binarybuilder /agent/cmd/agent/app ./app - -ENV HOST_PROC=/agent/host/proc \ - HOST_SYS=/agent/host/sys \ - HOST_ETC=/agent/host/etc \ - HOST_VAR=/agent/host/var \ - HOST_RUN=/agent/host/run \ - HOST_DEV=/agent/host/dev \ - DEBUG=false - -ENV [ID, SECRET, SERVER] - -VOLUME ["/agent/host/proc", "/agent/host/sys", "/agent/host/etc", "/agent/host/var", "/agent/host/run", "/agent/host/dev"] - -CMD /agent/app -s $SERVER -i $ID -p $SECRET -d $DEBUG diff --git a/README.md b/README.md index 5311c54..7ce5886 100644 --- a/README.md +++ b/README.md @@ -11,148 +11,18 @@ C/S 采用 gRPC 通信,客户端通过添加主机生成的单独 Token 上报 - 首次连接:上报基本信息(系统、CPU基本信息),后面管理员可从客户端主动拉取更新。 - 监控上报:每隔 3s 向服务器上报系统信息 -## 部署指南 +## 一键脚本 -### 控制面板 + 节点一键启动 +WIP,尚未完成,还在做监控端安装 -1. 创建一个文件夹 +```shell +curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install.sh -o nezha.sh && chmod +x nezha.sh +sudo nezha.sh +``` +## FAQ - ```shell - mkdir nezha - ``` +- 反代后打开面板提示「实时通道断开」:[https://www.google.com/search?q=nginx+%E5%8F%8D%E4%BB%A3+websocket](Nginx 反代 WebSocket) -2. 进入文件夹并创建 `docker-compose.yaml` 文件 +## 社区文章 - ```shell - cd nezha && nano docker-compose.yaml - ``` - - 将以下内容粘贴进去,注意查看 `environment` 中的几项配置。ID、密钥是在管理面板添加服务器之后才有的,不是你的 GitHub ID。 - - ```yaml - version: "3.3" - - services: - dashboard: - image: ghcr.io/naiba/nezha-dashboard - restart: always - volumes: - - ./data:/dashboard/data - ports: - - 8008:80 - - 5555:5555 - agent: - image: ghcr.io/naiba/nezha-agent - restart: always - depends_on: - - dashboard - environment: - - ID=1 #节点ID,启动后在管理后台添加后显示 - - SECRET=secret #节点密钥,启动后在管理后台添加后显示 - - SERVER=ops.naibahq.com:5555 #服务器RPC端口 - - DEBUG=false #服务器地址使用IP时设置为true - volumes: - - /proc:/agent/host/proc:ro - - /sys:/agent/host/sys:ro - - /etc:/agent/host/etc:ro - - /var:/agent/host/var:ro - - /run:/agent/host/run:ro - - /dev:/agent/host/dev:ro - ``` - -3. 创建控制面板配置文件 - - ```shell - mkdir data && nano config.yaml - ``` - - 将以下内容粘贴进去 - - ```yaml - debug: true - httpport: 80 - github: - admin: # 多管理员 - - 1 #管理员 GitHub ID,复制自己GitHub头像图片地址,/[ID].png - - 2 - clientid: GitHub Oauth App clientID # 在 https://github.com/settings/developers 创建,无需审核 Callback 填 http(s)://域名或IP/oauth2/callback - clientsecret: client secret - site: - brand: 站点标题 - cookiename: tulong #浏览器 Cookie 字段名,可不改 - ``` - -4. 启动管理面板 - - ```shell - docker-compose up -d - ``` - -5. 更新,可以使用下方的命令,或者配置 **WatchTower** 自动更新所有容器 - - ```shell - docker-compose pull && docker-compose up -d - ``` - -6. *agent* 配置:登入你的管理面板添加服务器,把节点的 ID、密钥 编辑进 `docker-compose.yaml` 文件中,然后重启 agent。 - - ```shell - docker-compose restart agent - ``` - -### 单节点部署 - -1. 登入你的管理面板添加服务器,把节点的 ID、密钥 记录下来,下面会用到。 - -2. 创建一个文件夹 - - ```shell - mkdir nezha - ``` - -3. 进入文件夹并创建 `docker-compose.yaml` 文件,将 ID、密钥 编辑进去。 - - ```shell - cd nezha && nano docker-compose.yaml - ``` - - 将以下内容粘贴进去,ID、密钥是在管理面板添加服务器之后才有的,不是你的 GitHub ID。 - - ```yaml - version: "3.3" - - services: - agent: - image: ghcr.io/naiba/nezha-agent - restart: always - environment: - - ID=1 #节点ID,启动后在管理后台添加后显示 - - SECRET=secret #节点密钥,启动后在管理后台添加后显示 - - SERVER=ops.naibahq.com:5555 #服务器RPC端口 - - DEBUG=false #服务器地址使用IP时设置为true - volumes: - - /proc:/agent/host/proc:ro - - /sys:/agent/host/sys:ro - - /etc:/agent/host/etc:ro - - /var:/agent/host/var:ro - - /run:/agent/host/run:ro - - /dev:/agent/host/dev:ro - ``` - -4. 启动 - - ```shell - docker-compose up -d - ``` - -5. 更新,可以使用下方的命令,或者配置 **WatchTower** 自动更新所有容器 - - ```shell - docker-compose pull && docker-compose up -d - ``` - -**Windows、MacOS、Andorid 等也可监控,需要参照教程文章里面的文章编译 agent 并启动。** - -## 教程文章 - - - [哪吒面板:小鸡们的最佳探针](https://www.zhujizixun.com/2843.html) *(已过时)* \ No newline at end of file + - [哪吒面板:小鸡们的最佳探针](https://www.zhujizixun.com/2843.html) *(已过时)* diff --git a/cmd/dashboard/controller/oauth2.go b/cmd/dashboard/controller/oauth2.go index e6cea50..15e7779 100644 --- a/cmd/dashboard/controller/oauth2.go +++ b/cmd/dashboard/controller/oauth2.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "strings" "github.com/naiba/com" @@ -68,8 +69,8 @@ func (oa *oauth2controller) callback(c *gin.Context) { } var isAdmin bool if gu.GetID() > 0 { - for i := 0; i < len(dao.Conf.GitHub.Admin); i++ { - if gu.GetID() == dao.Conf.GitHub.Admin[i] { + for _, admin := range strings.Split(dao.Conf.GitHub.Admin, ",") { + if fmt.Sprintf("%d", gu.GetID()) == admin { isAdmin = true break } diff --git a/model/config.go b/model/config.go index d1d578c..eac9476 100644 --- a/model/config.go +++ b/model/config.go @@ -15,7 +15,7 @@ type Config struct { CookieName string // 浏览器 Cookie 名称 } GitHub struct { - Admin []int64 // 管理员ID列表 + Admin string // 管理员ID列表 ClientID string ClientSecret string } diff --git a/script/build.sh b/script/build.sh deleted file mode 100755 index 79db598..0000000 --- a/script/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -# !/bin/sh -GOOS=linux CGO_ENABLED=1 GOARCH=amd64 go build -o ./release/nezha-$1 cmd/$1/main.go \ No newline at end of file diff --git a/script/config.yaml b/script/config.yaml new file mode 100644 index 0000000..78fe381 --- /dev/null +++ b/script/config.yaml @@ -0,0 +1,9 @@ +debug: true +httpport: 80 +github: + admin: "nz_admin_ids" #管理员 GitHub ID,复制自己GitHub头像图片地址,/[ID].png 多个用英文逗号隔开 + clientid: "nz_github_oauth_client_id" # 在 https://github.com/settings/developers 创建,无需审核 Callback 填 http(s)://域名或IP/oauth2/callback + clientsecret: "nz_github_oauth_client_secret" +site: + brand: "nz_site_title" + cookiename: "nezha-dashboard" #浏览器 Cookie 字段名,可不改 diff --git a/script/docker-compose.yaml b/script/docker-compose.yaml new file mode 100644 index 0000000..e6cfa22 --- /dev/null +++ b/script/docker-compose.yaml @@ -0,0 +1,11 @@ +version: "3.3" + +services: + dashboard: + image: ghcr.io/naiba/nezha-dashboard + restart: always + volumes: + - ./data:/dashboard/data + ports: + - 8008:80 + - 5555:5555 diff --git a/script/install.sh b/script/install.sh new file mode 100755 index 0000000..0d49b85 --- /dev/null +++ b/script/install.sh @@ -0,0 +1,364 @@ +#!/bin/bash + +#====================================================== +# System Required: CentOS 7+ / Debian 8+ / Ubuntu 16+ +# Description: 哪吒面板安装脚本 +# Github: https://github.com/naiba/nezha +#====================================================== + +NZ_BASE_PATH="/opt/nezha" +NZ_DASHBOARD_PATH="${NZ_BASE_PATH}/dashboard" +NZ_AGENT_PATH="${NZ_BASE_PATH}/agent" +NZ_VERSION="v1.0.0" + +red='\033[0;31m' +green='\033[0;32m' +yellow='\033[0;33m' +plain='\033[0m' + +os_version="" +os_arch="" + +pre_check() { + # check root + [[ $EUID -ne 0 ]] && echo -e "${red}错误: ${plain} 必须使用root用户运行此脚本!\n" && exit 1 + + # check os + if [[ -f /etc/redhat-release ]]; then + release="centos" + elif cat /etc/issue | grep -Eqi "debian"; then + release="debian" + elif cat /etc/issue | grep -Eqi "ubuntu"; then + release="ubuntu" + elif cat /etc/issue | grep -Eqi "centos|red hat|redhat"; then + release="centos" + elif cat /proc/version | grep -Eqi "debian"; then + release="debian" + elif cat /proc/version | grep -Eqi "ubuntu"; then + release="ubuntu" + elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then + release="centos" + else + echo -e "${red}未检测到系统版本,请联系脚本作者!${plain}\n" && exit 1 + fi + + # os version + if [[ -f /etc/os-release ]]; then + os_version=$(awk -F'[= ."]' '/VERSION_ID/{print $3}' /etc/os-release) + fi + if [[ -z "$os_version" && -f /etc/lsb-release ]]; then + os_version=$(awk -F'[= ."]+' '/DISTRIB_RELEASE/{print $2}' /etc/lsb-release) + fi + + if [[ x"${release}" == x"centos" ]]; then + if [[ ${os_version} -le 6 ]]; then + echo -e "${red}请使用 CentOS 7 或更高版本的系统!${plain}\n" && exit 1 + fi + elif [[ x"${release}" == x"ubuntu" ]]; then + if [[ ${os_version} -lt 16 ]]; then + echo -e "${red}请使用 Ubuntu 16 或更高版本的系统!${plain}\n" && exit 1 + fi + elif [[ x"${release}" == x"debian" ]]; then + if [[ ${os_version} -lt 8 ]]; then + echo -e "${red}请使用 Debian 8 或更高版本的系统!${plain}\n" && exit 1 + fi + fi + + ## os_arch + if $(uname -m | grep '64'); then + os_arch="amd64" + else + os_arch="386" + fi +} + +confirm() { + if [[ $# > 1 ]]; then + echo && read -p "$1 [默认$2]: " temp + if [[ x"${temp}" == x"" ]]; then + temp=$2 + fi + else + read -p "$1 [y/n]: " temp + fi + if [[ x"${temp}" == x"y" || x"${temp}" == x"Y" ]]; then + return 0 + else + return 1 + fi +} + +before_show_menu() { + echo && echo -n -e "${yellow}* 按回车返回主菜单 *${plain}" && read temp + show_menu +} + +install_base() { + (command -v git >/dev/null 2>&1 && command -v curl >/dev/null 2>&1 && command -v wget >/dev/null 2>&1) || + (install_soft curl wget git) +} + +install_soft() { + (command -v yum >/dev/null 2>&1 && yum install $* -y) || + (command -v apt >/dev/null 2>&1 && apt install $* -y) || + (command -v apt-get >/dev/null 2>&1 && apt-get install $* -y) +} + +install_dashboard() { + install_base + + echo -e "> 安装面板" + + # 哪吒面板文件夹 + mkdir -p $NZ_DASHBOARD_PATH + chmod 777 -R $NZ_DASHBOARD_PATH + + command -v docker >/dev/null 2>&1 + if [[ $? != 0 ]]; then + echo -e "正在安装 Docker" + bash <(curl -sL https://get.docker.com) >/dev/null 2>&1 + if [[ $? != 0 ]]; then + echo -e "${red}下载脚本失败,请检查本机能否连接 get.docker.com${plain}" + return 0 + fi + systemctl enable docker.service + systemctl start docker.service + echo -e "${green}Docker${plain} 安装成功" + fi + + command -v docker-compose >/dev/null 2>&1 + if [[ $? != 0 ]]; then + echo -e "正在安装 Docker Compose" + curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose >/dev/null 2>&1 && + chmod +x /usr/local/bin/docker-compose + if [[ $? != 0 ]]; then + echo -e "${red}下载脚本失败,请检查本机能否连接 github.com${plain}" + return 0 + fi + echo -e "${green}Docker Compose${plain} 安装成功" + fi + + if [[ $? != 0 ]]; then + echo -e "正在下载 Docker 脚本" + cd $NZ_DASHBOARD_PATH + curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/docker-compose.yaml -o docker-compose.yaml >/dev/null 2>&1 + if [[ $? != 0 ]]; then + echo -e "${red}下载脚本失败,请检查本机能否连接 raw.githubusercontent.com${plain}" + return 0 + fi + fi + + modify_dashboard_config 0 + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +install_agent() { + install_base + + echo -e "> 安装监控Agent" + + # 哪吒面板文件夹 + mkdir -p $NZ_AGENT_PATH + chmod 777 -R $NZ_AGENT_PATH + + if [[ $? != 0 ]]; then + echo -e "正在下载监控端" + cd $NZ_DASHBOARD_PATH + curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/docker-compose.yaml -o docker-compose.yaml >/dev/null 2>&1 + if [[ $? != 0 ]]; then + echo -e "${red}下载脚本失败,请检查本机能否连接 raw.githubusercontent.com${plain}" + return 0 + fi + fi + + modify_dashboard_config 0 + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +modify_dashboard_config() { + echo -e "> 修改面板配置" + + curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/config.yaml -o config.yaml >/dev/null 2>&1 + if [[ $? != 0 ]]; then + echo -e "${red}下载脚本失败,请检查本机能否连接 raw.githubusercontent.com${plain}" + return 0 + fi + + echo "关于管理员 GitHub ID:复制自己GitHub头像图片地址,/[ID].png 多个用英文逗号隔开 id1,id2,id3" && + read -p "请输入 ID 列表: " admin_list && + echo "关于 GitHub Oauth2 应用:在 https://github.com/settings/developers 创建,无需审核 Callback 填 http(s)://域名或IP/oauth2/callback" && + read -p "请输入 GitHub Oauth2 应用的 Client ID: " nz_github_oauth_client_id && + read -p "请输入 GitHub Oauth2 应用的 Client Secret: " nz_github_oauth_client_secret && + read -p "请输入站点标题: " nz_site_title + if [[ -z "${admin_list}" || -z "${nz_github_oauth_client_id}" || -z "${nz_github_oauth_client_secret}" || -z "${nz_site_title}" ]]; then + echo -e "${red}所有选项都不能为空${plain}" + before_show_menu + return 1 + fi + + sed -i "s/^admin_list/${admin_list}/" ${NZ_DASHBOARD_PATH}/config.yaml + sed -i "s/^nz_github_oauth_client_id/${nz_github_oauth_client_id}/" ${NZ_DASHBOARD_PATH}/config.yaml + sed -i "s/^nz_github_oauth_client_secret/${nz_github_oauth_client_secret}/" ${NZ_DASHBOARD_PATH}/config.yaml + sed -i "s/^nz_site_title/${nz_site_title}/" ${NZ_DASHBOARD_PATH}/config.yaml + + echo -e "面板配置 ${green}修改成功,请稍等重启生效${plain}" + + restart_dashboard + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +restart_dashboard() { + cd $NZ_DASHBOARD_PATH && docker-compose restart + if [[ $? == 0 ]]; then + echo -e "${green}哪吒面板 重启成功${plain}" + else + echo -e "${red}重启失败,可能是因为启动时间超过了两秒,请稍后查看日志信息${plain}" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +start_dashboard() { + cd $NZ_DASHBOARD_PATH && docker-compose up -d + if [[ $? == 0 ]]; then + echo -e "${green}哪吒面板 启动成功${plain}" + else + echo -e "${red}启动失败,请稍后查看日志信息${plain}" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +stop_dashboard() { + cd $NZ_DASHBOARD_PATH && docker-compose down + if [[ $? == 0 ]]; then + echo -e "${green}哪吒面板 停止成功${plain}" + else + echo -e "${red}停止失败,请稍后查看日志信息${plain}" + fi + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +show_dashboard_log() { + cd $NZ_DASHBOARD_PATH && docker-compose logs -f + + if [[ $# == 0 ]]; then + before_show_menu + fi +} + +check_install() { + command -v docker >/dev/null 2>&1 && command -v docker-compose >/dev/null 2>&1 && command -v git >/dev/null 2>&1 + if [[ $? != 0 ]]; then + install_base + fi +} + +show_usage() { + echo "哪吒面板 管理脚本使用方法: " + echo "------------------------------------------" + echo "./nbdomain.sh - 显示管理菜单" + echo "./nbdomain.sh install_dashboard - 安装面板端" + echo "./nbdomain.sh modify_dashboard_config - 修改面板配置" + echo "./nbdomain.sh start_dashboard - 启动面板" + echo "./nbdomain.sh stop_dashboard - 停止面板" + echo "./nbdomain.sh restart_dashboard - 重启面板" + echo "./nbdomain.sh show_dashboard_log - 查看面板日志" + echo "./nbdomain.sh install_agent - 安装监控Agent" + echo "------------------------------------------" +} + +show_menu() { + echo -e " + ${green}哪吒面板管理脚本${plain} ${red}${NZ_VERSION}${plain} + --- https://github.com/naiba/nezha --- + ${green}0.${plain} 退出脚本 + ———————————————— + ${green}1.${plain} 安装面板端 + ${green}2.${plain} 修改面板配置 + ${green}3.${plain} 启动面板 + ${green}4.${plain} 停止面板 + ${green}5.${plain} 重启面板 + ${green}6.${plain} 查看面板日志 + ———————————————— + ${green}7.${plain} 安装监控Agent + " + echo && read -p "请输入选择 [0-14]: " num + + case "${num}" in + 0) + exit 0 + ;; + 1) + check_install && install_dashboard + ;; + 2) + check_install && modify_dashboard_config + ;; + 3) + check_install && start_dashboard + ;; + 4) + check_install && stop_dashboard + ;; + 5) + check_install && restart_dashboard + ;; + 6) + check_install && show_dashboard_log + ;; + 7) + install_agent + ;; + *) + echo -e "${red}请输入正确的数字 [0-7]${plain}" + ;; + esac +} + +pre_check + +if [[ $# > 0 ]]; then + case $1 in + "install_dashboard") + check_install 0 && install_dashboard 0 + ;; + "modify_dashboard_config") + check_install 0 && modify_dashboard_config 0 + ;; + "start_dashboard") + check_install 0 && start_dashboard 0 + ;; + "stop_dashboard") + check_install 0 && stop_dashboard 0 + ;; + "restart_dashboard") + check_install 0 && restart_dashboard 0 + ;; + "show_dashboard_log") + check_install 0 && show_dashboard_log 0 + ;; + "install_agent") + install_agent 0 + ;; + *) show_usage ;; + esac +else + show_menu +fi diff --git a/script/nezha-agent.service b/script/nezha-agent.service index fc7ec70..0b3618c 100644 --- a/script/nezha-agent.service +++ b/script/nezha-agent.service @@ -2,7 +2,7 @@ Description=Nezha Agent After=syslog.target After=network.target -After=nezha-dashboard.service +#After=nezha-dashboard.service [Service] # Modify these two values and uncomment them if you have @@ -12,10 +12,10 @@ After=nezha-dashboard.service #LimitMEMLOCK=infinity #LimitNOFILE=65535 Type=simple -#User=root -#Group=root -WorkingDirectory=/root/nezha/agent/ -ExecStart=/root/nezha/agent/nezha-agent-linux-amd64 -d -s server_addr -i client_id -p client_secret +User=root +Group=root +WorkingDirectory=/opt/nezha/agent/ +ExecStart=/opt/nezha/agent/nezha-agent-linux-amd64 -d -s nezha_server_addr -i nezha_client_id -p nezha_client_secret Restart=always #Environment=DEBUG=true