Open-source, local-first apps.
docker pull ghcr.io/versity/versitygw
docker run -d --name epicenter -p 7070:7070 --restart always ghcr.io/versity/versitygw:latest
podman run -d --name epicenter -p 7070:7070 --restart always ghcr.io/versity/versitygw:latest
skopeo inspect docker://ghcr.io/versity/versitygw:latest
oras pull ghcr.io/versity/versitygw:latest
docker compose up -d
# Local object storage for hosted blobs (development + self-host).
#
# Run this ALONGSIDE the Bun server (`bun run dev:bun`). The two are decoupled
# over the S3 HTTP API, exactly as the hosted Worker talks to R2:
#
# docker compose up -d # start versitygw + create the bucket
# # then set these in apps/api/.env (see .env.example):
# # BLOBS_S3_ENDPOINT=http://localhost:7070
# # BLOBS_S3_ACCESS_KEY_ID=epicenter-local
# # BLOBS_S3_SECRET_ACCESS_KEY=epicenter-local-secret
# # BLOBS_S3_BUCKET=epicenter-blobs
# # BLOBS_S3_REGION=us-east-1
#
# Why versitygw: it is an S3 API in front of a plain folder, so your blobs are
# ordinary files under ./.data/blobs/epicenter-blobs that you can `ls` and back
# up, while the server runs the SAME portable S3 client it uses against R2. There
# is deliberately NO filesystem blob backend in the codebase: storage is a
# separate service you point an endpoint at. Swapping it is a config change, never
# a code change. To use Garage instead (a real object store rather than an
# S3-over-a-folder facade), replace the `versitygw` service with a `garage`
# service, follow https://garagehq.deuxfleurs.fr/documentation/quick-start/ to
# create the `epicenter-blobs` bucket + an access key, and repoint BLOBS_S3_* at
# it. The blob code does not change.
services:
versitygw:
image: ghcr.io/versity/versitygw:latest
restart: unless-stopped
ports:
- '7070:7070' # S3 API endpoint -> BLOBS_S3_ENDPOINT
- '8080:8080' # web console: browse buckets/objects at http://localhost:8080
environment:
ROOT_ACCESS_KEY: epicenter-local
ROOT_SECRET_KEY: epicenter-local-secret
VGW_PORT: ':7070'
VGW_REGION: us-east-1 # must match BLOBS_S3_REGION on the server
VGW_BACKEND: posix
VGW_BACKEND_ARGS: /data # each top-level dir under /data is a bucket
volumes:
- ./.data/blobs:/data
# One-shot: create the `epicenter-blobs` bucket the store expects, then exit.
# The store never calls CreateBucket, so the bucket must exist before the first
# upload. Idempotent: re-running `compose up` is safe.
create-bucket:
image: amazon/aws-cli:latest
depends_on:
- versitygw
environment:
AWS_ACCESS_KEY_ID: epicenter-local
AWS_SECRET_ACCESS_KEY: epicenter-local-secret
AWS_DEFAULT_REGION: us-east-1
entrypoint: ['/bin/sh', '-c']
command:
- |
until aws --endpoint-url http://versitygw:7070 s3 ls >/dev/null 2>&1; do
echo "waiting for versitygw..."; sleep 1;
done
aws --endpoint-url http://versitygw:7070 s3 mb s3://epicenter-blobs || true
echo "bucket epicenter-blobs ready at http://localhost:7070"