options.go 25 KB

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