diff --git a/docs/configuration/database.md b/docs/configuration/database.md index 3a7143593..f5be85164 100644 --- a/docs/configuration/database.md +++ b/docs/configuration/database.md @@ -44,6 +44,12 @@ grant all privileges on database gotosocial to gotosocial; GoToSocial makes use of ULIDs (Universally Unique Lexicographically Sortable Identifiers) which will not work in non-English collate environments. For this reason it is important to create the database with `C.UTF-8` locale. To do that on systems which were already initialized with non-C locale, `template0` pristine database template must be used. +If you want to use specific options when connecting to Postgres, you can use `db-postgres-connection-string` to define the connection string. If `db-postgres-connection-string` is defined, all other database related configuration fields will be ignored. For example, we can use `db-postgres-connection-string` to connect to `mySchema`, where the user name is `myUser` and password is `myPass` at `localhost` with the database name of `db`: + +```yaml +db-postgres-connection-string: 'postgres://myUser:myPass@localhost/db?search_path=mySchema' +``` + ## Settings !!! danger "SQLite cache sizes" @@ -177,6 +183,14 @@ db-sqlite-cache-size: "8MiB" # Default: "30m" db-sqlite-busy-timeout: "30m" +# String. Full Database connection string +# +# This connection string is only applicable for Postgres. When this field is defined, all other database related configuration field will be ignored. This field allow you to fine tune connection with Postgres +# +# Examples: ["postgres://user:pass@localhost/db?search_path=gotosocial", "postgres://user:pass@localhost:9999/db"] +# Default: "" +db-postgres-connection-string: "" + cache: # cache.memory-target sets a target limit that # the application will try to keep it's caches diff --git a/example/config.yaml b/example/config.yaml index 1fca954dc..f359db5d5 100644 --- a/example/config.yaml +++ b/example/config.yaml @@ -248,6 +248,14 @@ db-sqlite-cache-size: "8MiB" # Default: "30m" db-sqlite-busy-timeout: "30m" +# String. Full Database connection string +# +# This connection string is only applicable for Postgres. When this field is defined, all other database related configuration field will be ignored. This field allow you to fine tune connection with Postgres +# +# Examples: ["postgres://user:pass@localhost/db?search_path=gotosocial", "postgres://user:pass@localhost:9999/db"] +# Default: "" +db-postgres-connection-string: "" + cache: # cache.memory-target sets a target limit that # the application will try to keep it's caches diff --git a/internal/config/config.go b/internal/config/config.go index 79f74cf71..4bb9be0c4 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -60,19 +60,20 @@ type Configuration struct { TrustedProxies []string `name:"trusted-proxies" usage:"Proxies to trust when parsing x-forwarded headers into real IPs."` SoftwareVersion string `name:"software-version" usage:""` - DbType string `name:"db-type" usage:"Database type: eg., postgres"` - DbAddress string `name:"db-address" usage:"Database ipv4 address, hostname, or filename"` - DbPort int `name:"db-port" usage:"Database port"` - DbUser string `name:"db-user" usage:"Database username"` - DbPassword string `name:"db-password" usage:"Database password"` - DbDatabase string `name:"db-database" usage:"Database name"` - DbTLSMode string `name:"db-tls-mode" usage:"Database tls mode"` - DbTLSCACert string `name:"db-tls-ca-cert" usage:"Path to CA cert for db tls connection"` - DbMaxOpenConnsMultiplier int `name:"db-max-open-conns-multiplier" usage:"Multiplier to use per cpu for max open database connections. 0 or less is normalized to 1."` - DbSqliteJournalMode string `name:"db-sqlite-journal-mode" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_journal_mode"` - DbSqliteSynchronous string `name:"db-sqlite-synchronous" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_synchronous"` - DbSqliteCacheSize bytesize.Size `name:"db-sqlite-cache-size" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_cache_size"` - DbSqliteBusyTimeout time.Duration `name:"db-sqlite-busy-timeout" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_busy_timeout"` + DbType string `name:"db-type" usage:"Database type: eg., postgres"` + DbAddress string `name:"db-address" usage:"Database ipv4 address, hostname, or filename"` + DbPort int `name:"db-port" usage:"Database port"` + DbUser string `name:"db-user" usage:"Database username"` + DbPassword string `name:"db-password" usage:"Database password"` + DbDatabase string `name:"db-database" usage:"Database name"` + DbTLSMode string `name:"db-tls-mode" usage:"Database tls mode"` + DbTLSCACert string `name:"db-tls-ca-cert" usage:"Path to CA cert for db tls connection"` + DbMaxOpenConnsMultiplier int `name:"db-max-open-conns-multiplier" usage:"Multiplier to use per cpu for max open database connections. 0 or less is normalized to 1."` + DbSqliteJournalMode string `name:"db-sqlite-journal-mode" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_journal_mode"` + DbSqliteSynchronous string `name:"db-sqlite-synchronous" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_synchronous"` + DbSqliteCacheSize bytesize.Size `name:"db-sqlite-cache-size" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_cache_size"` + DbSqliteBusyTimeout time.Duration `name:"db-sqlite-busy-timeout" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_busy_timeout"` + DbPostgresConnectionString string `name:"db-postgres-connection-string" usage:"Full Database URL for connection to postgres"` WebTemplateBaseDir string `name:"web-template-base-dir" usage:"Basedir for html templating files for rendering pages and composing emails."` WebAssetBaseDir string `name:"web-asset-base-dir" usage:"Directory to serve static assets from, accessible at example.org/assets/"` diff --git a/internal/config/helpers.gen.go b/internal/config/helpers.gen.go index d75956963..f176676e5 100644 --- a/internal/config/helpers.gen.go +++ b/internal/config/helpers.gen.go @@ -700,6 +700,31 @@ func GetDbSqliteBusyTimeout() time.Duration { return global.GetDbSqliteBusyTimeo // SetDbSqliteBusyTimeout safely sets the value for global configuration 'DbSqliteBusyTimeout' field func SetDbSqliteBusyTimeout(v time.Duration) { global.SetDbSqliteBusyTimeout(v) } +// GetDbPostgresConnectionString safely fetches the Configuration value for state's 'DbPostgresConnectionString' field +func (st *ConfigState) GetDbPostgresConnectionString() (v string) { + st.mutex.RLock() + v = st.config.DbPostgresConnectionString + st.mutex.RUnlock() + return +} + +// SetDbPostgresConnectionString safely sets the Configuration value for state's 'DbPostgresConnectionString' field +func (st *ConfigState) SetDbPostgresConnectionString(v string) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.DbPostgresConnectionString = v + st.reloadToViper() +} + +// DbPostgresConnectionStringFlag returns the flag name for the 'DbPostgresConnectionString' field +func DbPostgresConnectionStringFlag() string { return "db-postgres-connection-string" } + +// GetDbPostgresConnectionString safely fetches the value for global configuration 'DbPostgresConnectionString' field +func GetDbPostgresConnectionString() string { return global.GetDbPostgresConnectionString() } + +// SetDbPostgresConnectionString safely sets the value for global configuration 'DbPostgresConnectionString' field +func SetDbPostgresConnectionString(v string) { global.SetDbPostgresConnectionString(v) } + // GetWebTemplateBaseDir safely fetches the Configuration value for state's 'WebTemplateBaseDir' field func (st *ConfigState) GetWebTemplateBaseDir() (v string) { st.mutex.RLock() diff --git a/internal/db/bundb/bundb.go b/internal/db/bundb/bundb.go index d5071d141..0e58cb7fb 100644 --- a/internal/db/bundb/bundb.go +++ b/internal/db/bundb/bundb.go @@ -396,6 +396,13 @@ func maxOpenConns() int { // deriveBunDBPGOptions takes an application config and returns either a ready-to-use set of options // with sensible defaults, or an error if it's not satisfied by the provided config. func deriveBunDBPGOptions() (*pgx.ConnConfig, error) { + url := config.GetDbPostgresConnectionString() + + // if database URL is defined, ignore other DB related configuration fields + if url != "" { + cfg, err := pgx.ParseConfig(url) + return cfg, err + } // these are all optional, the db adapter figures out defaults address := config.GetDbAddress() diff --git a/test/envparsing.sh b/test/envparsing.sh index f88b6a031..6838fecc3 100755 --- a/test/envparsing.sh +++ b/test/envparsing.sh @@ -81,6 +81,7 @@ EXPECT=$(cat << "EOF" "db-max-open-conns-multiplier": 3, "db-password": "hunter2", "db-port": 6969, + "db-postgres-connection-string": "", "db-sqlite-busy-timeout": 1000000000, "db-sqlite-cache-size": 0, "db-sqlite-journal-mode": "DELETE", @@ -212,6 +213,7 @@ GTS_BIND_ADDRESS='127.0.0.1' \ GTS_PORT=6969 \ GTS_TRUSTED_PROXIES='127.0.0.1/32,docker.host.local' \ GTS_DB_TYPE='sqlite' \ +GTS_DB_POSTGRES_CONNECTION_STRING='' \ GTS_DB_ADDRESS=':memory:' \ GTS_DB_PORT=6969 \ GTS_DB_USER='sex-haver' \