Skip to content

Commit 70bca7e

Browse files
added IsDockerContainer config var and used it in sanitycheck to allow running as root in docker container. Added getter and setter acordingly.
1 parent 6581708 commit 70bca7e

6 files changed

Lines changed: 127 additions & 62 deletions

File tree

server.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ package main
2222

2323
import (
2424
"embed"
25-
"os"
2625
"sync"
27-
"time"
2826

2927
"github.com/JacksonTheMaster/StationeersServerUI/v5/src/cli"
3028
"github.com/JacksonTheMaster/StationeersServerUI/v5/src/core/loader"
@@ -39,11 +37,8 @@ var v1uiFS embed.FS
3937
func main() {
4038
var wg sync.WaitGroup
4139
logger.ConfigureConsole()
42-
if err := loader.SanityCheck(); err != nil {
43-
logger.Main.Error("Sanity check failed, exiting in 10 secconds: " + err.Error())
44-
time.Sleep(10 * time.Second)
45-
os.Exit(1)
46-
}
40+
loader.SanityCheck(&wg)
41+
wg.Wait()
4742
logger.Main.Debug("Initializing resources...")
4843
loader.InitVirtFS(v1uiFS)
4944
logger.Install.Info("Starting setup...")

src/config/setters.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ func SetSkipSteamCMD(value bool) error {
5454
return nil
5555
}
5656

57+
func SetIsDockerContainer(value bool) error {
58+
ConfigMu.Lock()
59+
defer ConfigMu.Unlock()
60+
61+
IsDockerContainer = value
62+
return nil
63+
}
64+
5765
// ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT
5866
// ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT
5967
// ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT

src/config/vars.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,15 @@ var (
6161
LanguageSetting string
6262
AutoStartServerOnStartup bool
6363
SSUIIdentifier string
64-
CurrentBranchBuildID string // ONLY RUNTIME
65-
ExtractedGameVersion string // ONLY RUNTIME
66-
SkipSteamCMD bool // ONLY RUNTIME
64+
)
65+
66+
// Runtime only variables
67+
68+
var (
69+
CurrentBranchBuildID string // ONLY RUNTIME
70+
ExtractedGameVersion string // ONLY RUNTIME
71+
SkipSteamCMD bool // ONLY RUNTIME
72+
IsDockerContainer bool // ONLY RUNTIME
6773
)
6874

6975
// Discord integration

src/core/loader/helpers.go

Lines changed: 27 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package loader
22

33
import (
4+
"bufio"
45
"fmt"
56
"os"
6-
"path/filepath"
7-
"runtime"
87
"strings"
98

109
"github.com/JacksonTheMaster/StationeersServerUI/v5/src/config"
@@ -165,59 +164,35 @@ func PrintConfigDetails(logLevel ...string) {
165164
logger.Config.Debug("=======================================")
166165
}
167166

168-
func SanityCheck() error {
169-
170-
if runtime.GOOS == "windows" {
171-
return nil
172-
}
173-
174-
// Check if running as root (UID 0)
175-
if os.Geteuid() == 0 {
176-
return fmt.Errorf("root: SSUI should not be run as root")
167+
func IsInsideContainer() bool {
168+
// Check .dockerenv file (Docker-specific)
169+
if _, err := os.Stat("/.dockerenv"); err == nil {
170+
config.SetIsDockerContainer(true)
171+
return true
177172
}
173+
// Check cgroup (works for Docker and other container runtimes)
174+
return isContainerFromCGroup()
175+
}
178176

179-
// Get the current executable path from /proc/self/exe
180-
exePath, err := os.Readlink("/proc/self/exe")
177+
func isContainerFromCGroup() bool {
178+
file, err := os.Open("/proc/1/cgroup")
181179
if err != nil {
182-
return err
183-
}
184-
// Get the directory path of the executable
185-
dirPath := filepath.Dir(exePath)
186-
// Change the working directory to the executable's directory
187-
cwd, err := os.Getwd()
188-
if err != nil {
189-
return err
190-
}
191-
192-
if cwd != dirPath && !strings.Contains(dirPath, "/tmp") {
193-
err = os.Chdir(dirPath)
194-
if err != nil {
195-
return err
180+
return false
181+
}
182+
defer file.Close()
183+
184+
scanner := bufio.NewScanner(file)
185+
for scanner.Scan() {
186+
line := scanner.Text()
187+
// Check for various container runtime indicators
188+
if strings.Contains(line, "docker") ||
189+
strings.Contains(line, "containerd") ||
190+
strings.Contains(line, "kubepods") ||
191+
strings.Contains(line, "crio") ||
192+
strings.Contains(line, "libpod") {
193+
config.SetIsDockerContainer(true)
194+
return true
196195
}
197196
}
198-
199-
// Check if current working directory is writable
200-
workDir, err := os.Getwd()
201-
if err != nil {
202-
return fmt.Errorf("failed to get working directory: %w", err)
203-
}
204-
205-
// Try to create a temporary file to test write permissions
206-
testFile := filepath.Join(workDir, ".write_test")
207-
if err := os.WriteFile(testFile, []byte("test"), 0600); err != nil {
208-
return fmt.Errorf("cannot write to working directory %s: %w", workDir, err)
209-
}
210-
// Clean up test file
211-
if err := os.Remove(testFile); err != nil {
212-
return fmt.Errorf("failed to clean up sanity check writetest file: %w", err)
213-
}
214-
215-
// Check if steamcmd package is installed (requires further testing, disabled for now)
216-
//cmd := exec.Command("dpkg-query", "-W", "-f='${Status}'", "steamcmd")
217-
//output, err := cmd.CombinedOutput()
218-
//if err == nil && strings.Contains(string(output), "install ok installed") {
219-
// return fmt.Errorf("steamcmd package is installed")
220-
//}
221-
222-
return nil
197+
return false
223198
}

src/core/loader/loader.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package loader
33

44
import (
55
"embed"
6+
"os"
67
"sync"
8+
"time"
79

810
"github.com/JacksonTheMaster/StationeersServerUI/v5/src/config"
911
"github.com/JacksonTheMaster/StationeersServerUI/v5/src/discordbot"
@@ -98,3 +100,13 @@ func ReloadAppInfoPoller() {
98100
func InitVirtFS(v1uiFS embed.FS) {
99101
config.SetV1UIFS(v1uiFS)
100102
}
103+
104+
func SanityCheck(wg *sync.WaitGroup) {
105+
defer wg.Done()
106+
err := runSanityCheck()
107+
if err != nil {
108+
logger.Main.Error("Sanity check failed, exiting in 10 secconds: " + err.Error())
109+
time.Sleep(10 * time.Second)
110+
os.Exit(1)
111+
}
112+
}

src/core/loader/sanitycheck.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package loader
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
"runtime"
8+
"strings"
9+
)
10+
11+
func runSanityCheck() error {
12+
13+
if runtime.GOOS == "windows" {
14+
return nil
15+
}
16+
17+
// Check if running as root (UID 0)
18+
if os.Geteuid() == 0 {
19+
// Check if running inside a container
20+
if !IsInsideContainer() {
21+
return fmt.Errorf("root: SSUI should not be run as root")
22+
}
23+
}
24+
25+
// Get the current executable path from /proc/self/exe
26+
exePath, err := os.Readlink("/proc/self/exe")
27+
if err != nil {
28+
return err
29+
}
30+
// Get the directory path of the executable
31+
dirPath := filepath.Dir(exePath)
32+
// Change the working directory to the executable's directory
33+
cwd, err := os.Getwd()
34+
if err != nil {
35+
return err
36+
}
37+
38+
if cwd != dirPath && !strings.Contains(dirPath, "/tmp") {
39+
err = os.Chdir(dirPath)
40+
if err != nil {
41+
return err
42+
}
43+
}
44+
45+
// Check if current working directory is writable
46+
workDir, err := os.Getwd()
47+
if err != nil {
48+
return fmt.Errorf("failed to get working directory: %w", err)
49+
}
50+
51+
// Try to create a temporary file to test write permissions
52+
testFile := filepath.Join(workDir, ".write_test")
53+
if err := os.WriteFile(testFile, []byte("test"), 0600); err != nil {
54+
return fmt.Errorf("cannot write to working directory, please make sure your user has write permissions in %s: %w", workDir, err)
55+
}
56+
// Clean up test file
57+
if err := os.Remove(testFile); err != nil {
58+
return fmt.Errorf("failed to clean up sanity check writetest file: %w", err)
59+
}
60+
61+
// Check if steamcmd package is installed (requires further testing, disabled for now)
62+
//cmd := exec.Command("dpkg-query", "-W", "-f='${Status}'", "steamcmd")
63+
//output, err := cmd.CombinedOutput()
64+
//if err == nil && strings.Contains(string(output), "install ok installed") {
65+
// return fmt.Errorf("steamcmd package is installed")
66+
//}
67+
68+
return nil
69+
}

0 commit comments

Comments
 (0)