Skip to content

About

Fail-closed WireGuard confinement for selected NixOS systemd services using network namespaces and default-drop nftables.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Repository files navigation

vpn-confinement logo

VPN Confinement

OpenSSF Baseline OpenSSF Developer Best Practices OpenSSF Scorecard

Fail-closed WireGuard confinement for selected NixOS systemd services.

Give each service group a network namespace with WireGuard, default-drop nftables, and its own DNS policy. Other host services keep their normal routes. The project targets NixOS unstable and the networking.wireguard.interfaces backend.

Start here

Follow the complete Transmission recipe for a working application with persistent downloads, persistent secrets, and an authenticated local Web UI. The actual configuration is in examples/transmission.nix and is covered by a VM test.

For an existing service, add the flake input:

inputs.vpn-confinement.url = "github:nix-forge/vpn-confinement";
inputs.vpn-confinement.inputs.nixpkgs.follows = "nixpkgs";

Import inputs.vpn-confinement.nixosModules.default, configure the namespace and WireGuard interface using your provider's values, and select the service:

systemd.services.your-service.vpn = {
  enable = true;
  namespace = "downloads";
};

A service or socket declaring vpn.enable = true requires the global module to be enabled. Contradictory settings fail evaluation instead of dropping confinement.

Inspect your deployment without sending external requests or exposing keys:

sudo vpn-confinement-doctor
sudo vpn-confinement-doctor downloads --json

Security and privacy

Namespace routing and nftables prevent ordinary clearnet fallback. Strict DNS and IPv6 disable are defaults. Inline and store-backed WireGuard keys are rejected by default. Keep file-based secrets outside the world-readable Nix store.

An ISP still sees the VPN connection and traffic patterns. This is protection against direct traffic leakage, not a promise of anonymity. Host sockets, privileged helpers, application tracking, and the VPN operator require separate consideration. Read the threat model.

A remote VPN outage can leave an application running with traffic stalled. Stopping a managed WireGuard unit stops dependent services; restarting it restarts previously active consumers. See the architecture for exact lifecycle behavior.

Use balanced for services such as torrents that need changing destinations. Service hardening can independently be set to strict. Use highAssurance for narrow destination allowlists and stronger assertions.

publishToHost.tcp permits host ingress over a veth. It does not create a localhost listener, reverse proxy, or VPN-provider port forward. The Transmission example provides the local proxy explicitly.

Documentation

Development

  • Format: nix fmt
  • Check: nix flake check --show-trace --system x86_64-linux
  • Regenerate options: bash scripts/generate-options-doc.sh x86_64-linux
  • Build docs: bun install --cwd site --frozen-lockfile && bun run --cwd site build
  • Run the optional local benchmark: nix build .#vpn-benchmark

Runtime VM checks run on x86_64 Linux. ARM checks currently evaluate configuration; they do not provide equivalent VM coverage. The benchmark's raw results are in result/benchmark.json and describe a synthetic local tunnel.

See CONTRIBUTING.md and SECURITY.md. Licensed under MIT.

About

Fail-closed WireGuard confinement for selected NixOS systemd services using network namespaces and default-drop nftables.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Used by

Contributors

Languages