diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f41514c51..34c359174 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,6 +16,7 @@ on: - All - Binary - Android + - Windows - Apple - app-store - iOS @@ -793,6 +794,90 @@ jobs: ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }} SERVICE_ACCOUNT_CREDENTIALS: ${{ secrets.SERVICE_ACCOUNT_CREDENTIALS }} + build_windows_client: + name: Build Windows client + if: (github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Windows') && github.ref != 'refs/heads/oldstable' + runs-on: windows-latest + needs: + - calculate_version + steps: + - name: Checkout + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + with: + fetch-depth: 0 + submodules: 'recursive' + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: ~1.25.11 + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + package_json_file: clients/desktop/package.json + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 26 + cache: pnpm + cache-dependency-path: | + clients/desktop/pnpm-lock.yaml + clients/desktop/dashboard/pnpm-lock.yaml + - name: Set tag + run: |- + git ls-remote --exit-code --tags origin v${{ needs.calculate_version.outputs.version }} + if ($LASTEXITCODE -ne 0) { + "PUBLISHED=false" >> $env:GITHUB_ENV + } + git tag v${{ needs.calculate_version.outputs.version }} -f + - name: Checkout main branch + if: github.ref == 'refs/heads/testing' + run: |- + git -C clients/desktop checkout main + - name: Checkout submodule recursive + run: |- + git -C clients/desktop submodule update --init --recursive + - name: Update version + if: github.event_name == 'workflow_dispatch' + run: |- + go run -v ./cmd/internal/update_desktop_version --ci + - name: Update nightly version + if: github.event_name != 'workflow_dispatch' + run: |- + go run -v ./cmd/internal/update_desktop_version --ci --nightly + - name: Setup signing + run: |- + $certificatePath = Join-Path $env:RUNNER_TEMP "windows-signing.p12" + [IO.File]::WriteAllBytes($certificatePath, [Convert]::FromBase64String($env:WINDOWS_CERTIFICATES_P12)) + @{ + windows = @{ + certificateFile = $certificatePath + certificatePassword = $env:WINDOWS_P12_PASSWORD + } + } | ConvertTo-Json -Depth 3 | Set-Content -Encoding utf8NoBOM clients/desktop/signing.local.json + env: + WINDOWS_CERTIFICATES_P12: ${{ secrets.WINDOWS_CERTIFICATES_P12 }} + WINDOWS_P12_PASSWORD: ${{ secrets.WINDOWS_P12_PASSWORD }} + - name: Install dependencies + run: |- + pnpm -C clients/desktop install + - name: Build + run: |- + pnpm -C clients/desktop package:win + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Prepare upload + run: |- + $artifacts = @(Get-ChildItem clients/desktop/release/SFW-*.exe -File) + if ($artifacts.Count -ne 3) { + throw "expected 3 Windows installers, found $($artifacts.Count)" + } + New-Item -ItemType Directory -Force dist | Out-Null + Copy-Item $artifacts.FullName dist + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: binary-windows-client + path: 'dist' build_apple: name: Build Apple clients runs-on: macos-26 @@ -977,7 +1062,7 @@ jobs: path: 'dist' upload: name: Upload builds - if: "!failure() && github.event_name == 'workflow_dispatch' && (inputs.build == 'All' || inputs.build == 'Binary' || inputs.build == 'Android' || inputs.build == 'Apple' || inputs.build == 'macOS-standalone')" + if: "!failure() && github.event_name == 'workflow_dispatch' && (inputs.build == 'All' || inputs.build == 'Binary' || inputs.build == 'Android' || inputs.build == 'Windows' || inputs.build == 'Apple' || inputs.build == 'macOS-standalone')" runs-on: ubuntu-latest needs: - calculate_version @@ -985,6 +1070,7 @@ jobs: - build_darwin - build_windows - build_android + - build_windows_client - build_apple steps: - name: Checkout diff --git a/.gitmodules b/.gitmodules index 45ffb5639..cc95289e1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "clients/android"] path = clients/android url = https://github.com/SagerNet/sing-box-for-android.git +[submodule "clients/desktop"] + path = clients/desktop + url = https://github.com/SagerNet/sing-box-for-desktop.git diff --git a/clients/desktop b/clients/desktop new file mode 160000 index 000000000..cebee0d52 --- /dev/null +++ b/clients/desktop @@ -0,0 +1 @@ +Subproject commit cebee0d527c4e5d5500f971553628e0dfa8bae0f diff --git a/docs/clients/desktop/features.md b/docs/clients/desktop/features.md new file mode 100644 index 000000000..bb399a03b --- /dev/null +++ b/docs/clients/desktop/features.md @@ -0,0 +1,9 @@ +# :material-decagram: Features + +#### Service + +SFW runs sing-box as a system service, so no administrator elevation is required for daily use. + +### Chore + +* The working directory is located at `C:\ProgramData\sing-box-daemon` diff --git a/docs/clients/desktop/index.md b/docs/clients/desktop/index.md new file mode 100644 index 000000000..332636ebd --- /dev/null +++ b/docs/clients/desktop/index.md @@ -0,0 +1,22 @@ +--- +icon: material/laptop +--- + +# sing-box for Desktop + +SFW allows users to manage and run local or remote sing-box configuration files, and provides +platform-specific function implementation, such as TUN transparent proxy implementation. + +Linux support is on the way. + +## :material-graph: Requirements + +* Windows 10+ (x64 / x86 / arm64) + +## :material-download: Download + +* [GitHub Releases](https://github.com/SagerNet/sing-box/releases) + +## :material-source-repository: Source code + +* [GitHub](https://github.com/SagerNet/sing-box-for-desktop) diff --git a/docs/clients/index.md b/docs/clients/index.md index 45d2c9a94..c1232407e 100644 --- a/docs/clients/index.md +++ b/docs/clients/index.md @@ -6,7 +6,8 @@ Maintained by Project S to provide a unified experience and platform-specific fu |---------------------------------------|------------------------------------------| | :material-android: Android | [sing-box for Android](./android/) | | :material-apple: iOS/macOS/Apple tvOS | [sing-box for Apple platforms](./apple/) | -| :material-laptop: Desktop | Working in progress | +| :material-microsoft-windows: Windows | [sing-box for Desktop](./desktop/) | +| :material-linux: Linux | Working in progress | Some third-party projects that claim to use sing-box or use sing-box as a selling point are not listed here. The core motivation of the maintainers of such projects is to acquire more users, and even though they provide friendly VPN diff --git a/docs/clients/index.zh.md b/docs/clients/index.zh.md index 736b42ea2..d2fbb4d4b 100644 --- a/docs/clients/index.zh.md +++ b/docs/clients/index.zh.md @@ -6,7 +6,8 @@ |---------------------------------------|------------------------------------------| | :material-android: Android | [sing-box for Android](./android/) | | :material-apple: iOS/macOS/Apple tvOS | [sing-box for Apple platforms](./apple/) | -| :material-laptop: Desktop | 施工中 | +| :material-microsoft-windows: Windows | [sing-box for Desktop](./desktop/) | +| :material-linux: Linux | 施工中 | 此处没有列出一些声称使用或以 sing-box 为卖点的第三方项目。此类项目维护者的动机是获得更多用户,即使它们提供友好的商业 VPN 客户端功能, 但代码质量很差且包含广告。 diff --git a/mkdocs.yml b/mkdocs.yml index da838d572..f6beec14c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -62,6 +62,9 @@ nav: - Apple platforms: - clients/apple/index.md - Features: clients/apple/features.md + - Desktop: + - clients/desktop/index.md + - Features: clients/desktop/features.md - General: clients/general.md - Privacy policy: clients/privacy.md - Manual: