Docs
This commit is contained in:
@@ -325,8 +325,8 @@ func execServe(c *cli.Context) error {
|
|||||||
return errors.New("if upstream-base-url is set, base-url must also be set")
|
return errors.New("if upstream-base-url is set, base-url must also be set")
|
||||||
} else if upstreamBaseURL != "" && baseURL != "" && baseURL == upstreamBaseURL {
|
} else if upstreamBaseURL != "" && baseURL != "" && baseURL == upstreamBaseURL {
|
||||||
return errors.New("base-url and upstream-base-url cannot be identical, you'll likely want to set upstream-base-url to https://ntfy.sh, see https://ntfy.sh/docs/config/#ios-instant-notifications")
|
return errors.New("base-url and upstream-base-url cannot be identical, you'll likely want to set upstream-base-url to https://ntfy.sh, see https://ntfy.sh/docs/config/#ios-instant-notifications")
|
||||||
} else if authFile == "" && (enableSignup || enableLogin || requireLogin || enableReservations || stripeSecretKey != "") {
|
} else if authFile == "" && databaseURL == "" && (enableSignup || enableLogin || requireLogin || enableReservations || stripeSecretKey != "") {
|
||||||
return errors.New("cannot set enable-signup, enable-login, require-login, enable-reserve-topics, or stripe-secret-key if auth-file is not set")
|
return errors.New("cannot set enable-signup, enable-login, require-login, enable-reserve-topics, or stripe-secret-key if auth-file or database-url is not set")
|
||||||
} else if enableSignup && !enableLogin {
|
} else if enableSignup && !enableLogin {
|
||||||
return errors.New("cannot set enable-signup without also setting enable-login")
|
return errors.New("cannot set enable-signup without also setting enable-login")
|
||||||
} else if requireLogin && !enableLogin {
|
} else if requireLogin && !enableLogin {
|
||||||
@@ -335,8 +335,8 @@ func execServe(c *cli.Context) error {
|
|||||||
return errors.New("cannot set stripe-secret-key or stripe-webhook-key, support for payments is not available in this build (nopayments)")
|
return errors.New("cannot set stripe-secret-key or stripe-webhook-key, support for payments is not available in this build (nopayments)")
|
||||||
} else if stripeSecretKey != "" && (stripeWebhookKey == "" || baseURL == "") {
|
} else if stripeSecretKey != "" && (stripeWebhookKey == "" || baseURL == "") {
|
||||||
return errors.New("if stripe-secret-key is set, stripe-webhook-key and base-url must also be set")
|
return errors.New("if stripe-secret-key is set, stripe-webhook-key and base-url must also be set")
|
||||||
} else if twilioAccount != "" && (twilioAuthToken == "" || twilioPhoneNumber == "" || twilioVerifyService == "" || baseURL == "" || authFile == "") {
|
} else if twilioAccount != "" && (twilioAuthToken == "" || twilioPhoneNumber == "" || twilioVerifyService == "" || baseURL == "" || (authFile == "" && databaseURL == "")) {
|
||||||
return errors.New("if twilio-account is set, twilio-auth-token, twilio-phone-number, twilio-verify-service, base-url, and auth-file must also be set")
|
return errors.New("if twilio-account is set, twilio-auth-token, twilio-phone-number, twilio-verify-service, base-url, and auth-file (or database-url) must also be set")
|
||||||
} else if messageSizeLimit > server.DefaultMessageSizeLimit {
|
} else if messageSizeLimit > server.DefaultMessageSizeLimit {
|
||||||
log.Warn("message-size-limit is greater than 4K, this is not recommended and largely untested, and may lead to issues with some clients")
|
log.Warn("message-size-limit is greater than 4K, this is not recommended and largely untested, and may lead to issues with some clients")
|
||||||
if messageSizeLimit > 5*1024*1024 {
|
if messageSizeLimit > 5*1024*1024 {
|
||||||
|
|||||||
17
db/db.go
17
db/db.go
@@ -10,7 +10,14 @@ import (
|
|||||||
_ "github.com/jackc/pgx/v5/stdlib" // PostgreSQL driver
|
_ "github.com/jackc/pgx/v5/stdlib" // PostgreSQL driver
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultMaxOpenConns = 10
|
const (
|
||||||
|
paramMaxOpenConns = "pool_max_conns"
|
||||||
|
paramMaxIdleConns = "pool_max_idle_conns"
|
||||||
|
paramConnMaxLifetime = "pool_conn_max_lifetime"
|
||||||
|
paramConnMaxIdleTime = "pool_conn_max_idle_time"
|
||||||
|
|
||||||
|
defaultMaxOpenConns = 10
|
||||||
|
)
|
||||||
|
|
||||||
// Open opens a PostgreSQL database connection pool from a DSN string. It supports custom
|
// Open opens a PostgreSQL database connection pool from a DSN string. It supports custom
|
||||||
// query parameters for pool configuration: pool_max_conns (default 10), pool_max_idle_conns,
|
// query parameters for pool configuration: pool_max_conns (default 10), pool_max_idle_conns,
|
||||||
@@ -22,19 +29,19 @@ func Open(dsn string) (*sql.DB, error) {
|
|||||||
return nil, fmt.Errorf("invalid database URL: %w", err)
|
return nil, fmt.Errorf("invalid database URL: %w", err)
|
||||||
}
|
}
|
||||||
q := u.Query()
|
q := u.Query()
|
||||||
maxOpenConns, err := extractIntParam(q, "pool_max_conns", defaultMaxOpenConns)
|
maxOpenConns, err := extractIntParam(q, paramMaxOpenConns, defaultMaxOpenConns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
maxIdleConns, err := extractIntParam(q, "pool_max_idle_conns", 0)
|
maxIdleConns, err := extractIntParam(q, paramMaxIdleConns, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
connMaxLifetime, err := extractDurationParam(q, "pool_conn_max_lifetime", 0)
|
connMaxLifetime, err := extractDurationParam(q, paramConnMaxLifetime, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
connMaxIdleTime, err := extractDurationParam(q, "pool_conn_max_idle_time", 0)
|
connMaxIdleTime, err := extractDurationParam(q, paramConnMaxIdleTime, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,8 +153,12 @@ database-url: "postgres://user:pass@host:5432/ntfy"
|
|||||||
```
|
```
|
||||||
|
|
||||||
When `database-url` is set, ntfy will use PostgreSQL for all database-backed stores (message cache, user manager,
|
When `database-url` is set, ntfy will use PostgreSQL for all database-backed stores (message cache, user manager,
|
||||||
and web push subscriptions) instead of SQLite. The `cache-file`, `auth-file`, and `web-push-file` options are not
|
and web push subscriptions) instead of SQLite. The `cache-file`, `auth-file`, and `web-push-file` options must not
|
||||||
required in this case.
|
be set in this case.
|
||||||
|
|
||||||
|
Note that setting `database-url` implicitly enables authentication and access control (equivalent to setting
|
||||||
|
`auth-file` with SQLite). The default access is `read-write`, so anonymous users can still read and write to all
|
||||||
|
topics. To restrict access, set `auth-default-access` to `deny-all` (see [access control](#access-control)).
|
||||||
|
|
||||||
You can also set this via the environment variable `NTFY_DATABASE_URL` or the command line flag `--database-url`.
|
You can also set this via the environment variable `NTFY_DATABASE_URL` or the command line flag `--database-url`.
|
||||||
|
|
||||||
@@ -215,14 +219,15 @@ and `visitor-attachment-daily-bandwidth-limit`. Setting these conservatively is
|
|||||||
By default, the ntfy server is open for everyone, meaning **everyone can read and write to any topic** (this is how
|
By default, the ntfy server is open for everyone, meaning **everyone can read and write to any topic** (this is how
|
||||||
ntfy.sh is configured). To restrict access to your own server, you can optionally configure authentication and authorization.
|
ntfy.sh is configured). To restrict access to your own server, you can optionally configure authentication and authorization.
|
||||||
|
|
||||||
ntfy's auth is implemented with a simple [SQLite](https://www.sqlite.org/)-based backend. It implements two roles
|
ntfy's auth implements two roles (`user` and `admin`) and per-topic `read` and `write` permissions using an
|
||||||
(`user` and `admin`) and per-topic `read` and `write` permissions using an [access control list (ACL)](https://en.wikipedia.org/wiki/Access-control_list).
|
[access control list (ACL)](https://en.wikipedia.org/wiki/Access-control_list). Access control entries can be applied
|
||||||
Access control entries can be applied to users as well as the special everyone user (`*`), which represents anonymous API access.
|
to users as well as the special everyone user (`*`), which represents anonymous API access.
|
||||||
|
|
||||||
To set up auth, **configure the following options**:
|
To set up auth, **configure the following options**:
|
||||||
|
|
||||||
* `auth-file` is the user/access database; it is created automatically if it doesn't already exist; suggested
|
* `auth-file` is the user/access database (SQLite); it is created automatically if it doesn't already exist; suggested
|
||||||
location `/var/lib/ntfy/user.db` (easiest if deb/rpm package is used)
|
location `/var/lib/ntfy/user.db` (easiest if deb/rpm package is used). Alternatively, if `database-url` is set,
|
||||||
|
auth is automatically enabled using PostgreSQL (see [PostgreSQL database](#postgresql-database)).
|
||||||
* `auth-default-access` defines the default/fallback access if no access control entry is found; it can be
|
* `auth-default-access` defines the default/fallback access if no access control entry is found; it can be
|
||||||
set to `read-write` (default), `read-only`, `write-only` or `deny-all`. **If you are setting up a private instance,
|
set to `read-write` (default), `read-only`, `write-only` or `deny-all`. **If you are setting up a private instance,
|
||||||
you'll want to set this to `deny-all`** (see [private instance example](#example-private-instance)).
|
you'll want to set this to `deny-all`** (see [private instance example](#example-private-instance)).
|
||||||
@@ -1795,7 +1800,7 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
|
|||||||
| `cache-startup-queries` | `NTFY_CACHE_STARTUP_QUERIES` | *string (SQL queries)* | - | SQL queries to run during database startup; this is useful for tuning and [enabling WAL mode](#message-cache) |
|
| `cache-startup-queries` | `NTFY_CACHE_STARTUP_QUERIES` | *string (SQL queries)* | - | SQL queries to run during database startup; this is useful for tuning and [enabling WAL mode](#message-cache) |
|
||||||
| `cache-batch-size` | `NTFY_CACHE_BATCH_SIZE` | *int* | 0 | Max size of messages to batch together when writing to message cache (if zero, writes are synchronous) |
|
| `cache-batch-size` | `NTFY_CACHE_BATCH_SIZE` | *int* | 0 | Max size of messages to batch together when writing to message cache (if zero, writes are synchronous) |
|
||||||
| `cache-batch-timeout` | `NTFY_CACHE_BATCH_TIMEOUT` | *duration* | 0s | Timeout for batched async writes to the message cache (if zero, writes are synchronous) |
|
| `cache-batch-timeout` | `NTFY_CACHE_BATCH_TIMEOUT` | *duration* | 0s | Timeout for batched async writes to the message cache (if zero, writes are synchronous) |
|
||||||
| `auth-file` | `NTFY_AUTH_FILE` | *filename* | - | Auth database file used for access control. If set, enables authentication and access control. See [access control](#access-control). |
|
| `auth-file` | `NTFY_AUTH_FILE` | *filename* | - | Auth database file used for access control (SQLite). If set, enables authentication and access control. Not required if `database-url` is set. See [access control](#access-control). |
|
||||||
| `auth-default-access` | `NTFY_AUTH_DEFAULT_ACCESS` | `read-write`, `read-only`, `write-only`, `deny-all` | `read-write` | Default permissions if no matching entries in the auth database are found. Default is `read-write`. |
|
| `auth-default-access` | `NTFY_AUTH_DEFAULT_ACCESS` | `read-write`, `read-only`, `write-only`, `deny-all` | `read-write` | Default permissions if no matching entries in the auth database are found. Default is `read-write`. |
|
||||||
| `behind-proxy` | `NTFY_BEHIND_PROXY` | *bool* | false | If set, use forwarded header (e.g. X-Forwarded-For, X-Client-IP) to determine visitor IP address (for rate limiting) |
|
| `behind-proxy` | `NTFY_BEHIND_PROXY` | *bool* | false | If set, use forwarded header (e.g. X-Forwarded-For, X-Client-IP) to determine visitor IP address (for rate limiting) |
|
||||||
| `proxy-forwarded-header` | `NTFY_PROXY_FORWARDED_HEADER` | *string* | `X-Forwarded-For` | Use specified header to determine visitor IP address (for rate limiting) |
|
| `proxy-forwarded-header` | `NTFY_PROXY_FORWARDED_HEADER` | *string* | `X-Forwarded-For` | Use specified header to determine visitor IP address (for rate limiting) |
|
||||||
|
|||||||
@@ -1720,4 +1720,4 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
|
|||||||
|
|
||||||
**Features:**
|
**Features:**
|
||||||
|
|
||||||
* Add PostgreSQL as an alternative database backend for the web push subscription store via `database-url` config option
|
* Add PostgreSQL as an alternative database backend for all stores (message cache, user manager, web push subscriptions) via `database-url` config option, using a single shared connection pool with configurable pool settings (`pool_max_conns`, `pool_max_idle_conns`, `pool_conn_max_lifetime`, `pool_conn_max_idle_time`)
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ var (
|
|||||||
// Config is the main config struct for the application. Use New to instantiate a default config struct.
|
// Config is the main config struct for the application. Use New to instantiate a default config struct.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
File string // Config file, only used for testing
|
File string // Config file, only used for testing
|
||||||
DatabaseURL string // PostgreSQL connection string (e.g. "postgres://user:pass@host:5432/ntfy")
|
|
||||||
BaseURL string
|
BaseURL string
|
||||||
ListenHTTP string
|
ListenHTTP string
|
||||||
ListenHTTPS string
|
ListenHTTPS string
|
||||||
@@ -96,6 +95,7 @@ type Config struct {
|
|||||||
ListenUnixMode fs.FileMode
|
ListenUnixMode fs.FileMode
|
||||||
KeyFile string
|
KeyFile string
|
||||||
CertFile string
|
CertFile string
|
||||||
|
DatabaseURL string // PostgreSQL connection string (e.g. "postgres://user:pass@host:5432/ntfy")
|
||||||
FirebaseKeyFile string
|
FirebaseKeyFile string
|
||||||
CacheFile string
|
CacheFile string
|
||||||
CacheDuration time.Duration
|
CacheDuration time.Duration
|
||||||
@@ -193,7 +193,6 @@ type Config struct {
|
|||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
File: DefaultConfigFile, // Only used for testing
|
File: DefaultConfigFile, // Only used for testing
|
||||||
DatabaseURL: "",
|
|
||||||
BaseURL: "",
|
BaseURL: "",
|
||||||
ListenHTTP: DefaultListenHTTP,
|
ListenHTTP: DefaultListenHTTP,
|
||||||
ListenHTTPS: "",
|
ListenHTTPS: "",
|
||||||
@@ -201,6 +200,7 @@ func NewConfig() *Config {
|
|||||||
ListenUnixMode: 0,
|
ListenUnixMode: 0,
|
||||||
KeyFile: "",
|
KeyFile: "",
|
||||||
CertFile: "",
|
CertFile: "",
|
||||||
|
DatabaseURL: "",
|
||||||
FirebaseKeyFile: "",
|
FirebaseKeyFile: "",
|
||||||
CacheFile: "",
|
CacheFile: "",
|
||||||
CacheDuration: DefaultCacheDuration,
|
CacheDuration: DefaultCacheDuration,
|
||||||
|
|||||||
@@ -40,7 +40,10 @@
|
|||||||
|
|
||||||
# If "database-url" is set, ntfy will use PostgreSQL for all database-backed stores (message cache,
|
# If "database-url" is set, ntfy will use PostgreSQL for all database-backed stores (message cache,
|
||||||
# user manager, and web push subscriptions) instead of SQLite. When set, the "cache-file",
|
# user manager, and web push subscriptions) instead of SQLite. When set, the "cache-file",
|
||||||
# "auth-file", and "web-push-file" options are not required.
|
# "auth-file", and "web-push-file" options must not be set.
|
||||||
|
#
|
||||||
|
# Note: Setting "database-url" implicitly enables authentication and access control.
|
||||||
|
# The default access is "read-write" (see "auth-default-access").
|
||||||
#
|
#
|
||||||
# You can append connection pool parameters as query parameters:
|
# You can append connection pool parameters as query parameters:
|
||||||
# pool_max_conns=10 - Maximum number of open connections (default: 10)
|
# pool_max_conns=10 - Maximum number of open connections (default: 10)
|
||||||
@@ -90,6 +93,8 @@
|
|||||||
# If set, access to the ntfy server and API can be controlled on a granular level using
|
# If set, access to the ntfy server and API can be controlled on a granular level using
|
||||||
# the 'ntfy user' and 'ntfy access' commands. See the --help pages for details, or check the docs.
|
# the 'ntfy user' and 'ntfy access' commands. See the --help pages for details, or check the docs.
|
||||||
#
|
#
|
||||||
|
# Note: If "database-url" is set, auth is implicitly enabled and "auth-file" must not be set.
|
||||||
|
#
|
||||||
# - auth-file is the SQLite user/access database; it is created automatically if it doesn't already exist
|
# - auth-file is the SQLite user/access database; it is created automatically if it doesn't already exist
|
||||||
# - auth-default-access defines the default/fallback access if no access control entry is found; it can be
|
# - auth-default-access defines the default/fallback access if no access control entry is found; it can be
|
||||||
# set to "read-write" (default), "read-only", "write-only" or "deny-all".
|
# set to "read-write" (default), "read-only", "write-only" or "deny-all".
|
||||||
|
|||||||
Reference in New Issue
Block a user