gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit bc1d8a92656e8cc30500eaeb36b6b9864b6a722b
parent 05e9af089c3041fa162e4dca3b1c5906496e8e90
Author: Tobi Smethurst <31960611+tsmethurst@users.noreply.github.com>
Date:   Sat, 24 Jul 2021 19:02:41 +0200

allow custom ports for webserver and le (#111)


Diffstat:
MGETTINGSTARTED.md | 14+++++++++++---
Mcmd/gotosocial/generalflags.go | 6++++++
Mcmd/gotosocial/letsencryptflags.go | 6++++++
Mexample/config.yaml | 25+++++++++++++++++++++----
Minternal/config/config.go | 17+++++++++++++++++
Minternal/config/default.go | 7+++++++
Minternal/config/letsencrypt.go | 8+++++---
Minternal/router/router.go | 22++++++----------------
8 files changed, 79 insertions(+), 26 deletions(-)

diff --git a/GETTINGSTARTED.md b/GETTINGSTARTED.md @@ -33,7 +33,13 @@ docker run -d --network host --user postgres -e POSTGRES_PASSWORD=some_password On your local machine (not your server), with Go installed, clone the GoToSocial repository, and build the binary with the provided build script: ```bash -./build/sh +./build.sh +``` + +If you need to build for a different architecture other than the one you're running the build on (eg., you're running on a Raspberry Pi but building on an amd64 machine), you can put set `GOOS` or `GOARCH` environment variables before running the build script, eg: + +```bash +GOARCH=arm64 ./build.sh ``` ### 6: Prepare VPS @@ -52,7 +58,7 @@ Copy your binary from your local machine onto the VPS, using something like the scp ./gotosocial root@example.org:/gotosocial/gotosocial ``` -Replace `root` with whatever user you're actually running on your remote server. +Replace `root` with whatever user you're actually running on your remote server (you wouldn't run as root right? ;). ### 8: Copy Web Dir @@ -75,11 +81,13 @@ cd /gotosocial Then start the GoToSocial server with the following command (where `example.org` is the domain you set up in step 1, and `some_password` is the password you set for Postgres in step 4): ```bash -./gotosocial --host example.org --storage-serve-host example.org --letsencrypt-enabled=true server start +./gotosocial --host example.org --port 443 --storage-serve-host example.org --letsencrypt-enabled=true server start ``` The server should now start up and you should be able to access the splash page by navigating to your domain in the browser. Note that it might take up to a minute or so for your LetsEncrypt certificates to be created for the first time, so refresh a few times if necessary. +Note that for this example we're assuming that we're allowed to run on port 443 (standard https port), and that nothing else is running on this port. + ### 10: Create and confirm your user You can use the GoToSocial binary to also create, confirm, and promote your user account. diff --git a/cmd/gotosocial/generalflags.go b/cmd/gotosocial/generalflags.go @@ -62,5 +62,11 @@ func generalFlags(flagNames, envNames config.Flags, defaults config.Defaults) [] Value: defaults.Protocol, EnvVars: []string{envNames.Protocol}, }, + &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.", + Value: defaults.Port, + EnvVars: []string{envNames.Port}, + }, } } diff --git a/cmd/gotosocial/letsencryptflags.go b/cmd/gotosocial/letsencryptflags.go @@ -31,6 +31,12 @@ func letsEncryptFlags(flagNames, envNames config.Flags, defaults config.Defaults Value: defaults.LetsEncryptEnabled, EnvVars: []string{envNames.LetsEncryptEnabled}, }, + &cli.IntFlag{ + Name: flagNames.LetsEncryptPort, + Usage: "Port to listen on for letsencrypt certificate challenges. Must not be the same as the GtS webserver/API port.", + Value: defaults.LetsEncryptPort, + EnvVars: []string{envNames.LetsEncryptPort}, + }, &cli.StringFlag{ Name: flagNames.LetsEncryptCertDir, Usage: "Directory to store acquired letsencrypt certificates.", diff --git a/example/config.yaml b/example/config.yaml @@ -48,10 +48,22 @@ host: "localhost" accountDomain: "" # String. Protocol to use for the server. Only change to http for local testing! +# This should be the protocol part of the URI that your server is actually reachable on. So even if you're +# running GoToSocial behind a reverse proxy that handles SSL certificates for you, instead of using built-in +# letsencrypt, it should still be https. # Options: ["http","https"] # Default: "https" protocol: "https" +# 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 +# probably want to set this to 443 (standard https port), unless you have other services already using that port. +# This *MUST NOT* be the same as the letsencrypt port specified below, unless letsencrypt is turned off. +# Examples: [443, 6666, 8080] +# Default: 8080 +port: 8080 + ############################ ##### DATABASE CONFIG ###### ############################ @@ -256,16 +268,21 @@ statuses: letsEncrypt: # Bool. Whether or not letsencrypt should be enabled for the server. - # If true, the server will serve on port 443 (https) and obtain letsencrypt - # certificates automatically. - # If false, the server will serve on port 8080 (http), and the rest of the settings - # here will be ignored. + # If false, the rest of the settings here will be ignored. # You should only change this if you want to serve GoToSocial behind a reverse proxy # like Traefik, HAProxy, or Nginx. # Options: [true, false] # Default: true enabled: true + # Int. Port to listen for letsencrypt certificate challenges on. + # If letsencrypt is enabled, this port must be reachable or you won't be able to obtain certs. + # If letsencrypt is disabled, this port will not be used. + # This *must not* be the same as the webserver/API port specified above. + # Examples: [80, 8000, 1312] + # Default: 80 + port: 80 + # String. Directory in which to store LetsEncrypt certificates. # It is a good move to make this a sub-path within your storage directory, as it makes # backup easier, but you might wish to move them elsewhere if they're also accessed by other services. diff --git a/internal/config/config.go b/internal/config/config.go @@ -50,6 +50,7 @@ type Config struct { Host string `yaml:"host"` AccountDomain string `yaml:"accountDomain"` Protocol string `yaml:"protocol"` + Port int `yaml:"port"` DBConfig *DBConfig `yaml:"db"` TemplateConfig *TemplateConfig `yaml:"template"` AccountsConfig *AccountsConfig `yaml:"accounts"` @@ -150,6 +151,10 @@ func (c *Config) ParseCLIFlags(f KeyedFlags, version string) error { return errors.New("protocol was not set") } + if c.Port == 0 || f.IsSet(fn.Port) { + c.Port = f.Int(fn.Port) + } + // db flags if c.DBConfig.Type == "" || f.IsSet(fn.DbType) { c.DBConfig.Type = f.String(fn.DbType) @@ -262,6 +267,10 @@ func (c *Config) ParseCLIFlags(f KeyedFlags, version string) error { c.LetsEncryptConfig.Enabled = f.Bool(fn.LetsEncryptEnabled) } + if c.LetsEncryptConfig.Port == 0 || f.IsSet(fn.LetsEncryptPort) { + c.LetsEncryptConfig.Port = f.Int(fn.LetsEncryptPort) + } + if c.LetsEncryptConfig.CertDir == "" || f.IsSet(fn.LetsEncryptCertDir) { c.LetsEncryptConfig.CertDir = f.String(fn.LetsEncryptCertDir) } @@ -329,6 +338,7 @@ type Flags struct { Host string AccountDomain string Protocol string + Port string DbType string DbAddress string @@ -366,6 +376,7 @@ type Flags struct { LetsEncryptEnabled string LetsEncryptCertDir string LetsEncryptEmailAddress string + LetsEncryptPort string OIDCEnabled string OIDCIdpName string @@ -384,6 +395,7 @@ type Defaults struct { Host string AccountDomain string Protocol string + Port int SoftwareVersion string DbType string @@ -422,6 +434,7 @@ type Defaults struct { LetsEncryptEnabled bool LetsEncryptCertDir string LetsEncryptEmailAddress string + LetsEncryptPort int OIDCEnabled bool OIDCIdpName string @@ -442,6 +455,7 @@ func GetFlagNames() Flags { Host: "host", AccountDomain: "account-domain", Protocol: "protocol", + Port: "port", DbType: "db-type", DbAddress: "db-address", @@ -477,6 +491,7 @@ func GetFlagNames() Flags { StatusesMaxMediaFiles: "statuses-max-media-files", LetsEncryptEnabled: "letsencrypt-enabled", + LetsEncryptPort: "letsencrypt-port", LetsEncryptCertDir: "letsencrypt-cert-dir", LetsEncryptEmailAddress: "letsencrypt-email", @@ -500,6 +515,7 @@ func GetEnvNames() Flags { Host: "GTS_HOST", AccountDomain: "GTS_ACCOUNT_DOMAIN", Protocol: "GTS_PROTOCOL", + Port: "GTS_PORT", DbType: "GTS_DB_TYPE", DbAddress: "GTS_DB_ADDRESS", @@ -535,6 +551,7 @@ func GetEnvNames() Flags { StatusesMaxMediaFiles: "GTS_STATUSES_MAX_MEDIA_FILES", LetsEncryptEnabled: "GTS_LETSENCRYPT_ENABLED", + LetsEncryptPort: "GTS_LETSENCRYPT_PORT", LetsEncryptCertDir: "GTS_LETSENCRYPT_CERT_DIR", LetsEncryptEmailAddress: "GTS_LETSENCRYPT_EMAIL", diff --git a/internal/config/default.go b/internal/config/default.go @@ -10,6 +10,7 @@ func TestDefault() *Config { ApplicationName: defaults.ApplicationName, Host: defaults.Host, Protocol: defaults.Protocol, + Port: defaults.Port, SoftwareVersion: defaults.SoftwareVersion, DBConfig: &DBConfig{ Type: defaults.DbType, @@ -51,6 +52,7 @@ func TestDefault() *Config { }, LetsEncryptConfig: &LetsEncryptConfig{ Enabled: defaults.LetsEncryptEnabled, + Port: defaults.LetsEncryptPort, CertDir: defaults.LetsEncryptCertDir, EmailAddress: defaults.LetsEncryptEmailAddress, }, @@ -115,6 +117,7 @@ func Default() *Config { }, LetsEncryptConfig: &LetsEncryptConfig{ Enabled: defaults.LetsEncryptEnabled, + Port: defaults.LetsEncryptPort, CertDir: defaults.LetsEncryptCertDir, EmailAddress: defaults.LetsEncryptEmailAddress, }, @@ -140,6 +143,7 @@ func GetDefaults() Defaults { Host: "", AccountDomain: "", Protocol: "https", + Port: 8080, DbType: "postgres", DbAddress: "localhost", @@ -175,6 +179,7 @@ func GetDefaults() Defaults { StatusesMaxMediaFiles: 6, LetsEncryptEnabled: true, + LetsEncryptPort: 80, LetsEncryptCertDir: "/gotosocial/storage/certs", LetsEncryptEmailAddress: "", @@ -197,6 +202,7 @@ func GetTestDefaults() Defaults { Host: "localhost:8080", AccountDomain: "", Protocol: "http", + Port: 8080, DbType: "postgres", DbAddress: "localhost", @@ -230,6 +236,7 @@ func GetTestDefaults() Defaults { StatusesMaxMediaFiles: 6, LetsEncryptEnabled: false, + LetsEncryptPort: 0, LetsEncryptCertDir: "", LetsEncryptEmailAddress: "", diff --git a/internal/config/letsencrypt.go b/internal/config/letsencrypt.go @@ -3,9 +3,11 @@ package config // LetsEncryptConfig wraps everything needed to manage letsencrypt certificates from within gotosocial. type LetsEncryptConfig struct { // Should letsencrypt certificate fetching be enabled? - Enabled bool + Enabled bool `yaml:"enabled"` + // What port should the server listen for letsencrypt challenges on? + Port int `yaml:"port"` // Where should certificates be stored? - CertDir string + CertDir string `yaml:"certDir"` // Email address to pass to letsencrypt for notifications about certificate expiry etc. - EmailAddress string + EmailAddress string `yaml:"emailAddress"` } diff --git a/internal/router/router.go b/internal/router/router.go @@ -68,30 +68,24 @@ func (r *router) AttachStaticFS(relativePath string, fs http.FileSystem) { r.engine.StaticFS(relativePath, fs) } -// Start starts the router nicely. -// -// Different ports and handlers will be served depending on whether letsencrypt is enabled or not. -// If it is enabled, then port 80 will be used for handling LE requests, and port 443 will be used -// for serving actual requests. -// -// If letsencrypt is not being used, then port 8080 only will be used for serving requests. +// Start starts the router nicely. It will serve two handlers if letsencrypt is enabled, and only the web/API handler if letsencrypt is not enabled. func (r *router) Start() { if r.config.LetsEncryptConfig.Enabled { - // serve the http handler on port 80 for receiving letsencrypt requests and solving their devious riddles + // serve the http handler on the selected letsencrypt port, for receiving letsencrypt requests and solving their devious riddles go func() { - if err := http.ListenAndServe(":http", r.certManager.HTTPHandler(http.HandlerFunc(httpsRedirect))); err != nil && err != http.ErrServerClosed { + if err := http.ListenAndServe(fmt.Sprintf(":%d", r.config.LetsEncryptConfig.Port), r.certManager.HTTPHandler(http.HandlerFunc(httpsRedirect))); err != nil && err != http.ErrServerClosed { r.logger.Fatalf("listen: %s", err) } }() - // and serve the actual TLS handler on port 443 + // and serve the actual TLS handler go func() { if err := r.srv.ListenAndServeTLS("", ""); err != nil && err != http.ErrServerClosed { r.logger.Fatalf("listen: %s", err) } }() } else { - // no tls required so just serve on port 8080 + // no tls required go func() { if err := r.srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { r.logger.Fatalf("listen: %s", err) @@ -148,6 +142,7 @@ func New(cfg *config.Config, db db.DB, logger *logrus.Logger) (Router, error) { // create the http server here, passing the gin engine as handler s := &http.Server{ + Addr: fmt.Sprintf(":%d", cfg.Port), Handler: engine, ReadTimeout: readTimeout, WriteTimeout: writeTimeout, @@ -167,12 +162,7 @@ func New(cfg *config.Config, db db.DB, logger *logrus.Logger) (Router, error) { Cache: autocert.DirCache(cfg.LetsEncryptConfig.CertDir), Email: cfg.LetsEncryptConfig.EmailAddress, } - // and create an HTTPS server - s.Addr = ":https" s.TLSConfig = m.TLSConfig() - } else { - // le is NOT enabled, so just serve bare requests on port 8080 - s.Addr = ":8080" } return &router{