> ## Documentation Index
> Fetch the complete documentation index at: https://sure-917046f5-docs-cloudflare-tunnel-self-hosting.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-hosting with Docker

> Deploy Sure on your own infrastructure using Docker Compose

This guide shows you how to set up, update, and maintain a self-hosted Sure application with Docker Compose.

## Prerequisites

* Docker Engine installed and running
* Basic familiarity with the command line

## Installation

### Install Docker

1. Follow the [official Docker installation guide](https://docs.docker.com/engine/install/)
2. Start the Docker service on your machine
3. Verify the installation:

```bash theme={null}
docker run hello-world
```

If Docker is set up correctly, this command will succeed.

### Create your application directory

Create a directory where your app will run:

```bash theme={null}
mkdir -p ~/docker-apps/sure
cd ~/docker-apps/sure
```

### Download the Docker Compose file

Download the sample compose file from the Sure repository:

```bash theme={null}
curl -o compose.yml https://raw.githubusercontent.com/we-promise/sure/main/compose.example.yml
```

This creates a `compose.yml` file in your current directory with the default configuration.

## Configuration

By default, the `compose.example.yml` file runs without any configuration. For production deployments or if you're running outside of a local network, follow these steps to add security.

### Email configuration

To enable email notifications and password resets, configure SMTP settings in your `.env` file:

```txt theme={null}
SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_DOMAIN=example.com
SMTP_USERNAME=your-username
SMTP_PASSWORD=your-password
SMTP_AUTHENTICATION=plain
SMTP_ENABLE_STARTTLS_AUTO=true
```

#### SSL/TLS options

For SMTP servers with custom SSL certificates or self-signed certificates:

**Skip TLS verification** (not recommended for production):

```txt theme={null}
SMTP_OPENSSL_VERIFY_MODE=none
```

**Use custom CA certificate**:

```txt theme={null}
SSL_CA_FILE=/path/to/ca-certificate.pem
```

The `SSL_CA_FILE` option allows you to specify a custom CA certificate file for SSL verification when connecting to SMTP servers with self-signed or internal certificates.

### Create an environment file

Create a `.env` file where Docker will read environment variables:

```bash theme={null}
touch .env
```

### Generate a secret key

Generate a secret key using one of these methods:

**With OpenSSL:**

```bash theme={null}
openssl rand -hex 64
```

**Without OpenSSL:**

```bash theme={null}
head -c 64 /dev/urandom | od -An -tx1 | tr -d ' \n' && echo
```

Save the generated key for the next step.

### Configure environment variables

Open the `.env` file in your text editor and add:

```txt theme={null}
SECRET_KEY_BASE="your-generated-secret-key-here"
POSTGRES_PASSWORD="your-database-password-here"
```

Replace the placeholder values with your generated secret key and a secure database password.

### Optional: expose Sure with Cloudflare Tunnel

If you want to reach your self-hosted instance from the public internet without opening router ports, you can put a [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) in front of the `web` container.

1. Create a tunnel in Cloudflare Zero Trust and copy the tunnel token.
2. Add the token to your `.env` file:

```txt theme={null}
CLOUDFLARE_TUNNEL_TOKEN="your-cloudflare-tunnel-token"
```

3. Edit `compose.yml` and set:

```yaml theme={null}
RAILS_ASSUME_SSL: "true"
```

This tells Sure to generate HTTPS URLs correctly when Cloudflare terminates TLS before forwarding traffic to the container over HTTP.

4. Add a `cloudflared` service to your `compose.yml`:

```yaml theme={null}
  cloudflared:
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel run
    environment:
      TUNNEL_TOKEN: ${CLOUDFLARE_TUNNEL_TOKEN}
    depends_on:
      - web
    networks:
      - sure_net
```

5. In the Cloudflare tunnel dashboard, add a public hostname such as `sure.example.com` and point it at the internal Docker service:

```txt theme={null}
Service type: HTTP
URL: http://web:3000
```

6. Start the tunnel connector:

```bash theme={null}
docker compose up -d cloudflared
docker compose logs cloudflared --tail 20
```

Look for a successful tunnel registration message in the logs, then open `https://sure.example.com`.

<Note>
  Cloudflare should connect to `http://web:3000`, not `https://web:3000`. Sure speaks plain HTTP inside Docker and relies on `RAILS_ASSUME_SSL` to know the original request was HTTPS.
</Note>

<Tip>
  If you enable passkeys or security keys on a public hostname, also set `WEBAUTHN_RP_ID` and `WEBAUTHN_ALLOWED_ORIGINS` in `.env` to match that hostname.
</Tip>

<Warning>
  If you only want Cloudflare Tunnel access, do not leave port `3000` broadly exposed to the internet. Keep the host firewall closed or bind the published port more narrowly.
</Warning>

### Market data provider variables

Sure supports multiple securities pricing providers. You can configure them through environment variables or in the UI under **Settings > Self-Hosting**. See [market data providers](/providers/market-data) for details on each provider.

```txt theme={null}
# Comma-separated list of securities providers (e.g. yahoo_finance,tiingo,mfapi)
SECURITIES_PROVIDERS="yahoo_finance"

# Exchange rate provider (default: twelve_data)
EXCHANGE_RATE_PROVIDER="twelve_data"

# API keys (only needed for providers that require them)
TWELVE_DATA_API_KEY="your-key-here"
TIINGO_API_KEY="your-key-here"
EODHD_API_KEY="your-key-here"
ALPHA_VANTAGE_API_KEY="your-key-here"
```

<Note>
  Setting `SECURITIES_PROVIDERS` as an environment variable takes precedence over the UI setting. Leave it unset to manage providers from the UI only.
</Note>

## Running the application

### Start the application

Start the app to verify everything is working:

```bash theme={null}
docker compose up
```

This pulls the official Docker image and starts the app. You'll see logs in your terminal.

Open your browser and navigate to `http://localhost:3000`. You should see the Sure login screen.

### Create your account

On first run, register a new account:

1. Click "Create your account" on the login page
2. Enter your email
3. Enter a password

### Run in the background

To run Sure in the background:

1. Stop the current process with `Ctrl+C`
2. Start in detached mode:

```bash theme={null}
docker compose up -d
```

Verify it's running:

```bash theme={null}
docker compose ls
```

Your app is now accessible at `http://localhost:3000`.

## Updating

The Docker image in your `compose.yml` file controls which version of Sure you're running:

```yml theme={null}
image: ghcr.io/we-promise/sure:latest
```

### Recommended images

* `ghcr.io/we-promise/sure:latest` - Latest alpha release
* `ghcr.io/we-promise/sure:stable` - Latest stable release

You can also pin to a specific version from the [packages page](https://github.com/we-promise/sure/pkgs/container/sure).

### Update to the latest version

Your app does not automatically update. To update:

```bash theme={null}
cd ~/docker-apps/sure
docker compose pull
docker compose build
docker compose up --no-deps -d web worker
```

### Change update channel

To switch between update channels, edit the `compose.yml` file:

```yml theme={null}
image: ghcr.io/we-promise/sure:stable
```

Then restart the app:

```bash theme={null}
docker compose pull
docker compose build
docker compose up --no-deps -d web worker
```

## Backup service

The Docker Compose configuration includes an optional backup service that automatically backs up your PostgreSQL database.

### Enabling backups

The backup service uses Docker Compose profiles and is disabled by default. To enable it:

```bash theme={null}
docker compose --profile backup up -d
```

### Configure backup settings

The backup service uses the following default settings:

* **Schedule**: Daily at midnight
* **Retention**: 7 daily backups, 4 weekly backups, 6 monthly backups
* **Location**: `/opt/sure-data/backups` on your host machine

To customize these settings, edit the `backup` service in your `compose.yml` file:

```yml theme={null}
backup:
  profiles:
    - backup
  image: prodrigestivill/postgres-backup-local
  restart: unless-stopped
  volumes:
    - /your/custom/path:/backups  # Change this to your desired location
  environment:
    - POSTGRES_HOST=db
    - POSTGRES_DB=${POSTGRES_DB:-sure_production}
    - POSTGRES_USER=${POSTGRES_USER:-sure_user}
    - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-sure_password}
    - SCHEDULE=@daily              # Change schedule (e.g., @hourly, @weekly)
    - BACKUP_KEEP_DAYS=7           # Number of daily backups to keep
    - BACKUP_KEEP_WEEKS=4          # Number of weekly backups to keep
    - BACKUP_KEEP_MONTHS=6         # Number of monthly backups to keep
```

### Backup schedule options

You can use cron syntax or these shortcuts:

* `@hourly` - Every hour
* `@daily` - Once per day at midnight
* `@weekly` - Once per week
* `@monthly` - Once per month
* Custom cron: `0 2 * * *` (2 AM daily)

### Restoring from backup

To restore your database from a backup:

1. Stop the application:

```bash theme={null}
docker compose down
```

2. Locate your backup file in the backup directory (e.g., `/opt/sure-data/backups`)

3. Restore the backup:

```bash theme={null}
docker compose up -d db
docker compose exec -T db psql -U sure_user -d sure_production < /path/to/backup.sql
```

4. Restart the application:

```bash theme={null}
docker compose up -d
```

### Verifying backups

Check that backups are running correctly:

```bash theme={null}
# View backup service logs
docker compose logs backup

# List backup files
ls -lh /opt/sure-data/backups
```

## SSL certificate configuration

For self-hosted environments using self-signed certificates or custom certificate authorities, Sure provides SSL configuration options.

### Environment variables

Add these variables to your `.env` file:

```txt theme={null}
SSL_CA_FILE=/path/to/ca-bundle.pem
SSL_VERIFY=true
```

**SSL\_CA\_FILE**: Path to a custom CA certificate bundle (PEM format). Use this when:

* Your environment uses self-signed certificates
* You need to trust a custom certificate authority
* Corporate proxies inject their own certificates

**SSL\_VERIFY**: Controls SSL certificate verification (default: `true`)

* Set to `false` to disable SSL verification (not recommended for production)
* Only disable verification in development or testing environments

If you're using a custom CA bundle, mount it into your containers in `compose.yml`:

```yml theme={null}
services:
  web:
    volumes:
      - /path/to/your/ca-bundle.pem:/path/to/your/ca-bundle.pem:ro
  worker:
    volumes:
      - /path/to/your/ca-bundle.pem:/path/to/your/ca-bundle.pem:ro
```

Restart the application after updating your configuration:

```bash theme={null}
docker compose restart web worker
```

### Optional: SSL/TLS Configuration

Sure supports additional SSL/TLS configuration options for secure email delivery and API connections.

#### Custom CA Certificate

If you're using a custom Certificate Authority (CA) or self-signed certificates, you can specify a CA file:

```txt theme={null}
SSL_CA_FILE="/path/to/your/ca-certificate.pem"
```

This is useful when:

* Running Sure in a corporate environment with internal CAs
* Using self-signed certificates for development
* Connecting to services with custom certificate chains

#### Skip TLS Verification for Email

For development or testing environments, you can disable TLS verification for the email mailer:

```txt theme={null}
SMTP_ENABLE_STARTTLS_AUTO=false
SMTP_TLS_VERIFY=false
```

<Warning>
  Only disable TLS verification in development or trusted environments. In production, always use proper TLS verification to ensure secure email delivery.
</Warning>

**When to use this:**

* Development environments with self-signed certificates
* Testing email functionality locally
* Internal mail servers with custom certificates

**Production recommendations:**

* Always use valid SSL/TLS certificates in production
* Use the `SSL_CA_FILE` option instead of disabling verification
* Ensure your SMTP server supports STARTTLS

### Mailer SSL configuration

For SMTP connections, additional SSL options are available:

```txt theme={null}
SMTP_ENABLE_STARTTLS_AUTO=true
SMTP_OPENSSL_VERIFY_MODE=none
```

**SMTP\_ENABLE\_STARTTLS\_AUTO**: Enable STARTTLS for SMTP connections (default: `true`)

**SMTP\_OPENSSL\_VERIFY\_MODE**: SSL verification mode for SMTP

* `none`: Skip SSL verification
* `peer`: Verify the server certificate (default)

### Security considerations

<Warning>
  Disabling SSL verification (`SSL_VERIFY=false` or `SMTP_OPENSSL_VERIFY_MODE=none`) exposes your application to man-in-the-middle attacks. Only use these settings in trusted networks or development environments.
</Warning>

For production deployments:

* Use properly signed certificates from a trusted CA
* Keep `SSL_VERIFY=true`
* Use `SMTP_OPENSSL_VERIFY_MODE=peer`
* If you must use self-signed certificates, provide a CA bundle via `SSL_CA_FILE`

## Troubleshooting

### Database connection errors

If you encounter `ActiveRecord::DatabaseConnectionError` on first startup, Docker may have initialized the Postgres database with a different default role from a previous attempt.

<Warning>
  The following commands will delete all existing data in your Sure database. Only proceed if you're comfortable losing this data.
</Warning>

Reset the database:

```bash theme={null}
docker compose down
docker volume rm sure_postgres-data
docker compose up
docker compose exec db psql -U sure_user -d sure_development -c "SELECT 1;"
```

The last command verifies the issue is fixed.

### Slow CSV imports

If CSV imports are processing rows slower than expected, check your worker logs for errors:

```bash theme={null}
docker compose logs worker
```

Look for connection timeouts or Redis communication failures. The `sure-worker` container requires Redis to process CSV imports.

## Getting help

If you find bugs or have feature requests:

* Read the [contributing guide](https://github.com/we-promise/sure/wiki/How-to-Contribute-Effectively-to-Sure)
* Ask in the [Discord](https://discord.gg/36ZGBsxYEK)
* Open an [issue](https://github.com/we-promise/sure/issues/new/choose)
