config.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. package server
  2. import (
  3. "crypto/sha256"
  4. "encoding/json"
  5. "fmt"
  6. "io/fs"
  7. "net/netip"
  8. "text/template"
  9. "time"
  10. "heckel.io/ntfy/v2/user"
  11. )
  12. // Defines default config settings (excluding limits, see below)
  13. const (
  14. DefaultListenHTTP = ":80"
  15. DefaultCacheDuration = 12 * time.Hour
  16. DefaultCacheBatchTimeout = time.Duration(0)
  17. DefaultKeepaliveInterval = 45 * time.Second // Not too frequently to save battery (Android read timeout used to be 77s!)
  18. DefaultManagerInterval = time.Minute
  19. DefaultDelayedSenderInterval = 10 * time.Second
  20. DefaultMessageDelayMin = 10 * time.Second
  21. DefaultMessageDelayMax = 3 * 24 * time.Hour
  22. DefaultFirebaseKeepaliveInterval = 3 * time.Hour // ~control topic (Android), not too frequently to save battery
  23. DefaultFirebasePollInterval = 20 * time.Minute // ~poll topic (iOS), max. 2-3 times per hour (see docs)
  24. DefaultFirebaseQuotaExceededPenaltyDuration = 10 * time.Minute // Time that over-users are locked out of Firebase if it returns "quota exceeded"
  25. DefaultStripePriceCacheDuration = 3 * time.Hour // Time to keep Stripe prices cached in memory before a refresh is needed
  26. )
  27. // Platform-specific default paths (set in config_unix.go or config_windows.go)
  28. var (
  29. DefaultConfigFile string
  30. DefaultTemplateDir string
  31. )
  32. // Defines default Web Push settings
  33. const (
  34. DefaultWebPushExpiryWarningDuration = 55 * 24 * time.Hour
  35. DefaultWebPushExpiryDuration = 60 * 24 * time.Hour
  36. )
  37. // Defines all global and per-visitor limits
  38. // - message size limit: the max number of bytes for a message
  39. // - total topic limit: max number of topics overall
  40. // - various attachment limits
  41. const (
  42. DefaultMessageSizeLimit = 4096 // Bytes; note that FCM/APNS have a limit of ~4 KB for the entire message
  43. DefaultTotalTopicLimit = 15000
  44. DefaultAttachmentTotalSizeLimit = int64(5 * 1024 * 1024 * 1024) // 5 GB
  45. DefaultAttachmentFileSizeLimit = int64(15 * 1024 * 1024) // 15 MB
  46. DefaultAttachmentExpiryDuration = 3 * time.Hour
  47. )
  48. // Defines all per-visitor limits
  49. // - per visitor subscription limit: max number of subscriptions (active HTTP connections) per per-visitor/IP
  50. // - per visitor request limit: max number of PUT/GET/.. requests (here: 60 requests bucket, replenished at a rate of one per 5 seconds)
  51. // - per visitor email limit: max number of emails (here: 16 email bucket, replenished at a rate of one per hour)
  52. // - per visitor attachment size limit: total per-visitor attachment size in bytes to be stored on the server
  53. // - per visitor attachment daily bandwidth limit: number of bytes that can be transferred to/from the server
  54. const (
  55. DefaultVisitorSubscriptionLimit = 30
  56. DefaultVisitorRequestLimitBurst = 60
  57. DefaultVisitorRequestLimitReplenish = 5 * time.Second
  58. DefaultVisitorMessageDailyLimit = 0
  59. DefaultVisitorEmailLimitBurst = 16
  60. DefaultVisitorEmailLimitReplenish = time.Hour
  61. DefaultVisitorAccountCreationLimitBurst = 3
  62. DefaultVisitorAccountCreationLimitReplenish = 24 * time.Hour
  63. DefaultVisitorAuthFailureLimitBurst = 30
  64. DefaultVisitorAuthFailureLimitReplenish = time.Minute
  65. DefaultVisitorAttachmentTotalSizeLimit = 100 * 1024 * 1024 // 100 MB
  66. DefaultVisitorAttachmentDailyBandwidthLimit = 500 * 1024 * 1024 // 500 MB
  67. DefaultVisitorPrefixBitsIPv4 = 32 // Use the entire IPv4 address for rate limiting
  68. DefaultVisitorPrefixBitsIPv6 = 64 // Use /64 for IPv6 rate limiting
  69. )
  70. var (
  71. // DefaultVisitorStatsResetTime defines the time at which visitor stats are reset (wall clock only)
  72. DefaultVisitorStatsResetTime = time.Date(0, 0, 0, 0, 0, 0, 0, time.UTC)
  73. // DefaultDisallowedTopics defines the topics that are forbidden, because they are used elsewhere. This array can be
  74. // extended using the server.yml config. If updated, also update in Android and web app.
  75. DefaultDisallowedTopics = []string{"docs", "static", "file", "app", "metrics", "account", "settings", "signup", "login", "v1"}
  76. )
  77. // Config is the main config struct for the application. Use New to instantiate a default config struct.
  78. type Config struct {
  79. File string // Config file, only used for testing
  80. BaseURL string
  81. ListenHTTP string
  82. ListenHTTPS string
  83. ListenUnix string
  84. ListenUnixMode fs.FileMode
  85. KeyFile string
  86. CertFile string
  87. FirebaseKeyFile string
  88. CacheFile string
  89. CacheDuration time.Duration
  90. CacheStartupQueries string
  91. CacheBatchSize int
  92. CacheBatchTimeout time.Duration
  93. AuthFile string
  94. AuthStartupQueries string
  95. AuthDefault user.Permission
  96. AuthUsers []*user.User
  97. AuthAccess map[string][]*user.Grant
  98. AuthTokens map[string][]*user.Token
  99. AuthBcryptCost int
  100. AuthStatsQueueWriterInterval time.Duration
  101. AttachmentCacheDir string
  102. AttachmentTotalSizeLimit int64
  103. AttachmentFileSizeLimit int64
  104. AttachmentExpiryDuration time.Duration
  105. TemplateDir string // Directory to load named templates from
  106. KeepaliveInterval time.Duration
  107. ManagerInterval time.Duration
  108. DisallowedTopics []string
  109. WebRoot string // empty to disable
  110. DelayedSenderInterval time.Duration
  111. FirebaseKeepaliveInterval time.Duration
  112. FirebasePollInterval time.Duration
  113. FirebaseQuotaExceededPenaltyDuration time.Duration
  114. UpstreamBaseURL string
  115. UpstreamAccessToken string
  116. SMTPSenderAddr string
  117. SMTPSenderUser string
  118. SMTPSenderPass string
  119. SMTPSenderFrom string
  120. SMTPServerListen string
  121. SMTPServerDomain string
  122. SMTPServerAddrPrefix string
  123. TwilioAccount string
  124. TwilioAuthToken string
  125. TwilioPhoneNumber string
  126. TwilioCallsBaseURL string
  127. TwilioVerifyBaseURL string
  128. TwilioVerifyService string
  129. TwilioCallFormat *template.Template
  130. MetricsEnable bool
  131. MetricsListenHTTP string
  132. ProfileListenHTTP string
  133. MessageDelayMin time.Duration
  134. MessageDelayMax time.Duration
  135. MessageSizeLimit int
  136. TotalTopicLimit int
  137. TotalAttachmentSizeLimit int64
  138. VisitorSubscriptionLimit int
  139. VisitorAttachmentTotalSizeLimit int64
  140. VisitorAttachmentDailyBandwidthLimit int64
  141. VisitorRequestLimitBurst int
  142. VisitorRequestLimitReplenish time.Duration
  143. VisitorRequestExemptPrefixes []netip.Prefix
  144. VisitorMessageDailyLimit int
  145. VisitorEmailLimitBurst int
  146. VisitorEmailLimitReplenish time.Duration
  147. VisitorAccountCreationLimitBurst int
  148. VisitorAccountCreationLimitReplenish time.Duration
  149. VisitorAuthFailureLimitBurst int
  150. VisitorAuthFailureLimitReplenish time.Duration
  151. VisitorStatsResetTime time.Time // Time of the day at which to reset visitor stats
  152. VisitorSubscriberRateLimiting bool // Enable subscriber-based rate limiting for UnifiedPush topics
  153. VisitorPrefixBitsIPv4 int // Number of bits for IPv4 rate limiting (default: 32)
  154. VisitorPrefixBitsIPv6 int // Number of bits for IPv6 rate limiting (default: 64)
  155. BehindProxy bool // If true, the server will trust the proxy client IP header to determine the client IP address (IPv4 and IPv6 supported)
  156. ProxyForwardedHeader string // The header field to read the real/client IP address from, if BehindProxy is true, defaults to "X-Forwarded-For" (IPv4 and IPv6 supported)
  157. ProxyTrustedPrefixes []netip.Prefix // List of trusted proxy networks (IPv4 or IPv6) that will be stripped from the Forwarded header if BehindProxy is true
  158. StripeSecretKey string
  159. StripeWebhookKey string
  160. StripePriceCacheDuration time.Duration
  161. BillingContact string
  162. EnableSignup bool // Enable creation of accounts via API and UI
  163. EnableLogin bool
  164. RequireLogin bool
  165. EnableReservations bool // Allow users with role "user" to own/reserve topics
  166. EnableMetrics bool
  167. AccessControlAllowOrigin string // CORS header field to restrict access from web clients
  168. WebPushPrivateKey string
  169. WebPushPublicKey string
  170. WebPushFile string
  171. WebPushEmailAddress string
  172. WebPushStartupQueries string
  173. WebPushExpiryDuration time.Duration
  174. WebPushExpiryWarningDuration time.Duration
  175. Version string // injected by App
  176. }
  177. // NewConfig instantiates a default new server config
  178. func NewConfig() *Config {
  179. return &Config{
  180. File: DefaultConfigFile, // Only used for testing
  181. BaseURL: "",
  182. ListenHTTP: DefaultListenHTTP,
  183. ListenHTTPS: "",
  184. ListenUnix: "",
  185. ListenUnixMode: 0,
  186. KeyFile: "",
  187. CertFile: "",
  188. FirebaseKeyFile: "",
  189. CacheFile: "",
  190. CacheDuration: DefaultCacheDuration,
  191. CacheStartupQueries: "",
  192. CacheBatchSize: 0,
  193. CacheBatchTimeout: 0,
  194. AuthFile: "",
  195. AuthStartupQueries: "",
  196. AuthDefault: user.PermissionReadWrite,
  197. AuthBcryptCost: user.DefaultUserPasswordBcryptCost,
  198. AuthStatsQueueWriterInterval: user.DefaultUserStatsQueueWriterInterval,
  199. AttachmentCacheDir: "",
  200. AttachmentTotalSizeLimit: DefaultAttachmentTotalSizeLimit,
  201. AttachmentFileSizeLimit: DefaultAttachmentFileSizeLimit,
  202. AttachmentExpiryDuration: DefaultAttachmentExpiryDuration,
  203. TemplateDir: DefaultTemplateDir,
  204. KeepaliveInterval: DefaultKeepaliveInterval,
  205. ManagerInterval: DefaultManagerInterval,
  206. DisallowedTopics: DefaultDisallowedTopics,
  207. WebRoot: "/",
  208. DelayedSenderInterval: DefaultDelayedSenderInterval,
  209. FirebaseKeepaliveInterval: DefaultFirebaseKeepaliveInterval,
  210. FirebasePollInterval: DefaultFirebasePollInterval,
  211. FirebaseQuotaExceededPenaltyDuration: DefaultFirebaseQuotaExceededPenaltyDuration,
  212. UpstreamBaseURL: "",
  213. UpstreamAccessToken: "",
  214. SMTPSenderAddr: "",
  215. SMTPSenderUser: "",
  216. SMTPSenderPass: "",
  217. SMTPSenderFrom: "",
  218. SMTPServerListen: "",
  219. SMTPServerDomain: "",
  220. SMTPServerAddrPrefix: "",
  221. TwilioCallsBaseURL: "https://api.twilio.com", // Override for tests
  222. TwilioAccount: "",
  223. TwilioAuthToken: "",
  224. TwilioPhoneNumber: "",
  225. TwilioVerifyBaseURL: "https://verify.twilio.com", // Override for tests
  226. TwilioVerifyService: "",
  227. TwilioCallFormat: nil,
  228. MessageSizeLimit: DefaultMessageSizeLimit,
  229. MessageDelayMin: DefaultMessageDelayMin,
  230. MessageDelayMax: DefaultMessageDelayMax,
  231. TotalTopicLimit: DefaultTotalTopicLimit,
  232. TotalAttachmentSizeLimit: 0,
  233. VisitorSubscriptionLimit: DefaultVisitorSubscriptionLimit,
  234. VisitorSubscriberRateLimiting: false,
  235. VisitorAttachmentTotalSizeLimit: DefaultVisitorAttachmentTotalSizeLimit,
  236. VisitorAttachmentDailyBandwidthLimit: DefaultVisitorAttachmentDailyBandwidthLimit,
  237. VisitorRequestLimitBurst: DefaultVisitorRequestLimitBurst,
  238. VisitorRequestLimitReplenish: DefaultVisitorRequestLimitReplenish,
  239. VisitorRequestExemptPrefixes: make([]netip.Prefix, 0),
  240. VisitorMessageDailyLimit: DefaultVisitorMessageDailyLimit,
  241. VisitorEmailLimitBurst: DefaultVisitorEmailLimitBurst,
  242. VisitorEmailLimitReplenish: DefaultVisitorEmailLimitReplenish,
  243. VisitorAccountCreationLimitBurst: DefaultVisitorAccountCreationLimitBurst,
  244. VisitorAccountCreationLimitReplenish: DefaultVisitorAccountCreationLimitReplenish,
  245. VisitorAuthFailureLimitBurst: DefaultVisitorAuthFailureLimitBurst,
  246. VisitorAuthFailureLimitReplenish: DefaultVisitorAuthFailureLimitReplenish,
  247. VisitorStatsResetTime: DefaultVisitorStatsResetTime,
  248. VisitorPrefixBitsIPv4: DefaultVisitorPrefixBitsIPv4, // Default: use full IPv4 address
  249. VisitorPrefixBitsIPv6: DefaultVisitorPrefixBitsIPv6, // Default: use /64 for IPv6
  250. BehindProxy: false, // If true, the server will trust the proxy client IP header to determine the client IP address
  251. ProxyForwardedHeader: "X-Forwarded-For", // Default header for reverse proxy client IPs
  252. StripeSecretKey: "",
  253. StripeWebhookKey: "",
  254. StripePriceCacheDuration: DefaultStripePriceCacheDuration,
  255. BillingContact: "",
  256. EnableSignup: false,
  257. EnableLogin: false,
  258. EnableReservations: false,
  259. RequireLogin: false,
  260. AccessControlAllowOrigin: "*",
  261. Version: "",
  262. WebPushPrivateKey: "",
  263. WebPushPublicKey: "",
  264. WebPushFile: "",
  265. WebPushEmailAddress: "",
  266. WebPushExpiryDuration: DefaultWebPushExpiryDuration,
  267. WebPushExpiryWarningDuration: DefaultWebPushExpiryWarningDuration,
  268. }
  269. }
  270. // configHashData is a subset of Config fields used for computing the config hash.
  271. // It excludes sensitive fields (keys, passwords, tokens) and runtime-only fields.
  272. type configHashData struct {
  273. BaseURL string
  274. ListenHTTP string
  275. ListenHTTPS string
  276. ListenUnix string
  277. CacheDuration time.Duration
  278. AttachmentTotalSizeLimit int64
  279. AttachmentFileSizeLimit int64
  280. AttachmentExpiryDuration time.Duration
  281. KeepaliveInterval time.Duration
  282. ManagerInterval time.Duration
  283. DisallowedTopics []string
  284. WebRoot string
  285. MessageDelayMin time.Duration
  286. MessageDelayMax time.Duration
  287. MessageSizeLimit int
  288. TotalTopicLimit int
  289. VisitorSubscriptionLimit int
  290. VisitorAttachmentTotalSizeLimit int64
  291. VisitorAttachmentDailyBandwidthLimit int64
  292. VisitorRequestLimitBurst int
  293. VisitorRequestLimitReplenish time.Duration
  294. VisitorMessageDailyLimit int
  295. VisitorEmailLimitBurst int
  296. VisitorEmailLimitReplenish time.Duration
  297. EnableSignup bool
  298. EnableLogin bool
  299. RequireLogin bool
  300. EnableReservations bool
  301. EnableMetrics bool
  302. EnablePayments bool
  303. EnableCalls bool
  304. EnableEmails bool
  305. EnableWebPush bool
  306. BillingContact string
  307. Version string
  308. }
  309. // Hash computes a SHA-256 hash of the configuration. This is used to detect
  310. // configuration changes for the web app version check feature.
  311. func (c *Config) Hash() string {
  312. data := configHashData{
  313. BaseURL: c.BaseURL,
  314. ListenHTTP: c.ListenHTTP,
  315. ListenHTTPS: c.ListenHTTPS,
  316. ListenUnix: c.ListenUnix,
  317. CacheDuration: c.CacheDuration,
  318. AttachmentTotalSizeLimit: c.AttachmentTotalSizeLimit,
  319. AttachmentFileSizeLimit: c.AttachmentFileSizeLimit,
  320. AttachmentExpiryDuration: c.AttachmentExpiryDuration,
  321. KeepaliveInterval: c.KeepaliveInterval,
  322. ManagerInterval: c.ManagerInterval,
  323. DisallowedTopics: c.DisallowedTopics,
  324. WebRoot: c.WebRoot,
  325. MessageDelayMin: c.MessageDelayMin,
  326. MessageDelayMax: c.MessageDelayMax,
  327. MessageSizeLimit: c.MessageSizeLimit,
  328. TotalTopicLimit: c.TotalTopicLimit,
  329. VisitorSubscriptionLimit: c.VisitorSubscriptionLimit,
  330. VisitorAttachmentTotalSizeLimit: c.VisitorAttachmentTotalSizeLimit,
  331. VisitorAttachmentDailyBandwidthLimit: c.VisitorAttachmentDailyBandwidthLimit,
  332. VisitorRequestLimitBurst: c.VisitorRequestLimitBurst,
  333. VisitorRequestLimitReplenish: c.VisitorRequestLimitReplenish,
  334. VisitorMessageDailyLimit: c.VisitorMessageDailyLimit,
  335. VisitorEmailLimitBurst: c.VisitorEmailLimitBurst,
  336. VisitorEmailLimitReplenish: c.VisitorEmailLimitReplenish,
  337. EnableSignup: c.EnableSignup,
  338. EnableLogin: c.EnableLogin,
  339. RequireLogin: c.RequireLogin,
  340. EnableReservations: c.EnableReservations,
  341. EnableMetrics: c.EnableMetrics,
  342. EnablePayments: c.StripeSecretKey != "",
  343. EnableCalls: c.TwilioAccount != "",
  344. EnableEmails: c.SMTPSenderFrom != "",
  345. EnableWebPush: c.WebPushPublicKey != "",
  346. BillingContact: c.BillingContact,
  347. Version: c.Version,
  348. }
  349. b, _ := json.Marshal(data)
  350. return fmt.Sprintf("%x", sha256.Sum256(b))
  351. }