Compare commits

..

10 Commits

Author SHA1 Message Date
Alireza Ahmadi 86379818a2 v1.3.11 2026-02-28 13:28:48 +01:00
Alireza Ahmadi 8a07d2df7e Merge pull request #1033 from alireza0/dependabot/github_actions/actions/upload-artifact-7
Bump actions/upload-artifact from 6 to 7
2026-02-28 02:03:57 +01:00
Alireza Ahmadi 7d63da8be3 Merge pull request #1032 from alireza0/dependabot/github_actions/actions/download-artifact-8
Bump actions/download-artifact from 7 to 8
2026-02-28 02:03:39 +01:00
Alireza Ahmadi 06ee9cfce2 Sing-Box v1.12.23 2026-02-28 02:02:10 +01:00
Alireza Ahmadi 13d475da20 fix crash on restart due to change #1030 2026-02-28 01:52:34 +01:00
dependabot[bot] fbf46a72b0 Bump actions/upload-artifact from 6 to 7
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-27 16:53:23 +00:00
dependabot[bot] 5bb15ff2c9 Bump actions/download-artifact from 7 to 8
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7 to 8.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-27 16:53:18 +00:00
Alireza Ahmadi 5812d6a827 fix docker logs and db #1019 2026-02-17 21:14:37 +01:00
Seva 083f19324f Fix directory when running as administrator (#1009)
* Update install-windows.bat

* Update s-ui-windows.bat

* Update install-windows.bat

* Update build-windows.bat
2026-02-17 20:26:16 +01:00
Alireza Ahmadi dd07abf501 fix inbound delete affects on client #1008 2026-02-17 20:08:03 +01:00
18 changed files with 99 additions and 48 deletions
+2 -2
View File
@@ -23,7 +23,7 @@ jobs:
npm install
npm run build
- name: Upload frontend build artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: frontend-dist
path: frontend/dist/
@@ -35,7 +35,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v6.0.2
- name: Download frontend build artifact
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
name: frontend-dist
path: frontend_dist
+1 -1
View File
@@ -102,7 +102,7 @@ jobs:
run: tar -zcvf s-ui-linux-${{ matrix.platform }}.tar.gz s-ui
- name: Upload files to Artifacts
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: s-ui-linux-${{ matrix.platform }}
path: ./s-ui-linux-${{ matrix.platform }}.tar.gz
+2 -2
View File
@@ -85,7 +85,7 @@ jobs:
zip -r "s-ui-windows-amd64.zip" s-ui-windows
- name: Upload files to Artifacts
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: s-ui-windows-amd64
path: ./s-ui-windows-amd64.zip
@@ -157,7 +157,7 @@ jobs:
zip -r "s-ui-windows-arm64.zip" s-ui-windows
- name: Upload ARM64 files to Artifacts
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: s-ui-windows-arm64
path: ./s-ui-windows-arm64.zip
+2 -8
View File
@@ -386,13 +386,7 @@ func (a *ApiService) DeleteToken(c *gin.Context) {
}
func (a *ApiService) GetSingboxConfig(c *gin.Context) {
config, err := a.ConfigService.GetConfig("")
if err != nil {
c.Status(400)
c.Writer.WriteString(err.Error())
return
}
rawConfig, err := json.MarshalIndent(config, "", " ")
rawConfig, err := a.ConfigService.GetConfig("")
if err != nil {
c.Status(400)
c.Writer.WriteString(err.Error())
@@ -400,7 +394,7 @@ func (a *ApiService) GetSingboxConfig(c *gin.Context) {
}
c.Header("Content-Type", "application/json")
c.Header("Content-Disposition", "attachment; filename=config_"+time.Now().Format("20060102-150405")+".json")
c.Writer.Write(rawConfig)
c.Writer.Write(*rawConfig)
}
func (a *ApiService) GetCheckOutbound(c *gin.Context) {
+1 -1
View File
@@ -79,7 +79,7 @@ func (a *APP) Start() error {
return err
}
err = a.configService.StartCore("")
err = a.configService.StartCore()
if err != nil {
logger.Error(err)
}
+1 -1
View File
@@ -1 +1 @@
1.3.10
1.3.11
+3
View File
@@ -83,6 +83,9 @@ func (c *Core) Start(sbConfig []byte) error {
func (c *Core) Stop() error {
c.isRunning = false
if c.instance != nil {
return nil
}
return c.instance.Close()
}
+1 -1
View File
@@ -13,5 +13,5 @@ func NewCheckCoreJob() *CheckCoreJob {
}
func (s *CheckCoreJob) Run() {
s.ConfigService.StartCore("")
s.ConfigService.StartCore()
}
+6 -2
View File
@@ -1,4 +1,8 @@
#!/bin/sh
./sui migrate
./sui
DB_PATH="${SUI_DB_FOLDER:-/app/db}/s-ui.db"
if [ -f "$DB_PATH" ]; then
./sui migrate
fi
exec ./sui
+2 -2
View File
@@ -10,7 +10,7 @@ require (
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/robfig/cron/v3 v3.0.1
github.com/sagernet/sing v0.7.18
github.com/sagernet/sing-box v1.12.21
github.com/sagernet/sing-box v1.12.23
github.com/sagernet/sing-dns v0.4.6
github.com/shirou/gopsutil/v4 v4.26.1
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
@@ -20,7 +20,7 @@ require (
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
filippo.io/edwards25519 v1.2.0 // indirect
github.com/ajg/form v1.5.1 // indirect
github.com/akutz/memconn v0.1.0 // indirect
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
+6 -2
View File
@@ -1,5 +1,9 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw=
filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A=
@@ -217,8 +221,8 @@ github.com/sagernet/quic-go v0.52.0-sing-box-mod.3 h1:ySqffGm82rPqI1TUPqmtHIYd12
github.com/sagernet/quic-go v0.52.0-sing-box-mod.3/go.mod h1:OV+V5kEBb8kJS7k29MzDu6oj9GyMc7HA07sE1tedxz4=
github.com/sagernet/sing v0.7.18 h1:iZHkaru1/MoHugx3G+9S3WG4owMewKO/KvieE2Pzk4E=
github.com/sagernet/sing v0.7.18/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing-box v1.12.21 h1:SyTTag/f/JQmP7/1tTVlbhfKgAzB84sFhocmnwmANB8=
github.com/sagernet/sing-box v1.12.21/go.mod h1:jjM3DQWWJSMW3U0uv3AxYRjyLnHu/SXN3A6Svex83/w=
github.com/sagernet/sing-box v1.12.23 h1:egmRGPpzMZVmc4iCl0T1wBBAZea3NTxDmi//b3sXSsQ=
github.com/sagernet/sing-box v1.12.23/go.mod h1:jjM3DQWWJSMW3U0uv3AxYRjyLnHu/SXN3A6Svex83/w=
github.com/sagernet/sing-dns v0.4.6 h1:mjZC0o6d5sQ1sraoOBbK3G3apCbuL8wWYwu2RNu5rbM=
github.com/sagernet/sing-dns v0.4.6/go.mod h1:dweQs54ng2YGzoJfz+F9dGuDNdP5pJ3PLeggnK5VWc8=
github.com/sagernet/sing-mux v0.3.4 h1:ZQplKl8MNXutjzbMVtWvWG31fohhgOfCuUZR4dVQ8+s=
+17 -6
View File
@@ -23,15 +23,26 @@ func InitLogger(level logging.Level) {
var backend logging.Backend
var format logging.Formatter
backend, err = logging.NewSyslogBackend("")
if err != nil {
fmt.Println("Unable to use syslog: " + err.Error())
backend = logging.NewLogBackend(os.Stderr, "", 0)
_, inContainer := os.LookupEnv("container")
if !inContainer {
if _, statErr := os.Stat("/.dockerenv"); statErr == nil {
inContainer = true
}
}
if err != nil {
if inContainer {
backend = logging.NewLogBackend(os.Stderr, "", 0)
format = logging.MustStringFormatter(`%{time:2006/01/02 15:04:05} %{level} - %{message}`)
} else {
format = logging.MustStringFormatter(`%{level} - %{message}`)
backend, err = logging.NewSyslogBackend("")
if err != nil {
fmt.Println("Unable to use syslog: " + err.Error())
backend = logging.NewLogBackend(os.Stderr, "", 0)
}
if err != nil {
format = logging.MustStringFormatter(`%{time:2006/01/02 15:04:05} %{level} - %{message}`)
} else {
format = logging.MustStringFormatter(`%{level} - %{message}`)
}
}
backendFormatter := logging.NewBackendFormatter(backend, format)
+18 -6
View File
@@ -222,10 +222,16 @@ func (s *ClientService) UpdateClientsOnInboundAdd(tx *gorm.DB, initIds string, i
}
func (s *ClientService) UpdateClientsOnInboundDelete(tx *gorm.DB, id uint, tag string) error {
var clientIds []uint
err := tx.Raw("SELECT clients.id FROM clients, json_each(clients.inbounds) AS je WHERE je.value = ?", id).Scan(&clientIds).Error
if err != nil {
return err
}
if len(clientIds) == 0 {
return nil
}
var clients []model.Client
err := tx.Table("clients").
Where("EXISTS (SELECT 1 FROM json_each(clients.inbounds) WHERE json_each.value = ?)", id).
Find(&clients).Error
err = tx.Model(model.Client{}).Where("id IN ?", clientIds).Find(&clients).Error
if err != nil {
return err
}
@@ -265,10 +271,16 @@ func (s *ClientService) UpdateClientsOnInboundDelete(tx *gorm.DB, id uint, tag s
func (s *ClientService) UpdateLinksByInboundChange(tx *gorm.DB, inbounds *[]model.Inbound, hostname string, oldTag string) error {
var err error
for _, inbound := range *inbounds {
var clientIds []uint
err = tx.Raw("SELECT clients.id FROM clients, json_each(clients.inbounds) AS je WHERE je.value = ?", inbound.Id).Scan(&clientIds).Error
if err != nil {
return err
}
if len(clientIds) == 0 {
continue
}
var clients []model.Client
err = tx.Table("clients").
Where("EXISTS (SELECT 1 FROM json_each(clients.inbounds) WHERE json_each.value = ?)", inbound.Id).
Find(&clients).Error
err = tx.Model(model.Client{}).Where("id IN ?", clientIds).Find(&clients).Error
if err != nil {
return err
}
+32 -13
View File
@@ -44,7 +44,7 @@ func NewConfigService(core *core.Core) *ConfigService {
return &ConfigService{}
}
func (s *ConfigService) GetConfig(data string) (*SingBoxConfig, error) {
func (s *ConfigService) GetConfig(data string) (*[]byte, error) {
var err error
if len(data) == 0 {
data, err = s.SettingService.GetConfig()
@@ -74,22 +74,22 @@ func (s *ConfigService) GetConfig(data string) (*SingBoxConfig, error) {
if err != nil {
return nil, err
}
return &singboxConfig, nil
rawConfig, err := json.MarshalIndent(singboxConfig, "", " ")
if err != nil {
return nil, err
}
return &rawConfig, nil
}
func (s *ConfigService) StartCore(defaultConfig string) error {
func (s *ConfigService) StartCore() error {
if corePtr.IsRunning() {
return nil
}
singboxConfig, err := s.GetConfig(defaultConfig)
rawConfig, err := s.GetConfig("")
if err != nil {
return err
}
rawConfig, err := json.MarshalIndent(singboxConfig, "", " ")
if err != nil {
return err
}
err = corePtr.Start(rawConfig)
err = corePtr.Start(*rawConfig)
if err != nil {
logger.Error("start sing-box err:", err.Error())
return err
@@ -103,15 +103,34 @@ func (s *ConfigService) RestartCore() error {
if err != nil {
return err
}
return s.StartCore("")
return s.StartCore()
}
func (s *ConfigService) restartCoreWithConfig(config json.RawMessage) error {
err := s.StopCore()
var err error
defer func() {
if err != nil {
corePtr.Stop()
logger.Error("restart sing-box err:", err.Error())
} else {
logger.Info("sing-box restarted with new config")
}
}()
if corePtr.IsRunning() {
err = corePtr.GetInstance().Close()
if err != nil {
return err
}
}
rawConfig, err := s.GetConfig(string(config))
if err != nil {
return err
}
return s.StartCore(string(config))
err = corePtr.Start(*rawConfig)
if err != nil {
return err
}
return nil
}
func (s *ConfigService) StopCore() error {
@@ -144,7 +163,7 @@ func (s *ConfigService) Save(obj string, act string, data json.RawMessage, initU
tx.Commit()
// Try to start core if it is not running
if !corePtr.IsRunning() {
s.StartCore("")
s.StartCore()
}
} else {
tx.Rollback()
+2
View File
@@ -3,6 +3,8 @@ setlocal enabledelayedexpansion
echo Building S-UI for Windows...
cd /d "%~dp0"
REM Check if Go is installed
go version >nul 2>&1
if errorlevel 1 (
+1
View File
@@ -14,6 +14,7 @@ if %errorLevel% neq 0 (
exit /b 1
)
cd /d "%~dp0"
REM Set installation directory
set "INSTALL_DIR=C:\Program Files\s-ui"
set "SERVICE_NAME=s-ui"
+1
View File
@@ -4,6 +4,7 @@ setlocal enabledelayedexpansion
REM S-UI Windows Control Script
REM This script provides a menu-driven interface for managing S-UI on Windows
cd /d "%~dp0"
set "SERVICE_NAME=s-ui"
set "INSTALL_DIR=%SUI_HOME%"
if "%INSTALL_DIR%"=="" set "INSTALL_DIR=C:\Program Files\s-ui"