EmberlyEmberly Docs

Storage Configuration

Configure S3-compatible object storage for your self-hosted Emberly instance — MinIO, AWS S3, Cloudflare R2, and more.

Emberly stores all uploaded files in S3-compatible object storage. You can use any provider that speaks the S3 API — including self-hosted options like MinIO. Storage is configured after first run via Admin Panel → Settings → Integrations → Storage.


Choosing a Provider

Emberly's storage layer speaks the S3 API directly — any of these work as long as you can supply an endpoint, bucket name, region, and access keys. There's no built-in auto-provisioning for self-hosted instances; you create the bucket yourself with your provider, then enter its credentials in the Admin Panel.

ProviderBest forNotes
MinIO (self-hosted)Air-gapped or fully self-contained installsRun it as its own service (systemd, or however you deploy it) — no cloud account needed
AWS S3Production with existing AWS infrastructureReliable, well-documented, generous free tier
Cloudflare R2Zero egress costs, global CDNNo egress fees; requires Cloudflare account
Vultr Object StorageCost-effective, S3-compatibleCreate the bucket in the Vultr dashboard, then enter its keys manually — the automatic multi-bucket provisioning UI is a cloud-only feature
Linode / AkamaiLinode-hosted appsSame as Vultr — manual bucket + keys, no auto-provisioning for self-hosted
TigrisGlobally distributed S3Good Fly.io companion

MinIO (Self-Hosted)

MinIO is the easiest way to run a fully self-contained Emberly instance without any external cloud dependencies. Install and run it as its own service — see MinIO's installation docs for the current install steps on your OS; there's no bundled Docker Compose setup in the Emberly repo, so if you containerize MinIO yourself you'll manage that separately from the app.

Create a Bucket

Once MinIO is running, open its console (default http://localhost:9001) and log in with your root user/password. Then:

  1. Click Buckets → Create Bucket
  2. Name it emberly
  3. Leave other settings as default and click Create

Or use the mc CLI:

mc alias set local http://localhost:9000 <root-user> <root-password>
mc mb local/emberly
mc anonymous set download local/emberly

The last command makes the bucket publicly readable, which is required for Emberly's public file URLs to work.

Configure in Admin Panel

In Admin Panel → Settings → Integrations → Storage, set:

FieldValue
EndpointYour MinIO server's address, e.g. http://localhost:9000
Bucket nameemberly
Regionus-east-1 (MinIO accepts any value)
Access key IDYour MinIO access key
Secret access keyYour MinIO secret key
Public files URLA publicly reachable URL for the bucket

Public files URL in production

Public files URL must be a publicly accessible URL — not localhost. Put MinIO behind a reverse proxy (Nginx or Caddy) on a real domain, e.g. https://files.yourdomain.com, and use that as the public URL.

MinIO Behind a Reverse Proxy

To serve MinIO files from a real domain, add a Caddy or Nginx block alongside your main app:

Caddy:

files.yourdomain.com {
    reverse_proxy localhost:9000
}

Nginx:

server {
    listen 80;
    server_name files.yourdomain.com;
 
    location / {
        proxy_pass http://localhost:9000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        client_max_body_size 0;
    }
}

Then set Public files URL to https://files.yourdomain.com/emberly.


AWS S3

  1. Create a bucket in the S3 console
  2. Create an IAM user with s3:GetObject, s3:PutObject, s3:DeleteObject permissions on the bucket
  3. Generate an access key for that user
  4. In Admin Panel → Settings → Integrations → Storage:
FieldValue
Endpoint(leave blank — uses AWS default)
Bucket nameYour bucket name
Regione.g. us-east-1
Access key IDIAM user access key
Secret access keyIAM user secret
Public files URLhttps://your-bucket.s3.amazonaws.com or your CloudFront URL

To allow public downloads, configure the bucket policy to allow s3:GetObject for all principals, or use a CloudFront distribution with the bucket as origin.


Cloudflare R2

R2 has no egress fees, making it cost-effective for high-traffic instances.

  1. Create a bucket in the Cloudflare dashboard under R2
  2. Create an R2 API token with Object Read and Write permissions
  3. Enable Public access on the bucket (or use a custom domain)
  4. In Admin Panel → Settings → Integrations → Storage:
FieldValue
Endpointhttps://<account-id>.r2.cloudflarestorage.com
Bucket nameYour bucket name
Regionauto
Access key IDR2 API token Access Key ID
Secret access keyR2 API token Secret
Public files URLYour R2 public bucket URL or custom domain

Verifying Storage Works

After configuring, upload a test file through the Emberly dashboard. If the file appears and its URL loads in a browser, storage is working correctly.

If uploads fail, check:

  • The endpoint URL is correct and reachable from the app container
  • The bucket exists and the access key has write permissions
  • The Public files URL is publicly accessible (not blocked by firewall or auth)
  • For MinIO: the bucket anonymous policy is set to download

On this page