refactor: rename CLI binary to spx and update all command names

- Makefile: GO_PROJECT_NAME → spx, update build/test/dist paths
- root.go: Use → spx, update branding to Spinifex
- service.go: hive/hive-ui commands → spinifex/spinifex-ui
- Service name constants: hive → spinifex, hive-ui → spinifex-ui
- Update service_test.go switch cases
This commit is contained in:
Ben Duncan
2026-03-18 00:42:34 +00:00
parent 06804f5775
commit 00f5b6590e
6 changed files with 119 additions and 122 deletions
+15 -15
View File
@@ -1,4 +1,4 @@
GO_PROJECT_NAME := hive
GO_PROJECT_NAME := spx
SHELL := /bin/bash
# Detect architecture for cross-platform support
@@ -49,19 +49,19 @@ endif
build:
$(MAKE) go_build
# Build hive-ui frontend (requires pnpm)
# Build spinifex-ui frontend (requires pnpm)
build-ui:
@echo -e "\n....Building hive-ui frontend...."
cd hive/services/hiveui/frontend && pnpm build
@echo -e "\n....Building spinifex-ui frontend...."
cd spinifex/services/spinifexui/frontend && pnpm build
# GO commands
VERSION ?= $(shell git describe --tags --always --dirty)
COMMIT ?= $(shell git rev-parse --short HEAD)
LDFLAGS := -s -w -X github.com/mulgadc/hive/cmd/hive/cmd.Version=$(VERSION) -X github.com/mulgadc/hive/cmd/hive/cmd.Commit=$(COMMIT)
LDFLAGS := -s -w -X github.com/mulgadc/spinifex/cmd/spinifex/cmd.Version=$(VERSION) -X github.com/mulgadc/spinifex/cmd/spinifex/cmd.Commit=$(COMMIT)
go_build:
@echo -e "\n....Building $(GO_PROJECT_NAME)"
go build $(GO_BUILD_MOD) -ldflags "$(LDFLAGS)" -o ./bin/$(GO_PROJECT_NAME) cmd/hive/main.go
go build $(GO_BUILD_MOD) -ldflags "$(LDFLAGS)" -o ./bin/$(GO_PROJECT_NAME) cmd/spinifex/main.go
go_run:
@echo -e "\n....Running $(GO_PROJECT_NAME)...."
@@ -76,7 +76,7 @@ preflight:
# Run unit tests
test:
@echo -e "\n....Running tests for $(GO_PROJECT_NAME)...."
LOG_IGNORE=1 go test -timeout 120s ./hive/...
LOG_IGNORE=1 go test -timeout 120s ./spinifex/...
# Run unit tests with coverage profile
# Note: go test may exit non-zero due to Go version mismatch in coverage instrumentation
@@ -84,13 +84,13 @@ test:
COVERPROFILE ?= coverage.out
test-cover:
@echo -e "\n....Running tests with coverage for $(GO_PROJECT_NAME)...."
$(_Q)LOG_IGNORE=1 go test -timeout 120s -coverprofile=$(COVERPROFILE) -covermode=atomic ./hive/... $(_COVQ)
$(_Q)LOG_IGNORE=1 go test -timeout 120s -coverprofile=$(COVERPROFILE) -covermode=atomic ./spinifex/... $(_COVQ)
@scripts/check-coverage.sh $(COVERPROFILE) $(QUIET)
# Run unit tests with race detector
test-race:
@echo -e "\n....Running tests with race detector for $(GO_PROJECT_NAME)...."
$(_Q)LOG_IGNORE=1 go test -race -timeout 300s ./hive/... $(_RACEQ)
$(_Q)LOG_IGNORE=1 go test -race -timeout 300s ./spinifex/... $(_RACEQ)
# Check that new/changed code meets coverage threshold (runs tests first)
diff-coverage: test-cover
@@ -107,7 +107,7 @@ run:
clean:
rm -f ./bin/$(GO_PROJECT_NAME)
rm -rf hive/services/hiveui/frontend/dist
rm -rf spinifex/services/spinifexui/frontend/dist
install-system:
@echo -e "\n....Installing system dependencies for $(ARCH)...."
@@ -199,7 +199,7 @@ security-check:
# Build release tarballs for both architectures via Docker
distro:
@echo "Building hive $(VERSION) distribution tarballs..."
@echo "Building spinifex $(VERSION) distribution tarballs..."
@mkdir -p dist/
@echo "Building linux/amd64..."
docker buildx build \
@@ -208,8 +208,8 @@ distro:
-f build/Dockerfile.distro \
--output type=local,dest=dist/amd64/ \
../
tar -czf dist/hive-$(VERSION)-linux-amd64.tar.gz -C dist/amd64 .
sha256sum dist/hive-$(VERSION)-linux-amd64.tar.gz > dist/hive-$(VERSION)-linux-amd64.tar.gz.sha256
tar -czf dist/spinifex-$(VERSION)-linux-amd64.tar.gz -C dist/amd64 .
sha256sum dist/spinifex-$(VERSION)-linux-amd64.tar.gz > dist/spinifex-$(VERSION)-linux-amd64.tar.gz.sha256
@echo "Building linux/arm64..."
docker buildx build \
--platform linux/arm64 \
@@ -217,8 +217,8 @@ distro:
-f build/Dockerfile.distro \
--output type=local,dest=dist/arm64/ \
../
tar -czf dist/hive-$(VERSION)-linux-arm64.tar.gz -C dist/arm64 .
sha256sum dist/hive-$(VERSION)-linux-arm64.tar.gz > dist/hive-$(VERSION)-linux-arm64.tar.gz.sha256
tar -czf dist/spinifex-$(VERSION)-linux-arm64.tar.gz -C dist/arm64 .
sha256sum dist/spinifex-$(VERSION)-linux-arm64.tar.gz > dist/spinifex-$(VERSION)-linux-arm64.tar.gz.sha256
@echo ""
@echo "Distribution tarballs:"
@ls -lh dist/*.tar.gz
+9 -12
View File
@@ -32,20 +32,17 @@ var (
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "hive",
Short: "Hive - Open source AWS-compatible platform for secure edge deployments",
Use: "spx",
Short: "Spinifex - Open source AWS-compatible platform for secure edge deployments",
Long: `
__/\\\________/\\\__/\\\\\\\\\\\__/\\\________/\\\__/\\\\\\\\\\\\\\\_
_\/\\\_______\/\\\_\/////\\\///__\/\\\_______\/\\\_\/\\\///////////__
_\/\\\_______\/\\\_____\/\\\_____\//\\\______/\\\__\/\\\_____________
_\/\\\\\\\\\\\\\\\_____\/\\\______\//\\\____/\\\___\/\\\\\\\\\\\_____
_\/\\\/////////\\\_____\/\\\_______\//\\\__/\\\____\/\\\///////______
_\/\\\_______\/\\\_____\/\\\________\//\\\/\\\_____\/\\\_____________
_\/\\\_______\/\\\_____\/\\\_________\//\\\\\______\/\\\_____________
_\/\\\_______\/\\\__/\\\\\\\\\\\______\//\\\_______\/\\\\\\\\\\\\\\\_
_\///________\///__\///////////________\///________\///////////////__
_____ _____ _____ _ _ _____ ______ ________ __
/ ____| __ \_ _| \ | |_ _| ____| ____\ \ / /
| (___ | |__) || | | \| | | | | |__ | |__ \ V /
\___ \| ___/ | | | . ‘ | | | | __| | __| > <
____) | | _| |_| |\ |_| |_| | | |____ / . \
|_____/|_| |_____|_| \_|_____|_| |______/_/ \_\
Hive – Open source AWS-compatible platform for secure edge deployments.
Spinifex – Open source AWS-compatible platform for secure edge deployments.
Run EC2, VPC, S3, and EBS-like services on bare metal with full control.
Built for environments where running in the cloud isn’t an option.
Whether you’re deploying to edge sites, private data-centers, or operating
+76 -76
View File
@@ -35,7 +35,7 @@ import (
var serviceCmd = &cobra.Command{
Use: "service",
Short: "Manage Hive services",
Short: "Manage Spinifex services",
}
var predastoreCmd = &cobra.Command{
@@ -53,9 +53,9 @@ var natsCmd = &cobra.Command{
Short: "Manage the nats service",
}
var hiveCmd = &cobra.Command{
Use: "hive",
Short: "Manage the hive service",
var spinifexCmd = &cobra.Command{
Use: "spinifex",
Short: "Manage the spinifex service",
}
var awsgwCmd = &cobra.Command{
@@ -68,10 +68,10 @@ var vpcdCmd = &cobra.Command{
Short: "Manage the vpcd (VPC daemon) service",
}
var hiveUICmd = &cobra.Command{
Use: "hive-ui",
Aliases: []string{"ui", "hiveui"},
Short: "Manage the hive-ui service",
var spinifexUICmd = &cobra.Command{
Use: "spinifex-ui",
Aliases: []string{"ui", "spinifexui"},
Short: "Manage the spinifex-ui service",
}
var predastoreStartCmd = &cobra.Command{
@@ -410,12 +410,12 @@ var natsStatusCmd = &cobra.Command{
},
}
// Repeat for hive
var hiveStartCmd = &cobra.Command{
// Repeat for spinifex
var spinifexStartCmd = &cobra.Command{
Use: "start",
Short: "Start the hive service",
Short: "Start the spinifex service",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Starting hive service...")
fmt.Println("Starting spinifex service...")
cfgFile := viper.GetString("config")
@@ -451,53 +451,53 @@ var hiveStartCmd = &cobra.Command{
// Apply changes back to cluster config
clusterConfig.Nodes[clusterConfig.Node] = nodeConfig
svc, err := service.New("hive", clusterConfig)
svc, err := service.New("spinifex", clusterConfig)
if err != nil {
fmt.Println("Error starting hive service:", err)
fmt.Println("Error starting spinifex service:", err)
return
}
// Set config path for cluster manager
if hiveSvc, ok := svc.(interface{ SetConfigPath(string) }); ok {
hiveSvc.SetConfigPath(cfgFile)
if spxSvc, ok := svc.(interface{ SetConfigPath(string) }); ok {
spxSvc.SetConfigPath(cfgFile)
}
if _, err = svc.Start(); err != nil {
fmt.Println("Error starting hive service:", err)
fmt.Println("Error starting spinifex service:", err)
os.Exit(1)
}
fmt.Println("HIVE service started")
fmt.Println("Spinifex service started")
},
}
var hiveStopCmd = &cobra.Command{
var spinifexStopCmd = &cobra.Command{
Use: "stop",
Short: "Stop the hive service",
Short: "Stop the spinifex service",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Stopping hive service...")
fmt.Println("Stopping spinifex service...")
service, err := service.New("hive", &config.ClusterConfig{})
service, err := service.New("spinifex", &config.ClusterConfig{})
if err != nil {
fmt.Println("Error stopping hive service:", err)
fmt.Println("Error stopping spinifex service:", err)
return
}
if err = service.Stop(); err != nil {
fmt.Println("Error stopping hive service:", err)
fmt.Println("Error stopping spinifex service:", err)
os.Exit(1)
}
fmt.Println("Hive service stopped")
fmt.Println("Spinifex service stopped")
},
}
var hiveStatusCmd = &cobra.Command{
var spinifexStatusCmd = &cobra.Command{
Use: "status",
Short: "Get status of the hive service",
Short: "Get status of the spinifex service",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hive service status: ...")
fmt.Println("Spinifex service status: ...")
},
}
@@ -601,18 +601,18 @@ var awsgwStatusCmd = &cobra.Command{
},
}
var hiveUIStartCmd = &cobra.Command{
var spinifexUIStartCmd = &cobra.Command{
Use: "start",
Short: "Start the hive-ui service",
Short: "Start the spinifex-ui service",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Starting hive-ui service...")
fmt.Println("Starting spinifex-ui service...")
port := viper.GetInt("hive-ui-port")
host := viper.GetString("hive-ui-host")
tlsCert := viper.GetString("hive-ui-tls-cert")
tlsKey := viper.GetString("hive-ui-tls-key")
port := viper.GetInt("spinifex-ui-port")
host := viper.GetString("spinifex-ui-host")
tlsCert := viper.GetString("spinifex-ui-tls-cert")
tlsKey := viper.GetString("spinifex-ui-tls-key")
svc, err := service.New("hive-ui", &hiveui.Config{
svc, err := service.New("spinifex-ui", &spinifexui.Config{
Port: port,
Host: host,
TLSCert: tlsCert,
@@ -620,57 +620,57 @@ var hiveUIStartCmd = &cobra.Command{
})
if err != nil {
fmt.Println("Error starting hive-ui service:", err)
fmt.Println("Error starting spinifex-ui service:", err)
return
}
if _, err = svc.Start(); err != nil {
fmt.Println("Error starting hive-ui service:", err)
fmt.Println("Error starting spinifex-ui service:", err)
os.Exit(1)
}
fmt.Println("hive-ui service started")
fmt.Println("spinifex-ui service started")
},
}
var hiveUIStopCmd = &cobra.Command{
var spinifexUIStopCmd = &cobra.Command{
Use: "stop",
Short: "Stop the hive-ui service",
Short: "Stop the spinifex-ui service",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Stopping hive-ui service...")
fmt.Println("Stopping spinifex-ui service...")
svc, err := service.New("hive-ui", &hiveui.Config{})
svc, err := service.New("spinifex-ui", &spinifexui.Config{})
if err != nil {
fmt.Println("Error stopping hive-ui service:", err)
fmt.Println("Error stopping spinifex-ui service:", err)
return
}
if err = svc.Stop(); err != nil {
fmt.Println("Error stopping hive-ui service:", err)
fmt.Println("Error stopping spinifex-ui service:", err)
os.Exit(1)
}
fmt.Println("hive-ui service stopped")
fmt.Println("spinifex-ui service stopped")
},
}
var hiveUIStatusCmd = &cobra.Command{
var spinifexUIStatusCmd = &cobra.Command{
Use: "status",
Short: "Get status of the hive-ui service",
Short: "Get status of the spinifex-ui service",
Run: func(cmd *cobra.Command, args []string) {
svc, err := service.New("hive-ui", &hiveui.Config{})
svc, err := service.New("spinifex-ui", &spinifexui.Config{})
if err != nil {
fmt.Println("Error getting hive-ui service status:", err)
fmt.Println("Error getting spinifex-ui service status:", err)
return
}
status, err := svc.Status()
if err != nil {
fmt.Println("Error getting hive-ui service status:", err)
fmt.Println("Error getting spinifex-ui service status:", err)
return
}
fmt.Println("hive-ui service status:", status)
fmt.Println("spinifex-ui service status:", status)
},
}
@@ -827,7 +827,7 @@ func init() {
viper.BindEnv("s3-region", "HIVE_VIPERBLOCK_S3_REGION")
viper.BindPFlag("s3-region", predastoreCmd.PersistentFlags().Lookup("s3-region"))
viperblockCmd.PersistentFlags().String("plugin-path", "/opt/hive/lib/nbdkit-viperblock-plugin.so", "Pathname to the nbdkit viperblockplugin")
viperblockCmd.PersistentFlags().String("plugin-path", "/opt/spinifex/lib/nbdkit-viperblock-plugin.so", "Pathname to the nbdkit viperblockplugin")
viper.BindEnv("plugin-path", "HIVE_VIPERBLOCK_PLUGIN_PATH")
viper.BindPFlag("plugin-path", predastoreCmd.PersistentFlags().Lookup("plugin-path"))
@@ -864,15 +864,15 @@ func init() {
viper.BindPFlag("jetstream", natsCmd.PersistentFlags().Lookup("jetstream"))
// Hive
serviceCmd.AddCommand(hiveCmd)
serviceCmd.AddCommand(spinifexCmd)
hiveCmd.AddCommand(hiveStartCmd)
hiveCmd.AddCommand(hiveStopCmd)
hiveCmd.AddCommand(hiveStatusCmd)
spinifexCmd.AddCommand(spinifexStartCmd)
spinifexCmd.AddCommand(spinifexStopCmd)
spinifexCmd.AddCommand(spinifexStatusCmd)
hiveCmd.PersistentFlags().String("wal-dir", "", "Write-ahead log (WAL) directory. Place on high-speed NVMe disk, or tmpfs for development.")
spinifexCmd.PersistentFlags().String("wal-dir", "", "Write-ahead log (WAL) directory. Place on high-speed NVMe disk, or tmpfs for development.")
viper.BindEnv("wal-dir", "HIVE_WAL_DIR")
viper.BindPFlag("wal-dir", hiveCmd.PersistentFlags().Lookup("wal-dir"))
viper.BindPFlag("wal-dir", spinifexCmd.PersistentFlags().Lookup("wal-dir"))
// AWS GW
serviceCmd.AddCommand(awsgwCmd)
@@ -899,28 +899,28 @@ func init() {
awsgwCmd.AddCommand(awsgwStopCmd)
awsgwCmd.AddCommand(awsgwStatusCmd)
// hive-ui
serviceCmd.AddCommand(hiveUICmd)
// spinifex-ui
serviceCmd.AddCommand(spinifexUICmd)
hiveUICmd.PersistentFlags().Int("port", 3000, "hive-ui server port")
viper.BindEnv("hive-ui-port", "HIVE_UI_PORT")
viper.BindPFlag("hive-ui-port", hiveUICmd.PersistentFlags().Lookup("port"))
spinifexUICmd.PersistentFlags().Int("port", 3000, "spinifex-ui server port")
viper.BindEnv("spinifex-ui-port", "HIVE_UI_PORT")
viper.BindPFlag("spinifex-ui-port", spinifexUICmd.PersistentFlags().Lookup("port"))
hiveUICmd.PersistentFlags().String("host", "0.0.0.0", "hive-ui server host")
viper.BindEnv("hive-ui-host", "HIVE_UI_HOST")
viper.BindPFlag("hive-ui-host", hiveUICmd.PersistentFlags().Lookup("host"))
spinifexUICmd.PersistentFlags().String("host", "0.0.0.0", "spinifex-ui server host")
viper.BindEnv("spinifex-ui-host", "HIVE_UI_HOST")
viper.BindPFlag("spinifex-ui-host", spinifexUICmd.PersistentFlags().Lookup("host"))
hiveUICmd.PersistentFlags().String("tls-cert", "", "TLS certificate path")
viper.BindEnv("hive-ui-tls-cert", "HIVE_UI_TLS_CERT")
viper.BindPFlag("hive-ui-tls-cert", hiveUICmd.PersistentFlags().Lookup("tls-cert"))
spinifexUICmd.PersistentFlags().String("tls-cert", "", "TLS certificate path")
viper.BindEnv("spinifex-ui-tls-cert", "HIVE_UI_TLS_CERT")
viper.BindPFlag("spinifex-ui-tls-cert", spinifexUICmd.PersistentFlags().Lookup("tls-cert"))
hiveUICmd.PersistentFlags().String("tls-key", "", "TLS key path")
viper.BindEnv("hive-ui-tls-key", "HIVE_UI_TLS_KEY")
viper.BindPFlag("hive-ui-tls-key", hiveUICmd.PersistentFlags().Lookup("tls-key"))
spinifexUICmd.PersistentFlags().String("tls-key", "", "TLS key path")
viper.BindEnv("spinifex-ui-tls-key", "HIVE_UI_TLS_KEY")
viper.BindPFlag("spinifex-ui-tls-key", spinifexUICmd.PersistentFlags().Lookup("tls-key"))
hiveUICmd.AddCommand(hiveUIStartCmd)
hiveUICmd.AddCommand(hiveUIStopCmd)
hiveUICmd.AddCommand(hiveUIStatusCmd)
spinifexUICmd.AddCommand(spinifexUIStartCmd)
spinifexUICmd.AddCommand(spinifexUIStopCmd)
spinifexUICmd.AddCommand(spinifexUIStatusCmd)
// vpcd
serviceCmd.AddCommand(vpcdCmd)
+2 -2
View File
@@ -12,7 +12,7 @@ import (
func TestNew(t *testing.T) {
// Test known service types
services := []string{"nats", "predastore", "viperblock", "hive", "awsgw"}
services := []string{"nats", "predastore", "viperblock", "spinifex", "awsgw"}
for _, s := range services {
@@ -29,7 +29,7 @@ func TestNew(t *testing.T) {
// No special setup needed
case "viperblock":
svc, err = New(s, &viperblockd.Config{})
case "hive":
case "spinifex":
svc, err = New(s, &config.ClusterConfig{})
case "awsgw":
svc, err = New(s, &config.ClusterConfig{})
+4 -4
View File
@@ -10,7 +10,7 @@ import (
"github.com/mulgadc/spinifex/spinifex/utils"
)
var serviceName = "hive"
var serviceName = "spinifex"
type Service struct {
Config *config.ClusterConfig
@@ -20,7 +20,7 @@ type Service struct {
func New(cfg any) (svc *Service, err error) {
c, ok := cfg.(*config.ClusterConfig)
if !ok {
return nil, fmt.Errorf("invalid config type for hive service")
return nil, fmt.Errorf("invalid config type for spinifex service")
}
svc = &Service{
Config: c,
@@ -64,11 +64,11 @@ func launchService(config *config.ClusterConfig, configPath string) (err error)
d := daemon.NewDaemon(config)
d.SetConfigPath(configPath)
slog.Info("Starting Hive daemon ...")
slog.Info("Starting Spinifex daemon ...")
err = d.Start()
if err != nil {
slog.Warn("Failed to start Hive daemon", "err", err)
slog.Warn("Failed to start Spinifex daemon", "err", err)
return err
}
+13 -13
View File
@@ -24,12 +24,12 @@ import (
"github.com/mulgadc/spinifex/spinifex/utils"
)
var serviceName = "hive-ui"
var serviceName = "spinifex-ui"
//go:embed all:frontend/dist
var distFS embed.FS
// Config holds the configuration for the hive-ui service
// Config holds the configuration for the spinifex-ui service
type Config struct {
Port int `json:"port"`
Host string `json:"host"`
@@ -37,18 +37,18 @@ type Config struct {
TLSKey string `json:"tls_key"`
}
// Service represents the hive-ui service
// Service represents the spinifex-ui service
type Service struct {
Config *Config
server *http.Server
mu sync.Mutex
}
// New creates a new hive-ui service
// New creates a new spinifex-ui service
func New(config any) (*Service, error) {
cfg, ok := config.(*Config)
if !ok {
return nil, fmt.Errorf("invalid config type for hive-ui service")
return nil, fmt.Errorf("invalid config type for spinifex-ui service")
}
// Set defaults
@@ -64,10 +64,10 @@ func New(config any) (*Service, error) {
homeDir, err := os.UserHomeDir()
if err == nil {
if cfg.TLSCert == "" {
cfg.TLSCert = filepath.Join(homeDir, "hive", "config", "server.pem")
cfg.TLSCert = filepath.Join(homeDir, "spinifex", "config", "server.pem")
}
if cfg.TLSKey == "" {
cfg.TLSKey = filepath.Join(homeDir, "hive", "config", "server.key")
cfg.TLSKey = filepath.Join(homeDir, "spinifex", "config", "server.key")
}
}
}
@@ -77,7 +77,7 @@ func New(config any) (*Service, error) {
}, nil
}
// Start starts the hive-ui service
// Start starts the spinifex-ui service
func (svc *Service) Start() (int, error) {
if err := utils.WritePidFile(serviceName, os.Getpid()); err != nil {
slog.Error("Failed to write pid file", "err", err)
@@ -91,12 +91,12 @@ func (svc *Service) Start() (int, error) {
return os.Getpid(), nil
}
// Stop stops the hive-ui service
// Stop stops the spinifex-ui service
func (svc *Service) Stop() error {
return utils.StopProcess(serviceName)
}
// Status returns the status of the hive-ui service
// Status returns the status of the spinifex-ui service
func (svc *Service) Status() (string, error) {
pid, err := utils.ReadPidFile(serviceName)
if err != nil {
@@ -105,7 +105,7 @@ func (svc *Service) Status() (string, error) {
return fmt.Sprintf("running (pid: %d)", pid), nil
}
// Shutdown gracefully shuts down the hive-ui service
// Shutdown gracefully shuts down the spinifex-ui service
func (svc *Service) Shutdown() error {
svc.mu.Lock()
server := svc.server
@@ -119,7 +119,7 @@ func (svc *Service) Shutdown() error {
return svc.Stop()
}
// Reload reloads the hive-ui service configuration
// Reload reloads the spinifex-ui service configuration
func (svc *Service) Reload() error {
return nil
}
@@ -233,7 +233,7 @@ func (svc *Service) launchService() error {
tlsCfg: tlsConfig,
}
slog.Info("Starting hive-ui service with HTTPS (auto-redirect HTTP)", "addr", addr)
slog.Info("Starting spinifex-ui service with HTTPS (auto-redirect HTTP)", "addr", addr)
return server.Serve(splitLn)
}