改为手动触发流水线
This commit is contained in:
+181
-159
@@ -1,159 +1,181 @@
|
|||||||
name: Docker Image CI
|
name: Docker 镜像 CI
|
||||||
on:
|
|
||||||
push:
|
on:
|
||||||
tags:
|
workflow_dispatch:
|
||||||
- "*"
|
inputs:
|
||||||
workflow_dispatch:
|
tag:
|
||||||
|
description: "发布标签"
|
||||||
jobs:
|
required: true
|
||||||
frontend-build:
|
default: "v1.4.1"
|
||||||
runs-on: ubuntu-24.04
|
type: string
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
jobs:
|
||||||
uses: actions/checkout@v6.0.2
|
frontend-build:
|
||||||
with:
|
runs-on: ubuntu-24.04
|
||||||
submodules: recursive
|
steps:
|
||||||
- name: Set up Node.js
|
- name: 检出仓库
|
||||||
uses: actions/setup-node@v6
|
uses: actions/checkout@v6.0.2
|
||||||
with:
|
with:
|
||||||
node-version: 25
|
ref: ${{ inputs.tag }}
|
||||||
- name: Install dependencies and build frontend
|
submodules: recursive
|
||||||
run: |
|
|
||||||
cd frontend
|
- name: 设置 Node.js
|
||||||
npm install
|
uses: actions/setup-node@v6
|
||||||
npm run build
|
with:
|
||||||
- name: Upload frontend build artifact
|
node-version: 25
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
- name: 安装依赖并构建前端
|
||||||
name: frontend-dist
|
run: |
|
||||||
path: frontend/dist/
|
cd frontend
|
||||||
|
npm install
|
||||||
build:
|
npm run build
|
||||||
needs: frontend-build
|
|
||||||
strategy:
|
- name: 上传前端构建产物
|
||||||
fail-fast: false
|
uses: actions/upload-artifact@v7
|
||||||
matrix:
|
with:
|
||||||
include:
|
name: frontend-dist
|
||||||
- { platform: linux/amd64 }
|
path: frontend/dist/
|
||||||
- { platform: linux/386 }
|
|
||||||
- { platform: linux/arm64/v8 }
|
build:
|
||||||
- { platform: linux/arm/v7 }
|
needs: frontend-build
|
||||||
- { platform: linux/arm/v6 }
|
strategy:
|
||||||
runs-on: ubuntu-24.04
|
fail-fast: false
|
||||||
steps:
|
matrix:
|
||||||
- name: Checkout repository
|
include:
|
||||||
uses: actions/checkout@v6.0.2
|
- { platform: linux/amd64 }
|
||||||
- name: Download frontend build artifact
|
- { platform: linux/386 }
|
||||||
uses: actions/download-artifact@v8
|
- { platform: linux/arm64/v8 }
|
||||||
with:
|
- { platform: linux/arm/v7 }
|
||||||
name: frontend-dist
|
- { platform: linux/arm/v6 }
|
||||||
path: frontend_dist
|
runs-on: ubuntu-24.04
|
||||||
- name: Prepare
|
steps:
|
||||||
run: |
|
- name: 检出仓库
|
||||||
platform="${{ matrix.platform }}"
|
uses: actions/checkout@v6.0.2
|
||||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
with:
|
||||||
- name: Docker meta
|
ref: ${{ inputs.tag }}
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v6
|
- name: 下载前端构建产物
|
||||||
with:
|
uses: actions/download-artifact@v8
|
||||||
images: |
|
with:
|
||||||
alireza7/s-ui
|
name: frontend-dist
|
||||||
ghcr.io/alireza0/s-ui
|
path: frontend_dist
|
||||||
tags: |
|
|
||||||
type=ref,event=branch
|
- name: 准备
|
||||||
type=ref,event=tag
|
run: |
|
||||||
type=pep440,pattern={{version}}
|
platform="${{ matrix.platform }}"
|
||||||
- name: Set up QEMU
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
uses: docker/setup-qemu-action@v4
|
|
||||||
- name: Set up Docker Buildx
|
- name: Docker 元数据
|
||||||
uses: docker/setup-buildx-action@v4
|
id: meta
|
||||||
- name: Cache Docker layers
|
uses: docker/metadata-action@v6
|
||||||
uses: actions/cache@v5
|
with:
|
||||||
with:
|
images: |
|
||||||
path: /tmp/.buildx-cache
|
alireza7/s-ui
|
||||||
key: ${{ runner.os }}-buildx-${{ matrix.platform }}-${{ github.sha }}
|
ghcr.io/alireza0/s-ui
|
||||||
restore-keys: |
|
tags: |
|
||||||
${{ runner.os }}-buildx-${{ matrix.platform }}-
|
type=raw,value=${{ inputs.tag }}
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v4
|
- name: 设置 QEMU
|
||||||
with:
|
uses: docker/setup-qemu-action@v4
|
||||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
- name: 设置 Docker Buildx
|
||||||
- name: Login to GHCR
|
uses: docker/setup-buildx-action@v4
|
||||||
uses: docker/login-action@v4
|
|
||||||
with:
|
- name: 缓存 Docker 层
|
||||||
registry: ghcr.io
|
uses: actions/cache@v5
|
||||||
username: ${{ github.repository_owner }}
|
with:
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
path: /tmp/.buildx-cache
|
||||||
- name: Build and push by digest
|
key: ${{ runner.os }}-buildx-${{ matrix.platform }}-${{ github.sha }}
|
||||||
id: build
|
restore-keys: |
|
||||||
uses: docker/build-push-action@v7
|
${{ runner.os }}-buildx-${{ matrix.platform }}-
|
||||||
with:
|
|
||||||
context: .
|
- name: 登录 Docker Hub
|
||||||
file: Dockerfile.frontend-artifact
|
uses: docker/login-action@v4
|
||||||
platforms: ${{ matrix.platform }}
|
with:
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
tags: |
|
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
||||||
alireza7/s-ui
|
|
||||||
ghcr.io/alireza0/s-ui
|
- name: 登录 GHCR
|
||||||
cache-from: type=local,src=/tmp/.buildx-cache
|
uses: docker/login-action@v4
|
||||||
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
|
with:
|
||||||
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
|
registry: ghcr.io
|
||||||
- name: Export digest
|
username: ${{ github.repository_owner }}
|
||||||
run: |
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
mkdir -p ${{ runner.temp }}/digests
|
|
||||||
digest="${{ steps.build.outputs.digest }}"
|
- name: 按摘要构建并推送
|
||||||
echo "${digest#sha256:}" > "${{ runner.temp }}/digests/${digest#sha256:}"
|
id: build
|
||||||
- name: Upload digest
|
uses: docker/build-push-action@v7
|
||||||
uses: actions/upload-artifact@v7
|
with:
|
||||||
with:
|
context: .
|
||||||
name: digests-${{ env.PLATFORM_PAIR }}
|
file: Dockerfile.frontend-artifact
|
||||||
path: ${{ runner.temp }}/digests/*
|
platforms: ${{ matrix.platform }}
|
||||||
if-no-files-found: error
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
retention-days: 1
|
tags: |
|
||||||
|
alireza7/s-ui
|
||||||
merge:
|
ghcr.io/alireza0/s-ui
|
||||||
needs: build
|
cache-from: type=local,src=/tmp/.buildx-cache
|
||||||
runs-on: ubuntu-24.04
|
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
|
||||||
steps:
|
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
|
||||||
- name: Download digests
|
|
||||||
uses: actions/download-artifact@v8
|
- name: 导出摘要
|
||||||
with:
|
run: |
|
||||||
path: ${{ runner.temp }}/digests
|
mkdir -p ${{ runner.temp }}/digests
|
||||||
pattern: digests-*
|
digest="${{ steps.build.outputs.digest }}"
|
||||||
merge-multiple: true
|
echo "${digest#sha256:}" > "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v4
|
- name: 上传摘要
|
||||||
with:
|
uses: actions/upload-artifact@v7
|
||||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
with:
|
||||||
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
name: digests-${{ env.PLATFORM_PAIR }}
|
||||||
- name: Login to GHCR
|
path: ${{ runner.temp }}/digests/*
|
||||||
uses: docker/login-action@v4
|
if-no-files-found: error
|
||||||
with:
|
retention-days: 1
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
merge:
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
needs: build
|
||||||
- name: Set up Docker Buildx
|
runs-on: ubuntu-24.04
|
||||||
uses: docker/setup-buildx-action@v4
|
steps:
|
||||||
- name: Docker meta
|
- name: 下载摘要
|
||||||
id: meta
|
uses: actions/download-artifact@v8
|
||||||
uses: docker/metadata-action@v6
|
with:
|
||||||
with:
|
path: ${{ runner.temp }}/digests
|
||||||
images: |
|
pattern: digests-*
|
||||||
alireza7/s-ui
|
merge-multiple: true
|
||||||
ghcr.io/alireza0/s-ui
|
|
||||||
tags: |
|
- name: 登录 Docker Hub
|
||||||
type=ref,event=branch
|
uses: docker/login-action@v4
|
||||||
type=ref,event=tag
|
with:
|
||||||
type=pep440,pattern={{version}}
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
- name: Create manifest list and push
|
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
||||||
env:
|
|
||||||
DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
|
- name: 登录 GHCR
|
||||||
working-directory: ${{ runner.temp }}/digests
|
uses: docker/login-action@v4
|
||||||
run: |
|
with:
|
||||||
set -e
|
registry: ghcr.io
|
||||||
for img in alireza7/s-ui ghcr.io/alireza0/s-ui; do
|
username: ${{ github.repository_owner }}
|
||||||
TAGS_ARGS=$(echo "$DOCKER_METADATA_OUTPUT_JSON" | jq -cr --arg img "$img" '.tags | map(select(startswith($img))) | map("-t " + .) | join(" ")')
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
DIGEST_REFS=$(for f in *; do echo -n "${img}@sha256:$(cat "$f") "; done)
|
|
||||||
docker buildx imagetools create $TAGS_ARGS $DIGEST_REFS
|
- name: 设置 Docker Buildx
|
||||||
done
|
uses: docker/setup-buildx-action@v4
|
||||||
|
|
||||||
|
- name: Docker 元数据
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v6
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
alireza7/s-ui
|
||||||
|
ghcr.io/alireza0/s-ui
|
||||||
|
tags: |
|
||||||
|
type=raw,value=${{ inputs.tag }}
|
||||||
|
|
||||||
|
- name: 创建清单列表并推送
|
||||||
|
env:
|
||||||
|
DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
|
||||||
|
working-directory: ${{ runner.temp }}/digests
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
for img in alireza7/s-ui ghcr.io/alireza0/s-ui; do
|
||||||
|
TAGS_ARGS=$(echo "$DOCKER_METADATA_OUTPUT_JSON" | jq -cr --arg img "$img" '.tags | map(select(startswith($img))) | map("-t " + .) | join(" ")')
|
||||||
|
DIGEST_REFS=$(for f in *; do echo -n "${img}@sha256:$(cat "$f") "; done)
|
||||||
|
docker buildx imagetools create $TAGS_ARGS $DIGEST_REFS
|
||||||
|
done
|
||||||
|
|||||||
+193
-202
@@ -1,202 +1,193 @@
|
|||||||
name: Release S-UI
|
name: 发布 S-UI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
release:
|
inputs:
|
||||||
types: [published]
|
tag:
|
||||||
push:
|
description: "发布标签"
|
||||||
branches:
|
required: true
|
||||||
- main
|
default: "v1.4.1"
|
||||||
tags:
|
type: string
|
||||||
- "*"
|
|
||||||
paths:
|
env:
|
||||||
- '.github/workflows/release.yml'
|
NODE_VERSION: "25"
|
||||||
- 'frontend/**'
|
CRONET_GO_VERSION: "2fef65f9dba90ddb89a87d00a6eb6165487c10c1"
|
||||||
- '**.sh'
|
CRONET_GO_REPO: https://github.com/sagernet/cronet-go.git
|
||||||
- '**.go'
|
BOOTLIN_BASE_URL: https://toolchains.bootlin.com/downloads/releases/toolchains
|
||||||
- 'go.mod'
|
|
||||||
- 'go.sum'
|
jobs:
|
||||||
- 's-ui.service'
|
build-frontend:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
env:
|
steps:
|
||||||
NODE_VERSION: "25"
|
- name: 检出仓库(仅前端)
|
||||||
CRONET_GO_VERSION: "2fef65f9dba90ddb89a87d00a6eb6165487c10c1"
|
uses: actions/checkout@v6.0.2
|
||||||
CRONET_GO_REPO: https://github.com/sagernet/cronet-go.git
|
with:
|
||||||
BOOTLIN_BASE_URL: https://toolchains.bootlin.com/downloads/releases/toolchains
|
ref: ${{ inputs.tag }}
|
||||||
|
submodules: recursive
|
||||||
jobs:
|
fetch-depth: 1
|
||||||
build-frontend:
|
|
||||||
runs-on: ubuntu-latest
|
- name: 设置 Node.js
|
||||||
steps:
|
uses: actions/setup-node@v6
|
||||||
- name: Checkout repository (frontend only)
|
with:
|
||||||
uses: actions/checkout@v6.0.2
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
with:
|
cache: 'npm'
|
||||||
submodules: recursive
|
cache-dependency-path: frontend/package-lock.json
|
||||||
fetch-depth: 1
|
|
||||||
|
- name: 构建前端
|
||||||
- name: Setup Node.js
|
run: |
|
||||||
uses: actions/setup-node@v6
|
cd frontend
|
||||||
with:
|
npm install
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
npm run build
|
||||||
cache: 'npm'
|
cd ..
|
||||||
cache-dependency-path: frontend/package-lock.json
|
|
||||||
|
- name: 上传前端 dist
|
||||||
- name: Build frontend
|
uses: actions/upload-artifact@v7
|
||||||
run: |
|
with:
|
||||||
cd frontend
|
name: frontend-dist
|
||||||
npm install
|
path: frontend/dist/
|
||||||
npm run build
|
|
||||||
cd ..
|
build-linux:
|
||||||
|
name: 构建-${{ matrix.platform }}
|
||||||
- name: Upload frontend dist
|
needs: build-frontend
|
||||||
uses: actions/upload-artifact@v7
|
strategy:
|
||||||
with:
|
fail-fast: false
|
||||||
name: frontend-dist
|
matrix:
|
||||||
path: frontend/dist/
|
include:
|
||||||
|
- { platform: amd64, arch: amd64, bootlin: x86-64, naive: true }
|
||||||
build-linux:
|
- { platform: arm64, arch: arm64, bootlin: aarch64, naive: true }
|
||||||
name: build-${{ matrix.platform }}
|
- { platform: armv7, arch: arm, goarm: "7", bootlin: armv7-eabihf, naive: true }
|
||||||
needs: build-frontend
|
- { platform: armv6, arch: arm, goarm: "6", bootlin: armv6-eabihf, naive: true }
|
||||||
strategy:
|
- { platform: armv5, arch: arm, goarm: "5", bootlin: armv5-eabi, naive: false }
|
||||||
fail-fast: false
|
- { platform: "386", arch: "386", bootlin: x86-i686, naive: true }
|
||||||
matrix:
|
- { platform: s390x, arch: s390x, bootlin: s390x-z13, naive: false }
|
||||||
include:
|
runs-on: ubuntu-latest
|
||||||
- { platform: amd64, arch: amd64, bootlin: x86-64, naive: true }
|
steps:
|
||||||
- { platform: arm64, arch: arm64, bootlin: aarch64, naive: true }
|
- name: 检出仓库
|
||||||
- { platform: armv7, arch: arm, goarm: "7", bootlin: armv7-eabihf, naive: true }
|
uses: actions/checkout@v6.0.2
|
||||||
- { platform: armv6, arch: arm, goarm: "6", bootlin: armv6-eabihf, naive: true }
|
with:
|
||||||
- { platform: armv5, arch: arm, goarm: "5", bootlin: armv5-eabi, naive: false }
|
ref: ${{ inputs.tag }}
|
||||||
- { platform: "386", arch: "386", bootlin: x86-i686, naive: true }
|
|
||||||
- { platform: s390x, arch: s390x, bootlin: s390x-z13, naive: false }
|
- name: 下载前端 dist
|
||||||
runs-on: ubuntu-latest
|
uses: actions/download-artifact@v8
|
||||||
steps:
|
with:
|
||||||
- name: Checkout repository
|
name: frontend-dist
|
||||||
uses: actions/checkout@v6.0.2
|
path: web/html
|
||||||
|
|
||||||
- name: Download frontend dist
|
- name: 设置 Go
|
||||||
uses: actions/download-artifact@v8
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
name: frontend-dist
|
cache: false
|
||||||
path: web/html
|
go-version-file: go.mod
|
||||||
|
|
||||||
- name: Setup Go
|
# Naive 平台:仅使用 cronet 工具链(不使用 Bootlin)。
|
||||||
uses: actions/setup-go@v6
|
- name: 克隆 cronet-go(naive 使用的 cronet 工具链)
|
||||||
with:
|
if: matrix.naive
|
||||||
cache: false
|
run: |
|
||||||
go-version-file: go.mod
|
set -e
|
||||||
|
git init ~/cronet-go
|
||||||
# Naive platforms: use cronet toolchain only (no Bootlin).
|
git -C ~/cronet-go remote add origin ${{ env.CRONET_GO_REPO }}
|
||||||
- name: Clone cronet-go (cronet toolchain for naive)
|
git -C ~/cronet-go fetch --depth=1 origin "${{ env.CRONET_GO_VERSION }}"
|
||||||
if: matrix.naive
|
git -C ~/cronet-go checkout FETCH_HEAD
|
||||||
run: |
|
git -C ~/cronet-go submodule update --init --recursive --depth=1
|
||||||
set -e
|
|
||||||
git init ~/cronet-go
|
- name: 重新生成 Debian keyring(cronet sysroot)
|
||||||
git -C ~/cronet-go remote add origin ${{ env.CRONET_GO_REPO }}
|
if: matrix.naive
|
||||||
git -C ~/cronet-go fetch --depth=1 origin "${{ env.CRONET_GO_VERSION }}"
|
run: |
|
||||||
git -C ~/cronet-go checkout FETCH_HEAD
|
set -e
|
||||||
git -C ~/cronet-go submodule update --init --recursive --depth=1
|
rm -f ~/cronet-go/naiveproxy/src/build/linux/sysroot_scripts/keyring.gpg
|
||||||
|
cd ~/cronet-go
|
||||||
- name: Regenerate Debian keyring (cronet sysroot)
|
GPG_TTY=/dev/null ./naiveproxy/src/build/linux/sysroot_scripts/generate_keyring.sh
|
||||||
if: matrix.naive
|
|
||||||
run: |
|
- name: 缓存 Chromium 工具链
|
||||||
set -e
|
if: matrix.naive
|
||||||
rm -f ~/cronet-go/naiveproxy/src/build/linux/sysroot_scripts/keyring.gpg
|
id: cache-chromium-toolchain
|
||||||
cd ~/cronet-go
|
uses: actions/cache@v5
|
||||||
GPG_TTY=/dev/null ./naiveproxy/src/build/linux/sysroot_scripts/generate_keyring.sh
|
with:
|
||||||
|
path: |
|
||||||
- name: Cache Chromium toolchain
|
~/cronet-go/naiveproxy/src/third_party/llvm-build/
|
||||||
if: matrix.naive
|
~/cronet-go/naiveproxy/src/gn/out/
|
||||||
id: cache-chromium-toolchain
|
~/cronet-go/naiveproxy/src/chrome/build/pgo_profiles/
|
||||||
uses: actions/cache@v5
|
~/cronet-go/naiveproxy/src/out/sysroot-build/
|
||||||
with:
|
key: chromium-toolchain-${{ matrix.platform }}-musl-${{ env.CRONET_GO_VERSION }}
|
||||||
path: |
|
|
||||||
~/cronet-go/naiveproxy/src/third_party/llvm-build/
|
- name: 构建 cronet 库并设置工具链环境(CC、CXX、CGO_LDFLAGS、PATH)
|
||||||
~/cronet-go/naiveproxy/src/gn/out/
|
if: matrix.naive
|
||||||
~/cronet-go/naiveproxy/src/chrome/build/pgo_profiles/
|
run: |
|
||||||
~/cronet-go/naiveproxy/src/out/sysroot-build/
|
set -e
|
||||||
key: chromium-toolchain-${{ matrix.platform }}-musl-${{ env.CRONET_GO_VERSION }}
|
cd ~/cronet-go
|
||||||
|
go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl download-toolchain
|
||||||
- name: Build cronet lib and set toolchain env (CC, CXX, CGO_LDFLAGS, PATH)
|
go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl env | while IFS= read -r line; do
|
||||||
if: matrix.naive
|
line="${line#export }"
|
||||||
run: |
|
[[ -z "$line" ]] && continue
|
||||||
set -e
|
echo "$line" >> $GITHUB_ENV
|
||||||
cd ~/cronet-go
|
done
|
||||||
go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl download-toolchain
|
|
||||||
go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl env | while IFS= read -r line; do
|
- name: 设置 Go 构建环境(所有平台)
|
||||||
line="${line#export }"
|
run: |
|
||||||
[[ -z "$line" ]] && continue
|
echo "CGO_ENABLED=1" >> $GITHUB_ENV
|
||||||
echo "$line" >> $GITHUB_ENV
|
echo "GOOS=linux" >> $GITHUB_ENV
|
||||||
done
|
echo "GOARCH=${{ matrix.arch }}" >> $GITHUB_ENV
|
||||||
|
if [ -n "${{ matrix.goarm }}" ]; then echo "GOARM=${{ matrix.goarm }}" >> $GITHUB_ENV; fi
|
||||||
- name: Set Go build env (all platforms)
|
|
||||||
run: |
|
# 仅非 naive 平台:Bootlin musl(armv5、s390x)。
|
||||||
echo "CGO_ENABLED=1" >> $GITHUB_ENV
|
- name: 设置 Bootlin musl(armv5、s390x)
|
||||||
echo "GOOS=linux" >> $GITHUB_ENV
|
if: ${{ matrix.naive != true }}
|
||||||
echo "GOARCH=${{ matrix.arch }}" >> $GITHUB_ENV
|
run: |
|
||||||
if [ -n "${{ matrix.goarm }}" ]; then echo "GOARM=${{ matrix.goarm }}" >> $GITHUB_ENV; fi
|
set -e
|
||||||
|
BOOTLIN_ARCH="${{ matrix.bootlin }}"
|
||||||
# Non-naive platforms only: Bootlin musl (armv5, s390x).
|
echo "正在解析 arch=$BOOTLIN_ARCH 的 Bootlin musl 工具链(平台=${{ matrix.platform }})"
|
||||||
- name: Set up Bootlin musl (armv5, s390x)
|
TARBALL_BASE="${{ env.BOOTLIN_BASE_URL }}/$BOOTLIN_ARCH/tarballs/"
|
||||||
if: ${{ matrix.naive != true }}
|
TARBALL_URL=$(curl -fsSL "$TARBALL_BASE" | grep -oE "${BOOTLIN_ARCH}--musl--stable-[^\"]+\\.tar\\.xz" | sort -r | head -n1)
|
||||||
run: |
|
[ -z "$TARBALL_URL" ] && { echo "未找到 arch=$BOOTLIN_ARCH 的 Bootlin musl 工具链" >&2; exit 1; }
|
||||||
set -e
|
echo "正在下载:$TARBALL_URL"
|
||||||
BOOTLIN_ARCH="${{ matrix.bootlin }}"
|
cd /tmp
|
||||||
echo "Resolving Bootlin musl toolchain for arch=$BOOTLIN_ARCH (platform=${{ matrix.platform }})"
|
curl -fL -sS -o "$(basename "$TARBALL_URL")" "$TARBALL_BASE/$TARBALL_URL"
|
||||||
TARBALL_BASE="${{ env.BOOTLIN_BASE_URL }}/$BOOTLIN_ARCH/tarballs/"
|
tar -xf "$(basename "$TARBALL_URL")"
|
||||||
TARBALL_URL=$(curl -fsSL "$TARBALL_BASE" | grep -oE "${BOOTLIN_ARCH}--musl--stable-[^\"]+\\.tar\\.xz" | sort -r | head -n1)
|
TOOLCHAIN_DIR=$(find . -maxdepth 1 -type d -name "${BOOTLIN_ARCH}--musl--stable-*" | head -n1)
|
||||||
[ -z "$TARBALL_URL" ] && { echo "Failed to locate Bootlin musl toolchain for arch=$BOOTLIN_ARCH" >&2; exit 1; }
|
TOOLCHAIN_DIR="$(realpath "$TOOLCHAIN_DIR")"
|
||||||
echo "Downloading: $TARBALL_URL"
|
BIN_DIR="$TOOLCHAIN_DIR/bin"
|
||||||
cd /tmp
|
echo "PATH=$BIN_DIR:$PATH" >> $GITHUB_ENV
|
||||||
curl -fL -sS -o "$(basename "$TARBALL_URL")" "$TARBALL_BASE/$TARBALL_URL"
|
CC=$(find "$BIN_DIR" -maxdepth 1 \( -name '*-gcc.br_real' -o -name '*-gcc' \) -type f -executable 2>/dev/null | grep -v g++ | head -n1)
|
||||||
tar -xf "$(basename "$TARBALL_URL")"
|
[ -z "$CC" ] && { echo "在 $BIN_DIR 中未找到 gcc" >&2; exit 1; }
|
||||||
TOOLCHAIN_DIR=$(find . -maxdepth 1 -type d -name "${BOOTLIN_ARCH}--musl--stable-*" | head -n1)
|
echo "CC=$(realpath "$CC")" >> $GITHUB_ENV
|
||||||
TOOLCHAIN_DIR="$(realpath "$TOOLCHAIN_DIR")"
|
SYSROOT=""
|
||||||
BIN_DIR="$TOOLCHAIN_DIR/bin"
|
F=$(find "$TOOLCHAIN_DIR" -name "libc-header-start.h" 2>/dev/null | head -1)
|
||||||
echo "PATH=$BIN_DIR:$PATH" >> $GITHUB_ENV
|
if [ -n "$F" ]; then SYSROOT=$(dirname "$(dirname "$(dirname "$(dirname "$F")")")"); fi
|
||||||
CC=$(find "$BIN_DIR" -maxdepth 1 \( -name '*-gcc.br_real' -o -name '*-gcc' \) -type f -executable 2>/dev/null | grep -v g++ | head -n1)
|
if [ -n "$SYSROOT" ] && [ -d "$SYSROOT" ]; then
|
||||||
[ -z "$CC" ] && { echo "No gcc found in $BIN_DIR" >&2; exit 1; }
|
echo "CGO_CFLAGS=--sysroot=$SYSROOT" >> $GITHUB_ENV
|
||||||
echo "CC=$(realpath "$CC")" >> $GITHUB_ENV
|
echo "CGO_LDFLAGS=--sysroot=$SYSROOT -static" >> $GITHUB_ENV
|
||||||
SYSROOT=""
|
fi
|
||||||
F=$(find "$TOOLCHAIN_DIR" -name "libc-header-start.h" 2>/dev/null | head -1)
|
|
||||||
if [ -n "$F" ]; then SYSROOT=$(dirname "$(dirname "$(dirname "$(dirname "$F")")")"); fi
|
- name: 构建 s-ui
|
||||||
if [ -n "$SYSROOT" ] && [ -d "$SYSROOT" ]; then
|
run: |
|
||||||
echo "CGO_CFLAGS=--sysroot=$SYSROOT" >> $GITHUB_ENV
|
set -e
|
||||||
echo "CGO_LDFLAGS=--sysroot=$SYSROOT -static" >> $GITHUB_ENV
|
BUILD_TAGS="with_quic,with_grpc,with_utls,with_acme,with_gvisor,badlinkname,tfogo_checklinkname0,with_tailscale"
|
||||||
fi
|
[ "${{ matrix.naive }}" = "true" ] && BUILD_TAGS="${BUILD_TAGS},with_naive_outbound,with_musl"
|
||||||
|
go build -ldflags="-w -s -checklinkname=0 -linkmode external -extldflags '-static'" -tags "$BUILD_TAGS" -o sui main.go
|
||||||
- name: Build s-ui
|
file sui
|
||||||
run: |
|
ldd sui 2>/dev/null || echo "已确认静态二进制文件"
|
||||||
set -e
|
|
||||||
BUILD_TAGS="with_quic,with_grpc,with_utls,with_acme,with_gvisor,badlinkname,tfogo_checklinkname0,with_tailscale"
|
mkdir s-ui
|
||||||
[ "${{ matrix.naive }}" = "true" ] && BUILD_TAGS="${BUILD_TAGS},with_naive_outbound,with_musl"
|
cp sui s-ui/
|
||||||
go build -ldflags="-w -s -checklinkname=0 -linkmode external -extldflags '-static'" -tags "$BUILD_TAGS" -o sui main.go
|
cp s-ui.service s-ui/
|
||||||
file sui
|
cp s-ui.sh s-ui/
|
||||||
ldd sui 2>/dev/null || echo "Static binary confirmed"
|
|
||||||
|
- name: 打包
|
||||||
mkdir s-ui
|
run: tar -zcvf s-ui-linux-${{ matrix.platform }}.tar.gz s-ui
|
||||||
cp sui s-ui/
|
|
||||||
cp s-ui.service s-ui/
|
- name: 上传构建产物
|
||||||
cp s-ui.sh s-ui/
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
- name: Package
|
name: s-ui-linux-${{ matrix.platform }}
|
||||||
run: tar -zcvf s-ui-linux-${{ matrix.platform }}.tar.gz s-ui
|
path: ./s-ui-linux-${{ matrix.platform }}.tar.gz
|
||||||
|
retention-days: 30
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-artifact@v7
|
- name: 上传到 Release
|
||||||
with:
|
uses: svenstaro/upload-release-action@v2
|
||||||
name: s-ui-linux-${{ matrix.platform }}
|
with:
|
||||||
path: ./s-ui-linux-${{ matrix.platform }}.tar.gz
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
retention-days: 30
|
tag: ${{ inputs.tag }}
|
||||||
|
file: s-ui-linux-${{ matrix.platform }}.tar.gz
|
||||||
- name: Upload to Release
|
asset_name: s-ui-linux-${{ matrix.platform }}.tar.gz
|
||||||
uses: svenstaro/upload-release-action@v2
|
prerelease: true
|
||||||
if: |
|
overwrite: true
|
||||||
(github.event_name == 'release' && github.event.action == 'published') ||
|
|
||||||
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))
|
|
||||||
with:
|
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
tag: ${{ github.event_name == 'release' && github.event.release.tag_name || github.ref_name }}
|
|
||||||
file: s-ui-linux-${{ matrix.platform }}.tar.gz
|
|
||||||
asset_name: s-ui-linux-${{ matrix.platform }}.tar.gz
|
|
||||||
prerelease: true
|
|
||||||
overwrite: true
|
|
||||||
|
|||||||
+132
-140
@@ -1,140 +1,132 @@
|
|||||||
name: Build S-UI for Windows
|
name: 构建 Windows 版 S-UI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
release:
|
inputs:
|
||||||
types: [published]
|
tag:
|
||||||
push:
|
description: "发布标签"
|
||||||
branches:
|
required: true
|
||||||
- main
|
default: "v1.4.1"
|
||||||
tags:
|
type: string
|
||||||
- "*"
|
|
||||||
paths:
|
env:
|
||||||
- '.github/workflows/windows.yml'
|
NODE_VERSION: "25"
|
||||||
- 'frontend/**'
|
TAGS: "with_quic,with_grpc,with_utls,with_acme,with_gvisor,with_naive_outbound,with_purego,badlinkname,tfogo_checklinkname0,with_tailscale"
|
||||||
- '**.go'
|
LIBCRONET_BASE_URL: "https://github.com/SagerNet/cronet-go/releases/latest/download"
|
||||||
- 'go.mod'
|
|
||||||
- 'go.sum'
|
jobs:
|
||||||
- 'windows/**'
|
build-frontend:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
env:
|
steps:
|
||||||
NODE_VERSION: "25"
|
- name: 检出仓库
|
||||||
TAGS: "with_quic,with_grpc,with_utls,with_acme,with_gvisor,with_naive_outbound,with_purego,badlinkname,tfogo_checklinkname0,with_tailscale"
|
uses: actions/checkout@v6.0.2
|
||||||
LIBCRONET_BASE_URL: "https://github.com/SagerNet/cronet-go/releases/latest/download"
|
with:
|
||||||
|
ref: ${{ inputs.tag }}
|
||||||
jobs:
|
submodules: recursive
|
||||||
build-frontend:
|
fetch-depth: 1
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
- name: 设置 Node.js
|
||||||
- name: Checkout repository
|
uses: actions/setup-node@v6
|
||||||
uses: actions/checkout@v6.0.2
|
with:
|
||||||
with:
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
submodules: recursive
|
registry-url: 'https://registry.npmjs.org'
|
||||||
fetch-depth: 1
|
|
||||||
|
- name: 构建前端
|
||||||
- name: Setup Node.js
|
run: |
|
||||||
uses: actions/setup-node@v6
|
cd frontend
|
||||||
with:
|
npm install
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
npm run build
|
||||||
registry-url: 'https://registry.npmjs.org'
|
cd ..
|
||||||
|
|
||||||
- name: Build frontend
|
- name: 上传前端构建产物
|
||||||
run: |
|
uses: actions/upload-artifact@v7
|
||||||
cd frontend
|
with:
|
||||||
npm install
|
name: frontend-dist
|
||||||
npm run build
|
path: frontend/dist
|
||||||
cd ..
|
retention-days: 1
|
||||||
|
|
||||||
- name: Upload frontend artifact
|
build-windows:
|
||||||
uses: actions/upload-artifact@v7
|
needs: build-frontend
|
||||||
with:
|
name: 构建-windows-${{ matrix.arch }}
|
||||||
name: frontend-dist
|
strategy:
|
||||||
path: frontend/dist
|
fail-fast: false
|
||||||
retention-days: 1
|
matrix:
|
||||||
|
include:
|
||||||
build-windows:
|
- { arch: amd64, runner: windows-latest, cgo: "1" }
|
||||||
needs: build-frontend
|
- { arch: arm64, runner: ubuntu-latest, cgo: "0" }
|
||||||
name: build-windows-${{ matrix.arch }}
|
runs-on: ${{ matrix.runner }}
|
||||||
strategy:
|
steps:
|
||||||
fail-fast: false
|
- name: 检出仓库
|
||||||
matrix:
|
uses: actions/checkout@v6.0.2
|
||||||
include:
|
with:
|
||||||
- { arch: amd64, runner: windows-latest, cgo: "1" }
|
ref: ${{ inputs.tag }}
|
||||||
- { arch: arm64, runner: ubuntu-latest, cgo: "0" }
|
|
||||||
runs-on: ${{ matrix.runner }}
|
- name: 下载前端构建产物
|
||||||
steps:
|
uses: actions/download-artifact@v8
|
||||||
- name: Checkout repository
|
with:
|
||||||
uses: actions/checkout@v6.0.2
|
name: frontend-dist
|
||||||
|
path: web/html
|
||||||
- name: Download frontend artifact
|
|
||||||
uses: actions/download-artifact@v8
|
- name: 设置 Go
|
||||||
with:
|
uses: actions/setup-go@v6
|
||||||
name: frontend-dist
|
with:
|
||||||
path: web/html
|
cache: false
|
||||||
|
go-version-file: go.mod
|
||||||
- name: Setup Go
|
|
||||||
uses: actions/setup-go@v6
|
- name: 为 Windows 安装 zip
|
||||||
with:
|
if: matrix.arch == 'amd64'
|
||||||
cache: false
|
shell: powershell
|
||||||
go-version-file: go.mod
|
run: |
|
||||||
|
# 如果 Chocolatey 不可用,则安装 Chocolatey
|
||||||
- name: Install zip for Windows
|
if (!(Get-Command choco -ErrorAction SilentlyContinue)) {
|
||||||
if: matrix.arch == 'amd64'
|
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||||||
shell: powershell
|
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
|
||||||
run: |
|
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
|
||||||
# Install Chocolatey if not available
|
}
|
||||||
if (!(Get-Command choco -ErrorAction SilentlyContinue)) {
|
# 安装 zip
|
||||||
Set-ExecutionPolicy Bypass -Scope Process -Force
|
choco install zip -y
|
||||||
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
|
|
||||||
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
|
- name: 构建 s-ui
|
||||||
}
|
shell: bash
|
||||||
# Install zip
|
run: |
|
||||||
choco install zip -y
|
export CGO_ENABLED=${{ matrix.cgo }}
|
||||||
|
export GOOS=windows
|
||||||
- name: Build s-ui
|
export GOARCH=${{ matrix.arch }}
|
||||||
shell: bash
|
|
||||||
run: |
|
echo "正在为 Windows ${{ matrix.arch }} 构建"
|
||||||
export CGO_ENABLED=${{ matrix.cgo }}
|
go version
|
||||||
export GOOS=windows
|
go env GOOS GOARCH
|
||||||
export GOARCH=${{ matrix.arch }}
|
|
||||||
|
go build -ldflags="-w -s -checklinkname=0" -tags "${{ env.TAGS }}" -o sui.exe main.go
|
||||||
echo "Building for Windows ${{ matrix.arch }}"
|
file sui.exe
|
||||||
go version
|
|
||||||
go env GOOS GOARCH
|
mkdir s-ui-windows
|
||||||
|
cp sui.exe s-ui-windows/
|
||||||
go build -ldflags="-w -s -checklinkname=0" -tags "${{ env.TAGS }}" -o sui.exe main.go
|
cp -r windows/* s-ui-windows/
|
||||||
file sui.exe
|
|
||||||
|
- name: 下载 libcronet-go
|
||||||
mkdir s-ui-windows
|
shell: bash
|
||||||
cp sui.exe s-ui-windows/
|
run: |
|
||||||
cp -r windows/* s-ui-windows/
|
curl -qsL -o s-ui-windows/libcronet.dll ${{ env.LIBCRONET_BASE_URL }}/libcronet-windows-${{ matrix.arch }}.dll
|
||||||
|
|
||||||
- name: Download libcronet-go
|
- name: 打包
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
curl -qsL -o s-ui-windows/libcronet.dll ${{ env.LIBCRONET_BASE_URL }}/libcronet-windows-${{ matrix.arch }}.dll
|
zip -r "s-ui-windows-${{ matrix.arch }}.zip" s-ui-windows
|
||||||
|
|
||||||
- name: Package
|
- name: 上传文件到构建产物
|
||||||
shell: bash
|
uses: actions/upload-artifact@v7
|
||||||
run: |
|
with:
|
||||||
zip -r "s-ui-windows-${{ matrix.arch }}.zip" s-ui-windows
|
name: s-ui-windows-${{ matrix.arch }}
|
||||||
|
path: ./s-ui-windows-${{ matrix.arch }}.zip
|
||||||
- name: Upload files to Artifacts
|
retention-days: 30
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
- name: 上传到 Release
|
||||||
name: s-ui-windows-${{ matrix.arch }}
|
uses: svenstaro/upload-release-action@v2
|
||||||
path: ./s-ui-windows-${{ matrix.arch }}.zip
|
with:
|
||||||
retention-days: 30
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
tag: ${{ inputs.tag }}
|
||||||
- name: Upload to Release
|
file: s-ui-windows-${{ matrix.arch }}.zip
|
||||||
uses: svenstaro/upload-release-action@v2
|
asset_name: s-ui-windows-${{ matrix.arch }}.zip
|
||||||
if: |
|
prerelease: true
|
||||||
(github.event_name == 'release' && github.event.action == 'published') ||
|
overwrite: true
|
||||||
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))
|
|
||||||
with:
|
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
tag: ${{ github.ref }}
|
|
||||||
file: s-ui-windows-${{ matrix.arch }}.zip
|
|
||||||
asset_name: s-ui-windows-${{ matrix.arch }}.zip
|
|
||||||
prerelease: true
|
|
||||||
overwrite: true
|
|
||||||
|
|||||||
@@ -1,259 +1,239 @@
|
|||||||
# S-UI
|
# S-UI
|
||||||
**An Advanced Web Panel • Built on SagerNet/Sing-Box**
|
**基于 SagerNet/Sing-Box 构建的高级 Web 面板**
|
||||||
|
|
||||||

|
|
||||||

|
> **免责声明:** 本项目仅供个人学习与交流使用,请勿用于非法用途,请勿在生产环境中使用。
|
||||||
[](https://goreportcard.com/report/github.com/admin8800/s-ui)
|
|
||||||
[](https://img.shields.io/github/downloads/alireza0/s-ui/total.svg)
|
|
||||||
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
## 快速概览
|
||||||
|
| 功能 | 是否支持 |
|
||||||
> **Disclaimer:** This project is only for personal learning and communication, please do not use it for illegal purposes, please do not use it in a production environment
|
| -------------------------------------- | :----------------: |
|
||||||
|
| 多协议 | :heavy_check_mark: |
|
||||||
**If you think this project is helpful to you, you may wish to give a**:star2:
|
| 多语言 | :heavy_check_mark: |
|
||||||
|
| 多客户端/入站 | :heavy_check_mark: |
|
||||||
**Want to contribute?** See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding conventions, testing, and the pull request process.
|
| 高级流量路由界面 | :heavy_check_mark: |
|
||||||
|
| 客户端、流量与系统状态 | :heavy_check_mark: |
|
||||||
[](https://www.buymeacoffee.com/alireza7)
|
| 订阅链接(link/json/clash + info) | :heavy_check_mark: |
|
||||||
|
| 深色/浅色主题 | :heavy_check_mark: |
|
||||||
<a href="https://nowpayments.io/donation/alireza7" target="_blank" rel="noreferrer noopener">
|
| API 接口 | :heavy_check_mark: |
|
||||||
<img src="https://nowpayments.io/images/embeds/donation-button-white.svg" alt="Crypto donation button by NOWPayments">
|
|
||||||
</a>
|
## 支持平台
|
||||||
|
| 平台 | 架构 | 状态 |
|
||||||
## Quick Overview
|
|----------|--------------|---------|
|
||||||
| Features | Enable? |
|
| Linux | amd64, arm64, armv7, armv6, armv5, 386, s390x | 支持 |
|
||||||
| -------------------------------------- | :----------------: |
|
| Windows | amd64, 386, arm64 | 支持 |
|
||||||
| Multi-Protocol | :heavy_check_mark: |
|
| macOS | amd64, arm64 | 实验性支持 |
|
||||||
| Multi-Language | :heavy_check_mark: |
|
|
||||||
| Multi-Client/Inbound | :heavy_check_mark: |
|
## 截图
|
||||||
| Advanced Traffic Routing Interface | :heavy_check_mark: |
|
|
||||||
| Client & Traffic & System Status | :heavy_check_mark: |
|

|
||||||
| Subscription Link (link/json/clash + info)| :heavy_check_mark: |
|
|
||||||
| Dark/Light Theme | :heavy_check_mark: |
|
## API 文档
|
||||||
| API Interface | :heavy_check_mark: |
|
|
||||||
|
[API 文档 Wiki](https://github.com/admin8800/s-ui/wiki/API-Documentation)
|
||||||
## Supported Platforms
|
|
||||||
| Platform | Architecture | Status |
|
## 默认安装信息
|
||||||
|----------|--------------|---------|
|
- 面板端口:2095
|
||||||
| Linux | amd64, arm64, armv7, armv6, armv5, 386, s390x | ✅ Supported |
|
- 面板路径:/app/
|
||||||
| Windows | amd64, 386, arm64 | ✅ Supported |
|
- 订阅端口:2096
|
||||||
| macOS | amd64, arm64 | 🚧 Experimental |
|
- 订阅路径:/sub/
|
||||||
|
- 用户名/密码:admin
|
||||||
## Screenshots
|
|
||||||
|
## 安装或升级到最新版本
|
||||||

|
|
||||||
|
### Linux/macOS
|
||||||
[Other UI Screenshots](https://github.com/admin8800/s-ui-frontend/blob/main/screenshots.md)
|
```sh
|
||||||
|
bash <(curl -Ls https://raw.githubusercontent.com/admin8800/s-ui/main/install.sh)
|
||||||
## API Documentation
|
```
|
||||||
|
|
||||||
[API-Documentation Wiki](https://github.com/admin8800/s-ui/wiki/API-Documentation)
|
### Windows
|
||||||
|
1. 从 [GitHub Releases](https://github.com/admin8800/s-ui/releases/latest) 下载最新 Windows 版本。
|
||||||
## Default Installation Information
|
2. 解压 ZIP 文件。
|
||||||
- Panel Port: 2095
|
3. 以管理员身份运行 `install-windows.bat`。
|
||||||
- Panel Path: /app/
|
4. 按照安装向导操作。
|
||||||
- Subscription Port: 2096
|
|
||||||
- Subscription Path: /sub/
|
## 安装旧版本
|
||||||
- User/Password: admin
|
|
||||||
|
**步骤 1:** 如果要安装指定旧版本,请在安装命令末尾追加版本号。例如版本 `1.0.0`:
|
||||||
## Install & Upgrade to Latest Version
|
|
||||||
|
```sh
|
||||||
### Linux/macOS
|
VERSION=1.0.0 && bash <(curl -Ls https://raw.githubusercontent.com/admin8800/s-ui/$VERSION/install.sh) $VERSION
|
||||||
```sh
|
```
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/alireza0/s-ui/master/install.sh)
|
|
||||||
```
|
## 手动安装
|
||||||
|
|
||||||
### Windows
|
### Linux/macOS
|
||||||
1. Download the latest Windows release from [GitHub Releases](https://github.com/admin8800/s-ui/releases/latest)
|
1. 根据你的系统和架构,从 GitHub 获取最新版本 S-UI:[https://github.com/admin8800/s-ui/releases/latest](https://github.com/admin8800/s-ui/releases/latest)
|
||||||
2. Extract the ZIP file
|
2. **可选:** 获取最新版 `s-ui.sh`:[https://raw.githubusercontent.com/admin8800/s-ui/main/s-ui.sh](https://raw.githubusercontent.com/admin8800/s-ui/main/s-ui.sh)
|
||||||
3. Run `install-windows.bat` as Administrator
|
3. **可选:** 将 `s-ui.sh` 复制到 `/usr/bin/`,并执行 `chmod +x /usr/bin/s-ui`。
|
||||||
4. Follow the installation wizard
|
4. 将 s-ui tar.gz 文件解压到你选择的目录,并进入解压后的目录。
|
||||||
|
5. 将 `*.service` 文件复制到 `/etc/systemd/system/`,然后执行 `systemctl daemon-reload`。
|
||||||
## Install legacy Version
|
6. 使用 `systemctl enable s-ui --now` 启用开机自启并启动 S-UI 服务。
|
||||||
|
7. 使用 `systemctl enable sing-box --now` 启动 sing-box 服务。
|
||||||
**Step 1:** To install your desired legacy version, add the version to the end of the installation command. e.g., ver `1.0.0`:
|
|
||||||
|
### Windows
|
||||||
```sh
|
1. 从 GitHub 获取最新 Windows 版本:[https://github.com/admin8800/s-ui/releases/latest](https://github.com/admin8800/s-ui/releases/latest)
|
||||||
VERSION=1.0.0 && bash <(curl -Ls https://raw.githubusercontent.com/alireza0/s-ui/$VERSION/install.sh) $VERSION
|
2. 下载适合的 Windows 包,例如 `s-ui-windows-amd64.zip`。
|
||||||
```
|
3. 将 ZIP 文件解压到你选择的目录。
|
||||||
|
4. 以管理员身份运行 `install-windows.bat`。
|
||||||
## Manual installation
|
5. 按照安装向导操作。
|
||||||
|
6. 访问面板:http://localhost:2095/app
|
||||||
### Linux/macOS
|
|
||||||
1. Get the latest version of S-UI based on your OS/Architecture from GitHub: [https://github.com/admin8800/s-ui/releases/latest](https://github.com/admin8800/s-ui/releases/latest)
|
## 卸载 S-UI
|
||||||
2. **OPTIONAL** Get the latest version of `s-ui.sh` [https://raw.githubusercontent.com/alireza0/s-ui/master/s-ui.sh](https://raw.githubusercontent.com/alireza0/s-ui/master/s-ui.sh)
|
|
||||||
3. **OPTIONAL** Copy `s-ui.sh` to /usr/bin/ and run `chmod +x /usr/bin/s-ui`.
|
```sh
|
||||||
4. Extract s-ui tar.gz file to a directory of your choice and navigate to the directory where you extracted the tar.gz file.
|
sudo -i
|
||||||
5. Copy *.service files to /etc/systemd/system/ and run `systemctl daemon-reload`.
|
|
||||||
6. Enable autostart and start S-UI service using `systemctl enable s-ui --now`
|
systemctl disable s-ui --now
|
||||||
7. Start sing-box service using `systemctl enable sing-box --now`
|
|
||||||
|
rm -f /etc/systemd/system/sing-box.service
|
||||||
### Windows
|
systemctl daemon-reload
|
||||||
1. Get the latest Windows version from GitHub: [https://github.com/admin8800/s-ui/releases/latest](https://github.com/admin8800/s-ui/releases/latest)
|
|
||||||
2. Download the appropriate Windows package (e.g., `s-ui-windows-amd64.zip`)
|
rm -fr /usr/local/s-ui
|
||||||
3. Extract the ZIP file to a directory of your choice
|
rm /usr/bin/s-ui
|
||||||
4. Run `install-windows.bat` as Administrator
|
```
|
||||||
5. Follow the installation wizard
|
|
||||||
6. Access the panel at http://localhost:2095/app
|
## 使用 Docker 安装
|
||||||
|
|
||||||
## Uninstall S-UI
|
<details>
|
||||||
|
<summary>点击查看详情</summary>
|
||||||
```sh
|
|
||||||
sudo -i
|
### 使用方式
|
||||||
|
|
||||||
systemctl disable s-ui --now
|
**步骤 1:** 安装 Docker
|
||||||
|
|
||||||
rm -f /etc/systemd/system/sing-box.service
|
```shell
|
||||||
systemctl daemon-reload
|
curl -fsSL https://get.docker.com | sh
|
||||||
|
```
|
||||||
rm -fr /usr/local/s-ui
|
|
||||||
rm /usr/bin/s-ui
|
**步骤 2:** 安装 S-UI
|
||||||
```
|
|
||||||
|
> Docker compose 方式
|
||||||
## Install using Docker
|
|
||||||
|
```shell
|
||||||
<details>
|
mkdir s-ui && cd s-ui
|
||||||
<summary>Click for details</summary>
|
wget -q https://raw.githubusercontent.com/admin8800/s-ui/main/docker-compose.yml
|
||||||
|
docker compose up -d
|
||||||
### Usage
|
```
|
||||||
|
|
||||||
**Step 1:** Install Docker
|
> 直接使用 docker
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl -fsSL https://get.docker.com | sh
|
mkdir s-ui && cd s-ui
|
||||||
```
|
docker run -itd \
|
||||||
|
-p 2095:2095 -p 2096:2096 -p 443:443 -p 80:80 \
|
||||||
**Step 2:** Install S-UI
|
-v $PWD/db/:/app/db/ \
|
||||||
|
-v $PWD/cert/:/root/cert/ \
|
||||||
> Docker compose method
|
--name s-ui --restart=unless-stopped \
|
||||||
|
alireza7/s-ui:latest
|
||||||
```shell
|
```
|
||||||
mkdir s-ui && cd s-ui
|
|
||||||
wget -q https://raw.githubusercontent.com/alireza0/s-ui/master/docker-compose.yml
|
> 自行构建镜像
|
||||||
docker compose up -d
|
|
||||||
```
|
```shell
|
||||||
|
git clone https://github.com/admin8800/s-ui
|
||||||
> Use docker
|
git submodule update --init --recursive
|
||||||
|
docker build -t s-ui .
|
||||||
```shell
|
```
|
||||||
mkdir s-ui && cd s-ui
|
|
||||||
docker run -itd \
|
</details>
|
||||||
-p 2095:2095 -p 2096:2096 -p 443:443 -p 80:80 \
|
|
||||||
-v $PWD/db/:/app/db/ \
|
## 手动运行(贡献开发)
|
||||||
-v $PWD/cert/:/root/cert/ \
|
|
||||||
--name s-ui --restart=unless-stopped \
|
<details>
|
||||||
alireza7/s-ui:latest
|
<summary>点击查看详情</summary>
|
||||||
```
|
|
||||||
|
### 构建并运行完整项目
|
||||||
> Build your own image
|
```shell
|
||||||
|
./runSUI.sh
|
||||||
```shell
|
```
|
||||||
git clone https://github.com/admin8800/s-ui
|
|
||||||
git submodule update --init --recursive
|
### 克隆仓库
|
||||||
docker build -t s-ui .
|
```shell
|
||||||
```
|
# 克隆仓库
|
||||||
|
git clone https://github.com/admin8800/s-ui
|
||||||
</details>
|
# 克隆子模块
|
||||||
|
git submodule update --init --recursive
|
||||||
## Manual run ( contribution )
|
```
|
||||||
|
|
||||||
<details>
|
### - 前端
|
||||||
<summary>Click for details</summary>
|
|
||||||
|
前端代码请查看 [s-ui-frontend](https://github.com/admin8800/s-ui-frontend)。
|
||||||
### Build and run whole project
|
|
||||||
```shell
|
### - 后端
|
||||||
./runSUI.sh
|
> 请先至少构建一次前端。
|
||||||
```
|
|
||||||
|
构建后端:
|
||||||
### Clone the repository
|
```shell
|
||||||
```shell
|
# 删除旧的前端编译文件
|
||||||
# clone repository
|
rm -fr web/html/*
|
||||||
git clone https://github.com/admin8800/s-ui
|
# 应用新的前端编译文件
|
||||||
# clone submodules
|
cp -R frontend/dist/ web/html/
|
||||||
git submodule update --init --recursive
|
# 构建
|
||||||
```
|
go build -o sui main.go
|
||||||
|
```
|
||||||
|
|
||||||
### - Frontend
|
运行后端(在仓库根目录执行):
|
||||||
|
```shell
|
||||||
Visit [s-ui-frontend](https://github.com/admin8800/s-ui-frontend) for frontend code
|
./sui
|
||||||
|
```
|
||||||
### - Backend
|
|
||||||
> Please build frontend once before!
|
</details>
|
||||||
|
|
||||||
To build backend:
|
## 语言
|
||||||
```shell
|
|
||||||
# remove old frontend compiled files
|
- 英语
|
||||||
rm -fr web/html/*
|
- 波斯语
|
||||||
# apply new frontend compiled files
|
- 越南语
|
||||||
cp -R frontend/dist/ web/html/
|
- 简体中文
|
||||||
# build
|
- 繁体中文
|
||||||
go build -o sui main.go
|
- 俄语
|
||||||
```
|
|
||||||
|
## 功能
|
||||||
To run backend (from root folder of repository):
|
|
||||||
```shell
|
- 支持的协议:
|
||||||
./sui
|
- 通用协议:Mixed、SOCKS、HTTP、HTTPS、Direct、Redirect、TProxy
|
||||||
```
|
- 基于 V2Ray 的协议:VLESS、VMess、Trojan、Shadowsocks
|
||||||
|
- 其他协议:ShadowTLS、Hysteria、Hysteria2、Naive、TUIC
|
||||||
</details>
|
- 支持 XTLS 协议。
|
||||||
|
- 提供高级流量路由界面,支持 PROXY Protocol、External、透明代理、SSL 证书和端口配置。
|
||||||
## Languages
|
- 提供高级入站和出站配置界面。
|
||||||
|
- 支持客户端流量上限和到期时间。
|
||||||
- English
|
- 显示在线客户端、入站、出站流量统计和系统状态监控。
|
||||||
- Farsi
|
- 订阅服务支持添加外部链接和订阅。
|
||||||
- Vietnamese
|
- Web 面板和订阅服务支持 HTTPS 安全访问(需自行提供域名和 SSL 证书)。
|
||||||
- Chinese (Simplified)
|
- 深色/浅色主题。
|
||||||
- Chinese (Traditional)
|
|
||||||
- Russian
|
## 环境变量
|
||||||
|
|
||||||
## Features
|
<details>
|
||||||
|
<summary>点击查看详情</summary>
|
||||||
- Supported protocols:
|
|
||||||
- General: Mixed, SOCKS, HTTP, HTTPS, Direct, Redirect, TProxy
|
### 使用方式
|
||||||
- V2Ray based: VLESS, VMess, Trojan, Shadowsocks
|
|
||||||
- Other protocols: ShadowTLS, Hysteria, Hysteria2, Naive, TUIC
|
| 变量 | 类型 | 默认值 |
|
||||||
- Supports XTLS protocols
|
| -------------- | :--------------------------------------------: | :------------ |
|
||||||
- An advanced interface for routing traffic, incorporating PROXY Protocol, External, and Transparent Proxy, SSL Certificate, and Port
|
| SUI_LOG_LEVEL | `"debug"` \| `"info"` \| `"warn"` \| `"error"` | `"info"` |
|
||||||
- An advanced interface for inbound and outbound configuration
|
| SUI_DEBUG | `boolean` | `false` |
|
||||||
- Clients’ traffic cap and expiration date
|
| SUI_BIN_FOLDER | `string` | `"bin"` |
|
||||||
- Displays online clients, inbounds and outbounds with traffic statistics, and system status monitoring
|
| SUI_DB_FOLDER | `string` | `"db"` |
|
||||||
- Subscription service with ability to add external links and subscription
|
| SINGBOX_API | `string` | - |
|
||||||
- HTTPS for secure access to the web panel and subscription service (self-provided domain + SSL certificate)
|
|
||||||
- Dark/Light theme
|
</details>
|
||||||
|
|
||||||
## Environment Variables
|
## SSL 证书
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Click for details</summary>
|
<summary>点击查看详情</summary>
|
||||||
|
|
||||||
### Usage
|
### Certbot
|
||||||
|
|
||||||
| Variable | Type | Default |
|
```bash
|
||||||
| -------------- | :--------------------------------------------: | :------------ |
|
snap install core; snap refresh core
|
||||||
| SUI_LOG_LEVEL | `"debug"` \| `"info"` \| `"warn"` \| `"error"` | `"info"` |
|
snap install --classic certbot
|
||||||
| SUI_DEBUG | `boolean` | `false` |
|
ln -s /snap/bin/certbot /usr/bin/certbot
|
||||||
| SUI_BIN_FOLDER | `string` | `"bin"` |
|
|
||||||
| SUI_DB_FOLDER | `string` | `"db"` |
|
certbot certonly --standalone --register-unsafely-without-email --non-interactive --agree-tos -d <你的域名>
|
||||||
| SINGBOX_API | `string` | - |
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## SSL Certificate
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Click for details</summary>
|
|
||||||
|
|
||||||
### Certbot
|
|
||||||
|
|
||||||
```bash
|
|
||||||
snap install core; snap refresh core
|
|
||||||
snap install --classic certbot
|
|
||||||
ln -s /snap/bin/certbot /usr/bin/certbot
|
|
||||||
|
|
||||||
certbot certonly --standalone --register-unsafely-without-email --non-interactive --agree-tos -d <Your Domain Name>
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Stargazers over Time
|
|
||||||
[](https://starchart.cc/alireza0/s-ui)
|
|
||||||
|
|||||||
+1
-6
@@ -1,7 +1,6 @@
|
|||||||
---
|
|
||||||
services:
|
services:
|
||||||
s-ui:
|
s-ui:
|
||||||
image: alireza7/s-ui
|
image: admin8800/s-ui
|
||||||
container_name: s-ui
|
container_name: s-ui
|
||||||
hostname: "s-ui"
|
hostname: "s-ui"
|
||||||
volumes:
|
volumes:
|
||||||
@@ -15,8 +14,4 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- s-ui
|
- s-ui
|
||||||
entrypoint: "./entrypoint.sh"
|
entrypoint: "./entrypoint.sh"
|
||||||
|
|
||||||
networks:
|
|
||||||
s-ui:
|
|
||||||
driver: bridge
|
|
||||||
|
|
||||||
+188
-188
@@ -1,188 +1,188 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
red='\033[0;31m'
|
red='\033[0;31m'
|
||||||
green='\033[0;32m'
|
green='\033[0;32m'
|
||||||
yellow='\033[0;33m'
|
yellow='\033[0;33m'
|
||||||
plain='\033[0m'
|
plain='\033[0m'
|
||||||
|
|
||||||
cur_dir=$(pwd)
|
cur_dir=$(pwd)
|
||||||
|
|
||||||
# check root
|
# 检查 root 权限
|
||||||
[[ $EUID -ne 0 ]] && echo -e "${red}Fatal error: ${plain} Please run this script with root privilege \n " && exit 1
|
[[ $EUID -ne 0 ]] && echo -e "${red}致命错误:${plain}请使用 root 权限运行此脚本 \n " && exit 1
|
||||||
|
|
||||||
# Check OS and set release variable
|
# 检查系统并设置 release 变量
|
||||||
if [[ -f /etc/os-release ]]; then
|
if [[ -f /etc/os-release ]]; then
|
||||||
source /etc/os-release
|
source /etc/os-release
|
||||||
release=$ID
|
release=$ID
|
||||||
elif [[ -f /usr/lib/os-release ]]; then
|
elif [[ -f /usr/lib/os-release ]]; then
|
||||||
source /usr/lib/os-release
|
source /usr/lib/os-release
|
||||||
release=$ID
|
release=$ID
|
||||||
else
|
else
|
||||||
echo "Failed to check the system OS, please contact the author!" >&2
|
echo "检测系统失败,请联系作者!" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "The OS release is: $release"
|
echo "当前系统发行版为:$release"
|
||||||
|
|
||||||
arch() {
|
arch() {
|
||||||
case "$(uname -m)" in
|
case "$(uname -m)" in
|
||||||
x86_64 | x64 | amd64) echo 'amd64' ;;
|
x86_64 | x64 | amd64) echo 'amd64' ;;
|
||||||
i*86 | x86) echo '386' ;;
|
i*86 | x86) echo '386' ;;
|
||||||
armv8* | armv8 | arm64 | aarch64) echo 'arm64' ;;
|
armv8* | armv8 | arm64 | aarch64) echo 'arm64' ;;
|
||||||
armv7* | armv7 | arm) echo 'armv7' ;;
|
armv7* | armv7 | arm) echo 'armv7' ;;
|
||||||
armv6* | armv6) echo 'armv6' ;;
|
armv6* | armv6) echo 'armv6' ;;
|
||||||
armv5* | armv5) echo 'armv5' ;;
|
armv5* | armv5) echo 'armv5' ;;
|
||||||
s390x) echo 's390x' ;;
|
s390x) echo 's390x' ;;
|
||||||
*) echo -e "${green}Unsupported CPU architecture! ${plain}" && rm -f install.sh && exit 1 ;;
|
*) echo -e "${green}不支持的 CPU 架构!${plain}" && rm -f install.sh && exit 1 ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "arch: $(arch)"
|
echo "架构:$(arch)"
|
||||||
|
|
||||||
install_base() {
|
install_base() {
|
||||||
case "${release}" in
|
case "${release}" in
|
||||||
centos | almalinux | rocky | oracle)
|
centos | almalinux | rocky | oracle)
|
||||||
yum -y update && yum install -y -q wget curl tar tzdata
|
yum -y update && yum install -y -q wget curl tar tzdata
|
||||||
;;
|
;;
|
||||||
fedora)
|
fedora)
|
||||||
dnf -y update && dnf install -y -q wget curl tar tzdata
|
dnf -y update && dnf install -y -q wget curl tar tzdata
|
||||||
;;
|
;;
|
||||||
arch | manjaro | parch)
|
arch | manjaro | parch)
|
||||||
pacman -Syu && pacman -Syu --noconfirm wget curl tar tzdata
|
pacman -Syu && pacman -Syu --noconfirm wget curl tar tzdata
|
||||||
;;
|
;;
|
||||||
opensuse-tumbleweed)
|
opensuse-tumbleweed)
|
||||||
zypper refresh && zypper -q install -y wget curl tar timezone
|
zypper refresh && zypper -q install -y wget curl tar timezone
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
apt-get update && apt-get install -y -q wget curl tar tzdata
|
apt-get update && apt-get install -y -q wget curl tar tzdata
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
config_after_install() {
|
config_after_install() {
|
||||||
echo -e "${yellow}Migration... ${plain}"
|
echo -e "${yellow}正在迁移... ${plain}"
|
||||||
/usr/local/s-ui/sui migrate
|
/usr/local/s-ui/sui migrate
|
||||||
|
|
||||||
echo -e "${yellow}Install/update finished! For security it's recommended to modify panel settings ${plain}"
|
echo -e "${yellow}安装/更新完成!出于安全考虑,建议修改面板设置 ${plain}"
|
||||||
read -p "Do you want to continue with the modification [y/n]? ": config_confirm
|
read -p "是否继续修改设置 [y/n]?": config_confirm
|
||||||
if [[ "${config_confirm}" == "y" || "${config_confirm}" == "Y" ]]; then
|
if [[ "${config_confirm}" == "y" || "${config_confirm}" == "Y" ]]; then
|
||||||
echo -e "Enter the ${yellow}panel port${plain} (leave blank for existing/default value):"
|
echo -e "请输入${yellow}面板端口${plain}(留空则使用现有/默认值):"
|
||||||
read config_port
|
read config_port
|
||||||
echo -e "Enter the ${yellow}panel path${plain} (leave blank for existing/default value):"
|
echo -e "请输入${yellow}面板路径${plain}(留空则使用现有/默认值):"
|
||||||
read config_path
|
read config_path
|
||||||
|
|
||||||
# Sub configuration
|
# 订阅配置
|
||||||
echo -e "Enter the ${yellow}subscription port${plain} (leave blank for existing/default value):"
|
echo -e "请输入${yellow}订阅端口${plain}(留空则使用现有/默认值):"
|
||||||
read config_subPort
|
read config_subPort
|
||||||
echo -e "Enter the ${yellow}subscription path${plain} (leave blank for existing/default value):"
|
echo -e "请输入${yellow}订阅路径${plain}(留空则使用现有/默认值):"
|
||||||
read config_subPath
|
read config_subPath
|
||||||
|
|
||||||
# Set configs
|
# 设置配置
|
||||||
echo -e "${yellow}Initializing, please wait...${plain}"
|
echo -e "${yellow}正在初始化,请稍候...${plain}"
|
||||||
params=""
|
params=""
|
||||||
[ -z "$config_port" ] || params="$params -port $config_port"
|
[ -z "$config_port" ] || params="$params -port $config_port"
|
||||||
[ -z "$config_path" ] || params="$params -path $config_path"
|
[ -z "$config_path" ] || params="$params -path $config_path"
|
||||||
[ -z "$config_subPort" ] || params="$params -subPort $config_subPort"
|
[ -z "$config_subPort" ] || params="$params -subPort $config_subPort"
|
||||||
[ -z "$config_subPath" ] || params="$params -subPath $config_subPath"
|
[ -z "$config_subPath" ] || params="$params -subPath $config_subPath"
|
||||||
/usr/local/s-ui/sui setting ${params}
|
/usr/local/s-ui/sui setting ${params}
|
||||||
|
|
||||||
read -p "Do you want to change admin credentials [y/n]? ": admin_confirm
|
read -p "是否修改管理员账号密码 [y/n]?": admin_confirm
|
||||||
if [[ "${admin_confirm}" == "y" || "${admin_confirm}" == "Y" ]]; then
|
if [[ "${admin_confirm}" == "y" || "${admin_confirm}" == "Y" ]]; then
|
||||||
# First admin credentials
|
# 首个管理员账号密码
|
||||||
read -p "Please set up your username:" config_account
|
read -p "请设置用户名:" config_account
|
||||||
read -p "Please set up your password:" config_password
|
read -p "请设置密码:" config_password
|
||||||
|
|
||||||
# Set credentials
|
# 设置账号密码
|
||||||
echo -e "${yellow}Initializing, please wait...${plain}"
|
echo -e "${yellow}正在初始化,请稍候...${plain}"
|
||||||
/usr/local/s-ui/sui admin -username ${config_account} -password ${config_password}
|
/usr/local/s-ui/sui admin -username ${config_account} -password ${config_password}
|
||||||
else
|
else
|
||||||
echo -e "${yellow}Your current admin credentials: ${plain}"
|
echo -e "${yellow}当前管理员账号密码:${plain}"
|
||||||
/usr/local/s-ui/sui admin -show
|
/usr/local/s-ui/sui admin -show
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${red}cancel...${plain}"
|
echo -e "${red}已取消...${plain}"
|
||||||
if [[ ! -f "/usr/local/s-ui/db/s-ui.db" ]]; then
|
if [[ ! -f "/usr/local/s-ui/db/s-ui.db" ]]; then
|
||||||
local usernameTemp=$(head -c 6 /dev/urandom | base64)
|
local usernameTemp=$(head -c 6 /dev/urandom | base64)
|
||||||
local passwordTemp=$(head -c 6 /dev/urandom | base64)
|
local passwordTemp=$(head -c 6 /dev/urandom | base64)
|
||||||
echo -e "this is a fresh installation,will generate random login info for security concerns:"
|
echo -e "这是全新安装,出于安全考虑将生成随机登录信息:"
|
||||||
echo -e "###############################################"
|
echo -e "###############################################"
|
||||||
echo -e "${green}username:${usernameTemp}${plain}"
|
echo -e "${green}用户名:${usernameTemp}${plain}"
|
||||||
echo -e "${green}password:${passwordTemp}${plain}"
|
echo -e "${green}密码:${passwordTemp}${plain}"
|
||||||
echo -e "###############################################"
|
echo -e "###############################################"
|
||||||
echo -e "${red}if you forgot your login info,you can type ${green}s-ui${red} for configuration menu${plain}"
|
echo -e "${red}如果忘记登录信息,可以输入 ${green}s-ui${red} 打开配置菜单${plain}"
|
||||||
/usr/local/s-ui/sui admin -username ${usernameTemp} -password ${passwordTemp}
|
/usr/local/s-ui/sui admin -username ${usernameTemp} -password ${passwordTemp}
|
||||||
else
|
else
|
||||||
echo -e "${red} this is your upgrade,will keep old settings,if you forgot your login info,you can type ${green}s-ui${red} for configuration menu${plain}"
|
echo -e "${red}这是升级安装,将保留旧设置;如果忘记登录信息,可以输入 ${green}s-ui${red} 打开配置菜单${plain}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare_services() {
|
prepare_services() {
|
||||||
if [[ -f "/etc/systemd/system/sing-box.service" ]]; then
|
if [[ -f "/etc/systemd/system/sing-box.service" ]]; then
|
||||||
echo -e "${yellow}Stopping sing-box service... ${plain}"
|
echo -e "${yellow}正在停止 sing-box 服务... ${plain}"
|
||||||
systemctl stop sing-box
|
systemctl stop sing-box
|
||||||
rm -f /usr/local/s-ui/bin/sing-box /usr/local/s-ui/bin/runSingbox.sh /usr/local/s-ui/bin/signal
|
rm -f /usr/local/s-ui/bin/sing-box /usr/local/s-ui/bin/runSingbox.sh /usr/local/s-ui/bin/signal
|
||||||
fi
|
fi
|
||||||
if [[ -e "/usr/local/s-ui/bin" ]]; then
|
if [[ -e "/usr/local/s-ui/bin" ]]; then
|
||||||
echo -e "###############################################################"
|
echo -e "###############################################################"
|
||||||
echo -e "${green}/usr/local/s-ui/bin${red} directory exists yet!"
|
echo -e "${green}/usr/local/s-ui/bin${red} 目录已存在!"
|
||||||
echo -e "Please check the content and delete it manually after migration ${plain}"
|
echo -e "请检查其中内容,并在迁移后手动删除 ${plain}"
|
||||||
echo -e "###############################################################"
|
echo -e "###############################################################"
|
||||||
fi
|
fi
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
}
|
}
|
||||||
|
|
||||||
install_s-ui() {
|
install_s-ui() {
|
||||||
cd /tmp/
|
cd /tmp/
|
||||||
|
|
||||||
if [ $# == 0 ]; then
|
if [ $# == 0 ]; then
|
||||||
last_version=$(curl -Ls "https://api.github.com/repos/alireza0/s-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
last_version=$(curl -Ls "https://api.github.com/repos/admin8800/s-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||||
if [[ ! -n "$last_version" ]]; then
|
if [[ ! -n "$last_version" ]]; then
|
||||||
echo -e "${red}Failed to fetch s-ui version, it maybe due to Github API restrictions, please try it later${plain}"
|
echo -e "${red}获取 s-ui 版本失败,可能是 Github API 限制导致,请稍后重试${plain}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo -e "Got s-ui latest version: ${last_version}, beginning the installation..."
|
echo -e "已获取 s-ui 最新版本:${last_version},开始安装..."
|
||||||
wget -N --no-check-certificate -O /tmp/s-ui-linux-$(arch).tar.gz https://github.com/admin8800/s-ui/releases/download/${last_version}/s-ui-linux-$(arch).tar.gz
|
wget -N --no-check-certificate -O /tmp/s-ui-linux-$(arch).tar.gz https://github.com/admin8800/s-ui/releases/download/${last_version}/s-ui-linux-$(arch).tar.gz
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
echo -e "${red}Downloading s-ui failed, please be sure that your server can access Github ${plain}"
|
echo -e "${red}下载 s-ui 失败,请确认服务器可以访问 Github ${plain}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
last_version=$1
|
last_version=$1
|
||||||
url="https://github.com/admin8800/s-ui/releases/download/${last_version}/s-ui-linux-$(arch).tar.gz"
|
url="https://github.com/admin8800/s-ui/releases/download/${last_version}/s-ui-linux-$(arch).tar.gz"
|
||||||
echo -e "Beginning the install s-ui v$1"
|
echo -e "开始安装 s-ui v$1"
|
||||||
wget -N --no-check-certificate -O /tmp/s-ui-linux-$(arch).tar.gz ${url}
|
wget -N --no-check-certificate -O /tmp/s-ui-linux-$(arch).tar.gz ${url}
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
echo -e "${red}download s-ui v$1 failed,please check the version exists${plain}"
|
echo -e "${red}下载 s-ui v$1 失败,请检查该版本是否存在${plain}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -e /usr/local/s-ui/ ]]; then
|
if [[ -e /usr/local/s-ui/ ]]; then
|
||||||
systemctl stop s-ui
|
systemctl stop s-ui
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tar zxvf s-ui-linux-$(arch).tar.gz
|
tar zxvf s-ui-linux-$(arch).tar.gz
|
||||||
rm s-ui-linux-$(arch).tar.gz -f
|
rm s-ui-linux-$(arch).tar.gz -f
|
||||||
|
|
||||||
chmod +x s-ui/sui s-ui/s-ui.sh
|
chmod +x s-ui/sui s-ui/s-ui.sh
|
||||||
cp s-ui/s-ui.sh /usr/bin/s-ui
|
cp s-ui/s-ui.sh /usr/bin/s-ui
|
||||||
cp -rf s-ui /usr/local/
|
cp -rf s-ui /usr/local/
|
||||||
cp -f s-ui/*.service /etc/systemd/system/
|
cp -f s-ui/*.service /etc/systemd/system/
|
||||||
rm -rf s-ui
|
rm -rf s-ui
|
||||||
|
|
||||||
config_after_install
|
config_after_install
|
||||||
prepare_services
|
prepare_services
|
||||||
|
|
||||||
systemctl enable s-ui --now
|
systemctl enable s-ui --now
|
||||||
|
|
||||||
echo -e "${green}s-ui v${last_version}${plain} installation finished, it is up and running now..."
|
echo -e "${green}s-ui v${last_version}${plain} 安装完成,现已启动并运行..."
|
||||||
echo -e "You may access the Panel with following URL(s):${green}"
|
echo -e "你可以通过以下 URL 访问面板:${green}"
|
||||||
/usr/local/s-ui/sui uri
|
/usr/local/s-ui/sui uri
|
||||||
echo -e "${plain}"
|
echo -e "${plain}"
|
||||||
echo -e ""
|
echo -e ""
|
||||||
s-ui help
|
s-ui help
|
||||||
}
|
}
|
||||||
|
|
||||||
echo -e "${green}Executing...${plain}"
|
echo -e "${green}正在执行...${plain}"
|
||||||
install_base
|
install_base
|
||||||
install_s-ui $1
|
install_s-ui $1
|
||||||
|
|||||||
Reference in New Issue
Block a user