> ## Documentation Index
> Fetch the complete documentation index at: https://docs.steward.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-Hosting

> Deploy your own Steward instance with PostgreSQL and Bun.

# Self-Hosting Steward

Steward is designed to be self-hosted. This guide covers deploying Steward on your own infrastructure.

## Requirements

* **Runtime:** [Bun](https://bun.sh) v1.0+
* **Database:** PostgreSQL 15+ (or [Neon](https://neon.tech) for serverless)
* **Node.js:** 18+ (for build tooling)
* **OS:** Linux (Ubuntu 22.04+ recommended), macOS, or Windows WSL2

## Quick Start

<Tabs>
  <Tab title="Docker Compose (Recommended)">
    ```bash theme={null}
    git clone https://github.com/Steward-Fi/steward.git
    cd steward
    cp .env.example .env
    # Edit .env with your values (see Environment Variables below)
    docker compose up -d
    ```

    See [Docker Deployment](/guides/docker) for the full `docker-compose.yml` and network isolation.
  </Tab>

  <Tab title="Manual">
    ```bash theme={null}
    git clone https://github.com/Steward-Fi/steward.git
    cd steward
    bun install
    cp .env.example .env
    # Edit .env, then:
    cd packages/db && bun run drizzle-kit push
    cd ../api && bun run dev
    ```
  </Tab>

  <Tab title="Embedded (PGLite)">
    For local development without PostgreSQL:

    ```bash theme={null}
    git clone https://github.com/Steward-Fi/steward.git
    cd steward
    bun install
    STEWARD_EMBEDDED=true STEWARD_MASTER_PASSWORD=dev-password bun run packages/api/src/index.ts
    ```

    Embedded mode uses [PGLite](https://pglite.dev) (an in-process Postgres) with data stored on disk. No third-party database needed.

    <Warning>
      Embedded mode is for **local development only**. Data is stored in a local directory and is not suitable for production. Use PostgreSQL for any deployment that handles real keys.
    </Warning>
  </Tab>
</Tabs>

## Environment Variables

### Core (Required)

```bash theme={null}
# Master encryption password — derives the AES-256-GCM key for all wallet/secret encryption
# CRITICAL: If lost, all encrypted keys are permanently inaccessible
STEWARD_MASTER_PASSWORD=your-strong-master-password-32-chars-min

# PostgreSQL connection string (not needed in embedded mode)
DATABASE_URL=postgres://user:pass@localhost:5432/steward
```

### API Server

```bash theme={null}
STEWARD_PORT=3200                           # API port (default: 3200)
STEWARD_BIND_HOST=0.0.0.0                   # Bind address
STEWARD_JWT_SECRET=separate-jwt-signing-key  # Defaults to master password if not set
STEWARD_PLATFORM_KEY=your-platform-admin-key # For platform-level management
STEWARD_EMBEDDED=false                       # Set true for PGLite mode
```

### Blockchain

```bash theme={null}
RPC_URL=https://mainnet.base.org             # Default EVM chain RPC
CHAIN_ID=8453                                # Default chain ID
SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
```

### Authentication

```bash theme={null}
# Passkeys (WebAuthn)
PASSKEY_RP_ID=myapp.com                      # Relying party ID (your domain)
PASSKEY_ORIGIN=https://myapp.com             # Expected origin for ceremonies
PASSKEY_RP_NAME="My App"                     # Display name in passkey dialogs

# Email magic links
RESEND_API_KEY=re_xxxxxxxxxxxx               # Resend.com API key
EMAIL_FROM=auth@myapp.com                    # Verified sender address
APP_URL=https://myapp.com                    # Used for magic link URLs

# OAuth providers (optional, enable any combination)
GOOGLE_CLIENT_ID=xxxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxxx
DISCORD_CLIENT_ID=1234567890
DISCORD_CLIENT_SECRET=xxxx
TWITTER_CLIENT_ID=xxxx
TWITTER_CLIENT_SECRET=xxxx
```

## Database Setup

Run the Drizzle migrations to set up the database schema:

```bash theme={null}
cd packages/db
bun run drizzle-kit push

# Or generate and run migrations
bun run drizzle-kit generate
bun run drizzle-kit migrate
```

## Running the API

```bash theme={null}
# Development
cd packages/api
bun run dev

# Production
bun run start
```

Verify it's running:

```bash theme={null}
curl http://localhost:3200/health
# {"ok":true,"timestamp":"2026-03-26T12:00:00Z"}
```

## Creating Your First Tenant

```bash theme={null}
curl -X POST http://localhost:3200/tenants \
  -H "Content-Type: application/json" \
  -d '{
    "id": "my-org",
    "name": "My Organization",
    "apiKeyHash": "your-api-key"
  }'
```

<Note>
  If you pass a non-hash string as `apiKeyHash`, Steward will SHA-256 hash it for you. The raw API key is returned once on creation.
</Note>

## Production Deployment

### Systemd Service

```ini theme={null}
[Unit]
Description=Steward API
After=network.target postgresql.service

[Service]
Type=simple
User=steward
WorkingDirectory=/opt/steward
ExecStart=/usr/local/bin/bun run packages/api/src/index.ts
Restart=always
RestartSec=5
Environment=NODE_ENV=production
EnvironmentFile=/opt/steward/.env

[Install]
WantedBy=multi-user.target
```

### Reverse Proxy (Nginx)

```nginx theme={null}
server {
    listen 443 ssl http2;
    server_name api.myapp.com;

    ssl_certificate /etc/letsencrypt/live/api.myapp.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.myapp.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3200;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

## Production Checklist

* [ ] Set a unique `STEWARD_MASTER_PASSWORD` (32+ chars, random)
* [ ] Set a separate `STEWARD_JWT_SECRET`
* [ ] Use TLS for all connections (API + database)
* [ ] Restrict database access to the Steward server only
* [ ] Set `STEWARD_PLATFORM_KEY` for admin operations
* [ ] Configure `PASSKEY_RP_ID` and `PASSKEY_ORIGIN` to match your domain
* [ ] Set up email provider (Resend) for magic link auth
* [ ] Run as non-root user
* [ ] Enable firewall (only expose ports 443 and SSH)
* [ ] Back up the database regularly

## Related

* [Docker Deployment](/guides/docker) — Deploy with Docker Compose
* [Architecture](/concepts/architecture) — System design overview
* [Auth Overview](/auth/overview) — Authentication configuration
* [API Overview](/api-reference/overview) — API authentication
