Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ modconfig.xml
UIMod/config/config.json
C:/custom/file.txt
UIMod/config/customdetections.json
./autostart.sh
./autostart.ps1
winhttp.dll
autostart*
__debug_bin*
frontend/node_modules
frontend/dist
frontend/build
UIMod/onboard_bundled/v2
StationeersServerUI.lnk
79 changes: 77 additions & 2 deletions UIMod/onboard_bundled/scripts/autostart.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,78 @@
#!/bin/bash
#!/usr/bin/env bash

Comment thread
akirilov marked this conversation as resolved.
# not yet implemented
# This script serves two purposes:
# 1. Installation: Creates and configures a systemd service (ssui.service) to run the StationeersServerControl (StationeersServerUI) application.
# 2. Runtime: When executed and Service already installed, finds and runs the latest StationeersServerControl binary (matching StationeersServerControlv*).
# The systemd service uses ExecStart=$SCRIPT_PATH to run this script, which then dynamically selects the latest binary version of SSUI to run.
# Check if running as root to prevent installing a service as root

if [[ $(id -u) = 0 ]]; then
echo "For security reasons, it is not recommended to run this service as a root user."
exit 10
fi

# Check if systemd is available
if [[ ! -d /run/systemd/system ]]; then
echo "Error: systemd is not the active init system."
exit 2
fi

# Determine the full path of this script
SCRIPT_PATH=$(readlink -f "$0")

# Determine the base directory
BASEDIR=$(dirname "$SCRIPT_PATH")
if [[ -z "$BASEDIR" || ! -d "$BASEDIR" ]]; then
echo "Error: Could not determine base directory from SCRIPT_PATH: '$SCRIPT_PATH'."
exit 3
fi


USERNAME=$(whoami)

# Create the systemd service file pointing to this script
sudo tee /etc/systemd/system/stationeersserverui.service > /dev/null <<EOF
[Unit]
Description=Stationeers Server UI
After=network.target

[Service]
Type=simple
Restart=always
RestartSec=5s
User=$USERNAME
WorkingDirectory=$BASEDIR
ExecStart=$BASEDIR/StationeersServerUI

[Install]
WantedBy=multi-user.target
EOF

Comment thread
akirilov marked this conversation as resolved.
sudo chmod 0644 /etc/systemd/system/ssui.service
if [[ $? -ne 0 ]]; then
echo "Error: Failed to set permissions on /etc/systemd/system/ssui.service."
exit 6
fi

# Reload systemd daemon
sudo systemctl daemon-reload
Comment thread
akirilov marked this conversation as resolved.
if [[ $? -ne 0 ]]; then
echo "Error: Failed to reload systemd daemon."
exit 7
fi

# Enable the service
sudo systemctl enable ssui.service
Comment thread
akirilov marked this conversation as resolved.
if [[ $? -ne 0 ]]; then
echo "Error: Failed to enable ssui.service."
exit 8
fi

# Start the service
sudo systemctl start ssui.service
Comment thread
akirilov marked this conversation as resolved.
if [[ $? -ne 0 ]]; then
echo "Error: Failed to start ssui.service."
exit 9
fi

echo "Success! Service installed in '/etc/systemd/system/ssui.service'"
78 changes: 78 additions & 0 deletions autostart.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env bash

# This script serves two purposes:
# 1. Installation: Creates and configures a systemd service (ssui.service) to run the StationeersServerControl (StationeersServerUI) application.
# 2. Runtime: When executed and Service already installed, finds and runs the latest StationeersServerControl binary (matching StationeersServerControlv*).
# The systemd service uses ExecStart=$SCRIPT_PATH to run this script, which then dynamically selects the latest binary version of SSUI to run.
# Check if running as root to prevent installing a service as root

if [[ $(id -u) = 0 ]]; then
echo "For security reasons, it is not recommended to run this service as a root user."
exit 10
fi

# Check if systemd is available
if [[ ! -d /run/systemd/system ]]; then
echo "Error: systemd is not the active init system."
exit 2
fi

# Determine the full path of this script
SCRIPT_PATH=$(readlink -f "$0")

# Determine the base directory
BASEDIR=$(dirname "$SCRIPT_PATH")
if [[ -z "$BASEDIR" || ! -d "$BASEDIR" ]]; then
echo "Error: Could not determine base directory from SCRIPT_PATH: '$SCRIPT_PATH'."
exit 3
fi


USERNAME=$(whoami)

# Create the systemd service file pointing to this script
sudo tee /etc/systemd/system/stationeersserverui.service > /dev/null <<EOF
[Unit]
Description=Stationeers Server UI
After=network.target

[Service]
Type=simple
Restart=always
RestartSec=5s
User=$USERNAME
WorkingDirectory=$BASEDIR
ExecStart=$BASEDIR/StationeersServerUI.lnk

[Install]
WantedBy=multi-user.target
EOF

