Skip to main content
Self-hosted InsForge stores files on the local filesystem by default (STORAGE_DIR, a Docker volume). That works out of the box, but an S3 backend adds presigned or proxied transfers, multipart uploads, and — most importantly — enables the S3-compatible gateway at /storage/v1/s3, so aws CLI, rclone, boto3, and Terraform can talk to your InsForge Storage directly. You have three options:

Bring your own S3-compatible store

Set these in your .env (all production compose files pass them through to the backend) and restart:
The legacy AWS_S3_BUCKET / AWS_REGION names still work as fallbacks, but the S3_* names are preferred — the store doesn’t have to be AWS. Storage auto-wires to the bucket on startup — no other configuration. The S3 gateway turns on automatically. Provider notes:
  • AWS S3, Wasabi, MinIO (public endpoint) — works with the defaults. Clients upload/download via presigned URLs directly against the store.
  • Cloudflare R2 — set S3_USE_PRESIGNED_URLS=false. R2 does not support S3 POST policies, which presigned browser uploads require; proxy mode routes all bytes through the backend instead.
  • Tencent COS, Aliyun OSS — set S3_FORCE_PATH_STYLE=false (they require virtual-hosted-style addressing).
  • Store on a private network (a MinIO/RustFS/Ceph the browser can’t reach) — set S3_USE_PRESIGNED_URLS=false.

Presigned vs. proxy mode

S3_USE_PRESIGNED_URLS (default true) decides how object bytes reach clients:
  • Presigned (default): the backend hands clients short-lived URLs signed against S3_ENDPOINT_URL; browsers transfer directly with the store. Requires the endpoint to be reachable by browsers and to support POST policies.
  • Proxy (false): strategies point at the backend’s own routes and every byte streams through it — the store can stay completely private. Ranged downloads (Range headers, media seeking) are supported. Uploads through the REST API/SDK are capped by the storage max-file-size setting (Dashboard → Storage → Settings, default 50 MB); larger objects go through the S3 gateway, which streams and supports multipart up to S3_MAX_OBJECT_SIZE_BYTES (default 5 GB per part/put).

Bundled MinIO

Run MinIO next to InsForge with a single overlay — no .env editing:
The overlay starts minio, creates the backing bucket, and points the backend at it in proxy mode. MinIO stays on the internal Docker network — it exposes no host ports and never needs TLS or a domain of its own. Change the default credentials before production use:

Bundled RustFS

Same shape with RustFS (Apache-2.0 licensed, written in Rust):
Both overlays also work with the dev compose (docker-compose.yml) and the deploy/docker-compose/docker-compose.yml self-host file (place the overlay next to it).
Switching an existing deployment from local storage to an S3 backend does not migrate previously uploaded files. Migrate the contents of the storage-data volume (e.g. with mc mirror or aws s3 sync) before switching, or start fresh.

Dokploy

Dokploy takes a single compose file, so overlays don’t apply. Two options:
  1. External store — set S3_BUCKET, S3_ENDPOINT_URL, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_FORCE_PATH_STYLE=true (and S3_USE_PRESIGNED_URLS=false for private endpoints) in Dokploy’s environment UI. docker-compose.dokploy.yml passes them through.
  2. MinIO/RustFS on the same Dokploy host — deploy the store as its own Dokploy service, then point the env vars above at its internal address.

Using the S3-compatible gateway

With any S3 backend configured, the gateway is live at <your-backend-url>/storage/v1/s3:
  1. Open Dashboard → Storage → Settings → S3 Configuration and create an access key. The secret is shown once.
  2. Point any SigV4 client at the gateway with path-style addressing:
Uploads made through the gateway appear immediately in the REST API and Dashboard. See S3-compatible gateway for supported operations and limits.

Reference

The AWS_* variables (AWS_S3_BUCKET, AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_CLOUDFRONT_*) are cloud-project and legacy names: the first two work as fallbacks for S3_BUCKET/S3_REGION, the credentials double as CloudWatch/CloudFront credentials, and CloudFront only applies to AWS S3 without a custom endpoint. Self-hosted deployments should stick to S3_*.

Upgrading from an AWS_* configuration

Older versions of deploy/docker-compose/docker-compose.yml did not pass storage variables at all, and the deployment guide recommended hand-adding AWS_S3_BUCKET (and friends) to the insforge service. If you did that: the current compose file passes only the S3_* names. Before adopting it, rename the variables in your .env to S3_BUCKET / S3_REGION / S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY — or keep your hand-edited environment block. The backend itself still honors AWS_* as fallbacks, so any value that reaches the container keeps working; the risk is only a compose file that no longer forwards them, which would silently fall back to local storage.