Docker Deployment
Remix Studio is designed for self-hosted and cloud-hosted deployments. Docker images are published to GHCR and run against your own PostgreSQL database and S3-compatible storage.
Use a separate environment file for containerized deployments so your local .env can keep using host addresses like localhost.
1. Clone the Repository
git clone https://github.com/ShinChven/remix-studio.git
cd remix-studio2. Create the Docker Deployment Environment File
cp .env.docker.example .env.dockerFor the bundled PostgreSQL + MinIO stack, keep these container-network addresses:
DATABASE_URL=postgresql://postgres:postgres@postgres:5432/remix_studio
S3_ENDPOINT=http://minio:9000Before starting the stack, set real values for:
PROVIDER_ENCRYPTION_KEY— must be a 64-character hex stringJWT_SECRETDEFAULT_ADMIN_PASSWORDS3_ACCESS_KEY_IDandS3_SECRET_ACCESS_KEY, if you do not want the default MinIO credentials
Generate an encryption key with:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"3. Start the Full Stack From the Published GHCR Image
docker compose -f docker/compose.minio.yml --env-file .env.docker up -dThe compose templates default to ghcr.io/shinchven/remix-studio:latest, which tracks successful builds from the default branch and may be newer than the latest tagged release. For stable deployments, set REMIX_STUDIO_IMAGE in .env.docker to a SemVer tag such as ghcr.io/shinchven/remix-studio:1.25.0, or :1.25 to pick up patch releases.
This starts:
appon3000postgreson5432minioAPI on9000minioconsole on9001
The application container runs prisma migrate deploy on startup before launching the server.
4. View Logs
docker compose -f docker/compose.minio.yml --env-file .env.docker logs -f app5. Stop the Stack
docker compose -f docker/compose.minio.yml --env-file .env.docker downBuilding From Source Instead
The root docker-compose.yml runs the same stack, with the app behind the app profile so docker compose up -d postgres minio starts only the services local development needs. With the profile it builds the image from the checkout:
docker compose --profile app --env-file .env.docker up -d --build
docker compose --profile app --env-file .env.docker logs -f app
docker compose --profile app --env-file .env.docker downChoosing a Compose Template
The docker/ directory ships several layouts. Pick the one that matches where your object storage lives:
| Template | Layout | Matching env file |
|---|---|---|
compose.minio.yml | app + PostgreSQL + MinIO (fully self-hosted, single host) | env.minio.example |
compose.aws-s3.yml | app + PostgreSQL, storage on AWS S3 or managed S3 | env.aws-s3.example |
compose.app-only.yml | app only (you provide PostgreSQL and object storage) | env.app-only.example |
Additional env examples are provided for cloudflare-r2, gcs, and aliyun-oss. See Storage Providers for per-provider configuration.
DLNA on the Host Network
TV mode and WebDAV work in every layout. DLNA discovery is UDP multicast, which Docker's bridge network does not forward, so DLNA needs the app on the host network. docker-compose.dlna.yml is an override for the root compose file that does that and sets DLNA_ENABLED:
docker compose -f docker-compose.yml -f docker-compose.dlna.yml --profile app --env-file .env.docker up -dOn the host network the app reaches PostgreSQL and MinIO through their host-published ports rather than by service name. It is Linux only: Docker Desktop on macOS and Windows does not share the host's LAN interfaces. See TV, WebDAV & DLNA.
Example: AWS S3 layout
cp docker/env.aws-s3.example .env
docker compose -f docker/compose.aws-s3.yml --env-file .env up -dPasskeys Behind a Reverse Proxy
If you use passkeys:
- Set
WEBAUTHN_RP_IDto the public site domain only, without protocol or port. Example:app.example.com. - If TLS terminates at a reverse proxy or load balancer, set
WEBAUTHN_ORIGINto the exact external origin, includinghttps://. Example:https://app.example.com.
Push Notifications
Browser notifications work without configuration: the server generates its VAPID key pair on first use and keeps it in the database. Set VAPID_SUBJECT to a contact address you own, and serve the app over HTTPS, which browsers require for push. See Configuration.
Health Checks
All templates expose:
- Liveness:
GET /healthz - Readiness:
GET /readyz
Image Tags and Cleanup
latesttracks the latest successful build from the main branch.- Version tags publish
1.0.0,1.0, and1style tags fromv1.0.0; use these for release deployments. edgeis deprecated; replace it withlatestfor default-branch tracking.- A scheduled workflow removes old untagged GHCR images weekly, keeps the newest 20 untagged images, and validates multi-architecture image integrity after cleanup.
Cutting a Release
On
main, bump the version inpackage.jsonandpackage-lock.jsonwithout tagging, date the release section inCHANGELOG.md, and add the release entry todocs-site/whats-new.md:bashnpm version 1.25.0 --no-git-tag-version git commit -am "chore(release): v1.25.0" git push origin mainTag the release commit and push the tag:
bashgit tag -a v1.25.0 -m "Release v1.25.0" git push origin v1.25.0
The push to main rebuilds latest and redeploys the docs site. The tag push runs .github/workflows/docker.yml again, which publishes the 1.25.0, 1.25 and 1 image tags and creates the GitHub Release with generated notes and the browser extension as remix-studio-chrome-extension.zip.
Related
- Backup & Restore — the compose templates mount
/app/backupsby default. - Upgrading — migration and compatibility notes.