flxbl-bot 00a2a1347a Fix SSH key permissions inside Docker container
Run container as root and chmod the mounted SSH key before
executing the sfp CLI command.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 11:26:03 +10:00

SFP Server Self-Hosted Deployment

Automated deployment and management of self-hosted SFP Pro server instances using GitHub Actions.

Overview

This repository provides GitHub Actions workflows to:

  • Initialize a new SFP server on your infrastructure
  • Update an existing server to the latest version
  • Check for new versions on a weekly schedule

The workflows connect to your server via SSH, download the SFP CLI from Gitea, and run the appropriate server lifecycle commands.

Prerequisites

Before using this repository, ensure you have:

  1. Linux server -- x86_64, 8+ vCPU, 32+ GB RAM, 250+ GB SSD
  2. Docker Engine 24+ and Docker Compose v2 installed on the server
  3. Domain name (FQDN) resolving to the server
  4. TLS certificate + private key (PEM format) -- or use Let's Encrypt for automatic TLS
  5. SSH access to the server from GitHub Actions runners
  6. Docker registry token for pulling SFP server images (the CLI runs from inside the image)
  7. Port 443 open on the server firewall

For detailed requirements, see the Self-Hosting Prerequisites guide.

Quick Setup

1. Fork or Clone This Repository

Fork this repository to your GitHub organization, or clone and push to a new private repository.

2. Configure GitHub Secrets

Go to Settings > Secrets and variables > Actions > Secrets and add:

Secret Description
SSH_PRIVATE_KEY SSH private key for connecting to the server
DOCKER_REGISTRY_TOKEN Token for authenticating with your Docker registry
ORIGIN_CERT TLS certificate in base64 PEM (only if using custom TLS)
ORIGIN_KEY TLS private key in base64 PEM (only if using custom TLS)

3. Configure GitHub Variables

Go to Settings > Secrets and variables > Actions > Variables and add:

Variable Required Default Description
SSH_HOST Yes -- Server hostname or IP address
TENANT_NAME Yes -- Tenant identifier (lowercase, alphanumeric, hyphens)
DOMAIN Yes -- FQDN for the server (e.g., sfp.yourcompany.com)
DOCKER_REGISTRY Yes -- Docker registry hostname (e.g., source.flxbl.io)
SSH_USER No root SSH username
IMAGE_FQDN Yes -- Full Docker image path (e.g., ghcr.io/flxbl-io/sfp-server-rc)
IMAGE_TAG No latest Docker image tag (e.g., latest, v3-latest, 3.28.0)
WORKERS No 1 Number of background workers (1-10)
BASE_DIR No ./sfp-server Base directory on the server

4. Run Initialization

  1. Go to Actions > Initialize SFP Server
  2. Click Run workflow
  3. Select the TLS mode (custom or letsencrypt)
  4. Click Run workflow

The init process will:

  • Pull the SFP server Docker image (the CLI runs from inside it)
  • Connect to your server via SSH
  • Create the directory structure and configuration
  • Auto-generate database credentials
  • Pull Docker images from your registry
  • Start all services
  • Create the default admin user

The admin credentials will be displayed in the workflow output.

5. Verify

Open https://your-domain in a browser to verify the server is accessible.

Post-Init: Integration Setup

After initialization, configure integrations by SSH-ing to the server and editing the .env file, or via the integration API:

GitHub OAuth (for user login)

  1. Create a GitHub OAuth App (instructions)
    • Homepage URL: https://your-domain
    • Callback URL: https://your-domain/auth/v1/callback
  2. SSH to the server and add to .env:
    GITHUB_OAUTH_ENABLED=true
    GITHUB_OAUTH_CLIENT_ID=your-client-id
    GITHUB_OAUTH_CLIENT_SECRET=your-client-secret
    
  3. Restart services: docker compose restart supabase-auth

GitHub App (for repository operations)

  1. Create a GitHub App (instructions)
    • Webhook URL: https://your-domain/sfp/api/webhook/github
  2. Configure via the integration API (POST /api/integrations) or add to .env:
    GITHUB_APP_ID=your-app-id
    GITHUB_APP_PRIVATE_KEY=your-private-key-pem
    

Slack, AI, and Other Integrations

Add the relevant environment variables to .env on the server and restart:

  • SLACK_APP_TOKEN, SLACK_SIGNING_SECRET, SLACK_BOT_TOKEN
  • OPENAI_API_KEY, AI_PROVIDER, AI_MODEL

Updating

To update the server to a new version:

  1. Go to Actions > Update SFP Server
  2. Click Run workflow
  3. Optionally specify a Docker tag (defaults to IMAGE_TAG variable or latest)
  4. Configure drain and backup options as needed
  5. Click Run workflow

The update process:

  1. Backs up current configuration (unless skipped)
  2. Waits for active workflows to complete (unless skipped)
  3. Updates configuration files
  4. Caddy serves a maintenance page while app services restart
  5. Pulls new Docker images
  6. Starts services and runs database migrations

Version Checks

The Check for Updates workflow runs weekly (Monday 8 AM UTC) and:

  • Queries Gitea for the latest release
  • Compares with the currently deployed version
  • Creates a GitHub Issue if a newer version is available

You can also trigger it manually from Actions > Check for Updates.

Backup and Recovery

The server's .env file contains auto-generated credentials that are critical for operation:

  • Supabase JWT secret and API keys
  • Database passwords
  • Hatchet workflow engine tokens

These are NOT stored in GitHub -- they live on the server.

We recommend:

  • Regularly backing up the .env file from {BASE_DIR}/tenants/{TENANT_NAME}/.env
  • The sfp server update command automatically backs up configuration before each update (stored in backups/ on the server)
  • Store a copy of .env in a secure location (e.g., password manager, secrets vault)

If the server is destroyed, you will need the backed-up .env to restore without re-initializing.

Troubleshooting

Workflow fails at image pull

  • Verify DOCKER_REGISTRY_TOKEN is valid
  • Verify DOCKER_REGISTRY and IMAGE_FQDN are correct
  • Check if the specified IMAGE_TAG exists in the registry

Workflow fails at SSH connection

  • Verify SSH_PRIVATE_KEY is the full private key (including headers)
  • Verify SSH_HOST is reachable from GitHub Actions runners
  • Verify the SSH user has permission to run docker commands

Server not accessible after init

  • Check port 443 is open in the firewall
  • Verify DNS resolves to the server IP
  • Check TLS certificate is valid for the domain
  • SSH to the server and check logs: docker compose logs caddy

File Reference

File Purpose
.github/actions/setup-sfp/action.yml Composite action: pull Docker image + configure SSH
.github/workflows/init.yml One-time server initialization workflow
.github/workflows/update.yml Server update workflow
.github/workflows/check-update.yml Weekly version check workflow
config/server-config.example.json Example JSON config for manual (non-workflow) init
.env.template Reference for all configuration variables
S
Description
Template for sfp-server-mangement using github actions
Readme 89 KiB