3x-ui/node/main.go

114 lines
3.2 KiB
Go

// Package main is the entry point for the 3x-ui node service (worker).
// This service runs XRAY Core and provides a REST API for the master panel to manage it.
package main
import (
"flag"
"fmt"
"log"
"os"
"os/signal"
"syscall"
"github.com/mhsanaei/3x-ui/v2/logger"
"github.com/mhsanaei/3x-ui/v2/node/api"
nodeConfig "github.com/mhsanaei/3x-ui/v2/node/config"
nodeLogs "github.com/mhsanaei/3x-ui/v2/node/logs"
"github.com/mhsanaei/3x-ui/v2/node/xray"
"github.com/op/go-logging"
)
func main() {
var port int
var apiKey string
flag.IntVar(&port, "port", 8080, "API server port")
flag.StringVar(&apiKey, "api-key", "", "API key for authentication (optional, can be set via registration)")
flag.Parse()
logger.InitLogger(logging.INFO)
// Initialize node configuration system
// Try to find config directory (same as XRAY config)
configDirs := []string{"bin", "config", ".", "/app/bin", "/app/config"}
var configDir string
for _, dir := range configDirs {
if _, err := os.Stat(dir); err == nil {
configDir = dir
break
}
}
if configDir == "" {
configDir = "." // Fallback
}
if err := nodeConfig.InitConfig(configDir); err != nil {
log.Fatalf("Failed to initialize node config: %v", err)
}
// Get API key from (in order of priority):
// 1. Command line flag
// 2. Environment variable (for backward compatibility)
// 3. Saved config file (from registration)
if apiKey == "" {
apiKey = os.Getenv("NODE_API_KEY")
}
if apiKey == "" {
// Try to load from saved config
savedConfig := nodeConfig.GetConfig()
if savedConfig.ApiKey != "" {
apiKey = savedConfig.ApiKey
log.Printf("Using API key from saved configuration")
}
}
// If still no API key, node can start but will need registration
if apiKey == "" {
log.Printf("WARNING: No API key found. Node will need to be registered via /api/v1/register endpoint")
log.Printf("You can set NODE_API_KEY environment variable or use -api-key flag for immediate use")
// Use a temporary key that will be replaced during registration
apiKey = "temp-unregistered"
}
// Initialize log pusher if panel URL is configured
// Get node address from saved config or environment variable
savedConfig := nodeConfig.GetConfig()
nodeAddress := savedConfig.NodeAddress
if nodeAddress == "" {
nodeAddress = os.Getenv("NODE_ADDRESS")
}
if nodeAddress == "" {
// Default to localhost with the port (panel will match by port if address doesn't match exactly)
nodeAddress = fmt.Sprintf("http://127.0.0.1:%d", port)
}
// Get panel URL from saved config or environment variable
panelURL := savedConfig.PanelURL
if panelURL == "" {
panelURL = os.Getenv("PANEL_URL")
}
nodeLogs.InitLogPusher(nodeAddress)
if panelURL != "" {
nodeLogs.SetPanelURL(panelURL)
}
// Connect log pusher to logger
logger.SetLogPusher(nodeLogs.PushLog)
xrayManager := xray.NewManager()
server := api.NewServer(port, apiKey, xrayManager)
log.Printf("Starting 3x-ui Node Service on port %d", port)
if err := server.Start(); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
<-sigCh
log.Println("Shutting down...")
xrayManager.Stop()
server.Stop()
log.Println("Shutdown complete")
}