Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: CI
on:
push:
branches: ['main']
pull_request:
branches: ['main']
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- run: dotnet restore
- run: dotnet build --configuration Release --no-restore
- run: dotnet test --configuration Release --no-build
57 changes: 57 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Release
on:
push:
tags: ['v*.*.*']
permissions:
contents: write
packages: write
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- run: dotnet restore
- run: dotnet build --configuration Release --no-restore
- run: dotnet test --configuration Release --no-build
docker:
needs: build-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/getlimen/forculus
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-
type=raw,value=latest
- uses: docker/build-push-action@v6
with:
context: .
file: src/Forculus.API/Dockerfile
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
release:
needs: docker
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
43 changes: 12 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,27 @@
# Forculus

> *Roman god of the **door panel***invoked in Roman religious practice as one of the deities guarding specific parts of a door.
> *Latin: "door panel"* — Roman deity of the solid door structure, the barrier between inside and outside.

Forculus is the **WireGuard hub** component of [Limen](https://github.com/getlimen/limen). All managed nodes' agents connect their tunnels into Forculus. Peer management is driven by Limen via a small HTTP API.
**Forculus** is the WireGuard hub component of [Limen](https://github.com/getlimen/limen). It runs alongside Limen on the control node and manages the server-side WireGuard interface via `wg syncconf`.

## Role in the Limen platform
## Not a standalone tool

- **Listens on:** UDP 51820 (WireGuard) + HTTP 3004 (control API)
- **Control API:** REST — `POST /peers`, `DELETE /peers/{publicKey}`, `GET /config`
- **WireGuard backend:** kernel module via `wg` CLI subprocess (`wg syncconf`)
- **State:** stateless — full config pulled from Limen on boot + every 60s as reconcile
- **Deployed on:** the `control`-role node (alongside Limen and Postgres) in v1
Forculus is deployed as part of the Limen control node stack. It has no database — peer config is pulled from Limen's API and reconciled every 60 seconds.

## How it's installed
## Features

Part of the Limen compose bundle. When you `docker compose up` Limen on the control node, Forculus comes up too.
- **Kernel WireGuard** via `wg` CLI subprocess
- **HTTP API** for peer management (POST/DELETE /peers, GET /config, GET /stats)
- **Periodic reconciliation** — pulls full config from Limen, diffs, applies
- **Boot recovery** — fetches config from Limen on startup with retry

## Tech stack

.NET 10 / NativeAOT • `wg` / `wg-quick` CLI subprocess • `System.Net.Http` • ASP.NET Core Minimal APIs
.NET 10 / ASP.NET Core • NativeAOT • `wg`/`wg-quick` subprocess

## Status
## Architecture

In active development. See [`limen/docs/superpowers/plans/2026-04-14-plan-03-wireguard-forculus.md`](https://github.com/getlimen/limen/blob/main/docs/superpowers/plans/2026-04-14-plan-03-wireguard-forculus.md).

## Development

Forculus needs the `wg`/`wg-quick` tools (Linux only). Local dev on Windows is limited to non-WG code paths (HTTP endpoints, limen connectivity). Full local testing runs under Docker.

### Sync contracts from limen

Limen.Contracts source is checked in locally under `src/Limen.Contracts/`. When it changes upstream, run:

```bash
bash scripts/sync-contracts.sh
```

### Build the Docker image

```bash
docker build -t ghcr.io/getlimen/forculus:dev -f src/Forculus.API/Dockerfile .
```
See the [Limen design spec](https://github.com/getlimen/limen/blob/main/docs/superpowers/specs/2026-04-14-limen-design.md).

## License

Expand Down
Loading