> For the complete documentation index, see [llms.txt](https://docs.flxbl.io/flxbl/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flxbl.io/flxbl/sfp-server/setting-up/prerequisites.md).

# Prerequisites

This document outlines everything you need to prepare **before** running `sfp server init`. Completing these steps in advance will ensure a smooth installation.

Download the sfp CLI from [source.flxbl.io/flxbl/sfp-pro/releases](https://source.flxbl.io/flxbl/sfp-pro/releases). Install it on whichever machine will run the init command — your local workstation (remote via SSH) or the server itself (local mode).

***

## **\[1]** Server Requirements

### **\[1.a]** Hardware

| Tier            | vCPU | RAM   | Disk       | Suitable For                               |
| --------------- | ---- | ----- | ---------- | ------------------------------------------ |
| **Minimum**     | 4    | 16 GB | 100 GB SSD | Small team (< 10 developers)               |
| **Recommended** | 8    | 32 GB | 250 GB SSD | Medium team (10–50 developers)             |
| **Production**  | 16   | 64 GB | 500 GB SSD | Large team (50+), heavy parallel workflows |

> Disk should be SSD. Workflow orchestration and database queries are I/O intensive.

### **\[1.b]** Operating System

* **Linux x86\_64** (Ubuntu 22.04+ or Debian 12+ recommended)
* ARM64 (e.g., AWS Graviton) is **not supported** at this time

### **\[1.c]** Software

| Software                                                      | Minimum Version                        | How to Check                                                                                                                                                                                                       |
| ------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Docker Engine (default) or Podman                             | Docker 24.x+ / Podman 4.x+             | `docker --version` or `podman --version`                                                                                                                                                                           |
| Docker Compose v2                                             | v2.x (plugin or standalone)            | `docker compose version` or `podman compose version`                                                                                                                                                               |
| SELinux graphroot label (Podman rootless on RHEL/Fedora only) | `data_home_t` or `container_var_lib_t` | `ls -Zd $(podman info --format '{{.Store.GraphRoot}}')` — must not show `user_home_t`. See [Podman Support → \[1.c\]](/flxbl/sfp-server/setting-up/podman.md#1c-selinux--graphroot-labels-rootless-podman-on-rhel) |
| sfp CLI                                                       | Latest                                 | `sfp --version`                                                                                                                                                                                                    |

> Docker Compose must be v2 (`docker compose`), not the legacy standalone `docker-compose`. See [Setting up Docker on the server](/flxbl/sfp-server/setting-up/setting-up-docker-on-the-server.md) for Docker installation, or [Podman Support](/flxbl/sfp-server/setting-up/podman.md) for Podman setup. Podman users: `podman-compose` (Python) is **not supported** — Docker Compose v2 is required as the Compose backend.

***

## **\[2]** Network & DNS

### **\[2.a]** Step 1: Choose your domain

Pick a subdomain for your SFP Server. Examples:

* `flxbl.yourcompany.com`
* `codev.yourcompany.com`
* `devops.internal.yourcompany.com` (private/internal domains work too)

### **\[2.b]** Step 2: Create a DNS record

In your DNS provider (Cloudflare, Route 53, GoDaddy, etc.), create an **A record**:

| Field     | Value                                                   |
| --------- | ------------------------------------------------------- |
| **Type**  | A                                                       |
| **Name**  | `sfp` (or your chosen subdomain)                        |
| **Value** | Your server's IP address                                |
| **Proxy** | Off / DNS-only (if using Cloudflare, set to grey cloud) |
| **TTL**   | Auto or 300                                             |

### **\[2.c]** Step 3: Verify DNS resolves

```bash
dig sfp.yourcompany.com +short
# Should return your server IP
```

If using a private/internal domain, verify from a machine on the same network.

### **\[2.d]** Step 4: Choose your TLS mode

Pick a mode and gather the inputs listed below. Full configuration steps live in [Setting up sfp server → \[2\] Configure TLS](/flxbl/sfp-server/setting-up/setting-up-sfp-server.md#2-configure-tls).

| Mode                     | `--tls-mode` value     | Best for                                                            | You need ready before init                                                                   |
| ------------------------ | ---------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| **Bring Your Own Cert**  | `cloudflare` (default) | Enterprise / private networks, corporate CA, Cloudflare Origin CA   | `ORIGIN_CERT` + `ORIGIN_KEY` (base64-encoded PEM)                                            |
| **Let's Encrypt**        | `letsencrypt`          | Public-facing servers, quick evaluation                             | Ports 80 + 443 open, public DNS resolving                                                    |
| **Custom / On-demand**   | `custom`               | On-demand TLS via Caddy                                             | Nothing — Caddy manages certs                                                                |
| **Behind Load Balancer** | `none`                 | Existing infra (ALB, F5, NGINX, tunnel, API Gateway) terminates TLS | Public HTTPS ingress forwards HTTP to Caddy and sets or preserves `X-Forwarded-Proto: https` |

### **\[2.e]** Firewall / Security Group

| Port     | Protocol | Purpose                                 | Required When                                |
| -------- | -------- | --------------------------------------- | -------------------------------------------- |
| **443**  | TCP      | HTTPS — main application entry point    | Always (except Option C)                     |
| **80**   | TCP      | Let's Encrypt ACME challenge            | Only for Option B (`--tls-mode letsencrypt`) |
| **8080** | TCP      | Hatchet Dashboard (workflow monitoring) | Restrict to admin IPs                        |
| **4873** | TCP      | Verdaccio (private npm registry)        | Restrict to admin/CI IPs                     |
| **3100** | TCP      | Supabase Studio (database management)   | Restrict to admin IPs                        |

> Ports 8080, 4873, and 3100 are **IP-restricted** by Caddy. To configure the allowlist, set `ALLOWED_IPS` in your `.env` file (comma-separated IPs or CIDR ranges). These ports do not need to be open to all users.

For GitHub.com, Azure DevOps, and other SaaS webhook providers, the HTTPS entry point must be reachable from the public internet. Private-only DNS names, bastion-only hosts, VPN-only hosts, and SSH `ProxyJump` paths are valid for operators, but not for inbound webhooks.

If the server itself is private, front it with public HTTPS ingress:

| Ingress                          | Public side                             | Private side                                                                                                            |
| -------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| AWS ALB / customer load balancer | Public DNS + valid TLS cert on port 443 | Target group forwards HTTP to Caddy; backend security group allows only LB-to-server traffic                            |
| Reverse proxy / tunnel           | Public HTTPS URL                        | Named tunnel or supervised proxy forwards to the private server; quick tunnels are for smoke/dev only                   |
| API Gateway                      | Public API Gateway HTTPS endpoint       | HTTP API private integration uses VPC Link to an internal ALB/NLB, then forwards to Caddy with the correct backend path |

The backend host stays private. For webhook-only ingress, expose only `POST /sfp/api/repository/webhook` on the public ingress and reject other public paths unless you intentionally publish the full sfp UI/API.

For GitHub.com webhooks, do not depend on source-IP allowlists as the primary control. IP ranges change and source IP does not prove authenticity. Expose only the public HTTPS ingress, keep the backend private to that ingress, and let sfp-server validate the provider signature.

For webhook ingress, verify the exact payload URL from the webhook provider, not only the root domain. The ingress must allow HTTPS `POST`, forward the raw request body, preserve signature/event headers, and return a `2xx` response quickly.

See [Webhook ingress for private servers](/flxbl/sfp-server/setting-up/webhook-ingress-for-private-servers.md), [Setting up sfp server → \[2.c\] Behind a Load Balancer](/flxbl/sfp-server/setting-up/setting-up-sfp-server.md#2c-behind-a-load-balancer-tls-mode-none), and [Troubleshooting → Webhooks](/flxbl/sfp-server/setting-up/setting-up-sfp-server/troubleshooting.md#webhooks) if webhook deliveries time out.

### **\[2.f]** SSH Access

The `sfp server init` command can be run **remotely** from your local machine via SSH, or **locally** on the server itself. If running remotely:

* The server must be accessible via SSH from the machine running `sfp`
* The SSH user must have permission to run `docker` commands (e.g., member of the `docker` group, or `root`)

### **\[2.g]** Outbound Access (Server)

The server requires outbound internet access for:

* Docker image pulls (GitHub Container Registry, Docker Hub) — during init and updates
* GitHub API — for OAuth authentication and repository operations at runtime

If using **Option B (`--tls-mode letsencrypt`)**, the server also needs:

* Let's Encrypt ACME (ports 80/443 outbound)

> The Supabase CLI is downloaded once during init as part of the database migration container. This happens inside Docker and requires the server to reach `github.com`.

### **\[2.h]** What you'll provide to `sfp server init`

After completing this section, you should have:

| Value                                   | Example                                          | Source |
| --------------------------------------- | ------------------------------------------------ | ------ |
| **Domain**                              | `sfp.yourcompany.com`                            | \[2.a] |
| **TLS mode**                            | `cloudflare`, `letsencrypt`, `custom`, or `none` | \[2.d] |
| **ORIGIN\_CERT** (cloudflare mode only) | Base64-encoded PEM certificate                   | \[2.d] |
| **ORIGIN\_KEY** (cloudflare mode only)  | Base64-encoded PEM private key                   | \[2.d] |

### **\[2.i]** Reverse proxy headers

If sfp-server sits behind one or more reverse proxies (Cloudflare, a customer load balancer, NGINX, etc.), every proxy in the chain must preserve or set these headers:

| Header              | Purpose                                                                                                                                                                         |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `X-Forwarded-For`   | Client IP — used for IP attribution, rate limiting, monitoring allowlists, and audit logs. Controlled by `trustProxyHops` (Express `trust proxy`, default `2`, range `0`–`10`). |
| `X-Forwarded-Proto` | Original protocol (`https`) — used for request-origin detection and redirect URLs. Read separately, not gated by `trustProxyHops`.                                              |
| `X-Forwarded-Host`  | Original hostname — used for auth callbacks and link generation. Read separately, not gated by `trustProxyHops`.                                                                |

See [Reference → Properties → `trustProxyHops`](/flxbl/sfp-server/setting-up/setting-up-sfp-server/reference.md#properties) and [Troubleshooting → Proxy / Client IP](/flxbl/sfp-server/setting-up/setting-up-sfp-server/troubleshooting.md#proxy--client-ip) if client IPs appear wrong after deployment.

***

## **\[3]** Git Provider & Login — configured after the server is up

You do **not** set up GitHub, Azure DevOps, or login auth here. None of it is needed for `sfp server init`. Once the server is running, you connect your git provider and configure authentication from the codev UI:

| What                                                                                    | Where                                                   | Guide                                                                                                                                            |
| --------------------------------------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Git provider** (GitHub App / Azure DevOps service principal) + repository integration | **Settings → Integrations** (and the onboarding wizard) | [Setting up sfp server → \[5\] Configure your git provider](/flxbl/sfp-server/setting-up/setting-up-sfp-server.md#5-configure-your-git-provider) |
| **Login auth** (GitHub OAuth / Azure OAuth / SAML SSO)                                  | `.env` + restart, or SAML connection                    | [Setting up sfp server → \[6\] Configure login](/flxbl/sfp-server/setting-up/setting-up-sfp-server.md#6-configure-login)                         |

You can prepare credentials in advance (a GitHub App or the `flxbl-cloud` install; an Azure service principal), but you enter them post-boot — see the guides above.

***

## **\[4]** Admin IP Addresses

Collect the public (or private, if on a corporate network) IP addresses of anyone who needs access to administrative dashboards:

* **Hatchet Dashboard** (workflow monitoring) — port 8080
* **Supabase Studio** (database management) — port 3100
* **Verdaccio** (npm registry browser) — port 4873

Set these as the `ALLOWED_IPS` value in your `.env` file after init:

* Single IPs: `ALLOWED_IPS=203.0.113.10`
* Multiple IPs: `ALLOWED_IPS=203.0.113.10,198.51.100.5`
* CIDR ranges: `ALLOWED_IPS=10.0.0.0/8,172.16.0.0/12`

> After changing `ALLOWED_IPS`, restart Caddy with `docker compose restart caddy` for the change to take effect.

***

## **\[5]** Secrets / Configuration

`sfp server init` reads its secrets from `--config-file` (recommended), environment variables, or a `--secrets-provider` (Infisical, AWS Secrets Manager). All database credentials (Postgres password, JWT secret, Supabase API keys) are **auto-generated** — you do not create them.

Only two things are genuine init-time secrets:

| Secret                       | When                    | Description                                                                                                                                                      |
| ---------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DOCKER_REGISTRY_TOKEN`      | Always                  | Pulls the server image — see [Setting up sfp server → \[1.1\]](/flxbl/sfp-server/setting-up/setting-up-sfp-server.md#11-generate-docker_registry_token-required) |
| `ORIGIN_CERT` + `ORIGIN_KEY` | `--tls-mode cloudflare` | Base64-encoded PEM cert + key (Section 2, Option A)                                                                                                              |

> Git provider credentials, login OAuth, and the GitHub Packages token are **not** init secrets — you configure them after the server is up (see Section 3). Don't put them in `server.json`.

> Place init secrets in the `secrets` block of `server.json` and pass it via `--config-file ./server.json` — the canonical path for repeatable deployments. See [Setting up sfp server → \[1\]](/flxbl/sfp-server/setting-up/setting-up-sfp-server.md#1-create-a-serverjson-on-your-local-machine) for the file shape.

***

## **\[6]** Pre-Installation Checklist

Use this checklist to confirm readiness before running `sfp server init`:

* [ ] Server provisioned with adequate resources (see Section 1)
* [ ] Docker Engine 24+ and Docker Compose v2 installed on the server
* [ ] Podman rootless on RHEL/Fedora: graphroot label is not `user_home_t` (see [Podman Support → \[1.c\]](/flxbl/sfp-server/setting-up/podman.md#1c-selinux--graphroot-labels-rootless-podman-on-rhel))
* [ ] SSH access to the server (if running `sfp server init` remotely)
* [ ] `sfp` CLI installed on the machine that will run the init command
* [ ] Domain DNS record configured and resolving to server IP
* [ ] TLS certificate and key ready as base64-encoded PEM (if using `--tls-mode cloudflare`)
* [ ] Firewall ports open: 443 (always) + 80 (only if using `--tls-mode letsencrypt`)
* [ ] Server has outbound internet access (Docker image pulls, provider API)
* [ ] `DOCKER_REGISTRY_TOKEN` obtained (required to pull the server image)
* [ ] Admin IP addresses collected for dashboard access (configured post-init via `ALLOWED_IPS`)
* [ ] *(After the server is up — Section 3)* git provider connected in the codev UI (Settings → Integrations); login provider configured (OAuth via `.env` + restart, or SAML)

***

## Next Steps

Once all prerequisites are in place, proceed to [Setting up sfp server](/flxbl/sfp-server/setting-up/setting-up-sfp-server.md) for installation, configuration, and first-run instructions.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flxbl.io/flxbl/sfp-server/setting-up/prerequisites.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
