Summary

nixremote is a declarative layer for remote work between Wayland machines. It provides persistent native terminals, address-cascading native app forwarding over waypipe and SSH, a declarative wayvnc plus noVNC whole -session-in-a-browser leg, and a self-hosted RustDesk remote-desktop server for the cases neither fits.

The design starts after the compositor already works: it needs nixpkgs plus home-manager and deliberately does not require the display-substrate projects. Each peer is declared once; the same SSH alias serves forwarding and persistent shells.

What it is

  • Home-manager modules (homeManagerModules): forward, fishDispatch, sunshine, shpool, console, moonlight, rustdeskClient, launcher (see flake.nix and home/).
  • NixOS modules including a RustDesk server leg (modules/rustdesk.nix) and tooling (modules/nixos-tools.nix, modules/tools.nix).
  • A system-manager module (modules/system-manager.nix) publishing official-repository and AUR package names for Arch reconciliation.
  • A shared nixremote.transport catalogue resolving matching nixpkgs derivations per platform into environment.systemPackages.
  • Declared checks through checks/default.nix plus experiments/ and studies/ material.

It is not a compositor, display manager, or network overlay. It assumes reachability exists and declares how to use it.

How it works

nixremote.forward.<peer> declares an ordered address cascade: native OpenSSH Match ... exec blocks try the fast LAN address first and fall back to a VPN or overlay address when away. A wrapper around waypipe’s own SSH mode launches the peer’s application as an ordinary local window.

nixremote.shpool reuses the same SSH alias for persistent shells while the local terminal emulator stays native. nixremote.console.<name> scopes a wayvnc plus noVNC session for whole-session browser access, and the RustDesk legs cover full remote desktop with a self-hosted server. The launcher module builds per-machine tabs from live .desktop inventory read over SSH and launches through the peer’s own forward wrapper. Two home modules receive a shared probeFact helper closed over as a plain function argument before the module system ever sees it, so a consumer importing them sees ordinary module functions with nothing extra to provide.

How to configure it

Compose the wanted home-manager modules, then declare peers and legs under the nixremote.* surface observed in home/:

  • nixremote.forward.<peer> — ordered addresses and forwarding behavior.
  • nixremote.shpool — persistent-shell participation.
  • nixremote.console.<name> — browser-session legs.
  • nixremote.transport — per-platform transport package catalogue.
  • nixremote.moonlight, nixremote.rustdeskClient — viewer and client halves of the streaming and RustDesk pairs.

Server-side RustDesk uses modules/rustdesk.nix on NixOS. Review the module headers in home/forward.nix, home/sunshine.nix, and home/console.nix for protocol boundaries before enabling legs.

Tutorial

This example uses invented values against the real option interface from the referenced revision. The interface shape below was evaluated with the actual homeManagerModules.forward module at the pinned revision using synthetic values only; no connection was opened.

# Synthetic example: invented peer and address choices.
{
  imports = [ inputs.nixremote.homeManagerModules.forward ];
 
  nixremote.forward.demo-peer.addresses = [
    { address = "demo-lan.example"; }
    { address = "demo-overlay.example"; }
  ];
}

Peers carry no enable flag; a non-empty ordered address list is the whole declaration, asserted at evaluation time. Each address is an object, and the generated wrapper command defaults to the waypipe@<peer> convention:

# Synthetic example: public placeholder only.
waypipe@demo-peer demo-app

Treat the address list as an ordered cascade to review and commit, not as probed live state.

Evidence and limits

This page is bound to public revision b0b1a0780dd9f0df048645c0da01e252f8895360. That tree contains the flake outputs, home/ modules, modules/ host modules, lib/tools.nix, checks/default.nix, and the experiments/ plus studies/ material discussed above.

CNIX has not independently established a successful evaluation, build, forwarding session, or remote-desktop result for that revision. The tutorial interface above was evaluated against the real module at that revision with synthetic values: the address cascade passes type checking, the non-empty-addresses assertion holds, and the wrapper name resolves to the default convention. Compositor compatibility, network reachability, and RustDesk server behavior are described from source structure, not from reproduced runs.

nixremote starts where a working Wayland session already exists. Compositor installation and launch wiring, shell environment, audio fabric references in forwarding, and host identity facts are sibling concerns with their own revision-addressed concepts. Its relationship to other Corbet Nix projects is currently a shared design direction, not evidence of runtime integration.