---
title: "Homebrew install, deployment guides, and hardened hosting"
date: "2026-04-18"
---

<Warning>
**GitHub webhook exposure is now explicit.** Fabro no longer starts Tailscale Funnel or rewrites the GitHub App webhook URL just because `[server.integrations.github.webhooks]` exists.

To migrate:
1. Set `strategy = "server_url"` for deployments with a stable HTTPS URL.
2. Set `strategy = "tailscale_funnel"` if you intentionally want Fabro to run Tailscale Funnel on startup.
</Warning>

## More ways to install and deploy Fabro

Homebrew is now a first-class install path, so macOS and Linux users can let Brew manage updates instead of downloading release archives manually.

```bash
brew install fabro-sh/tap/fabro-nightly
```

Self-hosting also has more direct paths: Railway uses the prebuilt GHCR image, Render has a blueprint and deploy button, Fly.io ships with a `fly.toml`, and DigitalOcean now has a Droplet plus Compose guide. The deployment docs cover persistent storage, required environment variables, server URLs, and how to point the CLI at the hosted server.

## Alpine and musl Linux support

Fabro now publishes `x86_64-unknown-linux-musl` and `aarch64-unknown-linux-musl` tarballs alongside the glibc Linux builds. The installer detects musl-based distributions through `ldd --version` and downloads the matching archive automatically, so Alpine and other musl hosts work without a custom build.

The Docker image also moved to an Alpine-based Docker Hardened Image. That keeps the release binary layout shared between the image and tarballs while reducing image size and trimming the default runtime surface.

## Server hardening by default

Fabro now emits baseline HTTP security headers on every server response and adds a report-only Content Security Policy for the web app. Operators get stronger defaults without having to place every deployment behind custom proxy header rules first.

The GitHub webhook handler now lives on the main API router at `POST /api/v1/webhooks/github`. When `GITHUB_APP_WEBHOOK_SECRET` is configured, Fabro verifies signed webhook deliveries whether or not it is configured to update the GitHub App webhook URL.

## More

<Accordion title="CLI">
- Added the Homebrew install path to the quick start and public install page
- `fabro version` now warns when the CLI and server versions differ
- `fabro version` now surfaces when the binary was built from a debug profile
</Accordion>

<Accordion title="Improvements">
- Added Render, Fly.io, and DigitalOcean deployment guides alongside the existing Railway path
- Added a production Docker Compose setup with Caddy handling automatic HTTPS in front of Fabro
- Added `/health` to the container deployment path so platform health checks can target the server directly
- Published the runtime image from the Docker Hardened Images Alpine base
</Accordion>

<Accordion title="Fixes">
- Fixed startup crashes on `aarch64-unknown-linux-musl` by building musl targets through `cargo-zigbuild`
- Fixed the SPA fallback so `/api/*` paths no longer resolve to the frontend shell
- Fixed Gemini API keys being sent as URL query parameters; they now use the `x-goog-api-key` header
- Hardened the `fabro-demo` cookie with `HttpOnly` and conditional `Secure`
- Fixed GitHub repo lookup path validation so encoded `..` segments cannot redirect server-side GitHub API requests
</Accordion>
