Initial commit: self-hosted SFP server deployment repository
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>
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
# 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. **Gitea token** for `source.flxbl.io` (provided by flxbl)
|
||||
7. **Docker registry token** for pulling SFP server images
|
||||
8. **Port 443** open on the server firewall
|
||||
|
||||
For detailed requirements, see the [Self-Hosting Prerequisites](https://source.flxbl.io/flxbl/sfp-pro/src/branch/main/docs/self-hosting-prerequisites.md) 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
|
||||
|
||||
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:
|
||||
- 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)
|
||||
|
||||
1. Create a GitHub OAuth App ([instructions](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app))
|
||||
- **Homepage URL**: `https://your-domain`
|
||||
- **Callback URL**: `https://your-domain/auth/v1/callback`
|
||||
2. SSH to the server and add to `.env`:
|
||||
```bash
|
||||
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](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app))
|
||||
- **Webhook URL**: `https://your-domain/sfp/api/webhook/github`
|
||||
2. Configure via the integration API (`POST /api/integrations`) or add to `.env`:
|
||||
```bash
|
||||
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 "Install SFP CLI"
|
||||
- Verify `GITEA_TOKEN` is valid and has read access to `flxbl/sfp-pro` releases
|
||||
- Check if a release exists with a `.deb` asset
|
||||
|
||||
### 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`
|
||||
|
||||
### Update fails during image pull
|
||||
- Verify `DOCKER_REGISTRY_TOKEN` is valid
|
||||
- Verify `DOCKER_REGISTRY` matches where your images are hosted
|
||||
- Check if the specified `IMAGE_TAG` exists 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 |
|
||||
Reference in New Issue
Block a user