# Garnix CI: Self-Hostable CI and Hosting Service for Nix Flake Repositories

> Garnix is an open-source CI and hosting service for GitHub repositories that use Nix flakes, evaluating flake outputs and caching builds on S3. It is for teams that use Nix and want a CI solution that understands flake structure without configuring a general-purpose CI system.

**garnix-io/garnix-ci** — CI and hosting for nix-based, flakified github repos

- Repository: https://github.com/garnix-io/garnix-ci
- Stars: 497 · Forks: 50
- Language: Haskell
- License: BSD-3-Clause
- Published: 2026-09-20 · Updated: 2026-09-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/garnix-io-garnix-ci

## CI Built Around Flake Outputs, Not Shell Scripts

Most CI systems require teams to write shell scripts or YAML pipelines that describe how to build their software. Garnix takes a different approach: it reads a Nix flake and builds whatever outputs the flake declares. A flake that declares a package, a NixOS configuration, and a devShell gets all three built without any CI-specific configuration.

This is the core value proposition for Nix users: the flake already describes everything that should be buildable, so the CI system can consume that description directly rather than duplicating it in pipeline YAML.

Garnix also provides hosting, not just CI. NixOS configurations built by Garnix can be deployed as hosted services, which makes it a combined CI and deployment platform for NixOS-based applications.

The repository is the source code for garnix.io, the hosted service. Teams can run their own Garnix instance using the code in this repository, which is the primary reason to interact with the repository rather than simply signing up for the hosted service.

## Architecture: Haskell Backend, Nix Frontend, and S3 Caching

The backend is written in Haskell and lives in the backend/ directory, built with cabal. The frontend lives in frontend/ and runs on npm. The DNS, opensearch, and hosting-gateway directories handle network routing and search. Build artifacts are stored in S3 buckets configured through environment variables: S3_CACHE_PUBLIC_BUCKET and S3_CACHE_PRIVATE_BUCKET for the public and private artifact caches, with S3_CACHE_HOST pointing to a Cloudflare R2 endpoint in the development configuration.

The justfile serves as the task runner. The backend development loop uses ghcid for fast reload during development:

```bash
just watch
```

This runs the cabal REPL with ghcid and re-runs tests on file changes. The server command in the justfile shows the environment variables required to start the server locally: GARNIX_URL, S3 bucket names, and several feature flags like DevApi, OpenSearchMocks, and StripeMocks.

Secrets are managed with sops. The dev.yaml file in secrets/ stores GitHub App credentials and other sensitive values, encrypted with the project's sops configuration.

## Spinning Up a Local Garnix Instance with QEMU VMs

The repository includes an example that spins up a complete local Garnix deployment using nixos-compose and QEMU:

```bash
nix run -L .#examples_spinUpVms
```

After the VMs start, check their status and find the server IP:

```bash
nixos-compose tap
nixos-compose status
```

Pointing a browser to the IP of the exampleGarnixServer VM shows the hosted CI interface. The /garnix-admin page provides development utilities, including the button to create a GitHub App.

The GitHub App setup is a prerequisite for builds to work. From the /garnix-admin page, pressing 'Submit to GitHub' creates a new GitHub App and returns credentials that must be stored in the secrets file:

```bash
sops edit secrets/dev.yaml
```

With the GitHub App enabled on a repository, a test build can be submitted via a curl POST to the API. The README shows the request format, targeting the /api/build/submit endpoint.

## Frontend Development Against a VM Backend

To develop the frontend while the backend runs in a VM:

```bash
nixos-compose up -v
cd frontend
npm run dev
```

The dev server runs on localhost:3000 and proxies API requests to the VM. This separation allows iterating on the Next.js frontend without rebuilding the Haskell backend, which is useful since Haskell compilation can be slow.

The admin page at /garnix-admin is documented as useful for some development tasks, though the README does not enumerate what those tasks are beyond the GitHub App creation button. Infrastructure diagrams can be generated using d2, as shown in the justfile's docs-infrastructure-generate target.

