Storage options
ShipLean stores attachments and profile photos in a folder, PostgreSQL, or an S3 bucket. Choose a persistent store before you add files, especially if you plan to run more than one app instance.
Choose a store
Section titled “Choose a store”| Store | Configure | Choose it when |
|---|---|---|
| Folder | SHIPLEAN_BLOB_ROOT |
You run one instance with a persistent disk mounted at the chosen path. The default is data/blobs in the app folder. The quick-start Compose file uses /data/blobs on a named volume. |
| PostgreSQL | SHIPLEAN_BLOB_DB_CONNECTION |
You want attachments in a PostgreSQL database, either the same database or a separate one. Choose it when you run multiple instances or the app has no persistent disk. |
| S3 | SHIPLEAN_BLOB_S3_CONNECTION |
You use AWS S3 or an S3-compatible service such as Cloudflare R2 or RustFS. Choose it when you run multiple instances or the app has no persistent disk. |
Know which store ShipLean uses
Section titled “Know which store ShipLean uses”No separate setting selects the store. ShipLean uses the first configured connection, checking them in this order:
SHIPLEAN_BLOB_S3_CONNECTIONselects S3.- Otherwise
SHIPLEAN_BLOB_DB_CONNECTIONselects PostgreSQL. - Otherwise ShipLean uses the folder at
SHIPLEAN_BLOB_ROOT, or the default folder if that setting is not set.
At startup, ShipLean logs the store it chose and the reason. The log omits passwords and secret keys. If both connection settings are present, ShipLean logs a warning and uses S3. It ignores the PostgreSQL blob setting.
Changing the store does not move existing files. Each file stays in the store where ShipLean wrote it. Plan and run any migration between stores separately, before you switch the setting.
Configure S3
Section titled “Configure S3”Set SHIPLEAN_BLOB_S3_CONNECTION to semicolon-separated name=value settings. bucket is required. Provide region or serviceUrl. Provide accessKey and secretKey together, or omit both to use the AWS default credential chain. The optional forcePathStyle setting takes true or false. ShipLean puts prefix before every object key. Create the bucket before you start ShipLean.
The examples use placeholder values. Put real credentials in a secret manager or a protected environment file. Restrict each key to the bucket that ShipLean uses.
AWS S3
Section titled “AWS S3”For AWS, use the bucket’s region and omit serviceUrl, so the SDK selects the AWS endpoint. For example:
SHIPLEAN_BLOB_S3_CONNECTION=bucket=shiplean-prod;region=ap-southeast-1;prefix=prod/The AWS S3 endpoint reference lists regional endpoints. AWS supports virtual-hosted and path-style addressing. The forcePathStyle option is usually unnecessary for AWS.
Download the AWS environment example.
Cloudflare R2
Section titled “Cloudflare R2”Use the account-specific R2 S3 endpoint, the region auto, and the Access Key ID and Secret Access Key from an R2 API token. The example uses path-style addressing:
SHIPLEAN_BLOB_S3_CONNECTION=bucket=shiplean-prod;region=auto;serviceUrl=https://<ACCOUNT_ID>.r2.cloudflarestorage.com;accessKey=<R2_ACCESS_KEY_ID>;secretKey=<R2_SECRET_ACCESS_KEY>;forcePathStyle=true;prefix=prod/Find your account ID and create bucket-scoped read and write credentials in the Cloudflare R2 S3 setup guide. Cloudflare lists auto as the S3 API region in its R2 S3 compatibility reference.
Download the R2 environment example.
Local RustFS
Section titled “Local RustFS”The RustFS Compose example pins the official RustFS 1.0.4-glibc image. It runs an S3-compatible service on the same Compose network as ShipLean. Copy its .env.example to .env and replace every placeholder before you start the stack. The app uses rustfs:9000 as the S3 endpoint, with the signing region us-east-1 and path-style addressing. Create the bucket named shiplean in the RustFS Console at http://localhost:9001 before you upload files.
Open the RustFS Compose example. It also includes PostgreSQL, so you can run the example as a complete stack. The official RustFS container guide documents its API and Console ports and its access-key settings. RustFS uses path-style S3 requests by default, as described in its URL addressing guide. This single-node example is for local evaluation only. RustFS documents no redundancy in single-node, single-disk mode.
Stop the example with docker compose down. Keep the named volumes to retain the database and stored objects. Remove the volumes only when you want to delete that data.