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
5 changes: 4 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Cursor, Gemini CLI, …). Read this before starting work, and follow the gates i
real API source (not memory, not docs summaries) and confirm the approach
before writing code.
- **No code duplicates.** Re-use existing code and logic where applicable.
- **Protect latency.** Keep database and external I/O outside shared locks unless ordering requires it; preserve lifecycle serialization and bound concurrent work.
- **Check performance regressions.** For routing, storage or lifecycle changes, compare encrypted cold/warm concurrent load and teardown timings, including errors and cleanup, before declaring ready.

## Submitting a PR

Expand Down Expand Up @@ -46,7 +48,8 @@ Every change ships only after it has run end-to-end on real hosts.
- The gRPC control channel is TLS. Each host needs `JWT_SIGNING_KEY`,
`MFA_ENCRYPTION_KEY`, `CONTROL_SERVICE_TLS_SAN`, and `ca-cert.pem` present in
`/root/nullnet/`, plus a rebuilt proxy. See SETUP.md for the full setup.
- Containers need a restart after nullnet restarts.
- Verify client restart recovery without restarting application containers;
startup cleanup must preserve Docker-owned interfaces and routes.
- To restart a Swarm stack, use `docker service update --force`.
- The default-deny eBPF firewall blocks Swarm ports. `2377`, `7946`, and `4789`
must be in the `.env` allowlists on strict nodes, or the worker goes Down.
Expand Down
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ All Nullnet releases with the relative changes are documented in this file.
- Per-service egress/ingress traffic filters: arbitrary AND/OR/group combinations of Country, Organization, Src IP (ingress), and Dst IP (egress) conditions, evaluated via `rpn-predicate-interpreter` — replaces the country-only egress/ingress policy ([#171](https://github.com/NullNet-ai/nullnet/pull/171) — fixes [#143](https://github.com/NullNet-ai/nullnet/issues/143))
- Persist ingress and egress sessions to SQLite and show the full history on the Sessions page, filterable by status, service, direction, and policy verdict, with its own retention window ([#170](https://github.com/NullNet-ai/nullnet/pull/170) — fixes [#156](https://github.com/NullNet-ai/nullnet/issues/156))
### Changed
- Improve routing performance and capped-network balancing, reduce storage contention, and harden tunnel setup, teardown, and recovery under concurrent load ([#199](https://github.com/NullNet-ai/nullnet/pull/199))
- Simplify the dashboard to linked session, service, and node count cards ([#194](https://github.com/NullNet-ai/nullnet/pull/194))
- Unify live and historical session views ([#191](https://github.com/NullNet-ai/nullnet/pull/191))
- Simplify backend configuration to a `backends` array of service names and derive trigger ports from peer declarations ([#190](https://github.com/NullNet-ai/nullnet/pull/190))
Expand All @@ -24,8 +25,8 @@ All Nullnet releases with the relative changes are documented in this file.
- Install BPF linker as a prebuilt binary rather than compiling it from source ([#158](https://github.com/NullNet-ai/nullnet/pull/158))
### Removed
### Fixed
- Route same-host egress directly with container-scoped forwarding and NAT ([#196](https://github.com/NullNet-ai/nullnet/pull/196))
- Track container overlay addresses when deciding whether backend connections are idle ([#195](https://github.com/NullNet-ai/nullnet/pull/195))
- Route same-host egress directly with container-scoped forwarding and NAT ([#197](https://github.com/NullNet-ai/nullnet/pull/197))
- Track container overlay addresses when deciding whether backend connections are idle ([#196](https://github.com/NullNet-ai/nullnet/pull/196))
- Make backend and egress trigger claims atomic, preserve liveness during setup, and report setup failures instead of transient packet-wait timeouts ([#186](https://github.com/NullNet-ai/nullnet/pull/186))
- Set both same-host veth MAC addresses at creation to prevent udev races from breaking encrypted connections ([#185](https://github.com/NullNet-ai/nullnet/pull/185))
- Stop a teardown from corrupting a chain that is still being set up ([#167](https://github.com/NullNet-ai/nullnet/pull/167) — fixes [#166](https://github.com/NullNet-ai/nullnet/issues/166))
Expand Down
18 changes: 9 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 23 additions & 1 deletion SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ plus the shared gRPC interface.

The repository should be cloned under `/root` so the provided `setup-*.sh` scripts and
`.service` units work without changes.
Run the setup scripts as root. The supplied systemd services also run as root; privileged commands execute directly without sudo.

## Usage

Expand Down Expand Up @@ -125,6 +126,11 @@ The repository should be cloned under `/root` so the provided `setup-*.sh` scrip
EVENT_RETENTION_DAYS=7 # how long an event is kept
EVENT_RETENTION_SWEEP_INTERVAL_SECS=3600 # how often the deletion sweep runs (1h)
```
Writes use a bounded queue and batched transactions; normal events appear after commit.
Storage failures retain accepted events and retry, reporting failure/recovery in Events
and stderr. A full queue drops new events instead of blocking routing; Events reports
the dropped count when storage catches up. Shutdown drains for up to five seconds;
a longer outage, forced kill or power loss can lose events still queued in memory.

- sessions (UI: *Sessions* page) are persisted the same way: every ingress session and every
external destination reached over an egress edge is stored, so the page shows the full
Expand All @@ -137,6 +143,14 @@ The repository should be cloned under `/root` so the provided `setup-*.sh` scrip
An active session is never pruned, however old. Sessions still marked active are closed
at startup, since the state they described died with the previous process.

- Upgrade server, proxy and clients together: VXLAN backend/egress packet release uses
an acknowledged `NetReady` command after both endpoints finish setup. Nullnet reserves
Linux interface groups `0x4e000000`–`0x4e400000` for tunnel cleanup; do not assign
unrelated interfaces to that range.
Failed setup is not acknowledged as ready. Failed teardown keeps its ID reserved;
after correcting the reported error, restart that client to purge stale state and
release the reservation. Application containers do not need restarting.

- the gRPC control channel itself (nullnet-client/nullnet-proxy ↔ nullnet-server) is TLS-only,
authenticated by a private CA. On first boot the server generates its own CA
(`members/nullnet-server/grpc-tls/ca-cert.pem` + `ca-key.pem`, created once and never
Expand Down Expand Up @@ -369,7 +383,15 @@ The repository should be cloned under `/root` so the provided `setup-*.sh` scrip
```
./setup-client.sh
```

Setup applies and persists a conntrack limit of at least 1,048,576 entries,
preserving a higher existing limit. No manual sysctl configuration is needed.
It also keeps NetworkManager and udev hotplug helpers from managing Nullnet-owned
interfaces, avoiding competing network-configuration work during tunnel bursts.

On upgrades, deploy the server, proxy and all clients from the same revision.
Client startup cleans stale Nullnet network state while preserving Docker interfaces;
routine container restarts are unnecessary. Containers already damaged by an older
client's cleanup need a one-time restart (Swarm: `docker service update --force SERVICE`).

### Observation mode

Expand Down
Loading
Loading