diff --git a/.env.template b/.env.template index 4ac78b8..7f24321 100644 --- a/.env.template +++ b/.env.template @@ -12,13 +12,10 @@ # ============================================================ # Token to authenticate with Docker registry for pulling images +# The SFP CLI is also used directly from inside the pulled image # GitHub Secret: DOCKER_REGISTRY_TOKEN # DOCKER_REGISTRY_TOKEN= -# Token for source.flxbl.io Gitea API (CLI download) -# GitHub Secret: GITEA_TOKEN -# GITEA_TOKEN= - # SSH private key to access the remote server # GitHub Secret: SSH_PRIVATE_KEY # SSH_PRIVATE_KEY= @@ -60,8 +57,9 @@ # GitHub Variable: SSH_USER # SSH_USER=root -# Full Docker image path (optional, overrides default) -# Example: source.flxbl.io/flxbl/sfp-server +# Full Docker image path (required) +# Example: ghcr.io/flxbl-io/sfp-server-rc, source.flxbl.io/flxbl/sfp-server +# The sfp CLI is used directly from inside this image # GitHub Variable: IMAGE_FQDN # IMAGE_FQDN= @@ -78,10 +76,6 @@ # GitHub Variable: BASE_DIR # BASE_DIR=./sfp-server -# SFP CLI version to download (optional, default: latest) -# GitHub Variable: SFP_CLI_VERSION -# SFP_CLI_VERSION=latest - # ============================================================ # Auto-generated during init (persisted on server's .env) # ============================================================ diff --git a/.github/actions/setup-sfp/action.yml b/.github/actions/setup-sfp/action.yml index b75594e..a3de6cf 100644 --- a/.github/actions/setup-sfp/action.yml +++ b/.github/actions/setup-sfp/action.yml @@ -1,89 +1,62 @@ name: 'Setup SFP CLI and SSH' -description: 'Downloads SFP CLI from Gitea releases and configures SSH access to the target server' +description: 'Pulls the SFP server Docker image and configures SSH access. The CLI is used directly from inside the container.' inputs: - gitea-token: - description: 'Token for authenticating to source.flxbl.io Gitea API' + docker-registry: + description: 'Docker registry hostname (e.g., ghcr.io, source.flxbl.io)' required: true + docker-registry-token: + description: 'Token for authenticating with the Docker registry' + required: true + docker-registry-user: + description: 'Username for Docker registry authentication' + required: false + default: 'sfp' + image-fqdn: + description: 'Full Docker image path (e.g., ghcr.io/flxbl-io/sfp-server-rc)' + required: true + image-tag: + description: 'Docker image tag' + required: false + default: 'latest' ssh-private-key: description: 'SSH private key for connecting to the remote server' required: true ssh-host: description: 'Hostname or IP of the target server' required: true - cli-version: - description: 'SFP CLI version to install (default: latest non-draft release)' - required: false - default: 'latest' + +outputs: + sfp-image: + description: 'Full Docker image reference that was pulled' + value: ${{ steps.pull.outputs.image }} runs: using: 'composite' steps: - - name: Install SFP CLI from Gitea + - name: Pull SFP server image + id: pull shell: bash env: - GITEA_TOKEN: ${{ inputs.gitea-token }} - CLI_VERSION: ${{ inputs.cli-version }} + DOCKER_REGISTRY: ${{ inputs.docker-registry }} + DOCKER_REGISTRY_TOKEN: ${{ inputs.docker-registry-token }} + DOCKER_REGISTRY_USER: ${{ inputs.docker-registry-user }} + IMAGE_FQDN: ${{ inputs.image-fqdn }} + IMAGE_TAG: ${{ inputs.image-tag }} run: | - echo "::group::Install SFP CLI" + echo "::group::Pull SFP server image" - GITEA_API="https://source.flxbl.io/api/v1/repos/flxbl/sfp-pro/releases" + echo "Logging in to $DOCKER_REGISTRY..." + echo "$DOCKER_REGISTRY_TOKEN" | docker login "$DOCKER_REGISTRY" -u "$DOCKER_REGISTRY_USER" --password-stdin - if [ "$CLI_VERSION" = "latest" ]; then - echo "Fetching latest release from Gitea..." - RELEASE_INFO=$(curl -sf -H "Authorization: token $GITEA_TOKEN" \ - "${GITEA_API}?limit=10") + IMAGE="${IMAGE_FQDN}:${IMAGE_TAG}" + echo "Pulling $IMAGE..." + docker pull "$IMAGE" - if [ $? -ne 0 ] || [ -z "$RELEASE_INFO" ]; then - echo "Failed to fetch releases from Gitea API" - exit 1 - fi - - # Find first non-draft release that has a .deb asset - DEB_URL=$(echo "$RELEASE_INFO" | jq -r ' - [.[] | select(.draft == false)] | first | - .assets[] | select(.name | test("_linux_amd64\\.deb$")) | - .browser_download_url') - else - echo "Fetching release matching version: $CLI_VERSION..." - RELEASE_INFO=$(curl -sf -H "Authorization: token $GITEA_TOKEN" \ - "${GITEA_API}?limit=50") - - if [ $? -ne 0 ] || [ -z "$RELEASE_INFO" ]; then - echo "Failed to fetch releases from Gitea API" - exit 1 - fi - - # Find release with matching version in asset names - DEB_URL=$(echo "$RELEASE_INFO" | jq -r --arg ver "$CLI_VERSION" ' - [.[] | select(.draft == false) | - select(.assets[]? | .name | contains($ver))] | first | - .assets[] | select(.name | test("_linux_amd64\\.deb$")) | - .browser_download_url') - fi - - if [ -z "$DEB_URL" ] || [ "$DEB_URL" = "null" ]; then - echo "No .deb package found for version: $CLI_VERSION" - echo "Available releases:" - echo "$RELEASE_INFO" | jq -r '[.[] | select(.draft == false)] | .[0:5] | .[] | " - \(.tag_name): \([.assets[].name] | join(", "))"' - exit 1 - fi - - echo "Downloading SFP CLI from: $DEB_URL" - curl -L -f -H "Authorization: token $GITEA_TOKEN" -o /tmp/sfp-pro.deb "$DEB_URL" - - if [ $? -ne 0 ]; then - echo "Failed to download SFP CLI package" - exit 1 - fi - - echo "Installing SFP CLI..." - sudo dpkg -i /tmp/sfp-pro.deb || sudo apt-get install -f -y - rm -f /tmp/sfp-pro.deb - - echo "SFP CLI installed:" - sfp --version + echo "Verifying sfp CLI inside image..." + docker run --rm "$IMAGE" sfp --version + echo "image=$IMAGE" >> $GITHUB_OUTPUT echo "::endgroup::" - name: Setup SSH diff --git a/.github/workflows/check-update.yml b/.github/workflows/check-update.yml index fc97f1a..5195636 100644 --- a/.github/workflows/check-update.yml +++ b/.github/workflows/check-update.yml @@ -1,4 +1,4 @@ -name: Check for Updates +name: Check Deployed Version on: schedule: @@ -7,38 +7,10 @@ on: jobs: check: - name: 'Check for new version' + name: 'Check deployed version' runs-on: ubuntu-latest steps: - - name: Check latest version on Gitea - id: check - env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - run: | - echo "Checking for latest SFP Server release..." - - RELEASE_INFO=$(curl -sf -H "Authorization: token $GITEA_TOKEN" \ - "https://source.flxbl.io/api/v1/repos/flxbl/sfp-pro/releases?limit=10") - - if [ $? -ne 0 ] || [ -z "$RELEASE_INFO" ]; then - echo "Failed to fetch releases from Gitea API" - exit 1 - fi - - # Get latest non-draft release - LATEST_TAG=$(echo "$RELEASE_INFO" | jq -r '[.[] | select(.draft == false)] | first | .tag_name // "unknown"') - LATEST_DATE=$(echo "$RELEASE_INFO" | jq -r '[.[] | select(.draft == false)] | first | .published_at // "unknown"') - LATEST_BODY=$(echo "$RELEASE_INFO" | jq -r '[.[] | select(.draft == false)] | first | .body // ""') - - echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT - echo "latest_date=$LATEST_DATE" >> $GITHUB_OUTPUT - - # Save release body for the issue - echo "$LATEST_BODY" > /tmp/release_notes.md - - echo "Latest release: $LATEST_TAG (published: $LATEST_DATE)" - - name: Check current deployed version id: current env: @@ -50,7 +22,7 @@ jobs: BASE_DIR="${{ vars.BASE_DIR || './sfp-server' }}" if [ -z "$SSH_HOST" ] || [ -z "$SSH_PRIVATE_KEY" ]; then - echo "SSH not configured, skipping deployed version check" + echo "SSH not configured, cannot check deployed version" echo "current_tag=unknown" >> $GITHUB_OUTPUT exit 0 fi @@ -64,102 +36,35 @@ jobs: "grep '^IMAGE_TAG=' ${BASE_DIR}/tenants/${TENANT}/.env 2>/dev/null | cut -d= -f2" \ 2>/dev/null || echo "unknown") + CURRENT_FQDN=$(ssh -i ~/.ssh/deploy_key "$SSH_USER@$SSH_HOST" \ + "grep '^IMAGE_FQDN=' ${BASE_DIR}/tenants/${TENANT}/.env 2>/dev/null | cut -d= -f2" \ + 2>/dev/null || echo "unknown") + echo "current_tag=$CURRENT_TAG" >> $GITHUB_OUTPUT - echo "Currently deployed: $CURRENT_TAG" + echo "current_fqdn=$CURRENT_FQDN" >> $GITHUB_OUTPUT + echo "Currently deployed: $CURRENT_FQDN:$CURRENT_TAG" - name: Generate summary run: | - LATEST="${{ steps.check.outputs.latest_tag }}" - CURRENT="${{ steps.current.outputs.current_tag }}" + CURRENT_TAG="${{ steps.current.outputs.current_tag }}" + CURRENT_FQDN="${{ steps.current.outputs.current_fqdn }}" + CONFIGURED_TAG="${{ vars.IMAGE_TAG || 'latest' }}" + CONFIGURED_FQDN="${{ vars.IMAGE_FQDN }}" - echo "## SFP Server Version Check" >> $GITHUB_STEP_SUMMARY + echo "## SFP Server Version Status" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "| | Version |" >> $GITHUB_STEP_SUMMARY - echo "|---|---------|" >> $GITHUB_STEP_SUMMARY - echo "| Latest Available | \`$LATEST\` |" >> $GITHUB_STEP_SUMMARY - echo "| Currently Deployed | \`$CURRENT\` |" >> $GITHUB_STEP_SUMMARY + echo "| | Image | Tag |" >> $GITHUB_STEP_SUMMARY + echo "|---|-------|-----|" >> $GITHUB_STEP_SUMMARY + echo "| **Deployed** | \`$CURRENT_FQDN\` | \`$CURRENT_TAG\` |" >> $GITHUB_STEP_SUMMARY + echo "| **Configured** | \`$CONFIGURED_FQDN\` | \`$CONFIGURED_TAG\` |" >> $GITHUB_STEP_SUMMARY - if [ "$LATEST" != "$CURRENT" ] && [ "$CURRENT" != "unknown" ] && [ "$LATEST" != "unknown" ]; then + if [ "$CURRENT_TAG" != "$CONFIGURED_TAG" ] && [ "$CURRENT_TAG" != "unknown" ]; then echo "" >> $GITHUB_STEP_SUMMARY - echo "A newer version is available. Run the **Update SFP Server** workflow to update." >> $GITHUB_STEP_SUMMARY - elif [ "$CURRENT" = "unknown" ]; then + echo "Deployed version differs from configured version. Run the **Update SFP Server** workflow to update." >> $GITHUB_STEP_SUMMARY + elif [ "$CURRENT_TAG" = "unknown" ]; then echo "" >> $GITHUB_STEP_SUMMARY echo "Could not determine currently deployed version." >> $GITHUB_STEP_SUMMARY else echo "" >> $GITHUB_STEP_SUMMARY - echo "Server is up to date." >> $GITHUB_STEP_SUMMARY + echo "Server is running the configured version." >> $GITHUB_STEP_SUMMARY fi - - - name: Create or update issue if update available - if: steps.check.outputs.latest_tag != steps.current.outputs.current_tag && steps.current.outputs.current_tag != 'unknown' && steps.check.outputs.latest_tag != 'unknown' - uses: actions/github-script@v7 - with: - script: | - const title = 'New SFP Server Version Available'; - const latest = '${{ steps.check.outputs.latest_tag }}'; - const current = '${{ steps.current.outputs.current_tag }}'; - const fs = require('fs'); - const releaseNotes = fs.existsSync('/tmp/release_notes.md') - ? fs.readFileSync('/tmp/release_notes.md', 'utf8') - : ''; - - const body = [ - `## New Version Available`, - ``, - `| | Version |`, - `|---|---------|`, - `| **Latest** | \`${latest}\` |`, - `| **Current** | \`${current}\` |`, - ``, - `### How to Update`, - `1. Go to **Actions** > **Update SFP Server**`, - `2. Click **Run workflow**`, - `3. Optionally specify the docker tag: \`${latest}\``, - ``, - releaseNotes ? `### Release Notes\n\n${releaseNotes}` : '', - ``, - `---`, - `*This issue was automatically created by the version check workflow.*` - ].join('\n'); - - // Check for existing open issue - const issues = await github.rest.issues.listForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - labels: 'update-available', - }); - - const existing = issues.data.find(i => i.title === title); - - if (existing) { - await github.rest.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: existing.number, - body: body, - }); - console.log(`Updated issue #${existing.number}`); - } else { - // Create label if it doesn't exist - try { - await github.rest.issues.createLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - name: 'update-available', - color: '0075ca', - description: 'A new SFP Server version is available', - }); - } catch (e) { - // Label may already exist - } - - const issue = await github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: title, - body: body, - labels: ['update-available'], - }); - console.log(`Created issue #${issue.data.number}`); - } diff --git a/.github/workflows/init.yml b/.github/workflows/init.yml index 575cde3..d59b491 100644 --- a/.github/workflows/init.yml +++ b/.github/workflows/init.yml @@ -11,9 +11,9 @@ on: description: 'TLS certificate mode' type: choice options: - - 'custom' - 'letsencrypt' - default: 'custom' + - 'custom' + default: 'letsencrypt' jobs: init: @@ -31,6 +31,7 @@ jobs: [ -z "${{ vars.TENANT_NAME }}" ] && MISSING="$MISSING TENANT_NAME" [ -z "${{ vars.DOMAIN }}" ] && MISSING="$MISSING DOMAIN" [ -z "${{ vars.DOCKER_REGISTRY }}" ] && MISSING="$MISSING DOCKER_REGISTRY" + [ -z "${{ vars.IMAGE_FQDN }}" ] && MISSING="$MISSING IMAGE_FQDN" if [ -n "$MISSING" ]; then echo "Missing required GitHub Variables:$MISSING" @@ -40,12 +41,15 @@ jobs: fi - name: Setup SFP CLI and SSH + id: setup uses: ./.github/actions/setup-sfp with: - gitea-token: ${{ secrets.GITEA_TOKEN }} + docker-registry: ${{ vars.DOCKER_REGISTRY }} + docker-registry-token: ${{ secrets.DOCKER_REGISTRY_TOKEN }} + image-fqdn: ${{ vars.IMAGE_FQDN }} + image-tag: ${{ vars.IMAGE_TAG || 'latest' }} ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} ssh-host: ${{ vars.SSH_HOST }} - cli-version: ${{ vars.SFP_CLI_VERSION || 'latest' }} - name: Initialize server env: @@ -53,6 +57,7 @@ jobs: DOCKER_REGISTRY_TOKEN: ${{ secrets.DOCKER_REGISTRY_TOKEN }} ORIGIN_CERT: ${{ secrets.ORIGIN_CERT }} ORIGIN_KEY: ${{ secrets.ORIGIN_KEY }} + SFP_IMAGE: ${{ steps.setup.outputs.sfp-image }} run: | TENANT="${{ vars.TENANT_NAME }}" DOMAIN="${{ vars.DOMAIN }}" @@ -61,6 +66,8 @@ jobs: TLS_MODE="${{ inputs.tls_mode }}" WORKERS="${{ vars.WORKERS || '1' }}" BASE_DIR="${{ vars.BASE_DIR || './sfp-server' }}" + IMAGE_FQDN="${{ vars.IMAGE_FQDN }}" + IMAGE_TAG="${{ vars.IMAGE_TAG || 'latest' }}" echo "Initializing SFP Server" echo " Tenant: $TENANT" @@ -68,7 +75,7 @@ jobs: echo " Host: $SSH_HOST" echo " TLS Mode: $TLS_MODE" echo " Workers: $WORKERS" - echo " Registry: $DOCKER_REGISTRY" + echo " Image: $SFP_IMAGE" # Build the init command INIT_CMD="sfp server init" @@ -82,38 +89,30 @@ jobs: INIT_CMD="$INIT_CMD --secrets-provider custom" INIT_CMD="$INIT_CMD --no-interactive" INIT_CMD="$INIT_CMD --ssh-connection \"$SSH_USER@$SSH_HOST\"" - INIT_CMD="$INIT_CMD --identity-file ~/.ssh/deploy_key" + INIT_CMD="$INIT_CMD --identity-file /root/.ssh/deploy_key" + INIT_CMD="$INIT_CMD --image \"${IMAGE_FQDN}:${IMAGE_TAG}\"" - # Add image override if IMAGE_FQDN is configured - IMAGE_FQDN="${{ vars.IMAGE_FQDN }}" - IMAGE_TAG="${{ vars.IMAGE_TAG || 'latest' }}" - if [ -n "$IMAGE_FQDN" ]; then - INIT_CMD="$INIT_CMD --image \"${IMAGE_FQDN}:${IMAGE_TAG}\"" - fi - - # Add force flag if requested if [ "${{ inputs.force }}" = "true" ]; then INIT_CMD="$INIT_CMD --force" fi - eval "$INIT_CMD" + # Run sfp CLI from inside the Docker image + docker run --rm \ + -v ~/.ssh/deploy_key:/root/.ssh/deploy_key:ro \ + -v ~/.ssh/known_hosts:/root/.ssh/known_hosts:ro \ + -e DOCKER_REGISTRY \ + -e DOCKER_REGISTRY_TOKEN \ + -e ORIGIN_CERT \ + -e ORIGIN_KEY \ + "$SFP_IMAGE" \ + bash -c "$INIT_CMD" - name: Output init results if: always() run: | TENANT="${{ vars.TENANT_NAME }}" - RESULT_FILE="sfp-server-init-${TENANT}.json" echo "## SFP Server Initialization" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - - if [ -f "$RESULT_FILE" ]; then - echo "### Results" >> $GITHUB_STEP_SUMMARY - echo '```json' >> $GITHUB_STEP_SUMMARY - cat "$RESULT_FILE" | jq '.' >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - fi - echo "" >> $GITHUB_STEP_SUMMARY echo "### Configuration" >> $GITHUB_STEP_SUMMARY echo "| Setting | Value |" >> $GITHUB_STEP_SUMMARY @@ -122,8 +121,7 @@ jobs: echo "| Domain | ${{ vars.DOMAIN }} |" >> $GITHUB_STEP_SUMMARY echo "| Host | ${{ vars.SSH_HOST }} |" >> $GITHUB_STEP_SUMMARY echo "| TLS Mode | ${{ inputs.tls_mode }} |" >> $GITHUB_STEP_SUMMARY - echo "| Registry | ${{ vars.DOCKER_REGISTRY }} |" >> $GITHUB_STEP_SUMMARY - + echo "| Image | ${{ steps.setup.outputs.sfp-image }} |" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### Next Steps" >> $GITHUB_STEP_SUMMARY echo "1. Verify the server is accessible at \`https://${{ vars.DOMAIN }}\`" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml index a832609..444ac43 100644 --- a/.github/workflows/update.yml +++ b/.github/workflows/update.yml @@ -35,6 +35,7 @@ jobs: [ -z "${{ vars.SSH_HOST }}" ] && MISSING="$MISSING SSH_HOST" [ -z "${{ vars.TENANT_NAME }}" ] && MISSING="$MISSING TENANT_NAME" [ -z "${{ vars.DOCKER_REGISTRY }}" ] && MISSING="$MISSING DOCKER_REGISTRY" + [ -z "${{ vars.IMAGE_FQDN }}" ] && MISSING="$MISSING IMAGE_FQDN" if [ -n "$MISSING" ]; then echo "Missing required GitHub Variables:$MISSING" @@ -43,35 +44,43 @@ jobs: exit 1 fi + - name: Resolve image tag + id: resolve + run: | + TAG="${{ inputs.docker_tag }}" + if [ -z "$TAG" ]; then + TAG="${{ vars.IMAGE_TAG || 'latest' }}" + fi + echo "tag=$TAG" >> $GITHUB_OUTPUT + - name: Setup SFP CLI and SSH + id: setup uses: ./.github/actions/setup-sfp with: - gitea-token: ${{ secrets.GITEA_TOKEN }} + docker-registry: ${{ vars.DOCKER_REGISTRY }} + docker-registry-token: ${{ secrets.DOCKER_REGISTRY_TOKEN }} + image-fqdn: ${{ vars.IMAGE_FQDN }} + image-tag: ${{ steps.resolve.outputs.tag }} ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} ssh-host: ${{ vars.SSH_HOST }} - cli-version: ${{ vars.SFP_CLI_VERSION || 'latest' }} - name: Update server env: DOCKER_REGISTRY: ${{ vars.DOCKER_REGISTRY }} DOCKER_REGISTRY_TOKEN: ${{ secrets.DOCKER_REGISTRY_TOKEN }} + SFP_IMAGE: ${{ steps.setup.outputs.sfp-image }} run: | TENANT="${{ vars.TENANT_NAME }}" SSH_USER="${{ vars.SSH_USER || 'root' }}" SSH_HOST="${{ vars.SSH_HOST }}" BASE_DIR="${{ vars.BASE_DIR || './sfp-server' }}" - - # Resolve image tag: workflow input > variable > "latest" - TAG="${{ inputs.docker_tag }}" - if [ -z "$TAG" ]; then - TAG="${{ vars.IMAGE_TAG || 'latest' }}" - fi + TAG="${{ steps.resolve.outputs.tag }}" echo "Updating SFP Server" echo " Tenant: $TENANT" echo " Host: $SSH_HOST" echo " Tag: $TAG" - echo " Registry: $DOCKER_REGISTRY" + echo " Image: $SFP_IMAGE" # Build the update command UPDATE_CMD="sfp server update" @@ -79,7 +88,7 @@ jobs: UPDATE_CMD="$UPDATE_CMD --base-dir \"$BASE_DIR\"" UPDATE_CMD="$UPDATE_CMD --secrets-provider custom" UPDATE_CMD="$UPDATE_CMD --ssh-connection \"$SSH_USER@$SSH_HOST\"" - UPDATE_CMD="$UPDATE_CMD --identity-file ~/.ssh/deploy_key" + UPDATE_CMD="$UPDATE_CMD --identity-file /root/.ssh/deploy_key" UPDATE_CMD="$UPDATE_CMD --docker-tag \"$TAG\"" if [ "${{ inputs.skip_drain }}" = "true" ]; then @@ -92,15 +101,19 @@ jobs: UPDATE_CMD="$UPDATE_CMD --skip-backup" fi - eval "$UPDATE_CMD" + # Run sfp CLI from inside the Docker image + docker run --rm \ + -v ~/.ssh/deploy_key:/root/.ssh/deploy_key:ro \ + -v ~/.ssh/known_hosts:/root/.ssh/known_hosts:ro \ + -e DOCKER_REGISTRY \ + -e DOCKER_REGISTRY_TOKEN \ + "$SFP_IMAGE" \ + bash -c "$UPDATE_CMD" - name: Output update results if: always() run: | - TAG="${{ inputs.docker_tag }}" - if [ -z "$TAG" ]; then - TAG="${{ vars.IMAGE_TAG || 'latest' }}" - fi + TAG="${{ steps.resolve.outputs.tag }}" echo "## SFP Server Update" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY @@ -108,7 +121,6 @@ jobs: echo "|---------|-------|" >> $GITHUB_STEP_SUMMARY echo "| Tenant | ${{ vars.TENANT_NAME }} |" >> $GITHUB_STEP_SUMMARY echo "| Host | ${{ vars.SSH_HOST }} |" >> $GITHUB_STEP_SUMMARY - echo "| Image Tag | $TAG |" >> $GITHUB_STEP_SUMMARY - echo "| Registry | ${{ vars.DOCKER_REGISTRY }} |" >> $GITHUB_STEP_SUMMARY + echo "| Image | ${{ steps.setup.outputs.sfp-image }} |" >> $GITHUB_STEP_SUMMARY echo "| Skip Drain | ${{ inputs.skip_drain }} |" >> $GITHUB_STEP_SUMMARY echo "| Skip Backup | ${{ inputs.skip_backup }} |" >> $GITHUB_STEP_SUMMARY diff --git a/README.md b/README.md index e47cad1..5a3c85c 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,8 @@ Before using this repository, ensure you have: 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 +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](https://source.flxbl.io/flxbl/sfp-pro/src/branch/main/docs/self-hosting-prerequisites.md) guide. @@ -40,7 +39,6 @@ Go to **Settings** > **Secrets and variables** > **Actions** > **Secrets** and a | 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)* | @@ -56,11 +54,10 @@ Go to **Settings** > **Secrets and variables** > **Actions** > **Variables** and | `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_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 | -| `SFP_CLI_VERSION` | No | `latest` | Specific SFP CLI version to use | ### 4. Run Initialization @@ -70,7 +67,7 @@ Go to **Settings** > **Secrets and variables** > **Actions** > **Variables** and 4. Click **Run workflow** The init process will: -- Install SFP CLI on the GitHub Actions runner +- 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 @@ -162,9 +159,10 @@ If the server is destroyed, you will need the backed-up `.env` to restore withou ## 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 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) @@ -177,16 +175,11 @@ If the server is destroyed, you will need the backed-up `.env` to restore withou - 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/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 |