Skip to main content
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
  2. Start the Docker service on your machine
  3. Verify the installation:
If Docker is set up correctly, this command will succeed.

Create your application directory

Create a directory where your app will run:

Download the Docker Compose file

Download the sample compose file from the Sure repository:
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:

SSL/TLS options

For SMTP servers with custom SSL certificates or self-signed certificates: Skip TLS verification (not recommended for production):
Use custom CA certificate:
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:

Generate a secret key

Generate a secret key using one of these methods: With OpenSSL:
Without OpenSSL:
Save the generated key for the next step.

Configure environment variables

Open the .env file in your text editor and add:
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 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:
  1. Edit compose.yml and set:
This tells Sure to generate HTTPS URLs correctly when Cloudflare terminates TLS before forwarding traffic to the container over HTTP.
  1. Add a cloudflared service to your compose.yml:
  1. In the Cloudflare tunnel dashboard, add a public hostname such as sure.example.com and point it at the internal Docker service:
  1. Start the tunnel connector:
Look for a successful tunnel registration message in the logs, then open https://sure.example.com.
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.
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.
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.

Import size variables

By default, Sure NDJSON imports are limited to a fixed maximum file size. Self-hosted admins can raise this limit with:
This applies to both the GUI upload and the API upload paths. If you do not set this variable, the default limit is used.

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 for details on each provider.
Setting SECURITIES_PROVIDERS as an environment variable takes precedence over the UI setting. Leave it unset to manage providers from the UI only.

Running the application

Start the application

Start the app to verify everything is working:
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

Restrict future signups

After creating your initial admin account, you can control how other people join your self-hosted instance from Settings > Self-Hosting > Onboarding.
  • Open: Anyone can create an account from the registration page.
  • Invite-only: Signups stay enabled, but a valid invite code is required.
  • Closed: The registration page is disabled for new signups.
If you do not want additional self-service registrations, switch the instance to Closed after the initial setup.

Run in the background

To run Sure in the background:
  1. Stop the current process with Ctrl+C
  2. Start in detached mode:
Verify it’s running:
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:
  • 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.

Update to the latest version

Your app does not automatically update. To update:

Change update channel

To switch between update channels, edit the compose.yml file:
Then restart the app:

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:

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:

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:
  1. Locate your backup file in the backup directory (e.g., /opt/sure-data/backups)
  2. Restore the backup:
  1. Restart the application:

Verifying backups

Check that backups are running correctly:

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:
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:
Restart the application after updating your configuration:

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:
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:
Only disable TLS verification in development or trusted environments. In production, always use proper TLS verification to ensure secure email delivery.
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:
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

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.
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.
The following commands will delete all existing data in your Sure database. Only proceed if you’re comfortable losing this data.
Reset the database:
The last command verifies the issue is fixed.

Turning on Active Record encryption after first boot

Self-hosted Sure can derive Active Record encryption keys from SECRET_KEY_BASE automatically. If you prefer dedicated keys, you can add:
If you add those keys after your instance already has data, the normal app startup path is not enough to rewrite older plaintext values:
  • db:prepare still runs automatically on startup for schema setup and migrations.
  • New writes use encryption after the app boots with the keys.
  • Existing rows are not automatically re-encrypted.
Run the backfill task once after the app is up:
The task is idempotent, so it is safe to rerun if needed.

Slow CSV imports

If CSV imports are processing rows slower than expected, check your worker logs for errors:
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: