options.go 24 KB

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