options.go 31 KB

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