mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 11:48:43 -07:00
267 lines
9.2 KiB
Go
267 lines
9.2 KiB
Go
// Copyright 2012-2016 Apcera Inc. All rights reserved.
|
|
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"net"
|
|
"net/url"
|
|
"os"
|
|
|
|
"github.com/nats-io/gnatsd/server"
|
|
)
|
|
|
|
var usageStr = `
|
|
Usage: gnatsd [options]
|
|
|
|
Server Options:
|
|
-a, --addr <host> Bind to host address (default: 0.0.0.0)
|
|
-p, --port <port> Use port for clients (default: 4222)
|
|
-P, --pid <file> File to store PID
|
|
-m, --http_port <port> Use port for http monitoring
|
|
-ms,--https_port <port> Use port for https monitoring
|
|
-c, --config <file> Configuration file
|
|
|
|
Logging Options:
|
|
-l, --log <file> File to redirect log output
|
|
-T, --logtime Timestamp log entries (default: true)
|
|
-s, --syslog Log to syslog or windows event log
|
|
-r, --remote_syslog <addr> Syslog server addr (udp://localhost:514)
|
|
-D, --debug Enable debugging output
|
|
-V, --trace Trace the raw protocol
|
|
-DV Debug and trace
|
|
|
|
Authorization Options:
|
|
--user <user> User required for connections
|
|
--pass <password> Password required for connections
|
|
--auth <token> Authorization token required for connections
|
|
|
|
TLS Options:
|
|
--tls Enable TLS, do not verify clients (default: false)
|
|
--tlscert <file> Server certificate file
|
|
--tlskey <file> Private key for server certificate
|
|
--tlsverify Enable TLS, verify client certificates
|
|
--tlscacert <file> Client certificate CA for verification
|
|
|
|
Cluster Options:
|
|
--routes <rurl-1, rurl-2> Routes to solicit and connect
|
|
--cluster <cluster-url> Cluster URL for solicited routes
|
|
--no_advertise <bool> Advertise known cluster IPs to clients
|
|
--connect_retries <number> For implicit routes, number of connect retries
|
|
|
|
|
|
Common Options:
|
|
-h, --help Show this message
|
|
-v, --version Show version
|
|
--help_tls TLS help
|
|
`
|
|
|
|
// usage will print out the flag options for the server.
|
|
func usage() {
|
|
fmt.Printf("%s\n", usageStr)
|
|
os.Exit(0)
|
|
}
|
|
|
|
func main() {
|
|
// Server Options
|
|
opts := &server.Options{}
|
|
|
|
var showVersion bool
|
|
var debugAndTrace bool
|
|
var configFile string
|
|
var showTLSHelp bool
|
|
|
|
// Parse flags
|
|
flag.IntVar(&opts.Port, "port", 0, "Port to listen on.")
|
|
flag.IntVar(&opts.Port, "p", 0, "Port to listen on.")
|
|
flag.StringVar(&opts.Host, "addr", "", "Network host to listen on.")
|
|
flag.StringVar(&opts.Host, "a", "", "Network host to listen on.")
|
|
flag.StringVar(&opts.Host, "net", "", "Network host to listen on.")
|
|
flag.BoolVar(&opts.Debug, "D", false, "Enable Debug logging.")
|
|
flag.BoolVar(&opts.Debug, "debug", false, "Enable Debug logging.")
|
|
flag.BoolVar(&opts.Trace, "V", false, "Enable Trace logging.")
|
|
flag.BoolVar(&opts.Trace, "trace", false, "Enable Trace logging.")
|
|
flag.BoolVar(&debugAndTrace, "DV", false, "Enable Debug and Trace logging.")
|
|
flag.BoolVar(&opts.Logtime, "T", true, "Timestamp log entries.")
|
|
flag.BoolVar(&opts.Logtime, "logtime", true, "Timestamp log entries.")
|
|
flag.StringVar(&opts.Username, "user", "", "Username required for connection.")
|
|
flag.StringVar(&opts.Password, "pass", "", "Password required for connection.")
|
|
flag.StringVar(&opts.Authorization, "auth", "", "Authorization token required for connection.")
|
|
flag.IntVar(&opts.HTTPPort, "m", 0, "HTTP Port for /varz, /connz endpoints.")
|
|
flag.IntVar(&opts.HTTPPort, "http_port", 0, "HTTP Port for /varz, /connz endpoints.")
|
|
flag.IntVar(&opts.HTTPSPort, "ms", 0, "HTTPS Port for /varz, /connz endpoints.")
|
|
flag.IntVar(&opts.HTTPSPort, "https_port", 0, "HTTPS Port for /varz, /connz endpoints.")
|
|
flag.StringVar(&configFile, "c", "", "Configuration file.")
|
|
flag.StringVar(&configFile, "config", "", "Configuration file.")
|
|
flag.StringVar(&opts.PidFile, "P", "", "File to store process pid.")
|
|
flag.StringVar(&opts.PidFile, "pid", "", "File to store process pid.")
|
|
flag.StringVar(&opts.LogFile, "l", "", "File to store logging output.")
|
|
flag.StringVar(&opts.LogFile, "log", "", "File to store logging output.")
|
|
flag.BoolVar(&opts.Syslog, "s", false, "Enable syslog as log method.")
|
|
flag.BoolVar(&opts.Syslog, "syslog", false, "Enable syslog as log method..")
|
|
flag.StringVar(&opts.RemoteSyslog, "r", "", "Syslog server addr (udp://localhost:514).")
|
|
flag.StringVar(&opts.RemoteSyslog, "remote_syslog", "", "Syslog server addr (udp://localhost:514).")
|
|
flag.BoolVar(&showVersion, "version", false, "Print version information.")
|
|
flag.BoolVar(&showVersion, "v", false, "Print version information.")
|
|
flag.IntVar(&opts.ProfPort, "profile", 0, "Profiling HTTP port")
|
|
flag.StringVar(&opts.RoutesStr, "routes", "", "Routes to actively solicit a connection.")
|
|
flag.StringVar(&opts.Cluster.ListenStr, "cluster", "", "Cluster url from which members can solicit routes.")
|
|
flag.StringVar(&opts.Cluster.ListenStr, "cluster_listen", "", "Cluster url from which members can solicit routes.")
|
|
flag.BoolVar(&opts.Cluster.NoAdvertise, "no_advertise", false, "Advertise known cluster IPs to clients.")
|
|
flag.IntVar(&opts.Cluster.ConnectRetries, "connect_retries", 0, "For implicit routes, number of connect retries")
|
|
flag.BoolVar(&showTLSHelp, "help_tls", false, "TLS help.")
|
|
flag.BoolVar(&opts.TLS, "tls", false, "Enable TLS.")
|
|
flag.BoolVar(&opts.TLSVerify, "tlsverify", false, "Enable TLS with client verification.")
|
|
flag.StringVar(&opts.TLSCert, "tlscert", "", "Server certificate file.")
|
|
flag.StringVar(&opts.TLSKey, "tlskey", "", "Private key for server certificate.")
|
|
flag.StringVar(&opts.TLSCaCert, "tlscacert", "", "Client certificate CA for verification.")
|
|
|
|
flag.Usage = func() {
|
|
fmt.Printf("%s\n", usageStr)
|
|
}
|
|
|
|
flag.Parse()
|
|
|
|
// Show version and exit
|
|
if showVersion {
|
|
server.PrintServerAndExit()
|
|
}
|
|
|
|
if showTLSHelp {
|
|
server.PrintTLSHelpAndDie()
|
|
}
|
|
|
|
// One flag can set multiple options.
|
|
if debugAndTrace {
|
|
opts.Trace, opts.Debug = true, true
|
|
}
|
|
|
|
// Process args looking for non-flag options,
|
|
// 'version' and 'help' only for now
|
|
showVersion, showHelp, err := server.ProcessCommandLineArgs(flag.CommandLine)
|
|
if err != nil {
|
|
server.PrintAndDie(err.Error() + usageStr)
|
|
} else if showVersion {
|
|
server.PrintServerAndExit()
|
|
} else if showHelp {
|
|
usage()
|
|
}
|
|
|
|
// Snapshot flag options.
|
|
*server.FlagSnapshot = *opts
|
|
|
|
// Parse config if given
|
|
if configFile != "" {
|
|
fileOpts, err := server.ProcessConfigFile(configFile)
|
|
if err != nil {
|
|
server.PrintAndDie(err.Error())
|
|
}
|
|
opts = server.MergeOptions(fileOpts, opts)
|
|
}
|
|
|
|
// Remove any host/ip that points to itself in Route
|
|
newroutes, err := server.RemoveSelfReference(opts.Cluster.Port, opts.Routes)
|
|
if err != nil {
|
|
server.PrintAndDie(err.Error())
|
|
}
|
|
opts.Routes = newroutes
|
|
|
|
// Configure TLS based on any present flags
|
|
configureTLS(opts)
|
|
|
|
// Configure cluster opts if explicitly set via flags.
|
|
err = configureClusterOpts(opts)
|
|
if err != nil {
|
|
server.PrintAndDie(err.Error())
|
|
}
|
|
|
|
// Create the server with appropriate options.
|
|
s := server.New(opts)
|
|
|
|
// Configure the logger based on the flags
|
|
s.ConfigureLogger()
|
|
|
|
// Start things up. Block here until done.
|
|
s.Start()
|
|
}
|
|
|
|
func configureTLS(opts *server.Options) {
|
|
// If no trigger flags, ignore the others
|
|
if !opts.TLS && !opts.TLSVerify {
|
|
return
|
|
}
|
|
if opts.TLSCert == "" {
|
|
server.PrintAndDie("TLS Server certificate must be present and valid.")
|
|
}
|
|
if opts.TLSKey == "" {
|
|
server.PrintAndDie("TLS Server private key must be present and valid.")
|
|
}
|
|
|
|
tc := server.TLSConfigOpts{}
|
|
tc.CertFile = opts.TLSCert
|
|
tc.KeyFile = opts.TLSKey
|
|
tc.CaFile = opts.TLSCaCert
|
|
|
|
if opts.TLSVerify {
|
|
tc.Verify = true
|
|
}
|
|
var err error
|
|
if opts.TLSConfig, err = server.GenTLSConfig(&tc); err != nil {
|
|
server.PrintAndDie(err.Error())
|
|
}
|
|
}
|
|
|
|
func configureClusterOpts(opts *server.Options) error {
|
|
// If we don't have cluster defined in the configuration
|
|
// file and no cluster listen string override, but we do
|
|
// have a routes override, we need to report misconfiguration.
|
|
if opts.Cluster.ListenStr == "" && opts.Cluster.Host == "" &&
|
|
opts.Cluster.Port == 0 {
|
|
if opts.RoutesStr != "" {
|
|
server.PrintAndDie("Solicited routes require cluster capabilities, e.g. --cluster.")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// If cluster flag override, process it
|
|
if opts.Cluster.ListenStr != "" {
|
|
clusterURL, err := url.Parse(opts.Cluster.ListenStr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
h, p, err := net.SplitHostPort(clusterURL.Host)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
opts.Cluster.Host = h
|
|
_, err = fmt.Sscan(p, &opts.Cluster.Port)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if clusterURL.User != nil {
|
|
pass, hasPassword := clusterURL.User.Password()
|
|
if !hasPassword {
|
|
return fmt.Errorf("Expected cluster password to be set.")
|
|
}
|
|
opts.Cluster.Password = pass
|
|
|
|
user := clusterURL.User.Username()
|
|
opts.Cluster.Username = user
|
|
} else {
|
|
// Since we override from flag and there is no user/pwd, make
|
|
// sure we clear what we may have gotten from config file.
|
|
opts.Cluster.Username = ""
|
|
opts.Cluster.Password = ""
|
|
}
|
|
}
|
|
|
|
// If we have routes but no config file, fill in here.
|
|
if opts.RoutesStr != "" && opts.Routes == nil {
|
|
opts.Routes = server.RoutesFromStr(opts.RoutesStr)
|
|
}
|
|
|
|
return nil
|
|
}
|