# ForgeFlow setup and first-test guide This is the canonical guide for turning the source release into a locally configured desktop application and testing one complete path: ```text local change -> commit -> push -> exact-SHA deployment -> healthcheck -> rollback ``` You never need to provide your Gitea token, SSH key or server credentials to a developer. Enter them only on the computer or server where they belong. --- ## Part 1 — Prepare the Windows desktop ### 1. Extract the release Extract the complete ForgeFlow ZIP to a normal local directory, for example: ```text C:\Tools\ForgeFlow ``` Avoid running it directly from inside the ZIP or from a temporary email folder. ### 2. Install the prerequisites Required: - Node.js 22 or newer; - npm, normally installed with Node.js; - Git for Windows available on `PATH`; - a normal signed-in Windows desktop session so Electron can use OS credential encryption. Optional manual check: ```powershell node --version npm --version git --version git config --global user.name git config --global user.email ``` Configure the Git identity when either value is empty: ```powershell git config --global user.name "YOUR NAME" git config --global user.email "YOUR EMAIL" ``` ### 3. Run the local setup command Open PowerShell in the extracted folder and run: ```powershell Set-ExecutionPolicy -Scope Process Bypass .\setup-windows.ps1 ``` This command: 1. checks Node.js, npm and Git; 2. installs the declared project dependency versions; 3. runs source validation and all automated tests; 4. starts the Electron desktop application. No Gitea or server credential is requested by the PowerShell script. --- ## Part 2 — Complete the ForgeFlow desktop wizard The first launch uses five explicit steps. ### Step 1. Readiness Select **Run readiness check**. ForgeFlow verifies: - Git CLI availability; - Git author identity; - writable application storage; - writable diagnostic storage; - availability of operating-system credential encryption. Warnings are informative. Red required checks block completion until resolved. A safe setup diagnostic ZIP can already be exported at this stage. ### Step 2. Gitea Create a Gitea access token (personal access token) in your own Gitea account. The exact scope labels can vary by Gitea version. Give it only the minimum rights needed for: - reading the repositories you want to show in ForgeFlow; - reading repository contents and branches; - reading Actions runs and jobs; - dispatching the fixed deployment and rollback workflows. Do not put this token in a Markdown file, `.env`, workflow or chat message. Enter locally in ForgeFlow: ```text Instance URL: https://YOUR-GITEA-HOST Access token: PASTE LOCALLY IN THE PASSWORD FIELD ``` Select **Validate & continue**. ForgeFlow confirms the user identity and repository access. When OS encryption is available, the token is stored with Electron `safeStorage`; otherwise it remains session-only and must be entered again after restarting. ### Step 3. Folders Choose one or more project roots that contain local repositories, for example: ```text C:\Development D:\Projects ``` Do not select the entire system disk. A focused project root produces faster and clearer discovery. The first configured root is also the default clone destination. When cloning `owner/repository`, ForgeFlow automatically creates: ```text \repository ``` The normal **Clone from Gitea** action does not open a folder picker. Use **Choose another location** only when a repository belongs under a different parent directory. ForgeFlow still creates the repository-named subfolder. ### Step 4. Discovery ForgeFlow scans Git metadata and matches each local `origin` to a Gitea repository. Generated dependency directories are skipped. ### Step 5. Ready Enter ForgeFlow. Repositories that could not be matched can still be linked or cloned from their repository screen. A clone is automatically linked and monitored after Git completes. --- ## Part 3 — Prepare one repository for deployment Start with a non-critical staging application when possible. ### 1. Verify the local repository The repository should have: - a configured `origin` pointing to the same Gitea repository; - a normal branch such as `main`; - no unresolved conflicts; - an upstream branch after the first push. ### 2. Add the fixed Gitea Actions workflows Copy: ```text examples/gitea-actions/deploy.yml examples/gitea-actions/rollback.yml ``` to the target repository as: ```text .gitea/workflows/deploy.yml .gitea/workflows/rollback.yml ``` Review the runner label in both files: ```yaml runs-on: forgeflow-production ``` Replace it with the exact label of the trusted runner that can reach the target server environment. Commit and push these workflow files before running the deployment preflight. The workflows accept only controlled inputs: ```text environment commit_sha or target_sha request_id ``` ForgeFlow creates the `request_id` automatically so desktop diagnostics, Actions output and server status can be correlated without exposing a secret. --- ## Part 4 — Prepare the server and trusted runner The example implementation targets a dedicated Git checkout deployed with Docker Compose. Adapt the allowlisted target values, not the security model. ### 1. Confirm the server prerequisites On the target server, verify: ```bash git --version docker --version docker compose version curl --version flock --version ``` The application checkout must already exist and have a working `origin` that the server can fetch without interactive prompts. Example: ```text /srv/YOUR-APP /srv/YOUR-APP/compose.yml ``` ### 2. Install the target configuration Copy the template: ```bash sudo install -d -o root -g root -m 0755 /etc/forgeflow sudo install -o root -g root -m 0640 \ examples/server/forgeflow-targets.conf \ /etc/forgeflow/targets.conf ``` Edit it as root: ```bash sudo nano /etc/forgeflow/targets.conf ``` Each active line has seven pipe-separated fields: ```text repository|environment|app_dir|branch|compose_file|healthcheck_url|status_file ``` Example: ```text jens/my-app|staging|/srv/my-app-staging|main|/srv/my-app-staging/compose.yml|http://127.0.0.1:18080/health|/var/lib/forgeflow-status/my-app-staging.json ``` Rules: - repository must exactly match `owner/repository` in Gitea; - environment must exactly match the ForgeFlow profile value; - all filesystem paths must be absolute; - status files must stay under `/var/lib/forgeflow-status/`; - the configuration must remain root-owned and not group/other writable. Validate permissions: ```bash sudo stat -c '%U %G %a %n' /etc/forgeflow/targets.conf ``` Expected owner is `root`; a mode such as `640` is appropriate. ### 3. Install the allowlisted deployment entry point ```bash sudo install -o root -g root -m 0755 \ examples/server/forgeflow-deploy \ /usr/local/bin/forgeflow-deploy ``` The script: - accepts only a valid repository, environment, full SHA and request ID; - resolves the repository/environment through the root-owned target file; - rejects unsafe paths and branches; - prevents concurrent deployments with `flock`; - fetches the allowed branch; - proves that the requested SHA is an ancestor of the remote branch; - resets only the dedicated deployment checkout; - runs the fixed Docker Compose redeploy; - performs repeated healthchecks; - writes live, previous and requested SHAs atomically; - records the correlation request ID and last exit code. ### 4. Restrict runner elevation Copy and edit the sudoers example: ```bash sudo install -o root -g root -m 0440 \ examples/server/forgeflow-runner.sudoers \ /etc/sudoers.d/forgeflow-runner sudo visudo -cf /etc/sudoers.d/forgeflow-runner ``` Replace `act_runner` with the actual trusted runner account. Do not grant that account unrestricted passwordless `sudo`, shell access or wildcard commands. ### 5. Register and start the Gitea runner Register a dedicated trusted runner according to your Gitea instance and runner version. Attach the exact label referenced by the workflow, for example: ```text forgeflow-production ``` Only repositories you control should be able to schedule jobs on a runner with production access. --- ## Part 5 — Publish server version status The server script writes one non-secret JSON status document per environment. Serve it over HTTPS independently of the application process so it can still report a failed release. Copy and adapt: ```text examples/server/nginx-forgeflow-status.conf ``` Example URL: ```text https://YOUR-APP-HOST/.well-known/forgeflow ``` Expected response: ```json { "repository": "jens/my-app", "environment": "staging", "request_id": "00000000-0000-0000-0000-000000000000", "commit_sha": "0123456789abcdef0123456789abcdef01234567", "previous_sha": "89abcdef0123456789abcdef0123456789abcdef", "requested_sha": "0123456789abcdef0123456789abcdef01234567", "deployed_at": "2026-07-24T12:00:00Z", "health": "healthy", "last_exit_code": 0 } ``` Test from the ForgeFlow desktop computer: ```powershell Invoke-WebRequest "https://YOUR-APP-HOST/.well-known/forgeflow" Invoke-WebRequest "https://YOUR-APP-HOST/health" ``` See [`STATUS_ENDPOINT.md`](STATUS_ENDPOINT.md) for the accepted contract. --- ## Part 6 — Create the deployment profile in ForgeFlow Open the linked repository and add an environment. Fill in: ```text Profile name: Staging Environment input: staging Allowed branch: main Deploy workflow: deploy.yml Rollback workflow: rollback.yml Status URL: https://YOUR-APP-HOST/.well-known/forgeflow Healthcheck URL: https://YOUR-APP-HOST/health Confirmation: enabled ``` Save the profile. --- ## Part 7 — Run Deployment preflight Select **Preflight** on the environment card. ForgeFlow must verify: 1. local repository link; 2. valid Git working tree; 3. allowed current branch; 4. clean working tree; 5. published upstream; 6. zero commits ahead and zero behind; 7. exact local SHA exists on the allowed remote branch; 8. local deploy workflow exists; 9. remote deploy workflow exists on Gitea; 10. Gitea Actions API is readable; 11. a configured server status endpoint; 12. current status-endpoint reachability; 13. application healthcheck result when configured. The status URL is mandatory because ForgeFlow uses it after the workflow to prove that the server applied the exact SHA for the exact request ID. An unreachable status document can be a warning before the very first deployment because the server script may create it, but the operation cannot finish successfully until the endpoint returns the requested SHA and request ID. Required failures block the Continue button and the deployment backend repeats its own Git/SHA checks at dispatch time. --- ## Part 8 — First safe end-to-end test Use a staging profile first. 1. Make a harmless visible change. 2. Review the diff in ForgeFlow. 3. Enter a commit message. 4. Select **Commit & push**. 5. Confirm that Local and Gitea show the same SHA. 6. Select **Deploy SHA -> Staging**. 7. Review and continue through Deployment preflight. 8. Confirm the exact SHA. 9. Follow workflow, job and healthcheck progress. 10. Confirm that the server status endpoint reports the same full SHA. 11. Create a second harmless commit and deploy it. 12. Use **Rollback** to restore the recorded previous SHA. Also test deliberately: - an uncommitted local change; - a local commit that was not pushed; - the wrong branch; - a missing workflow file; - a stopped runner; - a failed healthcheck; - a second deployment while the lock is held. ForgeFlow should block unsafe local states and clearly retain failed operation metadata for diagnostics. --- ## Part 9 — Export a diagnostic bundle without sharing credentials Open **Diagnostics**. 1. Run **System preflight**. 2. Select **Strict privacy** when sharing externally. 3. Select **Create diagnostic ZIP**. 4. Inspect the ZIP before sending it. The bundle deliberately contains no encrypted token field and omits raw runner logs. Before writing the ZIP, ForgeFlow runs a safety audit for known runtime secrets, private-key markers and unredacted URL credentials. If that audit fails, no bundle is written. See [`DIAGNOSTICS.md`](DIAGNOSTICS.md) for the exact contents and limitations. --- ## Part 8 — Configure an Unraid server Open **Settings → SSH / Unraid servers**. Enter the host, SSH port, username and `/mnt/user/appdata` as the base path. Prefer a private key. Save, then run **Test & trust** to record the server host-key fingerprint. For an existing project, enter its current server folder name. ForgeFlow inspects the root Git repository, tracked modifications, Compose files and nested repositories before it permits deployment. For a new project, use the repository name as server folder. Select the repository Compose file or enable basic generated Compose and enter host and container ports. See `docs/SSH_UNRAID_DEPLOYMENT.md`.