options.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package config // import "miniflux.app/v2/internal/config"
  4. import (
  5. "crypto/rand"
  6. "fmt"
  7. "sort"
  8. "strings"
  9. "time"
  10. "miniflux.app/v2/internal/version"
  11. )
  12. const (
  13. defaultHTTPS = false
  14. defaultLogFile = "stderr"
  15. defaultLogDateTime = false
  16. defaultLogFormat = "text"
  17. defaultLogLevel = "info"
  18. defaultHSTS = true
  19. defaultHTTPService = true
  20. defaultSchedulerService = true
  21. defaultDebug = false
  22. defaultTiming = false
  23. defaultBaseURL = "http://localhost"
  24. defaultRootURL = "http://localhost"
  25. defaultBasePath = ""
  26. defaultWorkerPoolSize = 5
  27. defaultPollingFrequency = 60
  28. defaultForceRefreshInterval = 30
  29. defaultBatchSize = 100
  30. defaultPollingScheduler = "round_robin"
  31. defaultSchedulerEntryFrequencyMinInterval = 5
  32. defaultSchedulerEntryFrequencyMaxInterval = 24 * 60
  33. defaultSchedulerEntryFrequencyFactor = 1
  34. defaultSchedulerRoundRobinMinInterval = 60
  35. defaultPollingParsingErrorLimit = 3
  36. defaultRunMigrations = false
  37. defaultDatabaseURL = "user=postgres password=postgres dbname=miniflux2 sslmode=disable"
  38. defaultDatabaseMaxConns = 20
  39. defaultDatabaseMinConns = 1
  40. defaultDatabaseConnectionLifetime = 5
  41. defaultListenAddr = "127.0.0.1:8080"
  42. defaultCertFile = ""
  43. defaultKeyFile = ""
  44. defaultCertDomain = ""
  45. defaultCleanupFrequencyHours = 24
  46. defaultCleanupArchiveReadDays = 60
  47. defaultCleanupArchiveUnreadDays = 180
  48. defaultCleanupArchiveBatchSize = 10000
  49. defaultCleanupRemoveSessionsDays = 30
  50. defaultProxyHTTPClientTimeout = 120
  51. defaultProxyOption = "http-only"
  52. defaultProxyMediaTypes = "image"
  53. defaultProxyUrl = ""
  54. defaultFetchOdyseeWatchTime = false
  55. defaultFetchYouTubeWatchTime = false
  56. defaultYouTubeEmbedUrlOverride = "https://www.youtube-nocookie.com/embed/"
  57. defaultCreateAdmin = false
  58. defaultAdminUsername = ""
  59. defaultAdminPassword = ""
  60. defaultOAuth2UserCreation = false
  61. defaultOAuth2ClientID = ""
  62. defaultOAuth2ClientSecret = ""
  63. defaultOAuth2RedirectURL = ""
  64. defaultOAuth2OidcDiscoveryEndpoint = ""
  65. defaultOAuth2Provider = ""
  66. defaultPocketConsumerKey = ""
  67. defaultHTTPClientTimeout = 20
  68. defaultHTTPClientMaxBodySize = 15
  69. defaultHTTPClientProxy = ""
  70. defaultHTTPServerTimeout = 300
  71. defaultAuthProxyHeader = ""
  72. defaultAuthProxyUserCreation = false
  73. defaultMaintenanceMode = false
  74. defaultMaintenanceMessage = "Miniflux is currently under maintenance"
  75. defaultMetricsCollector = false
  76. defaultMetricsRefreshInterval = 60
  77. defaultMetricsAllowedNetworks = "127.0.0.1/8"
  78. defaultMetricsUsername = ""
  79. defaultMetricsPassword = ""
  80. defaultWatchdog = true
  81. defaultInvidiousInstance = "yewtu.be"
  82. defaultWebAuthn = false
  83. )
  84. var defaultHTTPClientUserAgent = "Mozilla/5.0 (compatible; Miniflux/" + version.Version + "; +https://miniflux.app)"
  85. // Option contains a key to value map of a single option. It may be used to output debug strings.
  86. type Option struct {
  87. Key string
  88. Value interface{}
  89. }
  90. // Options contains configuration options.
  91. type Options struct {
  92. HTTPS bool
  93. logFile string
  94. logDateTime bool
  95. logFormat string
  96. logLevel string
  97. hsts bool
  98. httpService bool
  99. schedulerService bool
  100. serverTimingHeader bool
  101. baseURL string
  102. rootURL string
  103. basePath string
  104. databaseURL string
  105. databaseMaxConns int
  106. databaseMinConns int
  107. databaseConnectionLifetime int
  108. runMigrations bool
  109. listenAddr string
  110. certFile string
  111. certDomain string
  112. certKeyFile string
  113. cleanupFrequencyHours int
  114. cleanupArchiveReadDays int
  115. cleanupArchiveUnreadDays int
  116. cleanupArchiveBatchSize int
  117. cleanupRemoveSessionsDays int
  118. pollingFrequency int
  119. forceRefreshInterval int
  120. batchSize int
  121. pollingScheduler string
  122. schedulerEntryFrequencyMinInterval int
  123. schedulerEntryFrequencyMaxInterval int
  124. schedulerEntryFrequencyFactor int
  125. schedulerRoundRobinMinInterval int
  126. pollingParsingErrorLimit int
  127. workerPoolSize int
  128. createAdmin bool
  129. adminUsername string
  130. adminPassword string
  131. proxyHTTPClientTimeout int
  132. proxyOption string
  133. proxyMediaTypes []string
  134. proxyUrl string
  135. fetchOdyseeWatchTime bool
  136. fetchYouTubeWatchTime bool
  137. youTubeEmbedUrlOverride string
  138. oauth2UserCreationAllowed bool
  139. oauth2ClientID string
  140. oauth2ClientSecret string
  141. oauth2RedirectURL string
  142. oidcDiscoveryEndpoint string
  143. oauth2Provider string
  144. pocketConsumerKey string
  145. httpClientTimeout int
  146. httpClientMaxBodySize int64
  147. httpClientProxy string
  148. httpClientUserAgent string
  149. httpServerTimeout int
  150. authProxyHeader string
  151. authProxyUserCreation bool
  152. maintenanceMode bool
  153. maintenanceMessage string
  154. metricsCollector bool
  155. metricsRefreshInterval int
  156. metricsAllowedNetworks []string
  157. metricsUsername string
  158. metricsPassword string
  159. watchdog bool
  160. invidiousInstance string
  161. proxyPrivateKey []byte
  162. webAuthn bool
  163. }
  164. // NewOptions returns Options with default values.
  165. func NewOptions() *Options {
  166. randomKey := make([]byte, 16)
  167. rand.Read(randomKey)
  168. return &Options{
  169. HTTPS: defaultHTTPS,
  170. logFile: defaultLogFile,
  171. logDateTime: defaultLogDateTime,
  172. logFormat: defaultLogFormat,
  173. logLevel: defaultLogLevel,
  174. hsts: defaultHSTS,
  175. httpService: defaultHTTPService,
  176. schedulerService: defaultSchedulerService,
  177. serverTimingHeader: defaultTiming,
  178. baseURL: defaultBaseURL,
  179. rootURL: defaultRootURL,
  180. basePath: defaultBasePath,
  181. databaseURL: defaultDatabaseURL,
  182. databaseMaxConns: defaultDatabaseMaxConns,
  183. databaseMinConns: defaultDatabaseMinConns,
  184. databaseConnectionLifetime: defaultDatabaseConnectionLifetime,
  185. runMigrations: defaultRunMigrations,
  186. listenAddr: defaultListenAddr,
  187. certFile: defaultCertFile,
  188. certDomain: defaultCertDomain,
  189. certKeyFile: defaultKeyFile,
  190. cleanupFrequencyHours: defaultCleanupFrequencyHours,
  191. cleanupArchiveReadDays: defaultCleanupArchiveReadDays,
  192. cleanupArchiveUnreadDays: defaultCleanupArchiveUnreadDays,
  193. cleanupArchiveBatchSize: defaultCleanupArchiveBatchSize,
  194. cleanupRemoveSessionsDays: defaultCleanupRemoveSessionsDays,
  195. pollingFrequency: defaultPollingFrequency,
  196. forceRefreshInterval: defaultForceRefreshInterval,
  197. batchSize: defaultBatchSize,
  198. pollingScheduler: defaultPollingScheduler,
  199. schedulerEntryFrequencyMinInterval: defaultSchedulerEntryFrequencyMinInterval,
  200. schedulerEntryFrequencyMaxInterval: defaultSchedulerEntryFrequencyMaxInterval,
  201. schedulerEntryFrequencyFactor: defaultSchedulerEntryFrequencyFactor,
  202. schedulerRoundRobinMinInterval: defaultSchedulerRoundRobinMinInterval,
  203. pollingParsingErrorLimit: defaultPollingParsingErrorLimit,
  204. workerPoolSize: defaultWorkerPoolSize,
  205. createAdmin: defaultCreateAdmin,
  206. proxyHTTPClientTimeout: defaultProxyHTTPClientTimeout,
  207. proxyOption: defaultProxyOption,
  208. proxyMediaTypes: []string{defaultProxyMediaTypes},
  209. proxyUrl: defaultProxyUrl,
  210. fetchOdyseeWatchTime: defaultFetchOdyseeWatchTime,
  211. fetchYouTubeWatchTime: defaultFetchYouTubeWatchTime,
  212. youTubeEmbedUrlOverride: defaultYouTubeEmbedUrlOverride,
  213. oauth2UserCreationAllowed: defaultOAuth2UserCreation,
  214. oauth2ClientID: defaultOAuth2ClientID,
  215. oauth2ClientSecret: defaultOAuth2ClientSecret,
  216. oauth2RedirectURL: defaultOAuth2RedirectURL,
  217. oidcDiscoveryEndpoint: defaultOAuth2OidcDiscoveryEndpoint,
  218. oauth2Provider: defaultOAuth2Provider,
  219. pocketConsumerKey: defaultPocketConsumerKey,
  220. httpClientTimeout: defaultHTTPClientTimeout,
  221. httpClientMaxBodySize: defaultHTTPClientMaxBodySize * 1024 * 1024,
  222. httpClientProxy: defaultHTTPClientProxy,
  223. httpClientUserAgent: defaultHTTPClientUserAgent,
  224. httpServerTimeout: defaultHTTPServerTimeout,
  225. authProxyHeader: defaultAuthProxyHeader,
  226. authProxyUserCreation: defaultAuthProxyUserCreation,
  227. maintenanceMode: defaultMaintenanceMode,
  228. maintenanceMessage: defaultMaintenanceMessage,
  229. metricsCollector: defaultMetricsCollector,
  230. metricsRefreshInterval: defaultMetricsRefreshInterval,
  231. metricsAllowedNetworks: []string{defaultMetricsAllowedNetworks},
  232. metricsUsername: defaultMetricsUsername,
  233. metricsPassword: defaultMetricsPassword,
  234. watchdog: defaultWatchdog,
  235. invidiousInstance: defaultInvidiousInstance,
  236. proxyPrivateKey: randomKey,
  237. webAuthn: defaultWebAuthn,
  238. }
  239. }
  240. func (o *Options) LogFile() string {
  241. return o.logFile
  242. }
  243. // LogDateTime returns true if the date/time should be displayed in log messages.
  244. func (o *Options) LogDateTime() bool {
  245. return o.logDateTime
  246. }
  247. // LogFormat returns the log format.
  248. func (o *Options) LogFormat() string {
  249. return o.logFormat
  250. }
  251. // LogLevel returns the log level.
  252. func (o *Options) LogLevel() string {
  253. return o.logLevel
  254. }
  255. // SetLogLevel sets the log level.
  256. func (o *Options) SetLogLevel(level string) {
  257. o.logLevel = level
  258. }
  259. // HasMaintenanceMode returns true if maintenance mode is enabled.
  260. func (o *Options) HasMaintenanceMode() bool {
  261. return o.maintenanceMode
  262. }
  263. // MaintenanceMessage returns maintenance message.
  264. func (o *Options) MaintenanceMessage() string {
  265. return o.maintenanceMessage
  266. }
  267. // HasServerTimingHeader returns true if server-timing headers enabled.
  268. func (o *Options) HasServerTimingHeader() bool {
  269. return o.serverTimingHeader
  270. }
  271. // BaseURL returns the application base URL with path.
  272. func (o *Options) BaseURL() string {
  273. return o.baseURL
  274. }
  275. // RootURL returns the base URL without path.
  276. func (o *Options) RootURL() string {
  277. return o.rootURL
  278. }
  279. // BasePath returns the application base path according to the base URL.
  280. func (o *Options) BasePath() string {
  281. return o.basePath
  282. }
  283. // IsDefaultDatabaseURL returns true if the default database URL is used.
  284. func (o *Options) IsDefaultDatabaseURL() bool {
  285. return o.databaseURL == defaultDatabaseURL
  286. }
  287. // DatabaseURL returns the database URL.
  288. func (o *Options) DatabaseURL() string {
  289. return o.databaseURL
  290. }
  291. // DatabaseMaxConns returns the maximum number of database connections.
  292. func (o *Options) DatabaseMaxConns() int {
  293. return o.databaseMaxConns
  294. }
  295. // DatabaseMinConns returns the minimum number of database connections.
  296. func (o *Options) DatabaseMinConns() int {
  297. return o.databaseMinConns
  298. }
  299. // DatabaseConnectionLifetime returns the maximum amount of time a connection may be reused.
  300. func (o *Options) DatabaseConnectionLifetime() time.Duration {
  301. return time.Duration(o.databaseConnectionLifetime) * time.Minute
  302. }
  303. // ListenAddr returns the listen address for the HTTP server.
  304. func (o *Options) ListenAddr() string {
  305. return o.listenAddr
  306. }
  307. // CertFile returns the SSL certificate filename if any.
  308. func (o *Options) CertFile() string {
  309. return o.certFile
  310. }
  311. // CertKeyFile returns the private key filename for custom SSL certificate.
  312. func (o *Options) CertKeyFile() string {
  313. return o.certKeyFile
  314. }
  315. // CertDomain returns the domain to use for Let's Encrypt certificate.
  316. func (o *Options) CertDomain() string {
  317. return o.certDomain
  318. }
  319. // CleanupFrequencyHours returns the interval in hours for cleanup jobs.
  320. func (o *Options) CleanupFrequencyHours() int {
  321. return o.cleanupFrequencyHours
  322. }
  323. // CleanupArchiveReadDays returns the number of days after which marking read items as removed.
  324. func (o *Options) CleanupArchiveReadDays() int {
  325. return o.cleanupArchiveReadDays
  326. }
  327. // CleanupArchiveUnreadDays returns the number of days after which marking unread items as removed.
  328. func (o *Options) CleanupArchiveUnreadDays() int {
  329. return o.cleanupArchiveUnreadDays
  330. }
  331. // CleanupArchiveBatchSize returns the number of entries to archive for each interval.
  332. func (o *Options) CleanupArchiveBatchSize() int {
  333. return o.cleanupArchiveBatchSize
  334. }
  335. // CleanupRemoveSessionsDays returns the number of days after which to remove sessions.
  336. func (o *Options) CleanupRemoveSessionsDays() int {
  337. return o.cleanupRemoveSessionsDays
  338. }
  339. // WorkerPoolSize returns the number of background worker.
  340. func (o *Options) WorkerPoolSize() int {
  341. return o.workerPoolSize
  342. }
  343. // PollingFrequency returns the interval to refresh feeds in the background.
  344. func (o *Options) PollingFrequency() int {
  345. return o.pollingFrequency
  346. }
  347. // ForceRefreshInterval returns the force refresh interval
  348. func (o *Options) ForceRefreshInterval() int {
  349. return o.forceRefreshInterval
  350. }
  351. // BatchSize returns the number of feeds to send for background processing.
  352. func (o *Options) BatchSize() int {
  353. return o.batchSize
  354. }
  355. // PollingScheduler returns the scheduler used for polling feeds.
  356. func (o *Options) PollingScheduler() string {
  357. return o.pollingScheduler
  358. }
  359. // SchedulerEntryFrequencyMaxInterval returns the maximum interval in minutes for the entry frequency scheduler.
  360. func (o *Options) SchedulerEntryFrequencyMaxInterval() int {
  361. return o.schedulerEntryFrequencyMaxInterval
  362. }
  363. // SchedulerEntryFrequencyMinInterval returns the minimum interval in minutes for the entry frequency scheduler.
  364. func (o *Options) SchedulerEntryFrequencyMinInterval() int {
  365. return o.schedulerEntryFrequencyMinInterval
  366. }
  367. // SchedulerEntryFrequencyFactor returns the factor for the entry frequency scheduler.
  368. func (o *Options) SchedulerEntryFrequencyFactor() int {
  369. return o.schedulerEntryFrequencyFactor
  370. }
  371. func (o *Options) SchedulerRoundRobinMinInterval() int {
  372. return o.schedulerRoundRobinMinInterval
  373. }
  374. // PollingParsingErrorLimit returns the limit of errors when to stop polling.
  375. func (o *Options) PollingParsingErrorLimit() int {
  376. return o.pollingParsingErrorLimit
  377. }
  378. // IsOAuth2UserCreationAllowed returns true if user creation is allowed for OAuth2 users.
  379. func (o *Options) IsOAuth2UserCreationAllowed() bool {
  380. return o.oauth2UserCreationAllowed
  381. }
  382. // OAuth2ClientID returns the OAuth2 Client ID.
  383. func (o *Options) OAuth2ClientID() string {
  384. return o.oauth2ClientID
  385. }
  386. // OAuth2ClientSecret returns the OAuth2 client secret.
  387. func (o *Options) OAuth2ClientSecret() string {
  388. return o.oauth2ClientSecret
  389. }
  390. // OAuth2RedirectURL returns the OAuth2 redirect URL.
  391. func (o *Options) OAuth2RedirectURL() string {
  392. return o.oauth2RedirectURL
  393. }
  394. // OIDCDiscoveryEndpoint returns the OAuth2 OIDC discovery endpoint.
  395. func (o *Options) OIDCDiscoveryEndpoint() string {
  396. return o.oidcDiscoveryEndpoint
  397. }
  398. // OAuth2Provider returns the name of the OAuth2 provider configured.
  399. func (o *Options) OAuth2Provider() string {
  400. return o.oauth2Provider
  401. }
  402. // HasHSTS returns true if HTTP Strict Transport Security is enabled.
  403. func (o *Options) HasHSTS() bool {
  404. return o.hsts
  405. }
  406. // RunMigrations returns true if the environment variable RUN_MIGRATIONS is not empty.
  407. func (o *Options) RunMigrations() bool {
  408. return o.runMigrations
  409. }
  410. // CreateAdmin returns true if the environment variable CREATE_ADMIN is not empty.
  411. func (o *Options) CreateAdmin() bool {
  412. return o.createAdmin
  413. }
  414. // AdminUsername returns the admin username if defined.
  415. func (o *Options) AdminUsername() string {
  416. return o.adminUsername
  417. }
  418. // AdminPassword returns the admin password if defined.
  419. func (o *Options) AdminPassword() string {
  420. return o.adminPassword
  421. }
  422. // FetchYouTubeWatchTime returns true if the YouTube video duration
  423. // should be fetched and used as a reading time.
  424. func (o *Options) FetchYouTubeWatchTime() bool {
  425. return o.fetchYouTubeWatchTime
  426. }
  427. // YouTubeEmbedUrlOverride returns YouTube URL which will be used for embeds
  428. func (o *Options) YouTubeEmbedUrlOverride() string {
  429. return o.youTubeEmbedUrlOverride
  430. }
  431. // FetchOdyseeWatchTime returns true if the Odysee video duration
  432. // should be fetched and used as a reading time.
  433. func (o *Options) FetchOdyseeWatchTime() bool {
  434. return o.fetchOdyseeWatchTime
  435. }
  436. // ProxyOption returns "none" to never proxy, "http-only" to proxy non-HTTPS, "all" to always proxy.
  437. func (o *Options) ProxyOption() string {
  438. return o.proxyOption
  439. }
  440. // ProxyMediaTypes returns a slice of media types to proxy.
  441. func (o *Options) ProxyMediaTypes() []string {
  442. return o.proxyMediaTypes
  443. }
  444. // ProxyUrl returns a string of a URL to use to proxy image requests
  445. func (o *Options) ProxyUrl() string {
  446. return o.proxyUrl
  447. }
  448. // ProxyHTTPClientTimeout returns the time limit in seconds before the proxy HTTP client cancel the request.
  449. func (o *Options) ProxyHTTPClientTimeout() int {
  450. return o.proxyHTTPClientTimeout
  451. }
  452. // HasHTTPService returns true if the HTTP service is enabled.
  453. func (o *Options) HasHTTPService() bool {
  454. return o.httpService
  455. }
  456. // HasSchedulerService returns true if the scheduler service is enabled.
  457. func (o *Options) HasSchedulerService() bool {
  458. return o.schedulerService
  459. }
  460. // PocketConsumerKey returns the Pocket Consumer Key if configured.
  461. func (o *Options) PocketConsumerKey(defaultValue string) string {
  462. if o.pocketConsumerKey != "" {
  463. return o.pocketConsumerKey
  464. }
  465. return defaultValue
  466. }
  467. // HTTPClientTimeout returns the time limit in seconds before the HTTP client cancel the request.
  468. func (o *Options) HTTPClientTimeout() int {
  469. return o.httpClientTimeout
  470. }
  471. // HTTPClientMaxBodySize returns the number of bytes allowed for the HTTP client to transfer.
  472. func (o *Options) HTTPClientMaxBodySize() int64 {
  473. return o.httpClientMaxBodySize
  474. }
  475. // HTTPClientProxy returns the proxy URL for HTTP client.
  476. func (o *Options) HTTPClientProxy() string {
  477. return o.httpClientProxy
  478. }
  479. // HTTPServerTimeout returns the time limit in seconds before the HTTP server cancel the request.
  480. func (o *Options) HTTPServerTimeout() int {
  481. return o.httpServerTimeout
  482. }
  483. // HasHTTPClientProxyConfigured returns true if the HTTP proxy is configured.
  484. func (o *Options) HasHTTPClientProxyConfigured() bool {
  485. return o.httpClientProxy != ""
  486. }
  487. // AuthProxyHeader returns an HTTP header name that contains username for
  488. // authentication using auth proxy.
  489. func (o *Options) AuthProxyHeader() string {
  490. return o.authProxyHeader
  491. }
  492. // IsAuthProxyUserCreationAllowed returns true if user creation is allowed for
  493. // users authenticated using auth proxy.
  494. func (o *Options) IsAuthProxyUserCreationAllowed() bool {
  495. return o.authProxyUserCreation
  496. }
  497. // HasMetricsCollector returns true if metrics collection is enabled.
  498. func (o *Options) HasMetricsCollector() bool {
  499. return o.metricsCollector
  500. }
  501. // MetricsRefreshInterval returns the refresh interval in seconds.
  502. func (o *Options) MetricsRefreshInterval() int {
  503. return o.metricsRefreshInterval
  504. }
  505. // MetricsAllowedNetworks returns the list of networks allowed to connect to the metrics endpoint.
  506. func (o *Options) MetricsAllowedNetworks() []string {
  507. return o.metricsAllowedNetworks
  508. }
  509. func (o *Options) MetricsUsername() string {
  510. return o.metricsUsername
  511. }
  512. func (o *Options) MetricsPassword() string {
  513. return o.metricsPassword
  514. }
  515. // HTTPClientUserAgent returns the global User-Agent header for miniflux.
  516. func (o *Options) HTTPClientUserAgent() string {
  517. return o.httpClientUserAgent
  518. }
  519. // HasWatchdog returns true if the systemd watchdog is enabled.
  520. func (o *Options) HasWatchdog() bool {
  521. return o.watchdog
  522. }
  523. // InvidiousInstance returns the invidious instance used by miniflux
  524. func (o *Options) InvidiousInstance() string {
  525. return o.invidiousInstance
  526. }
  527. // ProxyPrivateKey returns the private key used by the media proxy
  528. func (o *Options) ProxyPrivateKey() []byte {
  529. return o.proxyPrivateKey
  530. }
  531. // WebAuthn returns true if WebAuthn logins are supported
  532. func (o *Options) WebAuthn() bool {
  533. return o.webAuthn
  534. }
  535. // SortedOptions returns options as a list of key value pairs, sorted by keys.
  536. func (o *Options) SortedOptions(redactSecret bool) []*Option {
  537. var keyValues = map[string]interface{}{
  538. "ADMIN_PASSWORD": redactSecretValue(o.adminPassword, redactSecret),
  539. "ADMIN_USERNAME": o.adminUsername,
  540. "AUTH_PROXY_HEADER": o.authProxyHeader,
  541. "AUTH_PROXY_USER_CREATION": o.authProxyUserCreation,
  542. "BASE_PATH": o.basePath,
  543. "BASE_URL": o.baseURL,
  544. "BATCH_SIZE": o.batchSize,
  545. "CERT_DOMAIN": o.certDomain,
  546. "CERT_FILE": o.certFile,
  547. "CLEANUP_ARCHIVE_BATCH_SIZE": o.cleanupArchiveBatchSize,
  548. "CLEANUP_ARCHIVE_READ_DAYS": o.cleanupArchiveReadDays,
  549. "CLEANUP_ARCHIVE_UNREAD_DAYS": o.cleanupArchiveUnreadDays,
  550. "CLEANUP_FREQUENCY_HOURS": o.cleanupFrequencyHours,
  551. "CLEANUP_REMOVE_SESSIONS_DAYS": o.cleanupRemoveSessionsDays,
  552. "CREATE_ADMIN": o.createAdmin,
  553. "DATABASE_CONNECTION_LIFETIME": o.databaseConnectionLifetime,
  554. "DATABASE_MAX_CONNS": o.databaseMaxConns,
  555. "DATABASE_MIN_CONNS": o.databaseMinConns,
  556. "DATABASE_URL": redactSecretValue(o.databaseURL, redactSecret),
  557. "DISABLE_HSTS": !o.hsts,
  558. "DISABLE_HTTP_SERVICE": !o.httpService,
  559. "DISABLE_SCHEDULER_SERVICE": !o.schedulerService,
  560. "FETCH_YOUTUBE_WATCH_TIME": o.fetchYouTubeWatchTime,
  561. "FETCH_ODYSEE_WATCH_TIME": o.fetchOdyseeWatchTime,
  562. "HTTPS": o.HTTPS,
  563. "HTTP_CLIENT_MAX_BODY_SIZE": o.httpClientMaxBodySize,
  564. "HTTP_CLIENT_PROXY": o.httpClientProxy,
  565. "HTTP_CLIENT_TIMEOUT": o.httpClientTimeout,
  566. "HTTP_CLIENT_USER_AGENT": o.httpClientUserAgent,
  567. "HTTP_SERVER_TIMEOUT": o.httpServerTimeout,
  568. "HTTP_SERVICE": o.httpService,
  569. "INVIDIOUS_INSTANCE": o.invidiousInstance,
  570. "KEY_FILE": o.certKeyFile,
  571. "LISTEN_ADDR": o.listenAddr,
  572. "LOG_FILE": o.logFile,
  573. "LOG_DATE_TIME": o.logDateTime,
  574. "LOG_FORMAT": o.logFormat,
  575. "LOG_LEVEL": o.logLevel,
  576. "MAINTENANCE_MESSAGE": o.maintenanceMessage,
  577. "MAINTENANCE_MODE": o.maintenanceMode,
  578. "METRICS_ALLOWED_NETWORKS": strings.Join(o.metricsAllowedNetworks, ","),
  579. "METRICS_COLLECTOR": o.metricsCollector,
  580. "METRICS_PASSWORD": redactSecretValue(o.metricsPassword, redactSecret),
  581. "METRICS_REFRESH_INTERVAL": o.metricsRefreshInterval,
  582. "METRICS_USERNAME": o.metricsUsername,
  583. "OAUTH2_CLIENT_ID": o.oauth2ClientID,
  584. "OAUTH2_CLIENT_SECRET": redactSecretValue(o.oauth2ClientSecret, redactSecret),
  585. "OAUTH2_OIDC_DISCOVERY_ENDPOINT": o.oidcDiscoveryEndpoint,
  586. "OAUTH2_PROVIDER": o.oauth2Provider,
  587. "OAUTH2_REDIRECT_URL": o.oauth2RedirectURL,
  588. "OAUTH2_USER_CREATION": o.oauth2UserCreationAllowed,
  589. "POCKET_CONSUMER_KEY": redactSecretValue(o.pocketConsumerKey, redactSecret),
  590. "POLLING_FREQUENCY": o.pollingFrequency,
  591. "FORCE_REFRESH_INTERVAL": o.forceRefreshInterval,
  592. "POLLING_PARSING_ERROR_LIMIT": o.pollingParsingErrorLimit,
  593. "POLLING_SCHEDULER": o.pollingScheduler,
  594. "PROXY_HTTP_CLIENT_TIMEOUT": o.proxyHTTPClientTimeout,
  595. "PROXY_MEDIA_TYPES": o.proxyMediaTypes,
  596. "PROXY_OPTION": o.proxyOption,
  597. "PROXY_PRIVATE_KEY": redactSecretValue(string(o.proxyPrivateKey), redactSecret),
  598. "PROXY_URL": o.proxyUrl,
  599. "ROOT_URL": o.rootURL,
  600. "RUN_MIGRATIONS": o.runMigrations,
  601. "SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL": o.schedulerEntryFrequencyMaxInterval,
  602. "SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL": o.schedulerEntryFrequencyMinInterval,
  603. "SCHEDULER_ENTRY_FREQUENCY_FACTOR": o.schedulerEntryFrequencyFactor,
  604. "SCHEDULER_ROUND_ROBIN_MIN_INTERVAL": o.schedulerRoundRobinMinInterval,
  605. "SCHEDULER_SERVICE": o.schedulerService,
  606. "SERVER_TIMING_HEADER": o.serverTimingHeader,
  607. "WATCHDOG": o.watchdog,
  608. "WORKER_POOL_SIZE": o.workerPoolSize,
  609. "YOUTUBE_EMBED_URL_OVERRIDE": o.youTubeEmbedUrlOverride,
  610. "WEBAUTHN": o.webAuthn,
  611. }
  612. keys := make([]string, 0, len(keyValues))
  613. for key := range keyValues {
  614. keys = append(keys, key)
  615. }
  616. sort.Strings(keys)
  617. var sortedOptions []*Option
  618. for _, key := range keys {
  619. sortedOptions = append(sortedOptions, &Option{Key: key, Value: keyValues[key]})
  620. }
  621. return sortedOptions
  622. }
  623. func (o *Options) String() string {
  624. var builder strings.Builder
  625. for _, option := range o.SortedOptions(false) {
  626. fmt.Fprintf(&builder, "%s=%v\n", option.Key, option.Value)
  627. }
  628. return builder.String()
  629. }
  630. func redactSecretValue(value string, redactSecret bool) string {
  631. if redactSecret && value != "" {
  632. return "<secret>"
  633. }
  634. return value
  635. }