File storage for IMP uploads — MinIO or AWS S3 via the COMPANION_S3_* variables.
IMP uses S3-compatible object storage for chat attachments, session files, and knowledge source uploads. The bucket must exist before the application starts — IMP does not create it.
File uploads go directly from the browser to the object store via presigned PUT URLs. The backend generates a signed URL, returns it to the frontend, and the browser uploads the file directly without passing through the backend. This keeps large uploads off the API process.
AWS SDK checksum gotcha. AWS SDK for JavaScript v3.729 and later injects an x-amz-checksum-crc32 header (computed over an empty body) into presigned PUT URLs by default. MinIO and some other S3-compatible stores validate that checksum against the uploaded bytes and reject the PUT with a checksum mismatch error, causing session file uploads to silently fail.IMP disables this default by setting requestChecksumCalculation: "WHEN_REQUIRED" and responseChecksumValidation: "WHEN_REQUIRED" on the shared S3 client (fix shipped in backend commit fa88d2e). If you build @exulu/backend from a revision older than that commit, upgrades to AWS SDK >= 3.729 will break file uploads against MinIO.
Network reachability.COMPANION_S3_ENDPOINT is used server-side (by the backend) to generate presigned URLs. The endpoint must be reachable from the backend container. If the backend and MinIO are on the same Docker network, use the container name (e.g. http://exulu-minio:9000). The presigned URL returned to the browser must resolve from the end user’s machine — configure a public URL or reverse proxy for MinIO’s API port if users are outside the Docker network.Bucket policy. The bucket does not need to be public. Presigned URLs grant time-limited read and write access to individual objects without a bucket-level public policy.Signature expiry. IMP presigns URLs with a 1-day expiry (expiresIn = 86400). Uploads or downloads attempted after the signature expires will receive a 403 from S3.
{"docsConfig":{"theme":"aspen","$schema":"https://mintlify.com/docs.json","name":"IMP Docs","description":"Documentation for IMP — the Intelligence Management Platform.","colors":{"primary":"#6f9a37","light":"#cef79e","dark":"#557a26"},"logo":{"light":"https://mintcdn.com/exulu/AoxglAoKLnpiSWrg/logo/imp-wordmark-light.svg?fit=max\u0026auto=format\u0026n=AoxglAoKLnpiSWrg\u0026q=85\u0026s=9b42068ec92bdc8c9edbfd0a097c1103","dark":"https://mintcdn.com/exulu/AoxglAoKLnpiSWrg/logo/imp-wordmark-dark.svg?fit=max\u0026auto=format\u0026n=AoxglAoKLnpiSWrg\u0026q=85\u0026s=a84a8146d264791641105aafa8cfce99"},"favicon":"https://mintcdn.com/exulu/AoxglAoKLnpiSWrg/logo/imp-icon.svg?fit=max\u0026auto=format\u0026n=AoxglAoKLnpiSWrg\u0026q=85\u0026s=7ac4f534736be19d46aa980180530371","background":{"color":{"light":"#f8f6f1","dark":"#1b1714"}},"footer":{"links":[{"header":"IMP","items":[{"label":"Intelligence Management Platform","href":"/get-started/what-is-imp"}]}]},"icons":{"library":"lucide"},"contextual":{"options":["copy","view","chatgpt","claude","perplexity","mcp","cursor","vscode"],"display":"header"},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"exulu","hasAudioNarration":false,"actualSubdomain":"exulu","customDomains":["docs.intelligence-management-platform.com"],"gitSource":{"type":"github","owner":"qventu","repo":"exulu-backend","deployBranch":"main","contentDirectory":"mintlify-docs","isPrivate":false,"mountPath":"","label":""},"feedback":{"thumbs":true,"edits":true,"issues":true},"entitlements":{},"buildId":"6ad7083d07bd205c1a9ff19c","clientVersion":"0.0.4094","searchFilterCounts":[{"language":"default","tag":"API Reference","count":101},{"language":"default","tag":"REST","count":73},{"language":"default","tag":"Developers","count":54},{"language":"default","tag":"Building","count":24},{"language":"default","tag":"Core classes","count":24},{"language":"default","tag":"Core types","count":23},{"language":"default","tag":"User Guide","count":21},{"language":"default","tag":"Self-Hosting","count":16},{"language":"default","tag":"Skills","count":16},{"language":"default","tag":"Chat","count":15}]},"assistantConfig":{},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"styles.css","content":"@font-face{font-family:\"Aspekta\";font-style:normal;font-weight:400;src:url(\"/fonts/inter-tight-400.woff2\") format(\"woff2\");font-display:swap}@font-face{font-family:\"Aspekta\";font-style:normal;font-weight:500;src:url(\"/fonts/inter-tight-500.woff2\") format(\"woff2\");font-display:swap}@font-face{font-family:\"RobotoMono\";font-style:normal;font-weight:400;src:url(\"/fonts/roboto-mono-400.woff2\") format(\"woff2\");font-display:swap}:root{--imp-bone: #f8f6f1;--imp-ink: #222f30;--imp-void: #1b1714;--imp-tissue: #efece4;--imp-lime: #cef79e;--imp-olive: #6f9a37;--imp-hair-light: #e4ddd0;--imp-hair-dark: #4d5757}body{font-family:\"Aspekta\", \"Inter Tight\", system-ui, sans-serif;letter-spacing:-0.011em}h1,h2,h3,h4{font-family:\"Aspekta\", \"Inter Tight\", system-ui, sans-serif;font-weight:500;letter-spacing:-0.03em}code,pre,kbd,samp{font-family:\"RobotoMono\", \"Roboto Mono\", ui-monospace, monospace}*,*::before,*::after{border-radius:0!important}"}],"page":{"pagePath":"self-hosting/services/s3-storage","slug":"/self-hosting/services/s3-storage","pageMetadata":{"title":"S3-compatible storage","description":"File storage for IMP uploads — MinIO or AWS S3 via the COMPANION_S3_* variables.","icon":"hard-drive","href":"/self-hosting/services/s3-storage"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"File storage for IMP uploads — MinIO or AWS S3 via the COMPANION_S3_* variables.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Table,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(_components.p,{children:`IMP uses S3-compatible object storage for chat attachments, session files, and knowledge source uploads. The bucket must exist before the application starts — IMP does not create it.`}),`\n`,_jsx(Heading,{level:`2`,id:`supported-backends`,children:`Supported backends`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`AWS S3`}),` — set `,_jsx(_components.code,{children:`COMPANION_S3_ENDPOINT`}),` to empty / omit it.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`MinIO`}),` — set `,_jsx(_components.code,{children:`COMPANION_S3_ENDPOINT`}),` to the MinIO API URL (e.g. `,_jsx(_components.code,{children:`http://exulu-minio:9000`}),`) and IMP enables `,_jsx(_components.code,{children:`forcePathStyle: true`}),` automatically.`]}),`\n`,_jsx(_components.li,{children:`Any other S3-compatible store that supports presigned PUT URLs.`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`presigned-url-flow`,children:`Presigned URL flow`}),`\n`,_jsx(_components.p,{children:`File uploads go directly from the browser to the object store via presigned PUT URLs. The backend generates a signed URL, returns it to the frontend, and the browser uploads the file directly without passing through the backend. This keeps large uploads off the API process.`}),`\n`,_jsxs(Warning,{children:[_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`AWS SDK checksum gotcha.`}),` AWS SDK for JavaScript v3.729 and later injects an `,_jsx(_components.code,{children:`x-amz-checksum-crc32`}),` header (computed over an empty body) into presigned PUT URLs by default. MinIO and some other S3-compatible stores validate that checksum against the uploaded bytes and reject the PUT with a checksum mismatch error, causing session file uploads to silently fail.`]}),_jsxs(_components.p,{children:[`IMP disables this default by setting `,_jsx(_components.code,{children:`requestChecksumCalculation: \"WHEN_REQUIRED\"`}),` and `,_jsx(_components.code,{children:`responseChecksumValidation: \"WHEN_REQUIRED\"`}),` on the shared S3 client (fix shipped in backend commit `,_jsx(_components.code,{children:`fa88d2e`}),`). If you build `,_jsx(_components.code,{children:`@exulu/backend`}),` from a revision older than that commit, upgrades to AWS SDK >= 3.729 will break file uploads against MinIO.`]})]}),`\n`,_jsx(Heading,{level:`2`,id:`create-the-bucket-before-starting-imp`,children:`Create the bucket before starting IMP`}),`\n`,_jsx(_components.p,{children:`IMP does not create the bucket. Create it first:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`3`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# MinIO via mcli`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`mc`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` alias`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` set`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` local`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` http://localhost:9000`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`root-use`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`r`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`>`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`root-passwor`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`d`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`>`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`mc`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` mb`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` local/`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`bucket-nam`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`e`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`>`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Or create it through the MinIO web console at `,_jsx(_components.code,{children:`http://localhost:9001`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`configuration-reference`,children:`Configuration reference`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Variable`}),_jsx(_components.th,{children:`Example`}),_jsx(_components.th,{children:`Description`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`COMPANION_S3_REGION`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`eu-central-1`})}),_jsx(_components.td,{children:`Bucket region. For MinIO this matches the region you configured.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`COMPANION_S3_KEY`})}),_jsx(_components.td,{children:`—`}),_jsx(_components.td,{children:`Access key ID`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`COMPANION_S3_SECRET`})}),_jsx(_components.td,{children:`—`}),_jsx(_components.td,{children:`Secret access key`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`COMPANION_S3_BUCKET`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`exulu-uploads`})}),_jsx(_components.td,{children:`Bucket name. Must exist before startup.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`COMPANION_S3_ENDPOINT`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`http://exulu-minio:9000`})}),_jsx(_components.td,{children:`Endpoint URL. Omit for AWS S3. Set to the MinIO API URL for MinIO.`})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`compose-excerpt-minio`,children:`Compose excerpt (MinIO)`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`17`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`17`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`exulu-minio`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` image`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`quay.io/minio/minio:RELEASE.2025-04-22T22-12-26Z`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` restart`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`unless-stopped`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` command`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`server /data --console-address \":9001\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` environment`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` MINIO_ROOT_USER`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:'\"${MINIO_ROOT_USER}\"'})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` MINIO_ROOT_PASSWORD`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:'\"${MINIO_ROOT_PASSWORD}\"'})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` ports`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"9000:9000\"`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` # API`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"9001:9001\"`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` # Web console`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` volumes`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`minio-data:/data`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` healthcheck`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` test`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"CMD\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"mc\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"ready\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"local\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` interval`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`30s`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` timeout`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`20s`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` retries`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`3`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`Point the backend at MinIO:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`ini`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`ini`,children:_jsxs(_components.code,{language:`ini`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`COMPANION_S3_ENDPOINT`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`=http://exulu-minio:9000`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`COMPANION_S3_REGION`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`=eu-central-1`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`COMPANION_S3_KEY`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`=\u003cyour-access-key>`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`COMPANION_S3_SECRET`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`=\u003cyour-secret-key>`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`COMPANION_S3_BUCKET`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`=\u003cyour-bucket-name>`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`operational-notes`,children:`Operational notes`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Network reachability.`}),` `,_jsx(_components.code,{children:`COMPANION_S3_ENDPOINT`}),` is used server-side (by the backend) to generate presigned URLs. The endpoint must be reachable from the backend container. If the backend and MinIO are on the same Docker network, use the container name (e.g. `,_jsx(_components.code,{children:`http://exulu-minio:9000`}),`). The presigned URL returned to the browser must resolve from the end user’s machine — configure a public URL or reverse proxy for MinIO’s API port if users are outside the Docker network.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Bucket policy.`}),` The bucket does not need to be public. Presigned URLs grant time-limited read and write access to individual objects without a bucket-level public policy.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Signature expiry.`}),` IMP presigns URLs with a 1-day expiry (`,_jsx(_components.code,{children:`expiresIn = 86400`}),`). Uploads or downloads attempted after the signature expires will receive a 403 from S3.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"S3-compatible storage","description":"File storage for IMP uploads — MinIO or AWS S3 via the COMPANION_S3_* variables.","icon":"hard-drive","href":"/self-hosting/services/s3-storage"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Supported backends","slug":"supported-backends","depth":2,"children":[]},{"title":"Presigned URL flow","slug":"presigned-url-flow","depth":2,"children":[]},{"title":"Create the bucket before starting IMP","slug":"create-the-bucket-before-starting-imp","depth":2,"children":[]},{"title":"Configuration reference","slug":"configuration-reference","depth":2,"children":[]},{"title":"Compose excerpt (MinIO)","slug":"compose-excerpt-minio","depth":2,"children":[]},{"title":"Operational notes","slug":"operational-notes","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"exulu","siteName":"IMP Docs","title":"S3-compatible storage - IMP Docs","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-07-15T17:47:11.674Z","originalFileLocation":"self-hosting/services/s3-storage.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"File storage for IMP uploads — MinIO or AWS S3 via the COMPANION_S3_* variables.\">\u003cmeta data-mint-head name=\"application-name\" content=\"IMP Docs\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/exulu/N9cNIKTf5pwOldAi/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/exulu/N9cNIKTf5pwOldAi/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/exulu/N9cNIKTf5pwOldAi/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/exulu/N9cNIKTf5pwOldAi/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/exulu/N9cNIKTf5pwOldAi/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/exulu/N9cNIKTf5pwOldAi/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/exulu/N9cNIKTf5pwOldAi/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/exulu/N9cNIKTf5pwOldAi/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/exulu/N9cNIKTf5pwOldAi/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"S3-compatible storage - IMP Docs\">\u003cmeta data-mint-head property=\"og:description\" content=\"File storage for IMP uploads — MinIO or AWS S3 via the COMPANION_S3_* variables.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"IMP Docs\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.intelligence-management-platform.com/self-hosting/services/s3-storage\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://exulu.mintlify.site/_mintlify/api/og/v2?division=Services\u0026amp;title=S3-compatible+storage\u0026amp;description=File+storage+for+IMP+uploads+%E2%80%94+MinIO+or+AWS+S3+via+the+COMPANION_S3_*+variables.\u0026amp;theme=0a86c3c8bb60ae0aa06a3652\u0026amp;signature=661fe394ee964873a7e30b3c92d8d6783d52fdc80d57152588cd90b45efb2932\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"S3-compatible storage - IMP Docs\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"File storage for IMP uploads — MinIO or AWS S3 via the COMPANION_S3_* variables.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://exulu.mintlify.site/_mintlify/api/og/v2?division=Services\u0026amp;title=S3-compatible+storage\u0026amp;description=File+storage+for+IMP+uploads+%E2%80%94+MinIO+or+AWS+S3+via+the+COMPANION_S3_*+variables.\u0026amp;theme=0a86c3c8bb60ae0aa06a3652\u0026amp;signature=661fe394ee964873a7e30b3c92d8d6783d52fdc80d57152588cd90b45efb2932\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/exulu/N9cNIKTf5pwOldAi/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"IMP Docs\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#6f9a37\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.intelligence-management-platform.com/self-hosting/services/s3-storage\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/self-hosting/services/s3-storage.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.intelligence-management-platform.com/#organization\",\"name\":\"IMP Docs\",\"url\":\"https://docs.intelligence-management-platform.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/exulu/AoxglAoKLnpiSWrg/logo/imp-wordmark-light.svg?fit=max\u0026auto=format\u0026n=AoxglAoKLnpiSWrg\u0026q=85\u0026s=9b42068ec92bdc8c9edbfd0a097c1103\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.intelligence-management-platform.com#website\",\"name\":\"IMP Docs\",\"url\":\"https://docs.intelligence-management-platform.com\",\"publisher\":{\"@id\":\"https://docs.intelligence-management-platform.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.intelligence-management-platform.com/self-hosting/services/s3-storage#webpage\",\"url\":\"https://docs.intelligence-management-platform.com/self-hosting/services/s3-storage\",\"name\":\"S3-compatible storage\",\"description\":\"File storage for IMP uploads — MinIO or AWS S3 via the COMPANION_S3_* variables.\",\"dateModified\":\"2026-07-15T17:47:11.674Z\",\"isPartOf\":{\"@id\":\"https://docs.intelligence-management-platform.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.intelligence-management-platform.com/self-hosting/services/s3-storage#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.intelligence-management-platform.com/self-hosting/services/s3-storage#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Services\",\"item\":\"https://docs.intelligence-management-platform.com/self-hosting/services/postgres\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"S3-compatible storage\",\"item\":\"https://docs.intelligence-management-platform.com/self-hosting/services/s3-storage\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.intelligence-management-platform.com/self-hosting/services/s3-storage#article\",\"headline\":\"S3-compatible storage\",\"name\":\"S3-compatible storage\",\"description\":\"File storage for IMP uploads — MinIO or AWS S3 via the COMPANION_S3_* variables.\",\"url\":\"https://docs.intelligence-management-platform.com/self-hosting/services/s3-storage\",\"mainEntityOfPage\":{\"@id\":\"https://docs.intelligence-management-platform.com/self-hosting/services/s3-storage#webpage\"},\"dateModified\":\"2026-07-15T17:47:11.674Z\",\"publisher\":{\"@id\":\"https://docs.intelligence-management-platform.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.intelligence-management-platform.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"IMP Docs\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"IMP Docs","nav":{"global":null,"tabs":[{"tab":"Get Started","icon":"rocket","pages":[{"title":"Get Started","href":""}]},{"tab":"User Guide","icon":"message-square","pages":[{"title":"User Guide","href":"/user-guide/chat/overview"}]},{"tab":"Building","icon":"hammer","pages":[{"title":"Building","href":"/building/agents/overview"}]},{"tab":"Administration","icon":"shield","pages":[{"title":"Administration","href":"/administration/users-access/overview"}]},{"tab":"Self-Hosting","icon":"server","groups":[{"group":"Deploy","pages":[{"title":"Architecture","icon":"network","href":"/self-hosting/architecture"},{"title":"Requirements","icon":"list-checks","href":"/self-hosting/requirements"},{"title":"Quickstart","icon":"play","href":"/self-hosting/quickstart"}]},{"group":"Services","pages":[{"title":"Postgres","icon":"database","href":"/self-hosting/services/postgres"},{"title":"Redis","description":"Redis powers IMP's BullMQ job queues. Required only when running worker containers.","icon":"layers","href":"/self-hosting/services/redis"},{"title":"S3-compatible storage","icon":"hard-drive","href":"/self-hosting/services/s3-storage"},{"title":"LiteLLM proxy","description":"LiteLLM is IMP's single model registry: chat routing, embeddings, reranking, OCR, image generation, and budget tracking.","icon":"cpu","href":"/self-hosting/services/litellm"},{"title":"Whisper transcription server","icon":"mic","href":"/self-hosting/services/whisper"},{"title":"SMTP and authentication","icon":"lock","href":"/self-hosting/services/smtp-and-auth"},{"title":"Observability","icon":"activity","href":"/self-hosting/services/observability"}]},{"group":"Operate","pages":[{"title":"Containers","icon":"box","href":"/self-hosting/containers"},{"title":"Environment variables","icon":"settings","href":"/self-hosting/environment-variables"},{"title":"Branding","icon":"paintbrush","href":"/self-hosting/branding"},{"title":"Database","icon":"database","href":"/self-hosting/database"},{"title":"Operations","icon":"settings-2","href":"/self-hosting/operations"},{"title":"Troubleshooting","icon":"circle-help","href":"/self-hosting/troubleshooting"}]}]},{"tab":"Developers","icon":"code","pages":[{"title":"Developers","href":"/developers/setup"}]},{"tab":"API Reference","icon":"braces","pages":[{"title":"API Reference","href":"/api-reference/rest/introduction"}]},{"tab":"Changelog","icon":"history","pages":[{"title":"Changelog","href":"/changelog"}]}]},"basePath":"","title":"S3-compatible storage - IMP Docs","buildId":"dpl_42LwxxU1kGN114H4XzwGYXa9ZDah","deploymentId":"dpl_42LwxxU1kGN114H4XzwGYXa9ZDah","dynamics":[],"chunks":[]}