options.go 27 KB

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