diff --git a/cmd/gotosocial/generalflags.go b/cmd/gotosocial/generalflags.go index f33ef5b49..9f321b760 100644 --- a/cmd/gotosocial/generalflags.go +++ b/cmd/gotosocial/generalflags.go @@ -62,6 +62,12 @@ func generalFlags(flagNames, envNames config.Flags, defaults config.Defaults) [] Value: defaults.Protocol, EnvVars: []string{envNames.Protocol}, }, + &cli.StringFlag{ + Name: flagNames.BindAddress, + Usage: "Bind address to use for the GoToSocial server (eg., 0.0.0.0, 172.138.0.9, [::], localhost). For ipv6, enclose the address in square brackets, eg [2a02:1807:1430:500:13f5:5efb:3f3a:1191]. Default binds to all interfaces.", + Value: defaults.BindAddress, + EnvVars: []string{envNames.BindAddress}, + }, &cli.IntFlag{ Name: flagNames.Port, Usage: "Port to use for GoToSocial. Change this to 443 if you're running the binary directly on the host machine.", diff --git a/docs/configuration/general.md b/docs/configuration/general.md index 4bb5f76d1..df9eaa4b0 100644 --- a/docs/configuration/general.md +++ b/docs/configuration/general.md @@ -1,6 +1,6 @@ # General -The top-level configuration for GoToSocial, including basic things like host and transport protocol. +The top-level configuration for GoToSocial, including basic things like host, port, bind address and transport protocol. The only things you *really* need to set here are `host`, which should be the hostname where your instance is reachable, and probably `port`. @@ -48,6 +48,15 @@ accountDomain: "" # Default: "https" protocol: "https" +# String. Address to bind the GoToSocial server to. +# This can be an IPv4 address or an IPv6 address (surrounded in square brackets), or a hostname. +# Default value will bind to all interfaces. +# You probably won't need to change this unless you're setting GoToSocial up in some fancy way or +# you have specific networking requirements. +# Examples: ["0.0.0.0", "172.128.0.16", "localhost", "[::]", "[2a02:1807:1430:500:13f5:5efb:3f3a:1191]"] +# Default: "0.0.0.0" +bindAddress: "0.0.0.0" + # Int. Listen port for the GoToSocial webserver + API. If you're running behind a reverse proxy and/or in a docker, # container, just set this to whatever you like (or leave the default), and make sure it's forwarded properly. # If you are running with built-in letsencrypt enabled, and running GoToSocial directly on a host machine, you will diff --git a/example/config.yaml b/example/config.yaml index 51472418f..7e7bd3a35 100644 --- a/example/config.yaml +++ b/example/config.yaml @@ -55,6 +55,15 @@ accountDomain: "" # Default: "https" protocol: "https" +# String. Address to bind the GoToSocial server to. +# This can be an IPv4 address or an IPv6 address (surrounded in square brackets), or a hostname. +# Default value will bind to all interfaces. +# You probably won't need to change this unless you're setting GoToSocial up in some fancy way or +# you have specific networking requirements. +# Examples: ["0.0.0.0", "172.128.0.16", "localhost", "[::]", "[2a02:1807:1430:500:13f5:5efb:3f3a:1191]"] +# Default: "0.0.0.0" +bindAddress: "0.0.0.0" + # Int. Listen port for the GoToSocial webserver + API. If you're running behind a reverse proxy and/or in a docker, # container, just set this to whatever you like (or leave the default), and make sure it's forwarded properly. # If you are running with built-in letsencrypt enabled, and running GoToSocial directly on a host machine, you will diff --git a/internal/config/config.go b/internal/config/config.go index 7a3a92af9..9daeba0f0 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -53,6 +53,7 @@ type Config struct { Host string `yaml:"host"` AccountDomain string `yaml:"accountDomain"` Protocol string `yaml:"protocol"` + BindAddress string `yaml:"bindAddress"` Port int `yaml:"port"` TrustedProxies []string `yaml:"trustedProxies"` DBConfig *DBConfig `yaml:"db"` @@ -159,6 +160,10 @@ func (c *Config) ParseCLIFlags(f KeyedFlags, version string) error { return errors.New("protocol was not set") } + if c.BindAddress == "" || f.IsSet(fn.BindAddress) { + c.BindAddress = f.String(fn.BindAddress) + } + if c.Port == 0 || f.IsSet(fn.Port) { c.Port = f.Int(fn.Port) } @@ -374,6 +379,7 @@ type Flags struct { Host string AccountDomain string Protocol string + BindAddress string Port string TrustedProxies string @@ -438,6 +444,7 @@ type Defaults struct { Host string AccountDomain string Protocol string + BindAddress string Port int TrustedProxies []string SoftwareVersion string @@ -505,6 +512,7 @@ func GetFlagNames() Flags { Host: "host", AccountDomain: "account-domain", Protocol: "protocol", + BindAddress: "bind-address", Port: "port", TrustedProxies: "trusted-proxies", @@ -572,6 +580,7 @@ func GetEnvNames() Flags { Host: "GTS_HOST", AccountDomain: "GTS_ACCOUNT_DOMAIN", Protocol: "GTS_PROTOCOL", + BindAddress: "GTS_BIND_ADDRESS", Port: "GTS_PORT", TrustedProxies: "GTS_TRUSTED_PROXIES", diff --git a/internal/config/default.go b/internal/config/default.go index 5868655ff..996033ae4 100644 --- a/internal/config/default.go +++ b/internal/config/default.go @@ -11,6 +11,7 @@ func TestDefault() *Config { Host: defaults.Host, AccountDomain: defaults.AccountDomain, Protocol: defaults.Protocol, + BindAddress: defaults.BindAddress, Port: defaults.Port, TrustedProxies: defaults.TrustedProxies, SoftwareVersion: defaults.SoftwareVersion, @@ -85,6 +86,7 @@ func Default() *Config { ApplicationName: defaults.ApplicationName, Host: defaults.Host, Protocol: defaults.Protocol, + BindAddress: defaults.BindAddress, Port: defaults.Port, TrustedProxies: defaults.TrustedProxies, SoftwareVersion: defaults.SoftwareVersion, @@ -161,6 +163,7 @@ func GetDefaults() Defaults { Host: "", AccountDomain: "", Protocol: "https", + BindAddress: "0.0.0.0", Port: 8080, TrustedProxies: []string{"127.0.0.1/32"}, // localhost @@ -227,6 +230,7 @@ func GetTestDefaults() Defaults { Host: "localhost:8080", AccountDomain: "localhost:8080", Protocol: "http", + BindAddress: "127.0.0.1", Port: 8080, TrustedProxies: []string{"127.0.0.1/32"}, diff --git a/internal/router/router.go b/internal/router/router.go index 130832f74..aef5c32e4 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -72,7 +72,8 @@ func (r *router) Start() { if r.config.LetsEncryptConfig.Enabled { // serve the http handler on the selected letsencrypt port, for receiving letsencrypt requests and solving their devious riddles go func() { - if err := http.ListenAndServe(fmt.Sprintf(":%d", r.config.LetsEncryptConfig.Port), r.certManager.HTTPHandler(http.HandlerFunc(httpsRedirect))); err != nil && err != http.ErrServerClosed { + listen := fmt.Sprintf("%s:%d", r.config.BindAddress, r.config.LetsEncryptConfig.Port) + if err := http.ListenAndServe(listen, r.certManager.HTTPHandler(http.HandlerFunc(httpsRedirect))); err != nil && err != http.ErrServerClosed { logrus.Fatalf("listen: %s", err) } }() @@ -138,8 +139,9 @@ func New(ctx context.Context, cfg *config.Config, db db.DB) (Router, error) { } // create the http server here, passing the gin engine as handler + listen := fmt.Sprintf("%s:%d", cfg.BindAddress, cfg.Port) s := &http.Server{ - Addr: fmt.Sprintf(":%d", cfg.Port), + Addr: listen, Handler: engine, ReadTimeout: readTimeout, WriteTimeout: writeTimeout,