Provides GitHub Actions workflows for customers to initialize, update, and monitor their self-hosted SFP Pro server instances. Includes a composite action for CLI installation from Gitea and SSH setup. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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:
- Linux server -- x86_64, 8+ vCPU, 32+ GB RAM, 250+ GB SSD
- Docker Engine 24+ and Docker Compose v2 installed on the server
- Domain name (FQDN) resolving to the server
- TLS certificate + private key (PEM format) -- or use Let's Encrypt for automatic TLS
- SSH access to the server from GitHub Actions runners
- Gitea token for
source.flxbl.io(provided by flxbl) - Docker registry token for pulling SFP server images
- 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 |
GITEA_TOKEN |
Token for source.flxbl.io (CLI downloads) |
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 |
No | -- | Full Docker image path (e.g., source.flxbl.io/flxbl/sfp-server) |
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 |
SFP_CLI_VERSION |
No | latest |
Specific SFP CLI version to use |
4. Run Initialization
- Go to Actions > Initialize SFP Server
- Click Run workflow
- Select the TLS mode (
customorletsencrypt) - Click Run workflow
The init process will:
- Install SFP CLI on the GitHub Actions runner
- 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)
- Create a GitHub OAuth App (instructions)
- Homepage URL:
https://your-domain - Callback URL:
https://your-domain/auth/v1/callback
- Homepage URL:
- 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 - Restart services:
docker compose restart supabase-auth
GitHub App (for repository operations)
- Create a GitHub App (instructions)
- Webhook URL:
https://your-domain/sfp/api/webhook/github
- Webhook URL:
- 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_TOKENOPENAI_API_KEY,AI_PROVIDER,AI_MODEL
Updating
To update the server to a new version:
- Go to Actions > Update SFP Server
- Click Run workflow
- Optionally specify a Docker tag (defaults to
IMAGE_TAGvariable orlatest) - Configure drain and backup options as needed
- Click Run workflow
The update process:
- Backs up current configuration (unless skipped)
- Waits for active workflows to complete (unless skipped)
- Updates configuration files
- Caddy serves a maintenance page while app services restart
- Pulls new Docker images
- 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
.envfile from{BASE_DIR}/tenants/{TENANT_NAME}/.env - The
sfp server updatecommand automatically backs up configuration before each update (stored inbackups/on the server) - Store a copy of
.envin 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 "Install SFP CLI"
- Verify
GITEA_TOKENis valid and has read access toflxbl/sfp-proreleases - Check if a release exists with a
.debasset
Workflow fails at SSH connection
- Verify
SSH_PRIVATE_KEYis the full private key (including headers) - Verify
SSH_HOSTis reachable from GitHub Actions runners - Verify the SSH user has permission to run
dockercommands
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
Update fails during image pull
- Verify
DOCKER_REGISTRY_TOKENis valid - Verify
DOCKER_REGISTRYmatches where your images are hosted - Check if the specified
IMAGE_TAGexists in the registry
File Reference
| File | Purpose |
|---|---|
.github/actions/setup-sfp/action.yml |
Composite action: install SFP CLI + 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 |