No description
Find a file
gustavobelfort 327a40538a
feat: initial release of warsaw-nix
NixOS and Home Manager modules to run Warsaw (Guardião) natively on NixOS.
Warsaw is the banking security daemon by Diebold Nixdorf required by many
Brazilian banks (Itaú, Banco do Brasil, Caixa, Sicredi, and others).

Key discovery: Warsaw has anti-sandbox detection — bwrap/FHS env gets r:0
(not installed), native execution gets r:1 (installed). This module uses
autoPatchelfHook + activation script symlinks instead of buildFHSEnv.

Includes:
- Package with autoPatchelfHook for NixOS library paths
- NixOS module (services.warsaw) with systemd service + activation script
- Home Manager module (programs.warsaw) for browser cert trust via certutil
- flake-parts consumer module
- Eval checks and GitHub Actions CI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 12:26:04 -03:00
.github/workflows feat: initial release of warsaw-nix 2026-03-23 12:26:04 -03:00
modules feat: initial release of warsaw-nix 2026-03-23 12:26:04 -03:00
.gitignore feat: initial release of warsaw-nix 2026-03-23 12:26:04 -03:00
checks.nix feat: initial release of warsaw-nix 2026-03-23 12:26:04 -03:00
flake.lock feat: initial release of warsaw-nix 2026-03-23 12:26:04 -03:00
flake.nix feat: initial release of warsaw-nix 2026-03-23 12:26:04 -03:00
LICENSE feat: initial release of warsaw-nix 2026-03-23 12:26:04 -03:00
package.nix feat: initial release of warsaw-nix 2026-03-23 12:26:04 -03:00
README.md feat: initial release of warsaw-nix 2026-03-23 12:26:04 -03:00

warsaw-nix

NixOS and Home Manager modules to run Warsaw (Guardiao) natively on NixOS.

What is Warsaw?

Warsaw is the security module by GAS Tecnologia / Diebold Nixdorf required by many Brazilian banks for internet banking. It runs as a local daemon on port 30800/30900 and validates the browser environment before allowing access to banking websites. This flake packages Warsaw and provides declarative NixOS + Home Manager modules so it runs natively on NixOS without FHS containers or VMs.

Supported banks

Confirmed working:

  • Itau
  • Banco do Brasil
  • Caixa Economica Federal
  • Sicredi

Reported working:

  • Safra
  • Banese
  • Banco do Nordeste
  • Banco de Brasilia (BRB)
  • Banco da Amazonia

Not Warsaw (different security modules):

  • Bradesco -- uses its own security module
  • Santander -- uses MPS (Monitor de Pagamentos Seguros)

Quick start

NixOS module

Add warsaw-nix to your flake inputs and enable the NixOS module for the system daemon, plus the Home Manager module for browser certificate trust.

# flake.nix
{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    home-manager.url = "github:nix-community/home-manager";
    warsaw-nix.url = "github:gustavobelfort/warsaw-nix";
  };

  outputs = { nixpkgs, home-manager, warsaw-nix, ... }: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        warsaw-nix.nixosModules.warsaw
        home-manager.nixosModules.home-manager
        {
          # System daemon
          services.warsaw.enable = true;

          # Browser certificate trust (inside home-manager)
          home-manager.users.youruser = {
            imports = [ warsaw-nix.homeManagerModules.warsaw ];
            programs.warsaw = {
              enable = true;
              browsers = [ "firefox" "chromium" ]; # default: [ "firefox" ]
            };
          };
        }
      ];
    };
  };
}

flake-parts usage

If your flake uses flake-parts, import the consumer module to re-export all warsaw-nix outputs:

# flake.nix (flake-parts consumer)
{
  inputs.warsaw-nix.url = "github:gustavobelfort/warsaw-nix";

  outputs = inputs:
    inputs.flake-parts.lib.mkFlake { inherit inputs; } {
      imports = [ inputs.warsaw-nix.flakeModules.default ];

      # warsaw-nix.nixosModules, homeManagerModules, and overlays
      # are now available in your flake outputs.
    };
}

How it works

Key discovery: anti-sandbox detection

Warsaw actively detects sandboxed environments. When run inside bwrap or an FHS container it reports r:0 (not installed) to the bank's detection JavaScript, even though the daemon is running and accepting WebSocket connections. Running natively on the host produces r:1 (installed). This is why we use autoPatchelfHook and symlinks instead of buildFHSEnv.

