config.go 25 KB

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