The last push to the repository was on 2026-06-17. The repository erased its git history when open-sourcing, so the commit history visible in the repository starts from the open-source release rather than the project's internal development history.

## What Garnix Requires to Self-Host

Self-hosting Garnix is not a simple docker compose up. The deployment depends on NixOS, nixos-compose, and QEMU for the VM-based deployment path. Teams that do not use NixOS on their infrastructure cannot self-host without adopting it.

The GitHub App is mandatory. Without it, Garnix cannot receive webhooks from GitHub and cannot report build status back to pull requests. Creating the GitHub App requires the /garnix-admin page to be reachable, which means the server must be running before the GitHub App can be configured.

Stripe is integrated into the production configuration, as shown by the StripeMocks flag in the justfile. Self-hosting teams that want to charge for access to their Garnix instance need to configure Stripe credentials. Teams running a private internal instance can leave Stripe mocked.

OpenSearch is used for log and artifact search, as indicated by the OpenSearchMocks flag and the opensearch/ directory. A production deployment needs a running OpenSearch or compatible instance.

## Garnix vs. Hercules CI for Nix Flake Projects

Hercules CI is another CI service that understands Nix flakes natively. Both services evaluate flake outputs and cache builds. The key difference is deployment model: Hercules CI is a commercial cloud service with no self-hosted option documented in its public materials. Garnix provides its own source code, making self-hosting a documented option.

For teams that want to run their own Nix-native CI without depending on an external service, Garnix is the option with a published codebase. For teams that want a managed service without infrastructure responsibility, Hercules CI's hosted offering removes that operational burden.

The garnix.yaml file at the repository root is the configuration file for Garnix builds. This is the only file a repository owner needs to add to connect their repository to a Garnix instance.

## BSD-3-Clause License and Development Status

The repository is licensed under BSD-3-Clause, which permits use, modification, and redistribution with attribution. Commercial use is permitted.

The repository erased its git history when open-sourcing, and the current visible commit history begins from that point. The contributors credited in the README are the people who worked on the project before open-sourcing: Alex David, Evie Ciobanu, Greg Pfeil, Jean-Francois Roche, Julian Kirsten Arni, Ramses de Norre, and Sonke Hahn.

The last push was on 2026-06-17. There are no GitHub releases in the repository. The garnix.io hosted service is the production deployment of this codebase, so teams evaluating Garnix can test against the hosted service before deciding whether to self-host.

## Conclusion

Garnix suits teams that have already adopted Nix flakes and want a CI system that builds flake outputs natively, with S3-based caching and optional hosting. It is not suitable for teams that do not use Nix, and self-hosting the complete stack requires Nix itself, QEMU, and experience with NixOS configuration. Before self-hosting, note that setting up a GitHub App via the /garnix-admin page and storing its credentials through sops edit secrets/dev.yaml are prerequisites: without those, no builds can be submitted regardless of how the rest of the infrastructure runs.

## FAQ

### Does Garnix CI require NixOS, or does it work with any Linux system?

The self-hosted deployment path uses nixos-compose and QEMU VMs running NixOS. The hosted service at garnix.io handles builds without requiring NixOS on the client side, but self-hosting the full stack as documented in the README requires NixOS infrastructure.

### Is a GitHub App required to use Garnix CI?

Yes. The README states that a GitHub App is required for both production and testing. The /garnix-admin page provides a button to create one, and its credentials must be stored in secrets/dev.yaml via sops before Garnix can receive build events from GitHub.

### What is garnix.yaml and where does it go?

garnix.yaml is the configuration file that connects a repository to a Garnix instance. It lives at the root of the repository being built. The README does not detail the file's format, but the file is visible at the root of the garnix-ci repository itself as an example.

## Sources

- [garnix-io/garnix-ci on GitHub](https://github.com/garnix-io/garnix-ci)
- [Issues](https://github.com/garnix-io/garnix-ci/issues)
- [License: BSD-3-Clause](https://github.com/garnix-io/garnix-ci/blob/main/LICENSE)
- [README](https://github.com/garnix-io/garnix-ci/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/garnix-io-garnix-ci
