config.go 26 KB

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