Architecture

  1. Package (package.nix): Fetches the official .deb from Itau's CDN and uses autoPatchelfHook to patch ELF binaries for NixOS library paths (dbus, nss, at-spi2-atk, libXcursor, libXft).

  2. NixOS module (services.warsaw): On each boot, an activation script recreates /usr/local/{bin,lib}/warsaw/ as symlinks into the Nix store and points /usr/local/etc/warsaw at the mutable state directory. A systemd service starts the core daemon as root with Type=forking.

  3. Home Manager module (programs.warsaw): A per-user systemd service that waits for the Warsaw daemon to generate its CA certificate (/var/lib/warsaw/rootca.crt), then injects it into Firefox and/or Chromium NSS databases using certutil. This allows browsers to trust the local TLS connection on wss://127.0.0.1:30900.

  4. Mutable state: Warsaw writes runtime data to /var/lib/warsaw/. On impermanence systems (ephemeral root), persist this directory:

    environment.persistence."/nix/persist".directories = [ "/var/lib/warsaw" ];
    

Troubleshooting

Check the daemon is running

systemctl status warsaw
# Should show active (running), 2 core processes

Check the listening ports

ss -tlnp | grep -E '3080|3090'
# Should show:
#   127.0.0.1:30800   (HTTP WebSocket)
#   127.0.0.1:30900   (TLS WebSocket)

Test the TLS endpoint

curl --cacert /var/lib/warsaw/rootca.crt https://127.0.0.1:30900/
# Expected: HTTP 426 Upgrade Required (this confirms TLS works)

Verify in your browser

Open your bank's website. If Warsaw is running correctly, you should not see any "Install Guardiao" prompts.

Common issues

  • Service fails to start: Check journalctl -u warsaw for errors. Ensure /usr/local/bin/warsaw/core exists (the activation script creates it).
  • Browser still prompts for install: The HM module may not have injected the certificate yet. Run systemctl --user status warsaw-cert-trust and check if the cert file exists at /var/lib/warsaw/rootca.crt.
  • Certificate not trusted: Restart the HM service: systemctl --user restart warsaw-cert-trust. For Chromium, ensure ~/.pki/nssdb exists.

Overriding the .deb source

For airgapped environments, a local mirror, or to pin a specific version:

services.warsaw = {
  enable = true;
  package = warsaw-nix.packages.x86_64-linux.warsaw.overrideAttrs {
    src = pkgs.fetchurl {
      url = "https://your-mirror.example.com/warsaw_setup_64.deb";
      sha256 = "...";
    };
  };
};

Or with a local .deb file:

services.warsaw = {
  enable = true;
  package = warsaw-nix.packages.x86_64-linux.warsaw.overrideAttrs {
    src = ./warsaw_setup_64.deb;
  };
};

Comparison with itau-nix (VM approach)

warsaw-nix (native) itau-nix (VM)
Approach Patched binaries + symlinks Full QEMU/libvirt VM
Disk usage ~30 MB ~4 GB
RAM usage ~50 MB ~4 GB
Startup time Seconds Minutes
Bank compatibility Any Warsaw-based bank Itau only (preconfigured)
Sandbox detection Passes (r:1) N/A (full OS)
Complexity Low (2 module imports) High (VM management)

Security considerations

  • Warsaw runs as root via a systemd service. This is required by the software.
  • It listens only on localhost (127.0.0.1:30800 and 127.0.0.1:30900) — not exposed to the network.
  • The binary is proprietary and closed-source. The Nix code in this repository is MIT-licensed, but Warsaw itself is distributed under Diebold Nixdorf's terms.
  • The daemon generates a self-signed CA certificate and injects it into browser trust stores. This is by design -- it needs TLS for the local WebSocket connection.
  • On impermanence systems, /var/lib/warsaw must be persisted or the daemon will regenerate keys on each boot.

Contributing

PRs are welcome. To test changes locally:

# Evaluate without building
nix flake check --show-trace

# Build the package
nix build .#warsaw

# Test in a NixOS VM (if you have one configured)
sudo nixos-rebuild switch --flake .#yourhost

If you confirm Warsaw works with a bank not listed above, please open an issue or PR to update this README.

License

The Nix code in this repository is licensed under the MIT License.

Warsaw itself is proprietary software by GAS Tecnologia / Diebold Nixdorf. This project merely packages it for NixOS and does not redistribute the binary -- it is fetched directly from the official source at build time.