config.go 25 KB

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