# Instatic Deployment Options: Docker, VPS, Render, and Railway Guide

> Deploy Instatic easily with Docker, VPS, Render, or Railway. This guide explores your best options for quick and efficient setup of the Instatic platform.

- Repository: [CoreBunch/Instatic](https://github.com/CoreBunch/Instatic)
- Tags: how-to-guide
- Published: 2026-08-01

---

**Instatic supports four primary deployment methods: self-hosted Docker VPS using Compose, managed Render hosting, managed Railway hosting, and generic Docker image deployment on any container-compatible infrastructure.**

Instatic is a Bun-powered content management system developed by CoreBunch that ships with production-ready containerization. While the application can run on any platform capable of executing a Bun process, the project provides comprehensive Docker-based recipes optimized for VPS, Render, and Railway environments. All deployment configurations rely on the centralized [`server/config.ts`](https://github.com/CoreBunch/Instatic/blob/main/server/config.ts) module to manage runtime environment variables.

## Docker VPS Deployment

The self-hosted VPS option provides maximum flexibility through Docker Compose override files. The base configuration resides in [`docker-compose.yml`](https://github.com/CoreBunch/Instatic/blob/main/docker-compose.yml) and [`compose.prod.yml`](https://github.com/CoreBunch/Instatic/blob/main/compose.prod.yml), which define the core application service, networking, and environment defaults.

### SQLite with Docker Compose

For single-server deployments with moderate traffic, combine the production base with the SQLite override and optional TLS:

```bash
docker compose \
  -f compose.prod.yml \
  -f compose.sqlite.yml \
  -f compose.tls.yml \
  -f compose.build.yml \
  up -d --build

```

This stack creates an `app` container running the Bun server with `DATABASE_URL` set to `sqlite:/app/data/cms.db`. Data persists in named Docker volumes for both the database (`data`) and uploaded media (`uploads`). The [`compose.tls.yml`](https://github.com/CoreBunch/Instatic/blob/main/compose.tls.yml) file injects a Caddy container that handles TLS termination and forwards traffic to the application, while [`compose.build.yml`](https://github.com/CoreBunch/Instatic/blob/main/compose.build.yml) forces a local image rebuild from source.

### Postgres with TLS

For production workloads requiring concurrent connections, use the Postgres service instead of SQLite:

```bash
docker compose \
  -f compose.prod.yml \
  -f compose.tls.yml \
  -f compose.build.yml \
  up -d --build

```

This configuration launches three containers: `app`, `postgres`, and `caddy`. The application receives a `DATABASE_URL` pointing to the bundled Postgres instance. Detailed configuration options are documented in [`docs/deployment/vps.md`](https://github.com/CoreBunch/Instatic/blob/main/docs/deployment/vps.md).

## Render Deployment

Render hosts Instatic using the pre-built container image `ghcr.io/corebunch/instatic`. The platform pulls the image defined in the `Dockerfile` and exposes the application on port 3001.

A typical Render Blueprint configuration appears as follows:

```yaml
services:
  - name: web
    type: web
    env: docker
    dockerfile: Dockerfile
    docker_context: .
    ports:
      - 10000:3001
    env_vars:
      INSTATIC_SECRET_KEY: ${INSTATIC_SECRET_KEY}
      PUBLIC_ORIGIN: https://cms.example.com
    health_check:
      path: /health
      interval: 10s
    disks:
      - name: uploads
        mount_path: /app/uploads
        size_gb: 5

```

Render requires a persistent disk mounted at `/app/uploads` for media storage and provisions managed Postgres instances that automatically inject `DATABASE_URL` into the container environment. The health check endpoint at `/health` ensures zero-downtime deployments.

## Railway Deployment

Railway operates similarly to Render, pulling the `ghcr.io/corebunch/instatic` image and exposing the service on a public HTTP port. As detailed in [`docs/deployment/railway.md`](https://github.com/CoreBunch/Instatic/blob/main/docs/deployment/railway.md), Railway's "Image Auto Updates" feature keeps the deployment current without manual intervention.

A simplified Railway service definition:

```toml
[service]
name = "instatic"
image = "ghcr.io/corebunch/instatic:latest"
port = 10000

[service.env]
INSTATIC_SECRET_KEY = "REPLACE_WITH_GENERATED_KEY"
PUBLIC_ORIGIN = "https://my-cms.onrender.com"

[[service.volumes]]
path = "/app/uploads"
size = "5Gi"

```

Railway automatically configures health checks and enables persistent volume mounting for uploads. Managed Postgres databases can be attached via the Railway dashboard, which injects the connection string into the container's environment.

## Generic Docker Image Deployment

Any infrastructure capable of running Linux containers can host Instatic using the production image directly. The `Dockerfile` defines a multi-stage build that embeds the compiled admin SPA (`dist/`) and retains `esbuild` in production dependencies for runtime bundling.

For custom orchestration or Kubernetes environments:

```bash
docker run -d \
  -p 3001:3001 \
  -e INSTATIC_SECRET_KEY=<key> \
  -e DATABASE_URL=sqlite:/app/data/cms.db \
  -v instatic-uploads:/app/uploads \
  ghcr.io/corebunch/instatic:latest

```

This approach bypasses Compose entirely while maintaining persistent storage through Docker volumes. The image contract and additional examples are documented in [`docs/deployment/docker-image.md`](https://github.com/CoreBunch/Instatic/blob/main/docs/deployment/docker-image.md).

## Direct Bun Execution

For development environments or minimal installations where Docker is unavailable, Instatic can run directly on the host Bun runtime:

```bash
bun install
bun run build
INSTATIC_SECRET_KEY=$(bun run scripts/generate-secret-key.ts) \
  DATABASE_URL=sqlite:./data/cms.db \
  STATIC_DIR=./dist \
  UPLOADS_DIR=./uploads \
  PORT=3001 \
  bun run server/index.ts

```

This method requires manual environment configuration and places the burden of process management, TLS termination, and database administration on the operator.

## Configuration Management

All deployment methods rely on [`server/config.ts`](https://github.com/CoreBunch/Instatic/blob/main/server/config.ts) to normalize runtime settings. Critical environment variables include:

- `PORT`: HTTP server port (default 3001)
- `DATABASE_URL`: Connection string for SQLite or Postgres
- `UPLOADS_DIR`: Filesystem path for media storage (typically `/app/uploads`)
- `STATIC_DIR`: Location of compiled frontend assets
- `PUBLIC_ORIGIN`: Canonical URL for the instance
- `TRUSTED_PROXY_CIDRS`: IP ranges for reverse proxy trust
- `INSTATIC_SECRET_KEY`: Cryptographic key for session signing

These variables are defined in the various `.env` examples and injected by the respective deployment platforms' configuration files.

## Summary

- **Docker VPS** offers self-hosted flexibility with SQLite or Postgres backends, optional Caddy TLS termination via [`compose.tls.yml`](https://github.com/CoreBunch/Instatic/blob/main/compose.tls.yml), and persistent named volumes.
- **Render** provides managed hosting via Blueprint configuration, persistent disks, and integrated health checks using the pre-built `ghcr.io/corebunch/instatic` image.
- **Railway** delivers similar managed hosting with automatic image updates, volume persistence at `/app/uploads`, and managed database provisioning.
- **Generic Docker** enables deployment on any container-compatible infrastructure using standard `docker run` commands or Kubernetes manifests referencing the published image.

## Frequently Asked Questions

### Can I run Instatic without Docker?

Yes, though it requires manual environment configuration. You can execute `bun run server/index.ts` directly after running `bun install` and `bun run build`, setting `INSTATIC_SECRET_KEY`, `DATABASE_URL`, and other required variables manually. This approach is suitable for development or minimal installations but lacks the production hardening provided by the containerized deployment recipes.

### Which database should I use for production VPS deployments?

Use **Postgres** via [`compose.prod.yml`](https://github.com/CoreBunch/Instatic/blob/main/compose.prod.yml) without the SQLite override for production environments requiring high concurrency or multiple simultaneous connections. Use **SQLite** via [`compose.sqlite.yml`](https://github.com/CoreBunch/Instatic/blob/main/compose.sqlite.yml) for single-server deployments with lower traffic volumes, as it simplifies backup and reduces resource overhead according to [`docs/deployment/vps.md`](https://github.com/CoreBunch/Instatic/blob/main/docs/deployment/vps.md).

### How does TLS certificate management work in VPS deployments?

The [`compose.tls.yml`](https://github.com/CoreBunch/Instatic/blob/main/compose.tls.yml) file injects a Caddy reverse proxy container that automatically provisions and renews Let's Encrypt certificates. Caddy terminates TLS and forwards unencrypted traffic to the Instatic application container on the internal Docker network, requiring no manual certificate management.

### What are the minimum server requirements for VPS deployment?

Instatic requires a Linux server capable of running Docker Engine 20.10 or later with support for Compose V2. The Bun runtime consumes approximately 100-200MB RAM plus database overhead. SQLite deployments require minimal disk I/O, while Postgres deployments benefit from SSD storage for database volumes mounted via Docker named volumes.