config.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. package config
  2. import (
  3. "errors"
  4. "flag"
  5. "fmt"
  6. "math"
  7. "os"
  8. "regexp"
  9. "runtime"
  10. "strings"
  11. log "github.com/sirupsen/logrus"
  12. "github.com/imgproxy/imgproxy/v3/config/configurators"
  13. "github.com/imgproxy/imgproxy/v3/imagetype"
  14. "github.com/imgproxy/imgproxy/v3/version"
  15. )
  16. type URLReplacement = configurators.URLReplacement
  17. var (
  18. Network string
  19. Bind string
  20. Timeout int
  21. ReadRequestTimeout int
  22. WriteResponseTimeout int
  23. KeepAliveTimeout int
  24. ClientKeepAliveTimeout int
  25. DownloadTimeout int
  26. Workers int
  27. RequestsQueueSize int
  28. MaxClients int
  29. TTL int
  30. CacheControlPassthrough bool
  31. SetCanonicalHeader bool
  32. SoReuseport bool
  33. PathPrefix string
  34. MaxSrcResolution int
  35. MaxSrcFileSize int
  36. MaxAnimationFrames int
  37. MaxAnimationFrameResolution int
  38. MaxSvgCheckBytes int
  39. MaxRedirects int
  40. PngUnlimited bool
  41. SvgUnlimited bool
  42. MaxResultDimension int
  43. AllowedProcessiongOptions []string
  44. AllowSecurityOptions bool
  45. JpegProgressive bool
  46. PngInterlaced bool
  47. PngQuantize bool
  48. PngQuantizationColors int
  49. AvifSpeed int
  50. JxlEffort int
  51. WebpEffort int
  52. WebpPreset WebpPresetKind
  53. Quality int
  54. FormatQuality map[imagetype.Type]int
  55. StripMetadata bool
  56. KeepCopyright bool
  57. StripColorProfile bool
  58. AutoRotate bool
  59. EnforceThumbnail bool
  60. ReturnAttachment bool
  61. AutoWebp bool
  62. EnforceWebp bool
  63. AutoAvif bool
  64. EnforceAvif bool
  65. AutoJxl bool
  66. EnforceJxl bool
  67. EnableClientHints bool
  68. PreferredFormats []imagetype.Type
  69. SkipProcessingFormats []imagetype.Type
  70. UseLinearColorspace bool
  71. DisableShrinkOnLoad bool
  72. Keys [][]byte
  73. Salts [][]byte
  74. SignatureSize int
  75. TrustedSignatures []string
  76. Secret string
  77. AllowOrigin string
  78. UserAgent string
  79. IgnoreSslVerification bool
  80. DevelopmentErrorsMode bool
  81. AllowedSources []*regexp.Regexp
  82. AllowLoopbackSourceAddresses bool
  83. AllowLinkLocalSourceAddresses bool
  84. AllowPrivateSourceAddresses bool
  85. SanitizeSvg bool
  86. AlwaysRasterizeSvg bool
  87. CookiePassthrough bool
  88. CookieBaseURL string
  89. CookiePassthroughAll bool
  90. SourceURLQuerySeparator string
  91. LocalFileSystemRoot string
  92. S3Enabled bool
  93. S3Region string
  94. S3Endpoint string
  95. S3EndpointUsePathStyle bool
  96. S3AssumeRoleArn string
  97. S3AssumeRoleExternalID string
  98. S3DecryptionClientEnabled bool
  99. GCSEnabled bool
  100. GCSKey string
  101. GCSEndpoint string
  102. ABSEnabled bool
  103. ABSName string
  104. ABSKey string
  105. ABSEndpoint string
  106. SwiftEnabled bool
  107. SwiftUsername string
  108. SwiftAPIKey string
  109. SwiftAuthURL string
  110. SwiftDomain string
  111. SwiftTenant string
  112. SwiftAuthVersion int
  113. SwiftConnectTimeoutSeconds int
  114. SwiftTimeoutSeconds int
  115. ETagEnabled bool
  116. ETagBuster string
  117. LastModifiedEnabled bool
  118. BaseURL string
  119. URLReplacements []URLReplacement
  120. Base64URLIncludesFilename bool
  121. Presets []string
  122. OnlyPresets bool
  123. WatermarkData string
  124. WatermarkPath string
  125. WatermarkURL string
  126. WatermarkOpacity float64
  127. FallbackImageData string
  128. FallbackImagePath string
  129. FallbackImageURL string
  130. FallbackImageHTTPCode int
  131. FallbackImageTTL int
  132. DataDogEnable bool
  133. DataDogEnableMetrics bool
  134. NewRelicAppName string
  135. NewRelicKey string
  136. NewRelicLabels map[string]string
  137. PrometheusBind string
  138. PrometheusNamespace string
  139. OpenTelemetryEnable bool
  140. OpenTelemetryEnableMetrics bool
  141. OpenTelemetryServerCert string
  142. OpenTelemetryClientCert string
  143. OpenTelemetryClientKey string
  144. OpenTelemetryTraceIDGenerator string
  145. CloudWatchServiceName string
  146. CloudWatchNamespace string
  147. CloudWatchRegion string
  148. BugsnagKey string
  149. BugsnagStage string
  150. HoneybadgerKey string
  151. HoneybadgerEnv string
  152. SentryDSN string
  153. SentryEnvironment string
  154. SentryRelease string
  155. AirbrakeProjectID int
  156. AirbrakeProjectKey string
  157. AirbrakeEnv string
  158. ReportDownloadingErrors bool
  159. ReportIOErrors bool
  160. EnableDebugHeaders bool
  161. FreeMemoryInterval int
  162. DownloadBufferSize int
  163. BufferPoolCalibrationThreshold int
  164. HealthCheckPath string
  165. ArgumentsSeparator string
  166. )
  167. var (
  168. keyPath string
  169. saltPath string
  170. presetsPath string
  171. )
  172. func init() {
  173. Reset()
  174. flag.StringVar(&keyPath, "keypath", "", "path of the file with hex-encoded key")
  175. flag.StringVar(&saltPath, "saltpath", "", "path of the file with hex-encoded salt")
  176. flag.StringVar(&presetsPath, "presets", "", "path of the file with presets")
  177. }
  178. func Reset() {
  179. Network = "tcp"
  180. Bind = ":8080"
  181. Timeout = 10
  182. ReadRequestTimeout = 10
  183. WriteResponseTimeout = 10
  184. KeepAliveTimeout = 10
  185. ClientKeepAliveTimeout = 90
  186. DownloadTimeout = 5
  187. Workers = runtime.GOMAXPROCS(0) * 2
  188. RequestsQueueSize = 0
  189. MaxClients = 2048
  190. TTL = 31536000
  191. CacheControlPassthrough = false
  192. SetCanonicalHeader = false
  193. SoReuseport = false
  194. PathPrefix = ""
  195. MaxSrcResolution = 50000000
  196. MaxSrcFileSize = 0
  197. MaxAnimationFrames = 1
  198. MaxAnimationFrameResolution = 0
  199. MaxSvgCheckBytes = 32 * 1024
  200. MaxRedirects = 10
  201. PngUnlimited = false
  202. SvgUnlimited = false
  203. MaxResultDimension = 0
  204. AllowedProcessiongOptions = make([]string, 0)
  205. AllowSecurityOptions = false
  206. JpegProgressive = false
  207. PngInterlaced = false
  208. PngQuantize = false
  209. PngQuantizationColors = 256
  210. AvifSpeed = 8
  211. JxlEffort = 4
  212. WebpEffort = 4
  213. WebpPreset = WebpPresetDefault
  214. Quality = 80
  215. FormatQuality = map[imagetype.Type]int{
  216. imagetype.WEBP: 79,
  217. imagetype.AVIF: 63,
  218. imagetype.JXL: 77,
  219. }
  220. StripMetadata = true
  221. KeepCopyright = true
  222. StripColorProfile = true
  223. AutoRotate = true
  224. EnforceThumbnail = false
  225. ReturnAttachment = false
  226. AutoWebp = false
  227. EnforceWebp = false
  228. AutoAvif = false
  229. EnforceAvif = false
  230. AutoJxl = false
  231. EnforceJxl = false
  232. EnableClientHints = false
  233. PreferredFormats = []imagetype.Type{
  234. imagetype.JPEG,
  235. imagetype.PNG,
  236. imagetype.GIF,
  237. }
  238. SkipProcessingFormats = make([]imagetype.Type, 0)
  239. UseLinearColorspace = false
  240. DisableShrinkOnLoad = false
  241. Keys = make([][]byte, 0)
  242. Salts = make([][]byte, 0)
  243. SignatureSize = 32
  244. TrustedSignatures = make([]string, 0)
  245. Secret = ""
  246. AllowOrigin = ""
  247. UserAgent = "imgproxy/%current_version"
  248. IgnoreSslVerification = false
  249. DevelopmentErrorsMode = false
  250. AllowedSources = make([]*regexp.Regexp, 0)
  251. AllowLoopbackSourceAddresses = false
  252. AllowLinkLocalSourceAddresses = false
  253. AllowPrivateSourceAddresses = true
  254. SanitizeSvg = true
  255. AlwaysRasterizeSvg = false
  256. CookiePassthrough = false
  257. CookieBaseURL = ""
  258. CookiePassthroughAll = false
  259. SourceURLQuerySeparator = "?"
  260. LocalFileSystemRoot = ""
  261. S3Enabled = false
  262. S3Region = ""
  263. S3Endpoint = ""
  264. S3EndpointUsePathStyle = true
  265. S3AssumeRoleArn = ""
  266. S3AssumeRoleExternalID = ""
  267. S3DecryptionClientEnabled = false
  268. GCSEnabled = false
  269. GCSKey = ""
  270. ABSEnabled = false
  271. ABSName = ""
  272. ABSKey = ""
  273. ABSEndpoint = ""
  274. SwiftEnabled = false
  275. SwiftUsername = ""
  276. SwiftAPIKey = ""
  277. SwiftAuthURL = ""
  278. SwiftAuthVersion = 0
  279. SwiftTenant = ""
  280. SwiftDomain = ""
  281. SwiftConnectTimeoutSeconds = 10
  282. SwiftTimeoutSeconds = 60
  283. ETagEnabled = false
  284. ETagBuster = ""
  285. LastModifiedEnabled = false
  286. BaseURL = ""
  287. URLReplacements = make([]URLReplacement, 0)
  288. Base64URLIncludesFilename = false
  289. Presets = make([]string, 0)
  290. OnlyPresets = false
  291. WatermarkData = ""
  292. WatermarkPath = ""
  293. WatermarkURL = ""
  294. WatermarkOpacity = 1
  295. FallbackImageData = ""
  296. FallbackImagePath = ""
  297. FallbackImageURL = ""
  298. FallbackImageHTTPCode = 200
  299. FallbackImageTTL = 0
  300. DataDogEnable = false
  301. NewRelicAppName = ""
  302. NewRelicKey = ""
  303. NewRelicLabels = make(map[string]string)
  304. PrometheusBind = ""
  305. PrometheusNamespace = ""
  306. OpenTelemetryEnable = false
  307. OpenTelemetryEnableMetrics = false
  308. OpenTelemetryServerCert = ""
  309. OpenTelemetryClientCert = ""
  310. OpenTelemetryClientKey = ""
  311. OpenTelemetryTraceIDGenerator = "xray"
  312. CloudWatchServiceName = ""
  313. CloudWatchNamespace = "imgproxy"
  314. CloudWatchRegion = ""
  315. BugsnagKey = ""
  316. BugsnagStage = "production"
  317. HoneybadgerKey = ""
  318. HoneybadgerEnv = "production"
  319. SentryDSN = ""
  320. SentryEnvironment = "production"
  321. SentryRelease = fmt.Sprintf("imgproxy@%s", version.Version)
  322. AirbrakeProjectID = 0
  323. AirbrakeProjectKey = ""
  324. AirbrakeEnv = "production"
  325. ReportDownloadingErrors = true
  326. ReportIOErrors = false
  327. EnableDebugHeaders = false
  328. FreeMemoryInterval = 10
  329. DownloadBufferSize = 0
  330. BufferPoolCalibrationThreshold = 1024
  331. HealthCheckPath = ""
  332. ArgumentsSeparator = ":"
  333. }
  334. func Configure() error {
  335. Reset()
  336. if port := os.Getenv("PORT"); len(port) > 0 {
  337. Bind = fmt.Sprintf(":%s", port)
  338. }
  339. configurators.String(&Network, "IMGPROXY_NETWORK")
  340. configurators.String(&Bind, "IMGPROXY_BIND")
  341. if _, ok := os.LookupEnv("IMGPROXY_WRITE_TIMEOUT"); ok {
  342. log.Warning("IMGPROXY_WRITE_TIMEOUT is deprecated, use IMGPROXY_TIMEOUT instead")
  343. configurators.Int(&Timeout, "IMGPROXY_WRITE_TIMEOUT")
  344. }
  345. configurators.Int(&Timeout, "IMGPROXY_TIMEOUT")
  346. if _, ok := os.LookupEnv("IMGPROXY_READ_TIMEOUT"); ok {
  347. log.Warning("IMGPROXY_READ_TIMEOUT is deprecated, use IMGPROXY_READ_REQUEST_TIMEOUT instead")
  348. configurators.Int(&ReadRequestTimeout, "IMGPROXY_READ_TIMEOUT")
  349. }
  350. configurators.Int(&ReadRequestTimeout, "IMGPROXY_READ_REQUEST_TIMEOUT")
  351. configurators.Int(&WriteResponseTimeout, "IMGPROXY_WRITE_RESPONSE_TIMEOUT")
  352. configurators.Int(&KeepAliveTimeout, "IMGPROXY_KEEP_ALIVE_TIMEOUT")
  353. configurators.Int(&ClientKeepAliveTimeout, "IMGPROXY_CLIENT_KEEP_ALIVE_TIMEOUT")
  354. configurators.Int(&DownloadTimeout, "IMGPROXY_DOWNLOAD_TIMEOUT")
  355. if lambdaFn := os.Getenv("AWS_LAMBDA_FUNCTION_NAME"); len(lambdaFn) > 0 {
  356. Workers = 1
  357. log.Info("AWS Lambda environment detected, setting workers to 1")
  358. } else {
  359. configurators.Int(&Workers, "IMGPROXY_CONCURRENCY")
  360. configurators.Int(&Workers, "IMGPROXY_WORKERS")
  361. }
  362. configurators.Int(&RequestsQueueSize, "IMGPROXY_REQUESTS_QUEUE_SIZE")
  363. configurators.Int(&MaxClients, "IMGPROXY_MAX_CLIENTS")
  364. configurators.Int(&TTL, "IMGPROXY_TTL")
  365. configurators.Bool(&CacheControlPassthrough, "IMGPROXY_CACHE_CONTROL_PASSTHROUGH")
  366. configurators.Bool(&SetCanonicalHeader, "IMGPROXY_SET_CANONICAL_HEADER")
  367. configurators.Bool(&SoReuseport, "IMGPROXY_SO_REUSEPORT")
  368. configurators.URLPath(&PathPrefix, "IMGPROXY_PATH_PREFIX")
  369. configurators.MegaInt(&MaxSrcResolution, "IMGPROXY_MAX_SRC_RESOLUTION")
  370. configurators.Int(&MaxSrcFileSize, "IMGPROXY_MAX_SRC_FILE_SIZE")
  371. configurators.Int(&MaxSvgCheckBytes, "IMGPROXY_MAX_SVG_CHECK_BYTES")
  372. configurators.Int(&MaxAnimationFrames, "IMGPROXY_MAX_ANIMATION_FRAMES")
  373. configurators.MegaInt(&MaxAnimationFrameResolution, "IMGPROXY_MAX_ANIMATION_FRAME_RESOLUTION")
  374. configurators.Int(&MaxRedirects, "IMGPROXY_MAX_REDIRECTS")
  375. configurators.Patterns(&AllowedSources, "IMGPROXY_ALLOWED_SOURCES")
  376. configurators.Bool(&AllowLoopbackSourceAddresses, "IMGPROXY_ALLOW_LOOPBACK_SOURCE_ADDRESSES")
  377. configurators.Bool(&AllowLinkLocalSourceAddresses, "IMGPROXY_ALLOW_LINK_LOCAL_SOURCE_ADDRESSES")
  378. configurators.Bool(&AllowPrivateSourceAddresses, "IMGPROXY_ALLOW_PRIVATE_SOURCE_ADDRESSES")
  379. configurators.Bool(&SanitizeSvg, "IMGPROXY_SANITIZE_SVG")
  380. configurators.Bool(&AlwaysRasterizeSvg, "IMGPROXY_ALWAYS_RASTERIZE_SVG")
  381. configurators.Bool(&PngUnlimited, "IMGPROXY_PNG_UNLIMITED")
  382. configurators.Bool(&SvgUnlimited, "IMGPROXY_SVG_UNLIMITED")
  383. configurators.Int(&MaxResultDimension, "IMGPROXY_MAX_RESULT_DIMENSION")
  384. configurators.StringSlice(&AllowedProcessiongOptions, "IMGPROXY_ALLOWED_PROCESSING_OPTIONS")
  385. configurators.Bool(&AllowSecurityOptions, "IMGPROXY_ALLOW_SECURITY_OPTIONS")
  386. configurators.Bool(&JpegProgressive, "IMGPROXY_JPEG_PROGRESSIVE")
  387. configurators.Bool(&PngInterlaced, "IMGPROXY_PNG_INTERLACED")
  388. configurators.Bool(&PngQuantize, "IMGPROXY_PNG_QUANTIZE")
  389. configurators.Int(&PngQuantizationColors, "IMGPROXY_PNG_QUANTIZATION_COLORS")
  390. configurators.Int(&AvifSpeed, "IMGPROXY_AVIF_SPEED")
  391. configurators.Int(&JxlEffort, "IMGPROXY_JXL_EFFORT")
  392. configurators.Int(&WebpEffort, "IMGPROXY_WEBP_EFFORT")
  393. if err := configurators.FromMap(&WebpPreset, "IMGPROXY_WEBP_PRESET", WebpPresets); err != nil {
  394. return err
  395. }
  396. configurators.Int(&Quality, "IMGPROXY_QUALITY")
  397. if err := configurators.ImageTypesQuality(FormatQuality, "IMGPROXY_FORMAT_QUALITY"); err != nil {
  398. return err
  399. }
  400. configurators.Bool(&StripMetadata, "IMGPROXY_STRIP_METADATA")
  401. configurators.Bool(&KeepCopyright, "IMGPROXY_KEEP_COPYRIGHT")
  402. configurators.Bool(&StripColorProfile, "IMGPROXY_STRIP_COLOR_PROFILE")
  403. configurators.Bool(&AutoRotate, "IMGPROXY_AUTO_ROTATE")
  404. configurators.Bool(&EnforceThumbnail, "IMGPROXY_ENFORCE_THUMBNAIL")
  405. configurators.Bool(&ReturnAttachment, "IMGPROXY_RETURN_ATTACHMENT")
  406. if _, ok := os.LookupEnv("IMGPROXY_ENABLE_WEBP_DETECTION"); ok {
  407. log.Warning("IMGPROXY_ENABLE_WEBP_DETECTION is deprecated, use IMGPROXY_AUTO_WEBP instead")
  408. configurators.Bool(&AutoWebp, "IMGPROXY_ENABLE_WEBP_DETECTION")
  409. }
  410. if _, ok := os.LookupEnv("IMGPROXY_ENABLE_AVIF_DETECTION"); ok {
  411. log.Warning("IMGPROXY_ENABLE_AVIF_DETECTION is deprecated, use IMGPROXY_AUTO_AVIF instead")
  412. configurators.Bool(&AutoAvif, "IMGPROXY_ENABLE_AVIF_DETECTION")
  413. }
  414. configurators.Bool(&AutoWebp, "IMGPROXY_AUTO_WEBP")
  415. configurators.Bool(&EnforceWebp, "IMGPROXY_ENFORCE_WEBP")
  416. configurators.Bool(&AutoAvif, "IMGPROXY_AUTO_AVIF")
  417. configurators.Bool(&EnforceAvif, "IMGPROXY_ENFORCE_AVIF")
  418. configurators.Bool(&AutoJxl, "IMGPROXY_AUTO_JXL")
  419. configurators.Bool(&EnforceJxl, "IMGPROXY_ENFORCE_JXL")
  420. configurators.Bool(&EnableClientHints, "IMGPROXY_ENABLE_CLIENT_HINTS")
  421. configurators.URLPath(&HealthCheckPath, "IMGPROXY_HEALTH_CHECK_PATH")
  422. configurators.String(&ArgumentsSeparator, "IMGPROXY_ARGUMENTS_SEPARATOR")
  423. if err := configurators.ImageTypes(&PreferredFormats, "IMGPROXY_PREFERRED_FORMATS"); err != nil {
  424. return err
  425. }
  426. if err := configurators.ImageTypes(&SkipProcessingFormats, "IMGPROXY_SKIP_PROCESSING_FORMATS"); err != nil {
  427. return err
  428. }
  429. configurators.Bool(&UseLinearColorspace, "IMGPROXY_USE_LINEAR_COLORSPACE")
  430. configurators.Bool(&DisableShrinkOnLoad, "IMGPROXY_DISABLE_SHRINK_ON_LOAD")
  431. if err := configurators.HexSlice(&Keys, "IMGPROXY_KEY"); err != nil {
  432. return err
  433. }
  434. if err := configurators.HexSlice(&Salts, "IMGPROXY_SALT"); err != nil {
  435. return err
  436. }
  437. configurators.Int(&SignatureSize, "IMGPROXY_SIGNATURE_SIZE")
  438. configurators.StringSlice(&TrustedSignatures, "IMGPROXY_TRUSTED_SIGNATURES")
  439. if err := configurators.HexSliceFile(&Keys, keyPath); err != nil {
  440. return err
  441. }
  442. if err := configurators.HexSliceFile(&Salts, saltPath); err != nil {
  443. return err
  444. }
  445. configurators.String(&Secret, "IMGPROXY_SECRET")
  446. configurators.String(&AllowOrigin, "IMGPROXY_ALLOW_ORIGIN")
  447. configurators.String(&UserAgent, "IMGPROXY_USER_AGENT")
  448. UserAgent = strings.ReplaceAll(UserAgent, "%current_version", version.Version)
  449. fmt.Println("User-Agent:", UserAgent)
  450. configurators.Bool(&IgnoreSslVerification, "IMGPROXY_IGNORE_SSL_VERIFICATION")
  451. configurators.Bool(&DevelopmentErrorsMode, "IMGPROXY_DEVELOPMENT_ERRORS_MODE")
  452. configurators.Bool(&CookiePassthrough, "IMGPROXY_COOKIE_PASSTHROUGH")
  453. configurators.String(&CookieBaseURL, "IMGPROXY_COOKIE_BASE_URL")
  454. configurators.Bool(&CookiePassthroughAll, "IMGPROXY_COOKIE_PASSTHROUGH_ALL")
  455. // Can't rely on configurators.String here because it ignores empty values
  456. if s, ok := os.LookupEnv("IMGPROXY_SOURCE_URL_QUERY_SEPARATOR"); ok {
  457. SourceURLQuerySeparator = s
  458. }
  459. configurators.String(&LocalFileSystemRoot, "IMGPROXY_LOCAL_FILESYSTEM_ROOT")
  460. configurators.Bool(&S3Enabled, "IMGPROXY_USE_S3")
  461. configurators.String(&S3Region, "IMGPROXY_S3_REGION")
  462. configurators.String(&S3Endpoint, "IMGPROXY_S3_ENDPOINT")
  463. configurators.Bool(&S3EndpointUsePathStyle, "IMGPROXY_S3_ENDPOINT_USE_PATH_STYLE")
  464. configurators.String(&S3AssumeRoleArn, "IMGPROXY_S3_ASSUME_ROLE_ARN")
  465. configurators.String(&S3AssumeRoleExternalID, "IMGPROXY_S3_ASSUME_ROLE_EXTERNAL_ID")
  466. configurators.Bool(&S3DecryptionClientEnabled, "IMGPROXY_S3_USE_DECRYPTION_CLIENT")
  467. configurators.Bool(&GCSEnabled, "IMGPROXY_USE_GCS")
  468. configurators.String(&GCSKey, "IMGPROXY_GCS_KEY")
  469. configurators.String(&GCSEndpoint, "IMGPROXY_GCS_ENDPOINT")
  470. configurators.Bool(&ABSEnabled, "IMGPROXY_USE_ABS")
  471. configurators.String(&ABSName, "IMGPROXY_ABS_NAME")
  472. configurators.String(&ABSKey, "IMGPROXY_ABS_KEY")
  473. configurators.String(&ABSEndpoint, "IMGPROXY_ABS_ENDPOINT")
  474. configurators.Bool(&SwiftEnabled, "IMGPROXY_USE_SWIFT")
  475. configurators.String(&SwiftUsername, "IMGPROXY_SWIFT_USERNAME")
  476. configurators.String(&SwiftAPIKey, "IMGPROXY_SWIFT_API_KEY")
  477. configurators.String(&SwiftAuthURL, "IMGPROXY_SWIFT_AUTH_URL")
  478. configurators.String(&SwiftDomain, "IMGPROXY_SWIFT_DOMAIN")
  479. configurators.String(&SwiftTenant, "IMGPROXY_SWIFT_TENANT")
  480. configurators.Int(&SwiftConnectTimeoutSeconds, "IMGPROXY_SWIFT_CONNECT_TIMEOUT_SECONDS")
  481. configurators.Int(&SwiftTimeoutSeconds, "IMGPROXY_SWIFT_TIMEOUT_SECONDS")
  482. configurators.Bool(&ETagEnabled, "IMGPROXY_USE_ETAG")
  483. configurators.String(&ETagBuster, "IMGPROXY_ETAG_BUSTER")
  484. configurators.Bool(&LastModifiedEnabled, "IMGPROXY_USE_LAST_MODIFIED")
  485. configurators.String(&BaseURL, "IMGPROXY_BASE_URL")
  486. if err := configurators.Replacements(&URLReplacements, "IMGPROXY_URL_REPLACEMENTS"); err != nil {
  487. return err
  488. }
  489. configurators.Bool(&Base64URLIncludesFilename, "IMGPROXY_BASE64_URL_INCLUDES_FILENAME")
  490. presetsSep := ","
  491. configurators.String(&presetsSep, "IMGPROXY_PRESETS_SEPARATOR")
  492. configurators.StringSliceSep(&Presets, "IMGPROXY_PRESETS", presetsSep)
  493. if err := configurators.StringSliceFile(&Presets, presetsPath); err != nil {
  494. return err
  495. }
  496. configurators.Bool(&OnlyPresets, "IMGPROXY_ONLY_PRESETS")
  497. configurators.String(&WatermarkData, "IMGPROXY_WATERMARK_DATA")
  498. configurators.String(&WatermarkPath, "IMGPROXY_WATERMARK_PATH")
  499. configurators.String(&WatermarkURL, "IMGPROXY_WATERMARK_URL")
  500. configurators.Float(&WatermarkOpacity, "IMGPROXY_WATERMARK_OPACITY")
  501. configurators.String(&FallbackImageData, "IMGPROXY_FALLBACK_IMAGE_DATA")
  502. configurators.String(&FallbackImagePath, "IMGPROXY_FALLBACK_IMAGE_PATH")
  503. configurators.String(&FallbackImageURL, "IMGPROXY_FALLBACK_IMAGE_URL")
  504. configurators.Int(&FallbackImageHTTPCode, "IMGPROXY_FALLBACK_IMAGE_HTTP_CODE")
  505. configurators.Int(&FallbackImageTTL, "IMGPROXY_FALLBACK_IMAGE_TTL")
  506. configurators.Bool(&DataDogEnable, "IMGPROXY_DATADOG_ENABLE")
  507. configurators.Bool(&DataDogEnableMetrics, "IMGPROXY_DATADOG_ENABLE_ADDITIONAL_METRICS")
  508. configurators.String(&NewRelicAppName, "IMGPROXY_NEW_RELIC_APP_NAME")
  509. configurators.String(&NewRelicKey, "IMGPROXY_NEW_RELIC_KEY")
  510. configurators.StringMap(&NewRelicLabels, "IMGPROXY_NEW_RELIC_LABELS")
  511. configurators.String(&PrometheusBind, "IMGPROXY_PROMETHEUS_BIND")
  512. configurators.String(&PrometheusNamespace, "IMGPROXY_PROMETHEUS_NAMESPACE")
  513. configurators.Bool(&OpenTelemetryEnable, "IMGPROXY_OPEN_TELEMETRY_ENABLE")
  514. configurators.Bool(&OpenTelemetryEnableMetrics, "IMGPROXY_OPEN_TELEMETRY_ENABLE_METRICS")
  515. configurators.String(&OpenTelemetryServerCert, "IMGPROXY_OPEN_TELEMETRY_SERVER_CERT")
  516. configurators.String(&OpenTelemetryClientCert, "IMGPROXY_OPEN_TELEMETRY_CLIENT_CERT")
  517. configurators.String(&OpenTelemetryClientKey, "IMGPROXY_OPEN_TELEMETRY_CLIENT_KEY")
  518. configurators.String(&OpenTelemetryTraceIDGenerator, "IMGPROXY_OPEN_TELEMETRY_TRACE_ID_GENERATOR")
  519. configurators.String(&CloudWatchServiceName, "IMGPROXY_CLOUD_WATCH_SERVICE_NAME")
  520. configurators.String(&CloudWatchNamespace, "IMGPROXY_CLOUD_WATCH_NAMESPACE")
  521. configurators.String(&CloudWatchRegion, "IMGPROXY_CLOUD_WATCH_REGION")
  522. configurators.String(&BugsnagKey, "IMGPROXY_BUGSNAG_KEY")
  523. configurators.String(&BugsnagStage, "IMGPROXY_BUGSNAG_STAGE")
  524. configurators.String(&HoneybadgerKey, "IMGPROXY_HONEYBADGER_KEY")
  525. configurators.String(&HoneybadgerEnv, "IMGPROXY_HONEYBADGER_ENV")
  526. configurators.String(&SentryDSN, "IMGPROXY_SENTRY_DSN")
  527. configurators.String(&SentryEnvironment, "IMGPROXY_SENTRY_ENVIRONMENT")
  528. configurators.String(&SentryRelease, "IMGPROXY_SENTRY_RELEASE")
  529. configurators.Int(&AirbrakeProjectID, "IMGPROXY_AIRBRAKE_PROJECT_ID")
  530. configurators.String(&AirbrakeProjectKey, "IMGPROXY_AIRBRAKE_PROJECT_KEY")
  531. configurators.String(&AirbrakeEnv, "IMGPROXY_AIRBRAKE_ENVIRONMENT")
  532. configurators.Bool(&ReportDownloadingErrors, "IMGPROXY_REPORT_DOWNLOADING_ERRORS")
  533. configurators.Bool(&ReportIOErrors, "IMGPROXY_REPORT_IO_ERRORS")
  534. configurators.Bool(&EnableDebugHeaders, "IMGPROXY_ENABLE_DEBUG_HEADERS")
  535. configurators.Int(&FreeMemoryInterval, "IMGPROXY_FREE_MEMORY_INTERVAL")
  536. configurators.Int(&DownloadBufferSize, "IMGPROXY_DOWNLOAD_BUFFER_SIZE")
  537. configurators.Int(&BufferPoolCalibrationThreshold, "IMGPROXY_BUFFER_POOL_CALIBRATION_THRESHOLD")
  538. if len(Keys) != len(Salts) {
  539. return fmt.Errorf("Number of keys and number of salts should be equal. Keys: %d, salts: %d", len(Keys), len(Salts))
  540. }
  541. if len(Keys) == 0 {
  542. log.Warning("No keys defined, so signature checking is disabled")
  543. }
  544. if len(Salts) == 0 {
  545. log.Warning("No salts defined, so signature checking is disabled")
  546. }
  547. if SignatureSize < 1 || SignatureSize > 32 {
  548. return fmt.Errorf("Signature size should be within 1 and 32, now - %d\n", SignatureSize)
  549. }
  550. if len(Bind) == 0 {
  551. return errors.New("Bind address is not defined")
  552. }
  553. if Timeout <= 0 {
  554. return fmt.Errorf("Timeout should be greater than 0, now - %d\n", Timeout)
  555. }
  556. if ReadRequestTimeout <= 0 {
  557. return fmt.Errorf("Read request timeout should be greater than 0, now - %d\n", ReadRequestTimeout)
  558. }
  559. if WriteResponseTimeout <= 0 {
  560. return fmt.Errorf("Write response timeout should be greater than 0, now - %d\n", WriteResponseTimeout)
  561. }
  562. if KeepAliveTimeout < 0 {
  563. return fmt.Errorf("KeepAlive timeout should be greater than or equal to 0, now - %d\n", KeepAliveTimeout)
  564. }
  565. if ClientKeepAliveTimeout < 0 {
  566. return fmt.Errorf("Client KeepAlive timeout should be greater than or equal to 0, now - %d\n", ClientKeepAliveTimeout)
  567. }
  568. if DownloadTimeout <= 0 {
  569. return fmt.Errorf("Download timeout should be greater than 0, now - %d\n", DownloadTimeout)
  570. }
  571. if Workers <= 0 {
  572. return fmt.Errorf("Workers number should be greater than 0, now - %d\n", Workers)
  573. }
  574. if RequestsQueueSize < 0 {
  575. return fmt.Errorf("Requests queue size should be greater than or equal 0, now - %d\n", RequestsQueueSize)
  576. }
  577. if MaxClients < 0 {
  578. return fmt.Errorf("Max clients number should be greater than or equal 0, now - %d\n", MaxClients)
  579. }
  580. if TTL < 0 {
  581. return fmt.Errorf("TTL should be greater than or equal to 0, now - %d\n", TTL)
  582. }
  583. if MaxSrcResolution <= 0 {
  584. return fmt.Errorf("Max src resolution should be greater than 0, now - %d\n", MaxSrcResolution)
  585. }
  586. if MaxSrcFileSize < 0 {
  587. return fmt.Errorf("Max src file size should be greater than or equal to 0, now - %d\n", MaxSrcFileSize)
  588. }
  589. if MaxAnimationFrames <= 0 {
  590. return fmt.Errorf("Max animation frames should be greater than 0, now - %d\n", MaxAnimationFrames)
  591. }
  592. if PngQuantizationColors < 2 {
  593. return fmt.Errorf("Png quantization colors should be greater than 1, now - %d\n", PngQuantizationColors)
  594. } else if PngQuantizationColors > 256 {
  595. return fmt.Errorf("Png quantization colors can't be greater than 256, now - %d\n", PngQuantizationColors)
  596. }
  597. if AvifSpeed < 0 {
  598. return fmt.Errorf("Avif speed should be greater than or equal to 0, now - %d\n", AvifSpeed)
  599. } else if AvifSpeed > 9 {
  600. return fmt.Errorf("Avif speed can't be greater than 9, now - %d\n", AvifSpeed)
  601. }
  602. if JxlEffort < 1 {
  603. return fmt.Errorf("JXL effort should be greater than 0, now - %d\n", JxlEffort)
  604. } else if JxlEffort > 9 {
  605. return fmt.Errorf("JXL effort can't be greater than 9, now - %d\n", JxlEffort)
  606. }
  607. if WebpEffort < 1 {
  608. return fmt.Errorf("Webp effort should be greater than 0, now - %d\n", WebpEffort)
  609. } else if WebpEffort > 6 {
  610. return fmt.Errorf("Webp effort can't be greater than 6, now - %d\n", WebpEffort)
  611. }
  612. if Quality <= 0 {
  613. return fmt.Errorf("Quality should be greater than 0, now - %d\n", Quality)
  614. } else if Quality > 100 {
  615. return fmt.Errorf("Quality can't be greater than 100, now - %d\n", Quality)
  616. }
  617. if len(PreferredFormats) == 0 {
  618. return errors.New("At least one preferred format should be specified")
  619. }
  620. if IgnoreSslVerification {
  621. log.Warning("Ignoring SSL verification is very unsafe")
  622. }
  623. if LocalFileSystemRoot != "" {
  624. stat, err := os.Stat(LocalFileSystemRoot)
  625. if err != nil {
  626. return fmt.Errorf("Cannot use local directory: %s", err)
  627. }
  628. if !stat.IsDir() {
  629. return errors.New("Cannot use local directory: not a directory")
  630. }
  631. if LocalFileSystemRoot == "/" {
  632. log.Warning("Exposing root via IMGPROXY_LOCAL_FILESYSTEM_ROOT is unsafe")
  633. }
  634. }
  635. if _, ok := os.LookupEnv("IMGPROXY_USE_GCS"); !ok && len(GCSKey) > 0 {
  636. log.Warning("Set IMGPROXY_USE_GCS to true since it may be required by future versions to enable GCS support")
  637. GCSEnabled = true
  638. }
  639. if WatermarkOpacity <= 0 {
  640. return errors.New("Watermark opacity should be greater than 0")
  641. } else if WatermarkOpacity > 1 {
  642. return errors.New("Watermark opacity should be less than or equal to 1")
  643. }
  644. if FallbackImageTTL < 0 {
  645. return fmt.Errorf("Fallback image TTL should be greater than or equal to 0, now - %d\n", TTL)
  646. }
  647. if FallbackImageHTTPCode != 0 && (FallbackImageHTTPCode < 100 || FallbackImageHTTPCode > 599) {
  648. return errors.New("Fallback image HTTP code should be between 100 and 599")
  649. }
  650. if len(PrometheusBind) > 0 && PrometheusBind == Bind {
  651. return errors.New("Can't use the same binding for the main server and Prometheus")
  652. }
  653. if FreeMemoryInterval <= 0 {
  654. return errors.New("Free memory interval should be greater than zero")
  655. }
  656. if DownloadBufferSize < 0 {
  657. return errors.New("Download buffer size should be greater than or equal to 0")
  658. } else if DownloadBufferSize > math.MaxInt32 {
  659. return fmt.Errorf("Download buffer size can't be greater than %d", math.MaxInt32)
  660. }
  661. if BufferPoolCalibrationThreshold < 64 {
  662. return errors.New("Buffer pool calibration threshold should be greater than or equal to 64")
  663. }
  664. return nil
  665. }