From 08e5ae1dc960f218d3cbddaae3d6394c24184f02 Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Tue, 16 Sep 2025 18:18:17 +0100 Subject: [PATCH 01/45] add renovate configuration --- renovate.json | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 00000000..2f1948a0 --- /dev/null +++ b/renovate.json @@ -0,0 +1,121 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended", + + ":semanticCommits", + ":semanticCommitsAll", + ":rebaseStalePrs", + ":prConcurrentLimit10", + ":prHourlyLimit4", + ":labels(renovate)", + ":disableRateLimiting" + ], + + "timezone": "Etc/UTC", + "assignees": [], + "reviewers": [], + "dependencyDashboard": true, + "dependencyDashboardTitle": "Renovate Dashboard", + + "enabledManagers": [ + "gomod", + "npm", + "dockerfile", + "docker-compose", + "github-actions" + ], + + "npm": { + "managerFilePatterns": [ + "/^frontend/package.json$/" + ] + }, + + "ignorePaths": [ + "**/node_modules/**", + "**/dist/**", + "**/build/**", + "**/public/**", + "**/.svelte-kit/**", + "**/sscm/**", + "**/steamcmd/**", + "**/Steam/**", + "**/steamapps/**", + "**/UIMod/**", + "**/saves/**" + ], + + "packageRules": [ + { + "matchManagers": ["github-actions"], + "groupName": "github-actions", + "labels": ["ci", "renovate"], + "automerge": true, + "automergeType": "branch", + "platformAutomerge": true + }, + { + "matchManagers": ["dockerfile", "docker-compose"], + "groupName": "docker base images", + "labels": ["docker", "renovate"], + "pinDigests": true, + "matchUpdateTypes": ["digest"], + "automerge": true, + "automergeType": "branch", + "platformAutomerge": true + }, + { + "matchManagers": ["gomod"], + "groupName": "go modules (minor/patch)", + "labels": ["go", "renovate"], + "matchUpdateTypes": ["minor", "patch"], + "automerge": true, + "automergeType": "branch", + "platformAutomerge": true + }, + { + "matchManagers": ["gomod"], + "groupName": "go modules (major)", + "labels": ["go", "major"], + "matchUpdateTypes": ["major"], + "automerge": false + }, + { + "matchManagers": ["npm"], + "matchFileNames": [ + "^frontend/" + ], + "labels": ["frontend", "npm", "renovate"], + "matchUpdateTypes": ["patch", "minor"], + "groupName": "frontend deps (minor/patch)", + "automerge": true, + "automergeType": "branch", + "platformAutomerge": true + }, + { + "matchManagers": ["npm"], + "matchFileNames": [ + "^frontend/" + ], + "labels": ["frontend", "npm", "major"], + "matchUpdateTypes": ["major"], + "groupName": "frontend deps (major)", + "automerge": false + }, + { + "matchPackageNames": [ + "golang.org/x/*", + "github.com/golang/*", + "github.com/sirupsen/logrus", + "github.com/bwmarrin/discordgo" + ], + "labels": ["go", "important"], + "separateMinorPatch": false + } + ], + + "prCreation": "not-pending", + "minimumReleaseAge": "2 days", + "commitBodyTable": true +} From d051aa8575684d6de0e68c264dcedc0c7faa2c12 Mon Sep 17 00:00:00 2001 From: JLangisch Date: Wed, 17 Sep 2025 06:50:31 +0200 Subject: [PATCH 02/45] remove empty line from renovate.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- renovate.json | 1 - 1 file changed, 1 deletion(-) diff --git a/renovate.json b/renovate.json index 2f1948a0..c731a011 100644 --- a/renovate.json +++ b/renovate.json @@ -2,7 +2,6 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:recommended", - ":semanticCommits", ":semanticCommitsAll", ":rebaseStalePrs", From 31c82fd671c76129e21ffe19ca458c7112809f1c Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Thu, 18 Sep 2025 13:18:25 +0100 Subject: [PATCH 03/45] Update renovate.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- renovate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index c731a011..eeeaa669 100644 --- a/renovate.json +++ b/renovate.json @@ -27,7 +27,7 @@ "npm": { "managerFilePatterns": [ - "/^frontend/package.json$/" + "frontend/package.json" ] }, From da0b87e8dc56f2d7d754dd2310e598a6e8bd8321 Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Thu, 18 Sep 2025 13:26:21 +0100 Subject: [PATCH 04/45] Removes automerge and adds --- renovate.json | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/renovate.json b/renovate.json index eeeaa669..3af95a55 100644 --- a/renovate.json +++ b/renovate.json @@ -12,8 +12,10 @@ ], "timezone": "Etc/UTC", + "automerge": false, + "platformAutomerge": false, "assignees": [], - "reviewers": [], + "reviewers": ["JacksonTheMaster"], "dependencyDashboard": true, "dependencyDashboardTitle": "Renovate Dashboard", @@ -50,9 +52,9 @@ "matchManagers": ["github-actions"], "groupName": "github-actions", "labels": ["ci", "renovate"], - "automerge": true, + "automerge": false, "automergeType": "branch", - "platformAutomerge": true + "platformAutomerge": false }, { "matchManagers": ["dockerfile", "docker-compose"], @@ -60,18 +62,18 @@ "labels": ["docker", "renovate"], "pinDigests": true, "matchUpdateTypes": ["digest"], - "automerge": true, + "automerge": false, "automergeType": "branch", - "platformAutomerge": true + "platformAutomerge": false }, { "matchManagers": ["gomod"], "groupName": "go modules (minor/patch)", "labels": ["go", "renovate"], "matchUpdateTypes": ["minor", "patch"], - "automerge": true, + "automerge": false, "automergeType": "branch", - "platformAutomerge": true + "platformAutomerge": false }, { "matchManagers": ["gomod"], @@ -88,9 +90,9 @@ "labels": ["frontend", "npm", "renovate"], "matchUpdateTypes": ["patch", "minor"], "groupName": "frontend deps (minor/patch)", - "automerge": true, + "automerge": false, "automergeType": "branch", - "platformAutomerge": true + "platformAutomerge": false }, { "matchManagers": ["npm"], @@ -106,7 +108,6 @@ "matchPackageNames": [ "golang.org/x/*", "github.com/golang/*", - "github.com/sirupsen/logrus", "github.com/bwmarrin/discordgo" ], "labels": ["go", "important"], From 365a93872ad86e570254c1a781f1c142d86898a0 Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Thu, 18 Sep 2025 13:27:32 +0100 Subject: [PATCH 05/45] Add mitoskalandiel to reviewers in renovate.json --- renovate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index 3af95a55..ed7134d8 100644 --- a/renovate.json +++ b/renovate.json @@ -15,7 +15,7 @@ "automerge": false, "platformAutomerge": false, "assignees": [], - "reviewers": ["JacksonTheMaster"], + "reviewers": ["JacksonTheMaster", "mitoskalandiel"], "dependencyDashboard": true, "dependencyDashboardTitle": "Renovate Dashboard", From b2f679345a2d2915dec9d48aca3507a0b947b688 Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Thu, 18 Sep 2025 13:30:15 +0100 Subject: [PATCH 06/45] Add baseBranches configuration to renovate.json --- renovate.json | 1 + 1 file changed, 1 insertion(+) diff --git a/renovate.json b/renovate.json index ed7134d8..618ae955 100644 --- a/renovate.json +++ b/renovate.json @@ -15,6 +15,7 @@ "automerge": false, "platformAutomerge": false, "assignees": [], + "baseBranches": ["nightly"], "reviewers": ["JacksonTheMaster", "mitoskalandiel"], "dependencyDashboard": true, "dependencyDashboardTitle": "Renovate Dashboard", From b97863e93159a8b0b439bbcdebf4d99b294be587 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 19 Sep 2025 00:14:45 +0200 Subject: [PATCH 07/45] Add game version extraction functionality to detection manager and store in runtime config feature request MrDrummer25 --- src/config/getters.go | 6 ++++++ src/config/setters.go | 8 ++++++++ src/config/vars.go | 1 + src/managers/detectionmgr/detector.go | 14 ++++++++++++++ src/managers/detectionmgr/handlers.go | 6 ++++++ src/managers/detectionmgr/types.go | 1 + 6 files changed, 36 insertions(+) diff --git a/src/config/getters.go b/src/config/getters.go index f07be86a..936a4bbd 100644 --- a/src/config/getters.go +++ b/src/config/getters.go @@ -487,3 +487,9 @@ func GetAllowAutoGameServerUpdates() bool { defer ConfigMu.RUnlock() return AllowAutoGameServerUpdates } + +func GetExtractedGameVersion() string { + ConfigMu.RLock() + defer ConfigMu.RUnlock() + return ExtractedGameVersion +} diff --git a/src/config/setters.go b/src/config/setters.go index 10bf86fd..401b53c5 100644 --- a/src/config/setters.go +++ b/src/config/setters.go @@ -38,6 +38,14 @@ func SetCurrentBranchBuildID(value string) error { return nil } +func SetExtractedGameVersion(value string) error { + ConfigMu.Lock() + defer ConfigMu.Unlock() + + ExtractedGameVersion = value + return nil +} + // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT diff --git a/src/config/vars.go b/src/config/vars.go index 3c37b51d..0ba6fb1a 100644 --- a/src/config/vars.go +++ b/src/config/vars.go @@ -62,6 +62,7 @@ var ( AutoStartServerOnStartup bool SSUIIdentifier string CurrentBranchBuildID string // ONLY RUNTIME + ExtractedGameVersion string // ONLY RUNTIME ) // Discord integration diff --git a/src/managers/detectionmgr/detector.go b/src/managers/detectionmgr/detector.go index ddccf19c..0aec9a7d 100644 --- a/src/managers/detectionmgr/detector.go +++ b/src/managers/detectionmgr/detector.go @@ -7,6 +7,7 @@ import ( "strings" "time" + "github.com/JacksonTheMaster/StationeersServerUI/v5/src/config" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/discordbot" ) @@ -240,6 +241,19 @@ func (d *Detector) processRegexPatterns(logMessage string) { }) }, }, + { + pattern: regexp.MustCompile(`Version\s*:\s*(\d+\.\d+\.\d+\.\d+)`), + handler: func(matches []string, logMessage string) { + version := matches[1] + d.triggerEvent(Event{ + Type: EventVersionExtracted, + Message: fmt.Sprintf("Version %s detected", version), + RawLog: logMessage, + Timestamp: time.Now().Format(time.RFC3339), + }) + config.SetExtractedGameVersion(version) + }, + }, } for _, p := range patterns { diff --git a/src/managers/detectionmgr/handlers.go b/src/managers/detectionmgr/handlers.go index abcc6b9c..d8ff75f3 100644 --- a/src/managers/detectionmgr/handlers.go +++ b/src/managers/detectionmgr/handlers.go @@ -66,6 +66,12 @@ func DefaultHandlers() map[EventType]Handler { ssestream.BroadcastDetectionEvent(message) discordbot.SendMessageToStatusChannel(message) }, + EventVersionExtracted: func(event Event) { + message := fmt.Sprintf("๐ŸŽฎ [Gameserver] ๐Ÿ“ฆ Version %s detected", event.Message) + logger.Detection.Info(message) + ssestream.BroadcastDetectionEvent(message) + discordbot.SendMessageToStatusChannel(message) + }, EventServerRunning: func(event Event) { message := "๐ŸŽฎ [Gameserver] โœ… Server process has started!" logger.Detection.Info(message) diff --git a/src/managers/detectionmgr/types.go b/src/managers/detectionmgr/types.go index c24773f6..efa327d2 100644 --- a/src/managers/detectionmgr/types.go +++ b/src/managers/detectionmgr/types.go @@ -18,6 +18,7 @@ const ( EventSettingsChanged EventType = "SETTINGS_CHANGED" EventServerHosted EventType = "SERVER_HOSTED" EventNewGameStarted EventType = "NEW_GAME_STARTED" + EventVersionExtracted EventType = "VERSION_EXTRACTED" EventServerRunning EventType = "SERVER_RUNNING" EventCustomDetection EventType = "CUSTOM_DETECTION" ) From 8172cfd36bab0a4210ffed1b48a55cf200cd3558 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 19 Sep 2025 04:20:32 +0200 Subject: [PATCH 08/45] fix wiki link --- src/core/loader/terminalmsg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/loader/terminalmsg.go b/src/core/loader/terminalmsg.go index 22125f41..4f6803dc 100644 --- a/src/core/loader/terminalmsg.go +++ b/src/core/loader/terminalmsg.go @@ -48,6 +48,6 @@ func printFirstTimeSetupMessage() { logger.Core.Cleanf(" โ”‚ โ€ข Configure your server by visiting the WebUI! โ”‚") logger.Core.Cleanf(" โ”‚ โ€ข Support is provided at https://discord.gg/8n3vN92MyJ โ”‚") logger.Core.Cleanf(" โ”‚ โ€ข For more details, check the GitHub Wiki: โ”‚") - logger.Core.Cleanf(" โ”‚ โ€ข https://github.com/JacksonTheMaster/StationeersServerUI/v5/wiki โ”‚") + logger.Core.Cleanf(" โ”‚ โ€ข https://github.com/SteamServerUI/StationeersServerUI/v5/wiki โ”‚") logger.Core.Cleanf(" โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜") } From 5227a64937546c60583a6b1224edab1d5b923865 Mon Sep 17 00:00:00 2001 From: akirilov <***REMOVED***> Date: Fri, 19 Sep 2025 05:47:07 +0200 Subject: [PATCH 09/45] Added a check to prevent a world name with spaces --- UIMod/onboard_bundled/twoboxform/twoboxform.js | 6 ++++++ src/config/config.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/UIMod/onboard_bundled/twoboxform/twoboxform.js b/UIMod/onboard_bundled/twoboxform/twoboxform.js index 3423361b..bef99749 100644 --- a/UIMod/onboard_bundled/twoboxform/twoboxform.js +++ b/UIMod/onboard_bundled/twoboxform/twoboxform.js @@ -138,6 +138,12 @@ document.addEventListener('DOMContentLoaded', () => { } else if (configField === "SaveInfo") { const primaryValue = document.getElementById('primary-field').value.trim(); + // If the world type contains a space, it's invalid + if (primaryValue.includes(' ')) { + showNotification('The world type cannot contain spaces!', 'error'); + hidePreloader(); + return; // Prevent submission + } const secondaryValue = document.getElementById('secondary-field').value.trim(); if (secondaryValue === '' || secondaryValue === document.getElementById('secondary-field').placeholder) { showNotification('Please select a world type!', 'error'); diff --git a/src/config/config.go b/src/config/config.go index ab63a20f..f5c35304 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -11,7 +11,7 @@ import ( var ( // All configuration variables can be found in vars.go - Version = "5.6.5" + Version = "5.6.6" Branch = "release" ) From d1359089bc169406adaf2bab05449c376f5e668b Mon Sep 17 00:00:00 2001 From: akirilov <***REMOVED***> Date: Fri, 19 Sep 2025 05:51:48 +0200 Subject: [PATCH 10/45] Revert version number change for nightly --- src/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/config.go b/src/config/config.go index f5c35304..ab63a20f 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -11,7 +11,7 @@ import ( var ( // All configuration variables can be found in vars.go - Version = "5.6.6" + Version = "5.6.5" Branch = "release" ) From 0fde131876d0030caab43ca6f7ced49c68495e5b Mon Sep 17 00:00:00 2001 From: akirilov Date: Fri, 19 Sep 2025 12:52:20 +0900 Subject: [PATCH 11/45] Update UIMod/onboard_bundled/twoboxform/twoboxform.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- UIMod/onboard_bundled/twoboxform/twoboxform.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UIMod/onboard_bundled/twoboxform/twoboxform.js b/UIMod/onboard_bundled/twoboxform/twoboxform.js index bef99749..57f2feb1 100644 --- a/UIMod/onboard_bundled/twoboxform/twoboxform.js +++ b/UIMod/onboard_bundled/twoboxform/twoboxform.js @@ -138,9 +138,9 @@ document.addEventListener('DOMContentLoaded', () => { } else if (configField === "SaveInfo") { const primaryValue = document.getElementById('primary-field').value.trim(); - // If the world type contains a space, it's invalid + // If the world name contains a space, it's invalid if (primaryValue.includes(' ')) { - showNotification('The world type cannot contain spaces!', 'error'); + showNotification('The world name cannot contain spaces!', 'error'); hidePreloader(); return; // Prevent submission } From 05bd7454a8ccadc9d29385f5ceb8f3132536c060 Mon Sep 17 00:00:00 2001 From: akirilov <***REMOVED***> Date: Thu, 18 Sep 2025 07:16:47 +0200 Subject: [PATCH 12/45] Added working directory setup for Linux to handle symlink issues. --- server.go | 3 +++ src/core/loader/loader.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/server.go b/server.go index 7c5c6677..600f4293 100644 --- a/server.go +++ b/server.go @@ -37,6 +37,9 @@ var v1uiFS embed.FS func main() { var wg sync.WaitGroup logger.ConfigureConsole() + logger.Main.Debug("Initializing resources...") + loader.SetupWorkingDir() + loader.InitVirtFS(v1uiFS) logger.Install.Info("Starting setup...") loader.ReloadConfig() // Load the config file before starting the setup process loader.LoadCmdArgs() diff --git a/src/core/loader/loader.go b/src/core/loader/loader.go index 72830a12..ce211ef4 100644 --- a/src/core/loader/loader.go +++ b/src/core/loader/loader.go @@ -3,6 +3,9 @@ package loader import ( "embed" + "os" + "path/filepath" + "runtime" "sync" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/config" @@ -16,6 +19,36 @@ import ( "github.com/JacksonTheMaster/StationeersServerUI/v5/src/steamcmd" ) +func SetupWorkingDir() error { + if runtime.GOOS == "windows" { + // For now Windows doesn't have symlinking issues so we'll just let is use the current working directory + return nil + } + if runtime.GOOS == "linux" { + // Get the current executable path from /proc/self/exe + exePath, err := os.Readlink("/proc/self/exe") + if err != nil { + return err + } + // Get the directory path of the executable + dirPath := filepath.Dir(exePath) + // Change the working directory to the executable's directory + cwd, err := os.Getwd() + if err != nil { + return err + } + if cwd != dirPath { + logger.Core.Info("Changing working directory to " + dirPath) + err = os.Chdir(dirPath) + if err != nil { + return err + } + } + return nil + } + return nil +} + // only call this once at startup func InitBackend(wg *sync.WaitGroup) { wg.Add(1) From 31899f97918e427d5d27c2316b4a4e79ef7a6781 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 19 Sep 2025 18:14:00 +0200 Subject: [PATCH 13/45] adjusted logging and comments for SetupWorkingDir. --- server.go | 2 +- src/core/loader/loader.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/server.go b/server.go index 600f4293..81f254da 100644 --- a/server.go +++ b/server.go @@ -37,8 +37,8 @@ var v1uiFS embed.FS func main() { var wg sync.WaitGroup logger.ConfigureConsole() - logger.Main.Debug("Initializing resources...") loader.SetupWorkingDir() + logger.Main.Debug("Initializing resources...") loader.InitVirtFS(v1uiFS) logger.Install.Info("Starting setup...") loader.ReloadConfig() // Load the config file before starting the setup process diff --git a/src/core/loader/loader.go b/src/core/loader/loader.go index ce211ef4..dd6c6b85 100644 --- a/src/core/loader/loader.go +++ b/src/core/loader/loader.go @@ -19,6 +19,7 @@ import ( "github.com/JacksonTheMaster/StationeersServerUI/v5/src/steamcmd" ) +// SetupWorkingDir sets the working directory to the directory of the executable to prevent user errors func SetupWorkingDir() error { if runtime.GOOS == "windows" { // For now Windows doesn't have symlinking issues so we'll just let is use the current working directory @@ -38,7 +39,7 @@ func SetupWorkingDir() error { return err } if cwd != dirPath { - logger.Core.Info("Changing working directory to " + dirPath) + logger.Core.Debug("Changing working directory to " + dirPath) err = os.Chdir(dirPath) if err != nil { return err From 7c7151b0cf0c49683ba3cfe07cb1e407e2ca3b99 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 19 Sep 2025 18:15:56 +0200 Subject: [PATCH 14/45] fix linter warn in terminalmsg --- src/core/loader/terminalmsg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/loader/terminalmsg.go b/src/core/loader/terminalmsg.go index 4f6803dc..d22412c2 100644 --- a/src/core/loader/terminalmsg.go +++ b/src/core/loader/terminalmsg.go @@ -31,7 +31,7 @@ func printStartupMessage() { logger.Core.Cleanf(" โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•") // Web UI info - logger.Core.Cleanf("\n ๐ŸŒ Web UI available at: https://localhost:8443 (default) or https://:" + config.GetSSUIWebPort()) + logger.Core.Cleanf("\n ๐ŸŒ Web UI available at: https://localhost:8443 (default) or https://:%s", config.GetSSUIWebPort()) logger.Core.Cleanf("\n ๐ŸŒ Support available at: https://discord.gg/8n3vN92MyJ") // Quote From a72c7794d44ce59b8ad4d326950883eb15933fa2 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 19 Sep 2025 18:21:03 +0200 Subject: [PATCH 15/45] removed redundant Init of bundled assets --- server.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/server.go b/server.go index 81f254da..5045ee97 100644 --- a/server.go +++ b/server.go @@ -45,8 +45,6 @@ func main() { loader.LoadCmdArgs() setup.Install(&wg) wg.Wait() - logger.Main.Debug("Initializing resources...") - loader.InitVirtFS(v1uiFS) logger.Main.Debug("Initializing Backend...") loader.InitBackend(&wg) wg.Wait() From 542f22a45e4ba8b0f81992ad169962b183159e8f Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 19 Sep 2025 18:22:43 +0200 Subject: [PATCH 16/45] moved SetupWorkingDir from loder to loader helpers --- src/core/loader/helpers.go | 34 ++++++++++++++++++++++++++++++++++ src/core/loader/loader.go | 34 ---------------------------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/core/loader/helpers.go b/src/core/loader/helpers.go index 92d6f897..29e129fa 100644 --- a/src/core/loader/helpers.go +++ b/src/core/loader/helpers.go @@ -2,6 +2,9 @@ package loader import ( "fmt" + "os" + "path/filepath" + "runtime" "strings" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/config" @@ -161,3 +164,34 @@ func PrintConfigDetails(logLevel ...string) { logger.Config.Debug("=======================================") } + +// SetupWorkingDir sets the working directory to the directory of the executable to prevent user errors +func SetupWorkingDir() error { + if runtime.GOOS == "windows" { + // For now Windows doesn't have symlinking issues so we'll just let is use the current working directory + return nil + } + if runtime.GOOS == "linux" { + // Get the current executable path from /proc/self/exe + exePath, err := os.Readlink("/proc/self/exe") + if err != nil { + return err + } + // Get the directory path of the executable + dirPath := filepath.Dir(exePath) + // Change the working directory to the executable's directory + cwd, err := os.Getwd() + if err != nil { + return err + } + if cwd != dirPath { + logger.Core.Debug("Changing working directory to " + dirPath) + err = os.Chdir(dirPath) + if err != nil { + return err + } + } + return nil + } + return nil +} diff --git a/src/core/loader/loader.go b/src/core/loader/loader.go index dd6c6b85..72830a12 100644 --- a/src/core/loader/loader.go +++ b/src/core/loader/loader.go @@ -3,9 +3,6 @@ package loader import ( "embed" - "os" - "path/filepath" - "runtime" "sync" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/config" @@ -19,37 +16,6 @@ import ( "github.com/JacksonTheMaster/StationeersServerUI/v5/src/steamcmd" ) -// SetupWorkingDir sets the working directory to the directory of the executable to prevent user errors -func SetupWorkingDir() error { - if runtime.GOOS == "windows" { - // For now Windows doesn't have symlinking issues so we'll just let is use the current working directory - return nil - } - if runtime.GOOS == "linux" { - // Get the current executable path from /proc/self/exe - exePath, err := os.Readlink("/proc/self/exe") - if err != nil { - return err - } - // Get the directory path of the executable - dirPath := filepath.Dir(exePath) - // Change the working directory to the executable's directory - cwd, err := os.Getwd() - if err != nil { - return err - } - if cwd != dirPath { - logger.Core.Debug("Changing working directory to " + dirPath) - err = os.Chdir(dirPath) - if err != nil { - return err - } - } - return nil - } - return nil -} - // only call this once at startup func InitBackend(wg *sync.WaitGroup) { wg.Add(1) From 83d52f10108ee6c93194e8400036402e85a0c160 Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Fri, 19 Sep 2025 17:33:26 +0100 Subject: [PATCH 17/45] Add Docker entrypoint script and update Dockerfile --- .devcontainer/compose.yml | 29 ++++++++ .docker/docker-entrypoint.sh | 130 +++++++++++++++++++++++++++++++++++ Dockerfile | 8 +-- 3 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 .devcontainer/compose.yml create mode 100644 .docker/docker-entrypoint.sh diff --git a/.devcontainer/compose.yml b/.devcontainer/compose.yml new file mode 100644 index 00000000..a0e73a4a --- /dev/null +++ b/.devcontainer/compose.yml @@ -0,0 +1,29 @@ +services: + stationeers-server: + container_name: stationeers-server + build: . + image: stationeersserverui:test + stdin_open: true + tty: true + deploy: + resources: + limits: + cpus: '8' + memory: 16G + reservations: + cpus: '4' + memory: 8G + ports: + - "8443:8443" + - "27016:27016/udp" + - "27016:27016/tcp" + - "27015:27015/udp" + - "27015:27015/tcp" + volumes: + - app-data:/app + - ${PWD}/saves:/app/saves:rw + - ${PWD}/UIMod:/app/UIMod:rw + restart: unless-stopped + +volumes: + app-data: \ No newline at end of file diff --git a/.docker/docker-entrypoint.sh b/.docker/docker-entrypoint.sh new file mode 100644 index 00000000..2e870882 --- /dev/null +++ b/.docker/docker-entrypoint.sh @@ -0,0 +1,130 @@ +#!/bin/sh +set -e + +UMASK_VAL="022" + +APP_USER="app" +APP_GROUP="app" +APP_HOME="/app" + +detect_target_ids() { + # Try to detect from common bind-mounted paths + TARGET_UID="" + TARGET_GID="" + for p in \ + "$APP_HOME/UIMod" \ + "$APP_HOME/saves" \ + "$APP_HOME"; do + if [ -e "$p" ]; then + set -- $(stat -c '%u %g' "$p" 2>/dev/null || echo "0 0") + u="$1"; g="$2" + # Prefer non-root IDs when available + if [ "$u" != "0" ]; then TARGET_UID="$u"; fi + if [ "$g" != "0" ]; then TARGET_GID="$g"; fi + # If both found, stop early + if [ -n "$TARGET_UID" ] && [ -n "$TARGET_GID" ]; then + break + fi + fi + done + + # Fallback if detection failed + if [ -z "$TARGET_UID" ]; then TARGET_UID="1000"; fi + if [ -z "$TARGET_GID" ]; then TARGET_GID="1000"; fi +} + +is_path_on_mount() { + # True if the given path is a mountpoint or inside a mountpoint + # Compare against the mount points (field 5) in /proc/self/mountinfo + p="$1" + while read -r _ _ _ _ mp _; do + # Exact mountpoint + if [ "$p" = "$mp" ]; then + return 0 + fi + # Under the mountpoint (mp is a prefix followed by '/') + case "$p" in + "$mp"/*) return 0 ;; + esac + done < /proc/self/mountinfo + return 1 +} + +ensure_group() { + if getent group "$APP_GROUP" >/dev/null 2>&1; then + # Group exists; update GID if necessary + CURRENT_GID=$(getent group "$APP_GROUP" | cut -d: -f3) + if [ "$CURRENT_GID" != "$TARGET_GID" ]; then + groupmod -o -g "$TARGET_GID" "$APP_GROUP" 2>/dev/null || true + fi + else + # Try to reuse existing group with same GID, otherwise create + if getent group "$TARGET_GID" >/dev/null 2>&1; then + APP_GROUP=$(getent group "$TARGET_GID" | cut -d: -f1) + else + groupadd -o -g "$TARGET_GID" "$APP_GROUP" || true + fi + fi +} + +ensure_user() { + if id -u "$APP_USER" >/dev/null 2>&1; then + CURRENT_UID=$(id -u "$APP_USER") + if [ "$CURRENT_UID" != "$TARGET_UID" ]; then + usermod -o -u "$TARGET_UID" "$APP_USER" 2>/dev/null || true + fi + # Ensure user's primary group is APP_GROUP (with target GID) + usermod -g "$APP_GROUP" "$APP_USER" 2>/dev/null || true + usermod -d "$APP_HOME" -s /bin/sh "$APP_USER" 2>/dev/null || true + else + useradd -m -d "$APP_HOME" -s /bin/sh -u "$TARGET_UID" -g "$APP_GROUP" "$APP_USER" 2>/dev/null || true + fi +} + +fix_perms() { + # Create expected directories if missing (bind mounts may provide them) + mkdir -p \ + "$APP_HOME" \ + "$APP_HOME/saves" \ + "$APP_HOME/UIMod" \ + "$APP_HOME/UIMod/config" \ + "$APP_HOME/UIMod/tls" + + # Only adjust ownership for paths that are not on/under a bind mount + for p in \ + "$APP_HOME" \ + "$APP_HOME/saves" \ + "$APP_HOME/UIMod"; do + if ! is_path_on_mount "$p"; then + chown "$APP_USER:$APP_GROUP" "$p" 2>/dev/null || true + fi + done +} + +main() { + # Only attempt privilege drop if running as root + if [ "$(id -u)" = "0" ]; then + detect_target_ids + ensure_group + ensure_user + fix_perms + umask "$UMASK_VAL" + + # Execute as the app user + if [ $# -eq 0 ]; then + exec gosu "$APP_USER:$APP_GROUP" StationeersServerControl + else + exec gosu "$APP_USER:$APP_GROUP" "$@" + fi + else + # Already running as non-root + umask "$UMASK_VAL" + if [ $# -eq 0 ]; then + exec StationeersServerControl + else + exec "$@" + fi + fi +} + +main "$@" diff --git a/Dockerfile b/Dockerfile index e4406cab..8257caee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,6 +48,7 @@ RUN dpkg --add-architecture i386 \ locales \ lib32gcc-s1 \ file \ + gosu \ && rm -rf /var/lib/apt/lists/* RUN useradd -m -d /app -s /bin/sh app @@ -55,12 +56,11 @@ RUN useradd -m -d /app -s /bin/sh app # Copy compiled binary and license COPY --from=go-builder /out/StationeersServerControl /usr/local/bin/StationeersServerControl COPY ./LICENSE /app/LICENSE -RUN chmod +x /usr/local/bin/StationeersServerControl +COPY ./docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN chmod +x /usr/local/bin/StationeersServerControl /usr/local/bin/docker-entrypoint.sh RUN chown -R app:app /app -USER app - EXPOSE 8443/tcp 27016/udp 27015/udp -ENTRYPOINT ["/usr/local/bin/StationeersServerControl"] +ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] From fbcb70a197f19fd605cc8ad484c648f2875f9ed4 Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Fri, 19 Sep 2025 17:35:21 +0100 Subject: [PATCH 18/45] Move docker related stuff to .docker --- Dockerfile => .docker/Dockerfile | 0 {.devcontainer => .docker}/compose.yml | 0 compose.yml | 31 -------------------------- 3 files changed, 31 deletions(-) rename Dockerfile => .docker/Dockerfile (100%) rename {.devcontainer => .docker}/compose.yml (100%) delete mode 100644 compose.yml diff --git a/Dockerfile b/.docker/Dockerfile similarity index 100% rename from Dockerfile rename to .docker/Dockerfile diff --git a/.devcontainer/compose.yml b/.docker/compose.yml similarity index 100% rename from .devcontainer/compose.yml rename to .docker/compose.yml diff --git a/compose.yml b/compose.yml deleted file mode 100644 index aa382616..00000000 --- a/compose.yml +++ /dev/null @@ -1,31 +0,0 @@ -services: - stationeers-server: - container_name: stationeers-server - build : . - image: stationeers-server-ui:latest - deploy: - resources: - limits: - cpus: '8' - memory: 16G - reservations: - cpus: '4' - memory: 8G - ports: - - "8443:8443" - - "27016:27016/udp" - - "27016:27016/tcp" - - "27015:27015/udp" - - "27015:27015/tcp" - volumes: - # Persist app data between container restarts - - app-data:/app - # Mount saves and config for easy access/editing outside the container - - ./saves:/app/saves:rw - - ./UIMod/config:/app/UIMod/config:rw - - ./UIMod/tls:/app/UIMod/tls:rw - restart: unless-stopped - command: [] - -volumes: - app-data: \ No newline at end of file From f143e4bdcef93128ffb83b4902b0662c28f6c859 Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Fri, 19 Sep 2025 17:35:46 +0100 Subject: [PATCH 19/45] Update build context to use .docker directory for nightly and release workflows --- .github/workflows/ghcr-build-nightly.yaml | 2 +- .github/workflows/ghcr-build-release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ghcr-build-nightly.yaml b/.github/workflows/ghcr-build-nightly.yaml index 302364ad..8df50252 100644 --- a/.github/workflows/ghcr-build-nightly.yaml +++ b/.github/workflows/ghcr-build-nightly.yaml @@ -50,7 +50,7 @@ jobs: - name: Build and push uses: docker/build-push-action@v6 with: - context: . + context: ./.docker platforms: linux/amd64 push: true tags: ${{ steps.meta.outputs.tags }} diff --git a/.github/workflows/ghcr-build-release.yaml b/.github/workflows/ghcr-build-release.yaml index 43e3df7e..d430c03d 100644 --- a/.github/workflows/ghcr-build-release.yaml +++ b/.github/workflows/ghcr-build-release.yaml @@ -49,7 +49,7 @@ jobs: - name: Build and push uses: docker/build-push-action@v6 with: - context: . + context: ./.docker platforms: linux/amd64 push: true tags: ${{ steps.meta.outputs.tags }} From 1d11e1a7cb66e7cc20f6d13a70ae349f6ceb3918 Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Fri, 19 Sep 2025 18:05:13 +0100 Subject: [PATCH 20/45] Fix pathing across the board --- .docker/Dockerfile | 2 +- .github/workflows/ghcr-build-nightly.yaml | 3 ++- .github/workflows/ghcr-build-release.yaml | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.docker/Dockerfile b/.docker/Dockerfile index 8257caee..861998b4 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -56,7 +56,7 @@ RUN useradd -m -d /app -s /bin/sh app # Copy compiled binary and license COPY --from=go-builder /out/StationeersServerControl /usr/local/bin/StationeersServerControl COPY ./LICENSE /app/LICENSE -COPY ./docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +COPY ./.docker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh RUN chmod +x /usr/local/bin/StationeersServerControl /usr/local/bin/docker-entrypoint.sh RUN chown -R app:app /app diff --git a/.github/workflows/ghcr-build-nightly.yaml b/.github/workflows/ghcr-build-nightly.yaml index 8df50252..7fcfe13e 100644 --- a/.github/workflows/ghcr-build-nightly.yaml +++ b/.github/workflows/ghcr-build-nightly.yaml @@ -50,7 +50,8 @@ jobs: - name: Build and push uses: docker/build-push-action@v6 with: - context: ./.docker + context: . + file: ./.docker/Dockerfile platforms: linux/amd64 push: true tags: ${{ steps.meta.outputs.tags }} diff --git a/.github/workflows/ghcr-build-release.yaml b/.github/workflows/ghcr-build-release.yaml index d430c03d..560e0c05 100644 --- a/.github/workflows/ghcr-build-release.yaml +++ b/.github/workflows/ghcr-build-release.yaml @@ -49,7 +49,8 @@ jobs: - name: Build and push uses: docker/build-push-action@v6 with: - context: ./.docker + context: . + file: ./.docker/Dockerfile platforms: linux/amd64 push: true tags: ${{ steps.meta.outputs.tags }} From 9fe613b3a496cc0aafbcfa39a0d8874089a182ab Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 19 Sep 2025 19:57:24 +0200 Subject: [PATCH 21/45] set a "fake" HOME env var when running steamcmd on linux to make it not shit files into the actual users Home --- src/steamcmd/steamcmd.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/steamcmd/steamcmd.go b/src/steamcmd/steamcmd.go index 292ed1ce..7312e714 100644 --- a/src/steamcmd/steamcmd.go +++ b/src/steamcmd/steamcmd.go @@ -101,6 +101,25 @@ func runSteamCMD(steamCMDDir string) (int, error) { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr + if runtime.GOOS == "linux" { + env := os.Environ() + // Replace or set HOME + newEnv := make([]string, 0, len(env)+1) + foundHome := false + for _, e := range env { + if !strings.HasPrefix(e, "HOME=") { + newEnv = append(newEnv, e) + } else { + newEnv = append(newEnv, "HOME="+currentDir) + foundHome = true + } + } + if !foundHome { + newEnv = append(newEnv, "HOME="+currentDir) + } + cmd.Env = newEnv + } + // Run the command if config.GetLogLevel() == 10 { cmdString := strings.Join(cmd.Args, " ") From d9dcf77eda2ef6f13f15cc7f87ab5f68da3e187f Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Fri, 19 Sep 2025 21:30:21 +0100 Subject: [PATCH 22/45] Makes container rooted --- .docker/Dockerfile | 12 +--- .docker/docker-entrypoint.sh | 130 ----------------------------------- 2 files changed, 3 insertions(+), 139 deletions(-) delete mode 100644 .docker/docker-entrypoint.sh diff --git a/.docker/Dockerfile b/.docker/Dockerfile index 861998b4..e8d3a74a 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -47,20 +47,14 @@ RUN dpkg --add-architecture i386 \ ca-certificates \ locales \ lib32gcc-s1 \ - file \ - gosu \ + file \ && rm -rf /var/lib/apt/lists/* -RUN useradd -m -d /app -s /bin/sh app - # Copy compiled binary and license COPY --from=go-builder /out/StationeersServerControl /usr/local/bin/StationeersServerControl COPY ./LICENSE /app/LICENSE -COPY ./.docker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh -RUN chmod +x /usr/local/bin/StationeersServerControl /usr/local/bin/docker-entrypoint.sh - -RUN chown -R app:app /app +RUN chmod +x /usr/local/bin/StationeersServerControl EXPOSE 8443/tcp 27016/udp 27015/udp -ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] +ENTRYPOINT ["/usr/local/bin/StationeersServerControl"] diff --git a/.docker/docker-entrypoint.sh b/.docker/docker-entrypoint.sh deleted file mode 100644 index 2e870882..00000000 --- a/.docker/docker-entrypoint.sh +++ /dev/null @@ -1,130 +0,0 @@ -#!/bin/sh -set -e - -UMASK_VAL="022" - -APP_USER="app" -APP_GROUP="app" -APP_HOME="/app" - -detect_target_ids() { - # Try to detect from common bind-mounted paths - TARGET_UID="" - TARGET_GID="" - for p in \ - "$APP_HOME/UIMod" \ - "$APP_HOME/saves" \ - "$APP_HOME"; do - if [ -e "$p" ]; then - set -- $(stat -c '%u %g' "$p" 2>/dev/null || echo "0 0") - u="$1"; g="$2" - # Prefer non-root IDs when available - if [ "$u" != "0" ]; then TARGET_UID="$u"; fi - if [ "$g" != "0" ]; then TARGET_GID="$g"; fi - # If both found, stop early - if [ -n "$TARGET_UID" ] && [ -n "$TARGET_GID" ]; then - break - fi - fi - done - - # Fallback if detection failed - if [ -z "$TARGET_UID" ]; then TARGET_UID="1000"; fi - if [ -z "$TARGET_GID" ]; then TARGET_GID="1000"; fi -} - -is_path_on_mount() { - # True if the given path is a mountpoint or inside a mountpoint - # Compare against the mount points (field 5) in /proc/self/mountinfo - p="$1" - while read -r _ _ _ _ mp _; do - # Exact mountpoint - if [ "$p" = "$mp" ]; then - return 0 - fi - # Under the mountpoint (mp is a prefix followed by '/') - case "$p" in - "$mp"/*) return 0 ;; - esac - done < /proc/self/mountinfo - return 1 -} - -ensure_group() { - if getent group "$APP_GROUP" >/dev/null 2>&1; then - # Group exists; update GID if necessary - CURRENT_GID=$(getent group "$APP_GROUP" | cut -d: -f3) - if [ "$CURRENT_GID" != "$TARGET_GID" ]; then - groupmod -o -g "$TARGET_GID" "$APP_GROUP" 2>/dev/null || true - fi - else - # Try to reuse existing group with same GID, otherwise create - if getent group "$TARGET_GID" >/dev/null 2>&1; then - APP_GROUP=$(getent group "$TARGET_GID" | cut -d: -f1) - else - groupadd -o -g "$TARGET_GID" "$APP_GROUP" || true - fi - fi -} - -ensure_user() { - if id -u "$APP_USER" >/dev/null 2>&1; then - CURRENT_UID=$(id -u "$APP_USER") - if [ "$CURRENT_UID" != "$TARGET_UID" ]; then - usermod -o -u "$TARGET_UID" "$APP_USER" 2>/dev/null || true - fi - # Ensure user's primary group is APP_GROUP (with target GID) - usermod -g "$APP_GROUP" "$APP_USER" 2>/dev/null || true - usermod -d "$APP_HOME" -s /bin/sh "$APP_USER" 2>/dev/null || true - else - useradd -m -d "$APP_HOME" -s /bin/sh -u "$TARGET_UID" -g "$APP_GROUP" "$APP_USER" 2>/dev/null || true - fi -} - -fix_perms() { - # Create expected directories if missing (bind mounts may provide them) - mkdir -p \ - "$APP_HOME" \ - "$APP_HOME/saves" \ - "$APP_HOME/UIMod" \ - "$APP_HOME/UIMod/config" \ - "$APP_HOME/UIMod/tls" - - # Only adjust ownership for paths that are not on/under a bind mount - for p in \ - "$APP_HOME" \ - "$APP_HOME/saves" \ - "$APP_HOME/UIMod"; do - if ! is_path_on_mount "$p"; then - chown "$APP_USER:$APP_GROUP" "$p" 2>/dev/null || true - fi - done -} - -main() { - # Only attempt privilege drop if running as root - if [ "$(id -u)" = "0" ]; then - detect_target_ids - ensure_group - ensure_user - fix_perms - umask "$UMASK_VAL" - - # Execute as the app user - if [ $# -eq 0 ]; then - exec gosu "$APP_USER:$APP_GROUP" StationeersServerControl - else - exec gosu "$APP_USER:$APP_GROUP" "$@" - fi - else - # Already running as non-root - umask "$UMASK_VAL" - if [ $# -eq 0 ]; then - exec StationeersServerControl - else - exec "$@" - fi - fi -} - -main "$@" From f27ff5c7e24b73c45a50ee503a66097031ec6f3f Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Fri, 19 Sep 2025 23:33:52 +0100 Subject: [PATCH 23/45] Revert "Update LICENSE" This reverts commit 86bb14b33ead7046c856c56c1fcb11fa2b7cfb80. --- LICENSE | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index 1f18bc87..c4aa304e 100644 --- a/LICENSE +++ b/LICENSE @@ -7,7 +7,7 @@ The Licensor encourages community participation through the SSUI GitHub repository. For support, feature requests, or inquiries, contact the Licensor at github.com/JacksonTheMaster. -The Stationeers Server UI (โ€œSSUIโ€) is a proprietary software suite, including the Stationeers Server Command Manager (SSCM), designed to enhance Stationeers server administration. SSUI is developed as an source-available (https://www.linuxfoundation.org/licensebestpractices#not-os) project on GitHub (github.com/JacksonTheMaster/StationeersServerUI) to encourage community collaboration while maintaining legal control with the repository owner, JacksonTheMaster. This License Agreement governs the use, modification, and contribution to SSUI, balancing open development with controlled commercial use. SSCM is licensed separately under the Stationeers Server Command Manager License Agreement (see LICENSE in the SSCM folder). +The Stationeers Server UI (โ€œSSUIโ€) is a proprietary software suite, including the Stationeers Server Command Manager (SSCM), designed to enhance Stationeers server administration. SSUI is developed as an open-source project on GitHub (github.com/JacksonTheMaster/StationeersServerUI) to encourage community collaboration while maintaining legal control with the repository owner, JacksonTheMaster. This License Agreement governs the use, modification, and contribution to SSUI, balancing open development with controlled commercial use. SSCM is licensed separately under the Stationeers Server Command Manager License Agreement (see LICENSE in the SSCM folder). ## DEFINITIONS @@ -16,7 +16,7 @@ The Stationeers Server UI (โ€œSSUIโ€) is a proprietary software suite, includin - **Licensee**: You, the individual or entity using SSUI. - **Licensor**: JacksonTheMaster, the copyright holder and repository owner of SSUI. - **Non-Commercial Use**: Use for personal, educational, or open-source development purposes without profit or business revenue. -- **Commercial Use**: Use in a business, profit-generating, or commercial context. Does not apply to Content creators who create content on a SSUI powererd Server. +- **Commercial Use**: Use in a business, profit-generating, or commercial context. - **RocketWerkz**: RocketWerkz Studios Limited (Level 38, PwC Tower, 15 Customs St. West, 1010 Auckland, NZBN: 9429041553206) ## GRANT OF LICENSE @@ -173,4 +173,4 @@ This Agreement is in English. ## CONTACT -For inquiries or commercial licensing, contact the Licensor at [github.com/JacksonTheMaster](https://github.com/JacksonTheMaster). +For inquiries or commercial licensing, contact the Licensor at [github.com/JacksonTheMaster](https://github.com/JacksonTheMaster). \ No newline at end of file From 1e6e365952bd7f607da083bf041ac64f519a6458 Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Fri, 19 Sep 2025 23:35:11 +0100 Subject: [PATCH 24/45] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .docker/compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.docker/compose.yml b/.docker/compose.yml index a0e73a4a..ac8d05e4 100644 --- a/.docker/compose.yml +++ b/.docker/compose.yml @@ -21,8 +21,8 @@ services: - "27015:27015/tcp" volumes: - app-data:/app - - ${PWD}/saves:/app/saves:rw - - ${PWD}/UIMod:/app/UIMod:rw + - ./saves:/app/saves:rw + - ./UIMod:/app/UIMod:rw restart: unless-stopped volumes: From 44cea602fb6849586ad457de297e4b76862e2c5d Mon Sep 17 00:00:00 2001 From: Saul Burgess Date: Fri, 19 Sep 2025 23:35:18 +0100 Subject: [PATCH 25/45] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .docker/compose.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.docker/compose.yml b/.docker/compose.yml index ac8d05e4..516cd5ee 100644 --- a/.docker/compose.yml +++ b/.docker/compose.yml @@ -1,7 +1,9 @@ services: stationeers-server: container_name: stationeers-server - build: . + build: + context: .. + dockerfile: ./.docker/Dockerfile image: stationeersserverui:test stdin_open: true tty: true From ae1269fd71438bc2b4633c3236b80f442ee8403e Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sat, 20 Sep 2025 11:32:39 +0200 Subject: [PATCH 26/45] added a sanity check to startup, fails gracefully if run as root or cannot write to workdir --- server.go | 7 +++++++ src/core/loader/helpers.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/server.go b/server.go index 5045ee97..475e9967 100644 --- a/server.go +++ b/server.go @@ -22,7 +22,9 @@ package main import ( "embed" + "os" "sync" + "time" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/cli" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/core/loader" @@ -38,6 +40,11 @@ func main() { var wg sync.WaitGroup logger.ConfigureConsole() loader.SetupWorkingDir() + if err := loader.SanityCheck(); err != nil { + logger.Main.Error("Sanity check failed, exiting in 10 secconds: " + err.Error()) + time.Sleep(10 * time.Second) + os.Exit(1) + } logger.Main.Debug("Initializing resources...") loader.InitVirtFS(v1uiFS) logger.Install.Info("Starting setup...") diff --git a/src/core/loader/helpers.go b/src/core/loader/helpers.go index 29e129fa..724c7d37 100644 --- a/src/core/loader/helpers.go +++ b/src/core/loader/helpers.go @@ -195,3 +195,39 @@ func SetupWorkingDir() error { } return nil } + +func SanityCheck() error { + + if runtime.GOOS == "windows" { + return nil + } + // Check if running as root (UID 0) + if os.Geteuid() == 0 { + return fmt.Errorf("root: SSUI should not be run as root") + } + + // Check if current working directory is writable + workDir, err := os.Getwd() + if err != nil { + return fmt.Errorf("failed to get working directory: %w", err) + } + + // Try to create a temporary file to test write permissions + testFile := filepath.Join(workDir, ".write_test") + if err := os.WriteFile(testFile, []byte("test"), 0600); err != nil { + return fmt.Errorf("cannot write to working directory %s: %w", workDir, err) + } + // Clean up test file + if err := os.Remove(testFile); err != nil { + return fmt.Errorf("failed to clean up sanity check writetest file: %w", err) + } + + // Check if steamcmd package is installed (requires further testing, disabled for now) + //cmd := exec.Command("dpkg-query", "-W", "-f='${Status}'", "steamcmd") + //output, err := cmd.CombinedOutput() + //if err == nil && strings.Contains(string(output), "install ok installed") { + // return fmt.Errorf("steamcmd package is installed") + //} + + return nil +} From a978ef4eae43ee7b2c026397d29122c0fda6aabb Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sat, 20 Sep 2025 11:41:50 +0200 Subject: [PATCH 27/45] added a -SkipSteamCMD (-nosteam) arg --- .vscode/launch.json | 10 ++++++++++ src/config/getters.go | 6 ++++++ src/config/setters.go | 8 ++++++++ src/config/vars.go | 1 + src/core/loader/cmdargs.go | 7 +++++++ src/setup/install.go | 4 +++- 6 files changed, 35 insertions(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 5e1d543e..9b4ebad8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -19,6 +19,16 @@ "program": "${workspaceFolder}/server.go", "console": "integratedTerminal", "showLog": false, // Hides some Go Debugger(Delve) log stuff that is not useful for debugging atm + }, + { + "name": "Debug Go Server noSteamCMD noSvelte", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/server.go", + "console": "integratedTerminal", + "showLog": false, // Hides some Go Debugger(Delve) log stuff that is not useful for debugging atm + "args": ["--SkipSteamCMD"] } ] } \ No newline at end of file diff --git a/src/config/getters.go b/src/config/getters.go index 936a4bbd..bbc9e402 100644 --- a/src/config/getters.go +++ b/src/config/getters.go @@ -493,3 +493,9 @@ func GetExtractedGameVersion() string { defer ConfigMu.RUnlock() return ExtractedGameVersion } + +func GetSkipSteamCMD() bool { + ConfigMu.RLock() + defer ConfigMu.RUnlock() + return SkipSteamCMD +} diff --git a/src/config/setters.go b/src/config/setters.go index 401b53c5..2f9bd5fd 100644 --- a/src/config/setters.go +++ b/src/config/setters.go @@ -46,6 +46,14 @@ func SetExtractedGameVersion(value string) error { return nil } +func SetSkipSteamCMD(value bool) error { + ConfigMu.Lock() + defer ConfigMu.Unlock() + + SkipSteamCMD = value + return nil +} + // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT diff --git a/src/config/vars.go b/src/config/vars.go index 0ba6fb1a..41c84f42 100644 --- a/src/config/vars.go +++ b/src/config/vars.go @@ -63,6 +63,7 @@ var ( SSUIIdentifier string CurrentBranchBuildID string // ONLY RUNTIME ExtractedGameVersion string // ONLY RUNTIME + SkipSteamCMD bool // ONLY RUNTIME ) // Discord integration diff --git a/src/core/loader/cmdargs.go b/src/core/loader/cmdargs.go index 787d63e9..e1a950b5 100644 --- a/src/core/loader/cmdargs.go +++ b/src/core/loader/cmdargs.go @@ -21,6 +21,7 @@ func LoadCmdArgs() { var createSSUILogFile bool var recoveryPassword string var devMode bool + var skipSteamCMD bool flag.StringVar(&backendEndpointPort, "BackendEndpointPort", "", "Override the backend endpoint port (e.g., 8080)") flag.StringVar(&backendEndpointPort, "p", "", "(Alias) Override the backend endpoint port (e.g., 8080)") @@ -35,6 +36,8 @@ func LoadCmdArgs() { flag.BoolVar(&isDebugMode, "debug", false, "(Alias) Enable debug mode") flag.BoolVar(&createSSUILogFile, "CreateSSUILogFile", false, "Create a log file for SSUI") flag.BoolVar(&createSSUILogFile, "lf", false, "(Alias) Create a log file for SSUI") + flag.BoolVar(&skipSteamCMD, "SkipSteamCMD", false, "Skips SteamCMD installation") + flag.BoolVar(&skipSteamCMD, "nosteam", false, "(Alias) Skips SteamCMD installation") // Parse command-line flags flag.Parse() @@ -47,6 +50,10 @@ func LoadCmdArgs() { logger.Main.Info("Dev mode enabled: Auth enabled, admin user set to admin:admin:superadmin, console enabled") } + if skipSteamCMD { + config.SetSkipSteamCMD(true) + } + if backendEndpointPort != "" && backendEndpointPort != "8443" { oldPort := config.GetSSUIWebPort() config.SetSSUIWebPort(backendEndpointPort) diff --git a/src/setup/install.go b/src/setup/install.go index 12a33e80..dad418ad 100644 --- a/src/setup/install.go +++ b/src/setup/install.go @@ -42,7 +42,9 @@ func Install(wg *sync.WaitGroup) { logger.Install.Info("โœ…Blacklist.txt verified or created.") // Step 3: Install and run SteamCMD logger.Install.Info("๐Ÿ”„Installing and running SteamCMD...") - if config.GetBranch() != "indev-no-steamcmd" { + if config.GetSkipSteamCMD() { + logger.Install.Info("โœ…Skipping SteamCMD installation, SkipSteamCMD is true") + } else { steamcmd.InstallAndRunSteamCMD() } logger.Install.Info("โœ…Setup complete!") From aa8f2309750011c78f32e627e1602535df6c6df3 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sat, 20 Sep 2025 12:11:58 +0200 Subject: [PATCH 28/45] added new Steam "home" to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a2349175..ecfce688 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ UIMod/tls/cert.pem UIMod/tls/key.pem steamapps/** steamcmd/** +Steam/** rocketstation_BurstDebugInformation_DoNotShip/** StationeersServerControlv* UnityPlayer.so From 4c1def9d2d5043620f8b5c08917c2f1bb7143f42 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sat, 20 Sep 2025 12:13:16 +0200 Subject: [PATCH 29/45] combined SetupWorkingDir and SanityCheck, fixed go builds in /tmp using wrong wd in testing --- server.go | 1 - src/core/loader/helpers.go | 52 +++++++++++++++----------------------- 2 files changed, 21 insertions(+), 32 deletions(-) diff --git a/server.go b/server.go index 475e9967..eaac0cfd 100644 --- a/server.go +++ b/server.go @@ -39,7 +39,6 @@ var v1uiFS embed.FS func main() { var wg sync.WaitGroup logger.ConfigureConsole() - loader.SetupWorkingDir() if err := loader.SanityCheck(); err != nil { logger.Main.Error("Sanity check failed, exiting in 10 secconds: " + err.Error()) time.Sleep(10 * time.Second) diff --git a/src/core/loader/helpers.go b/src/core/loader/helpers.go index 724c7d37..d8497154 100644 --- a/src/core/loader/helpers.go +++ b/src/core/loader/helpers.go @@ -165,47 +165,37 @@ func PrintConfigDetails(logLevel ...string) { logger.Config.Debug("=======================================") } -// SetupWorkingDir sets the working directory to the directory of the executable to prevent user errors -func SetupWorkingDir() error { - if runtime.GOOS == "windows" { - // For now Windows doesn't have symlinking issues so we'll just let is use the current working directory - return nil - } - if runtime.GOOS == "linux" { - // Get the current executable path from /proc/self/exe - exePath, err := os.Readlink("/proc/self/exe") - if err != nil { - return err - } - // Get the directory path of the executable - dirPath := filepath.Dir(exePath) - // Change the working directory to the executable's directory - cwd, err := os.Getwd() - if err != nil { - return err - } - if cwd != dirPath { - logger.Core.Debug("Changing working directory to " + dirPath) - err = os.Chdir(dirPath) - if err != nil { - return err - } - } - return nil - } - return nil -} - func SanityCheck() error { if runtime.GOOS == "windows" { return nil } + // Check if running as root (UID 0) if os.Geteuid() == 0 { return fmt.Errorf("root: SSUI should not be run as root") } + // Get the current executable path from /proc/self/exe + exePath, err := os.Readlink("/proc/self/exe") + if err != nil { + return err + } + // Get the directory path of the executable + dirPath := filepath.Dir(exePath) + // Change the working directory to the executable's directory + cwd, err := os.Getwd() + if err != nil { + return err + } + + if cwd != dirPath && !strings.Contains(dirPath, "/tmp") { + err = os.Chdir(dirPath) + if err != nil { + return err + } + } + // Check if current working directory is writable workDir, err := os.Getwd() if err != nil { From 6581708bb9a76f8945d7d5ae300e58f43ab71f50 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sat, 20 Sep 2025 12:18:47 +0200 Subject: [PATCH 30/45] updated getAppInfo to use the new "fake" home in the SSUI dir too --- src/steamcmd/getappinfo.go | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/steamcmd/getappinfo.go b/src/steamcmd/getappinfo.go index ba6c6f89..53e68541 100644 --- a/src/steamcmd/getappinfo.go +++ b/src/steamcmd/getappinfo.go @@ -4,10 +4,12 @@ import ( "bytes" "fmt" "maps" + "os" "os/exec" "path/filepath" "regexp" "runtime" + "strings" "sync" "time" @@ -64,6 +66,13 @@ func AppInfoPoller() { // getAppInfo fetches the branches and their build IDs for the specified app ID using SteamCMD // and stores them in the package-level branches map. func getAppInfo() error { + + currentDir, err := os.Getwd() + if err != nil { + logger.Install.Error("โŒ Error getting current working directory: " + err.Error() + "\n") + return err + } + if steamMu.TryLock() { // Successfully acquired the lock; no other func holds it logger.Core.Debug("๐Ÿ”„ Locking SteamMu for SteamCMD AppInfo...") @@ -90,14 +99,32 @@ func getAppInfo() error { cmd.Stdout = &stdout cmd.Stderr = &stderr + if runtime.GOOS == "linux" { + env := os.Environ() + // Replace or set HOME + newEnv := make([]string, 0, len(env)+1) + foundHome := false + for _, e := range env { + if !strings.HasPrefix(e, "HOME=") { + newEnv = append(newEnv, e) + } else { + newEnv = append(newEnv, "HOME="+currentDir) + foundHome = true + } + } + if !foundHome { + newEnv = append(newEnv, "HOME="+currentDir) + } + cmd.Env = newEnv + } + // Log the command //if config.GetLogLevel() == 10 { // cmdString := strings.Join(cmd.Args, " ") // logger.Install.Debug("๐Ÿ•‘ Running SteamCMD for app info: " + cmdString) //} - // Run the command - err := cmd.Run() + err = cmd.Run() if err != nil { if exitErr, ok := err.(*exec.ExitError); ok { logger.Install.Errorf("โŒ SteamCMD app info failed (code %d): %s\n", exitErr.ExitCode(), stderr.String()) From 682feb5fd0c10e392e7d232e29d8582c02081f7e Mon Sep 17 00:00:00 2001 From: JLangisch Date: Thu, 18 Sep 2025 18:01:17 +0200 Subject: [PATCH 31/45] Update LICENSE --- LICENSE | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index c4aa304e..1f18bc87 100644 --- a/LICENSE +++ b/LICENSE @@ -7,7 +7,7 @@ The Licensor encourages community participation through the SSUI GitHub repository. For support, feature requests, or inquiries, contact the Licensor at github.com/JacksonTheMaster. -The Stationeers Server UI (โ€œSSUIโ€) is a proprietary software suite, including the Stationeers Server Command Manager (SSCM), designed to enhance Stationeers server administration. SSUI is developed as an open-source project on GitHub (github.com/JacksonTheMaster/StationeersServerUI) to encourage community collaboration while maintaining legal control with the repository owner, JacksonTheMaster. This License Agreement governs the use, modification, and contribution to SSUI, balancing open development with controlled commercial use. SSCM is licensed separately under the Stationeers Server Command Manager License Agreement (see LICENSE in the SSCM folder). +The Stationeers Server UI (โ€œSSUIโ€) is a proprietary software suite, including the Stationeers Server Command Manager (SSCM), designed to enhance Stationeers server administration. SSUI is developed as an source-available (https://www.linuxfoundation.org/licensebestpractices#not-os) project on GitHub (github.com/JacksonTheMaster/StationeersServerUI) to encourage community collaboration while maintaining legal control with the repository owner, JacksonTheMaster. This License Agreement governs the use, modification, and contribution to SSUI, balancing open development with controlled commercial use. SSCM is licensed separately under the Stationeers Server Command Manager License Agreement (see LICENSE in the SSCM folder). ## DEFINITIONS @@ -16,7 +16,7 @@ The Stationeers Server UI (โ€œSSUIโ€) is a proprietary software suite, includin - **Licensee**: You, the individual or entity using SSUI. - **Licensor**: JacksonTheMaster, the copyright holder and repository owner of SSUI. - **Non-Commercial Use**: Use for personal, educational, or open-source development purposes without profit or business revenue. -- **Commercial Use**: Use in a business, profit-generating, or commercial context. +- **Commercial Use**: Use in a business, profit-generating, or commercial context. Does not apply to Content creators who create content on a SSUI powererd Server. - **RocketWerkz**: RocketWerkz Studios Limited (Level 38, PwC Tower, 15 Customs St. West, 1010 Auckland, NZBN: 9429041553206) ## GRANT OF LICENSE @@ -173,4 +173,4 @@ This Agreement is in English. ## CONTACT -For inquiries or commercial licensing, contact the Licensor at [github.com/JacksonTheMaster](https://github.com/JacksonTheMaster). \ No newline at end of file +For inquiries or commercial licensing, contact the Licensor at [github.com/JacksonTheMaster](https://github.com/JacksonTheMaster). From bbd632e258778f2d7d3fd982e65b817d9299ee38 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sun, 21 Sep 2025 03:41:44 +0200 Subject: [PATCH 32/45] - added entrypoint script to copy executable from /opt/SSUIBuildFiles to app since /app is a volume and would be empty else - renamed all instanced of StationeersServerControl in docker related files to StationeersServerUI --- .docker/Dockerfile | 14 +++++++++----- .docker/entrypoint.sh | 6 ++++++ 2 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 .docker/entrypoint.sh diff --git a/.docker/Dockerfile b/.docker/Dockerfile index e8d3a74a..9bd45c49 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -29,7 +29,7 @@ COPY . ./ COPY --from=frontend-builder /src/UIMod /src/UIMod # Build the server (embed will include UIMod/* at build time) -RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /out/StationeersServerControl ./server.go +RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /out/StationeersServerUI ./server.go ############ # Runtime @@ -51,10 +51,14 @@ RUN dpkg --add-architecture i386 \ && rm -rf /var/lib/apt/lists/* # Copy compiled binary and license -COPY --from=go-builder /out/StationeersServerControl /usr/local/bin/StationeersServerControl -COPY ./LICENSE /app/LICENSE -RUN chmod +x /usr/local/bin/StationeersServerControl +RUN mkdir -p /opt/SSUIBuildFiles +COPY --from=go-builder /out/StationeersServerUI /opt/SSUIBuildFiles/StationeersServerUI +COPY ./LICENSE /opt/SSUIBuildFiles/LICENSE +COPY ./.docker/entrypoint.sh /entrypoint.sh +RUN chmod +x /opt/SSUIBuildFiles/StationeersServerUI +RUN chmod +x /entrypoint.sh + EXPOSE 8443/tcp 27016/udp 27015/udp -ENTRYPOINT ["/usr/local/bin/StationeersServerControl"] +ENTRYPOINT ["/entrypoint.sh"] diff --git a/.docker/entrypoint.sh b/.docker/entrypoint.sh new file mode 100644 index 00000000..0069b069 --- /dev/null +++ b/.docker/entrypoint.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +cp /opt/SSUIBuildFiles/StationeersServerUI /app/StationeersServerUI +cp /opt/SSUIBuildFiles/LICENSE /app/LICENSE +chmod +x /app/StationeersServerUI +exec /app/StationeersServerUI "$@" \ No newline at end of file From 70bca7e461d2fc25473bd85b2f8ff241e0051e0a Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sun, 21 Sep 2025 04:46:32 +0200 Subject: [PATCH 33/45] added IsDockerContainer config var and used it in sanitycheck to allow running as root in docker container. Added getter and setter acordingly. --- server.go | 9 +--- src/config/setters.go | 8 ++++ src/config/vars.go | 12 ++++-- src/core/loader/helpers.go | 79 ++++++++++++---------------------- src/core/loader/loader.go | 12 ++++++ src/core/loader/sanitycheck.go | 69 +++++++++++++++++++++++++++++ 6 files changed, 127 insertions(+), 62 deletions(-) create mode 100644 src/core/loader/sanitycheck.go diff --git a/server.go b/server.go index eaac0cfd..9f8226a4 100644 --- a/server.go +++ b/server.go @@ -22,9 +22,7 @@ package main import ( "embed" - "os" "sync" - "time" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/cli" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/core/loader" @@ -39,11 +37,8 @@ var v1uiFS embed.FS func main() { var wg sync.WaitGroup logger.ConfigureConsole() - if err := loader.SanityCheck(); err != nil { - logger.Main.Error("Sanity check failed, exiting in 10 secconds: " + err.Error()) - time.Sleep(10 * time.Second) - os.Exit(1) - } + loader.SanityCheck(&wg) + wg.Wait() logger.Main.Debug("Initializing resources...") loader.InitVirtFS(v1uiFS) logger.Install.Info("Starting setup...") diff --git a/src/config/setters.go b/src/config/setters.go index 2f9bd5fd..44a3cf9f 100644 --- a/src/config/setters.go +++ b/src/config/setters.go @@ -54,6 +54,14 @@ func SetSkipSteamCMD(value bool) error { return nil } +func SetIsDockerContainer(value bool) error { + ConfigMu.Lock() + defer ConfigMu.Unlock() + + IsDockerContainer = value + return nil +} + // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT diff --git a/src/config/vars.go b/src/config/vars.go index 41c84f42..71a6728d 100644 --- a/src/config/vars.go +++ b/src/config/vars.go @@ -61,9 +61,15 @@ var ( LanguageSetting string AutoStartServerOnStartup bool SSUIIdentifier string - CurrentBranchBuildID string // ONLY RUNTIME - ExtractedGameVersion string // ONLY RUNTIME - SkipSteamCMD bool // ONLY RUNTIME +) + +// Runtime only variables + +var ( + CurrentBranchBuildID string // ONLY RUNTIME + ExtractedGameVersion string // ONLY RUNTIME + SkipSteamCMD bool // ONLY RUNTIME + IsDockerContainer bool // ONLY RUNTIME ) // Discord integration diff --git a/src/core/loader/helpers.go b/src/core/loader/helpers.go index d8497154..98f3ec86 100644 --- a/src/core/loader/helpers.go +++ b/src/core/loader/helpers.go @@ -1,10 +1,9 @@ package loader import ( + "bufio" "fmt" "os" - "path/filepath" - "runtime" "strings" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/config" @@ -165,59 +164,35 @@ func PrintConfigDetails(logLevel ...string) { logger.Config.Debug("=======================================") } -func SanityCheck() error { - - if runtime.GOOS == "windows" { - return nil - } - - // Check if running as root (UID 0) - if os.Geteuid() == 0 { - return fmt.Errorf("root: SSUI should not be run as root") +func IsInsideContainer() bool { + // Check .dockerenv file (Docker-specific) + if _, err := os.Stat("/.dockerenv"); err == nil { + config.SetIsDockerContainer(true) + return true } + // Check cgroup (works for Docker and other container runtimes) + return isContainerFromCGroup() +} - // Get the current executable path from /proc/self/exe - exePath, err := os.Readlink("/proc/self/exe") +func isContainerFromCGroup() bool { + file, err := os.Open("/proc/1/cgroup") if err != nil { - return err - } - // Get the directory path of the executable - dirPath := filepath.Dir(exePath) - // Change the working directory to the executable's directory - cwd, err := os.Getwd() - if err != nil { - return err - } - - if cwd != dirPath && !strings.Contains(dirPath, "/tmp") { - err = os.Chdir(dirPath) - if err != nil { - return err + return false + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + // Check for various container runtime indicators + if strings.Contains(line, "docker") || + strings.Contains(line, "containerd") || + strings.Contains(line, "kubepods") || + strings.Contains(line, "crio") || + strings.Contains(line, "libpod") { + config.SetIsDockerContainer(true) + return true } } - - // Check if current working directory is writable - workDir, err := os.Getwd() - if err != nil { - return fmt.Errorf("failed to get working directory: %w", err) - } - - // Try to create a temporary file to test write permissions - testFile := filepath.Join(workDir, ".write_test") - if err := os.WriteFile(testFile, []byte("test"), 0600); err != nil { - return fmt.Errorf("cannot write to working directory %s: %w", workDir, err) - } - // Clean up test file - if err := os.Remove(testFile); err != nil { - return fmt.Errorf("failed to clean up sanity check writetest file: %w", err) - } - - // Check if steamcmd package is installed (requires further testing, disabled for now) - //cmd := exec.Command("dpkg-query", "-W", "-f='${Status}'", "steamcmd") - //output, err := cmd.CombinedOutput() - //if err == nil && strings.Contains(string(output), "install ok installed") { - // return fmt.Errorf("steamcmd package is installed") - //} - - return nil + return false } diff --git a/src/core/loader/loader.go b/src/core/loader/loader.go index 72830a12..de1bc1c5 100644 --- a/src/core/loader/loader.go +++ b/src/core/loader/loader.go @@ -3,7 +3,9 @@ package loader import ( "embed" + "os" "sync" + "time" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/config" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/discordbot" @@ -98,3 +100,13 @@ func ReloadAppInfoPoller() { func InitVirtFS(v1uiFS embed.FS) { config.SetV1UIFS(v1uiFS) } + +func SanityCheck(wg *sync.WaitGroup) { + defer wg.Done() + err := runSanityCheck() + if err != nil { + logger.Main.Error("Sanity check failed, exiting in 10 secconds: " + err.Error()) + time.Sleep(10 * time.Second) + os.Exit(1) + } +} diff --git a/src/core/loader/sanitycheck.go b/src/core/loader/sanitycheck.go new file mode 100644 index 00000000..fc5d2378 --- /dev/null +++ b/src/core/loader/sanitycheck.go @@ -0,0 +1,69 @@ +package loader + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" +) + +func runSanityCheck() error { + + if runtime.GOOS == "windows" { + return nil + } + + // Check if running as root (UID 0) + if os.Geteuid() == 0 { + // Check if running inside a container + if !IsInsideContainer() { + return fmt.Errorf("root: SSUI should not be run as root") + } + } + + // Get the current executable path from /proc/self/exe + exePath, err := os.Readlink("/proc/self/exe") + if err != nil { + return err + } + // Get the directory path of the executable + dirPath := filepath.Dir(exePath) + // Change the working directory to the executable's directory + cwd, err := os.Getwd() + if err != nil { + return err + } + + if cwd != dirPath && !strings.Contains(dirPath, "/tmp") { + err = os.Chdir(dirPath) + if err != nil { + return err + } + } + + // Check if current working directory is writable + workDir, err := os.Getwd() + if err != nil { + return fmt.Errorf("failed to get working directory: %w", err) + } + + // Try to create a temporary file to test write permissions + testFile := filepath.Join(workDir, ".write_test") + if err := os.WriteFile(testFile, []byte("test"), 0600); err != nil { + return fmt.Errorf("cannot write to working directory, please make sure your user has write permissions in %s: %w", workDir, err) + } + // Clean up test file + if err := os.Remove(testFile); err != nil { + return fmt.Errorf("failed to clean up sanity check writetest file: %w", err) + } + + // Check if steamcmd package is installed (requires further testing, disabled for now) + //cmd := exec.Command("dpkg-query", "-W", "-f='${Status}'", "steamcmd") + //output, err := cmd.CombinedOutput() + //if err == nil && strings.Contains(string(output), "install ok installed") { + // return fmt.Errorf("steamcmd package is installed") + //} + + return nil +} From 362993cf536435a3521990d17ae2468104f0805f Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sun, 21 Sep 2025 05:02:09 +0200 Subject: [PATCH 34/45] increment wait group to fix panic --- src/core/loader/loader.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/loader/loader.go b/src/core/loader/loader.go index de1bc1c5..a92f8d3b 100644 --- a/src/core/loader/loader.go +++ b/src/core/loader/loader.go @@ -102,6 +102,7 @@ func InitVirtFS(v1uiFS embed.FS) { } func SanityCheck(wg *sync.WaitGroup) { + wg.Add(1) defer wg.Done() err := runSanityCheck() if err != nil { From 56a866b9657bcbe3ea89aaf176c8085f61f6ab18 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sun, 21 Sep 2025 13:32:23 +0200 Subject: [PATCH 35/45] improved sanitycheck with steamcmd check and better logging --- src/core/loader/loader.go | 2 ++ src/core/loader/sanitycheck.go | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/core/loader/loader.go b/src/core/loader/loader.go index a92f8d3b..1e64959a 100644 --- a/src/core/loader/loader.go +++ b/src/core/loader/loader.go @@ -107,6 +107,8 @@ func SanityCheck(wg *sync.WaitGroup) { err := runSanityCheck() if err != nil { logger.Main.Error("Sanity check failed, exiting in 10 secconds: " + err.Error()) + logger.Main.Info("If you want to continue anyway, run SSUI with the --noSanityCheck flag, but be aware there may be Dragons ahead.") + logger.Main.Info("This is not recommended nor supported and may cause unexpected behavior, including potential data loss!") time.Sleep(10 * time.Second) os.Exit(1) } diff --git a/src/core/loader/sanitycheck.go b/src/core/loader/sanitycheck.go index fc5d2378..3b453aa7 100644 --- a/src/core/loader/sanitycheck.go +++ b/src/core/loader/sanitycheck.go @@ -3,6 +3,7 @@ package loader import ( "fmt" "os" + "os/exec" "path/filepath" "runtime" "strings" @@ -59,11 +60,11 @@ func runSanityCheck() error { } // Check if steamcmd package is installed (requires further testing, disabled for now) - //cmd := exec.Command("dpkg-query", "-W", "-f='${Status}'", "steamcmd") - //output, err := cmd.CombinedOutput() - //if err == nil && strings.Contains(string(output), "install ok installed") { - // return fmt.Errorf("steamcmd package is installed") - //} + cmd := exec.Command("dpkg-query", "-W", "-f='${Status}'", "steamcmd") + output, err := cmd.CombinedOutput() + if err == nil && strings.Contains(string(output), "install ok installed") { + return fmt.Errorf("steamcmd apt package is installed, it is not recommended to run SSUI when the apt steamcmd package is installed. Please uninstall the steamcmd package or have a look at our Docker image and try again") + } return nil } From 1291737928670c8734a1a899f3837c080d5935ac Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sun, 21 Sep 2025 13:55:33 +0200 Subject: [PATCH 36/45] - added NoSanityCheck flag - refactored flag handling to allow using NoSanityCheck early in the process - changed "CreateSSUILogFile" flag to "LogToFiles" --- .vscode/launch.json | 2 +- server.go | 4 +- src/config/getters.go | 6 ++ src/config/setters.go | 8 +++ src/config/vars.go | 1 + src/core/loader/cmdargs.go | 106 +++++++++++++++++++-------------- src/core/loader/sanitycheck.go | 6 ++ 7 files changed, 86 insertions(+), 47 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 9b4ebad8..b5d9d441 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -28,7 +28,7 @@ "program": "${workspaceFolder}/server.go", "console": "integratedTerminal", "showLog": false, // Hides some Go Debugger(Delve) log stuff that is not useful for debugging atm - "args": ["--SkipSteamCMD"] + "args": ["--NoSteamCMD"] } ] } \ No newline at end of file diff --git a/server.go b/server.go index 9f8226a4..78cfb337 100644 --- a/server.go +++ b/server.go @@ -37,13 +37,15 @@ var v1uiFS embed.FS func main() { var wg sync.WaitGroup logger.ConfigureConsole() + loader.ParseFlags() + loader.HandleSanityCheckFlag() loader.SanityCheck(&wg) wg.Wait() logger.Main.Debug("Initializing resources...") loader.InitVirtFS(v1uiFS) logger.Install.Info("Starting setup...") loader.ReloadConfig() // Load the config file before starting the setup process - loader.LoadCmdArgs() + loader.HandleFlags() setup.Install(&wg) wg.Wait() logger.Main.Debug("Initializing Backend...") diff --git a/src/config/getters.go b/src/config/getters.go index bbc9e402..0ead6a1d 100644 --- a/src/config/getters.go +++ b/src/config/getters.go @@ -499,3 +499,9 @@ func GetSkipSteamCMD() bool { defer ConfigMu.RUnlock() return SkipSteamCMD } + +func GetNoSanityCheck() bool { + ConfigMu.RLock() + defer ConfigMu.RUnlock() + return NoSanityCheck +} diff --git a/src/config/setters.go b/src/config/setters.go index 44a3cf9f..9928d5cc 100644 --- a/src/config/setters.go +++ b/src/config/setters.go @@ -62,6 +62,14 @@ func SetIsDockerContainer(value bool) error { return nil } +func SetNoSanityCheck(value bool) error { + ConfigMu.Lock() + defer ConfigMu.Unlock() + + NoSanityCheck = value + return nil +} + // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT diff --git a/src/config/vars.go b/src/config/vars.go index 71a6728d..edcb3c1d 100644 --- a/src/config/vars.go +++ b/src/config/vars.go @@ -70,6 +70,7 @@ var ( ExtractedGameVersion string // ONLY RUNTIME SkipSteamCMD bool // ONLY RUNTIME IsDockerContainer bool // ONLY RUNTIME + NoSanityCheck bool // ONLY RUNTIME ) // Discord integration diff --git a/src/core/loader/cmdargs.go b/src/core/loader/cmdargs.go index e1a950b5..1b04418c 100644 --- a/src/core/loader/cmdargs.go +++ b/src/core/loader/cmdargs.go @@ -4,45 +4,51 @@ import ( "flag" "fmt" "strings" + "time" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/config" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/core/security" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/logger" ) -// LoadCmdArgs parses command-line arguments ONCE at startup (called from func main) and applies them using the config setters. -// Because this is using the config rather than adding features to it, it is a part of the loader package. -func LoadCmdArgs() { - // Define flags matching the config variable names - var backendEndpointPort string - var gameBranch string - var logLevel int - var isDebugMode bool - var createSSUILogFile bool - var recoveryPassword string - var devMode bool - var skipSteamCMD bool +// Define flags matching the config variable names +var backendEndpointPortFlag string +var gameBranchFlag string +var logLevelFlag int +var isDebugModeFlag bool +var createSSUILogFileFlag bool +var recoveryPasswordFlag string +var devModeFlag bool +var skipSteamCMDFlag bool +var sanityCheckFlag bool - flag.StringVar(&backendEndpointPort, "BackendEndpointPort", "", "Override the backend endpoint port (e.g., 8080)") - flag.StringVar(&backendEndpointPort, "p", "", "(Alias) Override the backend endpoint port (e.g., 8080)") - flag.StringVar(&gameBranch, "GameBranch", "", "Override the game branch (e.g., beta)") - flag.StringVar(&gameBranch, "b", "", "(Alias) Override the game branch (e.g., beta)") - flag.StringVar(&recoveryPassword, "RecoveryPassword", "", "Adds a 'recovery' user (expects password as argument)") - flag.StringVar(&recoveryPassword, "r", "", "(Alias) Adds a 'recovery' user (expects password as argument)") - flag.BoolVar(&devMode, "dev", false, "Enable dev mode: Auth, and enables cli-console. For development only.") - flag.IntVar(&logLevel, "LogLevel", 0, "Override the log level (e.g., 10)") - flag.IntVar(&logLevel, "ll", 0, "(Alias) Override the log level (e.g., 10)") - flag.BoolVar(&isDebugMode, "IsDebugMode", false, "Enable debug mode") - flag.BoolVar(&isDebugMode, "debug", false, "(Alias) Enable debug mode") - flag.BoolVar(&createSSUILogFile, "CreateSSUILogFile", false, "Create a log file for SSUI") - flag.BoolVar(&createSSUILogFile, "lf", false, "(Alias) Create a log file for SSUI") - flag.BoolVar(&skipSteamCMD, "SkipSteamCMD", false, "Skips SteamCMD installation") - flag.BoolVar(&skipSteamCMD, "nosteam", false, "(Alias) Skips SteamCMD installation") +// ParseFlags parses command-line arguments ONCE at startup (called from func main) +func ParseFlags() { + flag.StringVar(&backendEndpointPortFlag, "BackendEndpointPort", "", "Override the backend endpoint port (e.g., 8080)") + flag.StringVar(&backendEndpointPortFlag, "p", "", "(Alias) Override the backend endpoint port (e.g., 8080)") + flag.StringVar(&gameBranchFlag, "GameBranch", "", "Override the game branch (e.g., beta)") + flag.StringVar(&gameBranchFlag, "b", "", "(Alias) Override the game branch (e.g., beta)") + flag.StringVar(&recoveryPasswordFlag, "RecoveryPassword", "", "Adds a 'recovery' user (expects password as argument)") + flag.StringVar(&recoveryPasswordFlag, "r", "", "(Alias) Adds a 'recovery' user (expects password as argument)") + flag.BoolVar(&devModeFlag, "dev", false, "Enable dev mode: Auth, and enables cli-console. For development only.") + flag.IntVar(&logLevelFlag, "LogLevel", 0, "Override the log level (e.g., 10)") + flag.IntVar(&logLevelFlag, "ll", 0, "(Alias) Override the log level (e.g., 10)") + flag.BoolVar(&isDebugModeFlag, "IsDebugMode", false, "Enable debug mode") + flag.BoolVar(&isDebugModeFlag, "debug", false, "(Alias) Enable debug mode") + flag.BoolVar(&createSSUILogFileFlag, "LogToFiles", false, "Create log files for SSUI") + flag.BoolVar(&createSSUILogFileFlag, "lf", false, "(Alias) Create log files for SSUI") + flag.BoolVar(&skipSteamCMDFlag, "NoSteamCMD", false, "Skips SteamCMD installation") + flag.BoolVar(&sanityCheckFlag, "NoSanityCheck", false, "Skips the sanity check. Not recommended.") // Parse command-line flags flag.Parse() +} + +// HandleCmdArgs handles command-line arguments ONCE at startup (called from func main) and applies them using the config setters. +// Because this is using the config rather than adding features to it, it is a part of the loader package. +func HandleFlags() { - if devMode { + if devModeFlag { config.SetAuthEnabled(true) config.SetIsFirstTimeSetup(false) config.SetUsers(map[string]string{"admin": "$2a$10$7QQhPkNAfT.MXhJhnnodXOyn3KKE/1eu7nYb0y2O1UBoAWc0Y/fda"}) // admin:admin @@ -50,53 +56,63 @@ func LoadCmdArgs() { logger.Main.Info("Dev mode enabled: Auth enabled, admin user set to admin:admin:superadmin, console enabled") } - if skipSteamCMD { + if skipSteamCMDFlag { config.SetSkipSteamCMD(true) } - if backendEndpointPort != "" && backendEndpointPort != "8443" { + if backendEndpointPortFlag != "" && backendEndpointPortFlag != "8443" { oldPort := config.GetSSUIWebPort() - config.SetSSUIWebPort(backendEndpointPort) - logger.Main.Info(fmt.Sprintf("Overriding SetSSUIWebPort from command line: Before=%s, Now=%s", oldPort, backendEndpointPort)) + config.SetSSUIWebPort(backendEndpointPortFlag) + logger.Main.Info(fmt.Sprintf("Overriding SetSSUIWebPort from command line: Before=%s, Now=%s", oldPort, backendEndpointPortFlag)) } - if gameBranch != "" { + if gameBranchFlag != "" { oldBranch := config.GetGameBranch() - config.SetGameBranch(gameBranch) - logger.Main.Info(fmt.Sprintf("Overriding GameBranch from command line: Before=%s, Now=%s", oldBranch, gameBranch)) + config.SetGameBranch(gameBranchFlag) + logger.Main.Info(fmt.Sprintf("Overriding GameBranch from command line: Before=%s, Now=%s", oldBranch, gameBranchFlag)) } - if recoveryPassword != "" { - recoveryPassword = strings.TrimSpace(recoveryPassword) - if recoveryPassword == "" { + if recoveryPasswordFlag != "" { + recoveryPasswordFlag = strings.TrimSpace(recoveryPasswordFlag) + if recoveryPasswordFlag == "" { logger.Main.Error("Recovery flag provided but password is empty. Skipping recovery user creation.") } else { - hashedPassword, err := security.HashPassword(recoveryPassword) + hashedPassword, err := security.HashPassword(recoveryPasswordFlag) if err != nil { logger.Main.Error(fmt.Sprintf("Failed to hash recovery password: %v", err)) return } config.SetUsers(map[string]string{"recovery": hashedPassword}) - logger.Main.Warn(fmt.Sprintf("Recovery user added with access level superadmin. Login with username 'recovery' and password '%s'", recoveryPassword)) + logger.Main.Warn(fmt.Sprintf("Recovery user added with access level superadmin. Login with username 'recovery' and password '%s'", recoveryPasswordFlag)) } } - if logLevel != 0 { + if logLevelFlag != 0 { oldLevel := config.GetLogLevel() - config.SetLogLevel(logLevel) - logger.Main.Info(fmt.Sprintf("Overriding LogLevel from command line: Before=%d, Now=%d", oldLevel, logLevel)) + config.SetLogLevel(logLevelFlag) + logger.Main.Info(fmt.Sprintf("Overriding LogLevel from command line: Before=%d, Now=%d", oldLevel, logLevelFlag)) } - if isDebugMode { + if isDebugModeFlag { oldDebug := config.GetIsDebugMode() config.SetIsDebugMode(true) config.SetLogLevel(10) logger.Main.Info(fmt.Sprintf("Overriding IsDebugMode from command line: Before=%t, Now=true", oldDebug)) } - if createSSUILogFile { + if createSSUILogFileFlag { oldCreateSSUILogFile := config.GetCreateSSUILogFile() config.SetCreateSSUILogFile(true) logger.Main.Info(fmt.Sprintf("Overriding CreateSSUILogFile from command line: Before=%t, Now=true", oldCreateSSUILogFile)) } } + +// HandleSanityCheckFlag has special handling to allow usage directly at startup before other systems are initialized. +func HandleSanityCheckFlag() { + if sanityCheckFlag { + config.NoSanityCheck = true + logger.Main.Warn("Sanity check flag enabled, skipping sanity check. Not recommended.") + logger.Main.Info("Sleeping for 5 seconds to remind you again to not use this flag in production.") + time.Sleep(5 * time.Second) + } +} diff --git a/src/core/loader/sanitycheck.go b/src/core/loader/sanitycheck.go index 3b453aa7..22be3706 100644 --- a/src/core/loader/sanitycheck.go +++ b/src/core/loader/sanitycheck.go @@ -7,6 +7,8 @@ import ( "path/filepath" "runtime" "strings" + + "github.com/JacksonTheMaster/StationeersServerUI/v5/src/config" ) func runSanityCheck() error { @@ -15,6 +17,10 @@ func runSanityCheck() error { return nil } + if config.GetNoSanityCheck() { + return nil + } + // Check if running as root (UID 0) if os.Geteuid() == 0 { // Check if running inside a container From 7bbfdf057a2eefbdab22938a5a35636eff9365bb Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sun, 21 Sep 2025 14:05:37 +0200 Subject: [PATCH 37/45] fixed indent in terminalmsg (again) --- src/core/loader/terminalmsg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/loader/terminalmsg.go b/src/core/loader/terminalmsg.go index d22412c2..588eed6f 100644 --- a/src/core/loader/terminalmsg.go +++ b/src/core/loader/terminalmsg.go @@ -23,7 +23,7 @@ func printStartupMessage() { logger.Core.Cleanf(" โ•šโ•โ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ• โ•šโ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•") logger.Core.Cleanf(" โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—") logger.Core.Cleanf(" โ•‘ ๐ŸŽฎ YOUR ONE-STOP SHOP FOR RUNNING A STATIONEERS SERVER ๐ŸŽฎ โ•‘") - logger.Core.Cleanf(" โ•‘ ๐Ÿš€ Version: %s ๐Ÿ“… %s ๐Ÿ’ป Runtime: %.3s/%s โ•‘", + logger.Core.Cleanf(" โ•‘ ๐Ÿš€ Version: %s ๐Ÿ“… %s ๐Ÿ’ป Runtime: %.3s/%s โ•‘", config.GetVersion(), time.Now().Format("2006-01-02 15:04"), runtime.GOOS, From e0f563784ab006905eaf45090ebfaf8b869b9e7c Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Sun, 21 Sep 2025 14:06:02 +0200 Subject: [PATCH 38/45] Improved loglevels of prints during startup --- server.go | 2 +- src/setup/install.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server.go b/server.go index 78cfb337..94cb1576 100644 --- a/server.go +++ b/server.go @@ -41,7 +41,7 @@ func main() { loader.HandleSanityCheckFlag() loader.SanityCheck(&wg) wg.Wait() - logger.Main.Debug("Initializing resources...") + logger.Main.Info("Initializing resources...") loader.InitVirtFS(v1uiFS) logger.Install.Info("Starting setup...") loader.ReloadConfig() // Load the config file before starting the setup process diff --git a/src/setup/install.go b/src/setup/install.go index dad418ad..99e1d82d 100644 --- a/src/setup/install.go +++ b/src/setup/install.go @@ -352,7 +352,7 @@ func checkAndCreateBlacklist() { logger.Install.Info("โœ…Created Blacklist.txt with dummy steamID64.") } else { - logger.Install.Info("โ™ป๏ธBlacklist.txt already exists. Skipping creation.") + logger.Install.Debug("โ™ป๏ธBlacklist.txt already exists. Skipping creation.") } } From 0a8d9bf871fefbb33814de46b1659b399ee20ec6 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Mon, 22 Sep 2025 01:22:55 +0200 Subject: [PATCH 39/45] the transition notice (SteamServerUi) is now hidden again --- UIMod/onboard_bundled/ui/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UIMod/onboard_bundled/ui/index.html b/UIMod/onboard_bundled/ui/index.html index 3ffbd622..4e70928e 100644 --- a/UIMod/onboard_bundled/ui/index.html +++ b/UIMod/onboard_bundled/ui/index.html @@ -107,7 +107,7 @@

signature sentence

JacksonTheMaster

-
+