sudo chmod 0644 /etc/systemd/system/ssui.service
if [[ $? -ne 0 ]]; then
echo "Error: Failed to set permissions on /etc/systemd/system/ssui.service."
exit 6
fi

# Reload systemd daemon
sudo systemctl daemon-reload
if [[ $? -ne 0 ]]; then
echo "Error: Failed to reload systemd daemon."
exit 7
fi

# Enable the service
sudo systemctl enable ssui.service
if [[ $? -ne 0 ]]; then
echo "Error: Failed to enable ssui.service."
exit 8
fi

# Start the service
sudo systemctl start ssui.service
if [[ $? -ne 0 ]]; then
echo "Error: Failed to start ssui.service."
exit 9
fi

echo "Success! Service installed in '/etc/systemd/system/ssui.service'"
5 changes: 3 additions & 2 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ 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()
setup.Install(&wg)
wg.Wait()
logger.Main.Debug("Initializing resources...")
loader.InitVirtFS(v1uiFS)
logger.Main.Debug("Initializing Backend...")
loader.InitBackend(&wg)
wg.Wait()
Expand Down
1 change: 0 additions & 1 deletion src/core/loader/afterstart.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ func AfterStartComplete(wg *sync.WaitGroup) {
logger.Core.Info("AutoStartServerOnStartup is enabled, starting server...")
gamemgr.InternalStartServer()
}
setup.SetupAutostartScripts()
discordrpc.StartDiscordRPC()

go func() {
Expand Down
20 changes: 20 additions & 0 deletions src/core/loader/cmdargs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ package loader
import (
"flag"
"fmt"
"os"
"runtime"
"strings"
"time"

"github.com/JacksonTheMaster/StationeersServerUI/v5/src/config"
"github.com/JacksonTheMaster/StationeersServerUI/v5/src/core/security"
"github.com/JacksonTheMaster/StationeersServerUI/v5/src/logger"
"github.com/JacksonTheMaster/StationeersServerUI/v5/src/setup/autostart"
)

// LoadCmdArgs parses command-line arguments ONCE at startup (called from func main) and applies them using the config setters.
Expand All @@ -21,6 +25,7 @@ func LoadCmdArgs() {
var createSSUILogFile bool
var recoveryPassword string
var devMode bool
var autoStartSSUIOnBoot 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)")
Expand All @@ -35,6 +40,7 @@ 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(&autoStartSSUIOnBoot, "setupautostart", false, "Setup Auto-start SSUI on boot")

// Parse command-line flags
flag.Parse()
Expand All @@ -47,6 +53,20 @@ func LoadCmdArgs() {
logger.Main.Info("Dev mode enabled: Auth enabled, admin user set to admin:admin:superadmin, console enabled")
}

if autoStartSSUIOnBoot {
if runtime.GOOS != "linux" {
logger.Core.Error("Autostart is only supported on Linux. Exiting in 5 seconds...")
time.Sleep(5 * time.Second)
os.Exit(0)
}
err := autostart.Initialize()
if err != nil {
logger.Core.Error("Failed to initialize autostart: " + err.Error())
}
time.Sleep(5 * time.Second)
os.Exit(0)
}

if backendEndpointPort != "" && backendEndpointPort != "8443" {
oldPort := config.GetSSUIWebPort()
config.SetSSUIWebPort(backendEndpointPort)
Expand Down
33 changes: 33 additions & 0 deletions src/core/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package loader

import (
"embed"
"os"
"path/filepath"
"runtime"
"sync"

"github.com/JacksonTheMaster/StationeersServerUI/v5/src/config"
Expand All @@ -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)
Expand Down
7 changes: 6 additions & 1 deletion src/core/loader/terminalmsg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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://<server-ip>:" + config.GetSSUIWebPort())
logger.Core.Cleanf("\n 🌐 Web UI available at: https://localhost:8443 (default) or https://<server-ip>:%s", config.GetSSUIWebPort())
logger.Core.Cleanf("\n 🌐 Support available at: https://discord.gg/8n3vN92MyJ")

// Quote
Expand All @@ -49,5 +49,10 @@ func printFirstTimeSetupMessage() {
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(" │ │")
if runtime.GOOS == "linux" {
logger.Core.Cleanf(" │ • Autostart: │")
logger.Core.Cleanf(" │ • to run SSUI automatically on boot, run SSUI with the --setupautostart flag once. │")
}
logger.Core.Cleanf(" └─────────────────────────────────────────────────────────────────────────────────────────────┘")
}
24 changes: 24 additions & 0 deletions src/setup/autostart/autostart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package autostart

import (
"fmt"
)

func Initialize() error {

err := SetupAutostartScripts()
if err != nil {
return fmt.Errorf("failed to setup autostart script, cannot proceed with autostart setup: %w", err)
}

err = SetupBinarySymlink()
if err != nil {
return fmt.Errorf("failed to create symlink for autostart: %w", err)
}

err = SetupService()
if err != nil {
return fmt.Errorf("failed to setup service: %w", err)
}
return nil
}
Loading