The Mullvad VPN app and its daemon now ship with Desktop Only, as the stock
NixOS service with nothing configured on top of it: no local-network boot
service, no DNS or firewall edits of our own, no Hub tile, no Feature Manager
card, no toggles. The account, the relay, the kill switch and the app's other
switches belong to the app.
modules/mullvad.nix is the whole change to the system: a role gate around
services.mullvad-vpn = {
enable = true; # daemon, pkgs.mullvad
gui.enable = true; # app, pkgs.mullvad-vpn
};
Server + Desktop and Bitcoin Node are machines that serve; a VPN client with its
own routing and DNS policy is not something their services asked for, so only
roles.desktop builds it. Every other option stays at the distribution's default
(early boot blocking off, the mullvad-exclude wrapper on), and the only
consequences are the ones the NixOS module already defines — the tun module, and
systemd-resolved with NetworkManager pointed at it while the client is enabled.
The Hub and the desktop shell are untouched: no tile, no feature card, no
service description, no icon, no GNOME folder edit. An app that is simply
installed has no decision to put in front of the user, and no state to report.
README, SECURITY.md (what the app's own kill switch and DNS behaviour mean, so
the change in network behaviour is not a surprise), CHANGELOG, the custom.nix
template (the mkForce line that removes it) and the installer's Desktop card
document it as an app rather than a service.
tests/test_mullvad_desktop_only.py guards the gate and the restraint: the client
builds on Desktop and nowhere else, the module adds no services, no DNS or
firewall edits and no packages, the Hub and desktop shell never mention it, and
it ships no tile icon.
Checked by evaluating the real module against the revision flake.lock pins
(3d23ea05a8a3) with eval-config.nix, four cases: Desktop -> daemon and GUI on,
one unit (mullvad-daemon), mullvad + mullvad-vpn in systemPackages, every other
option at the distribution default; Bitcoin Node and Server + Desktop -> nothing
at all, not even the tun module or resolved; Desktop with
`services.mullvad-vpn.enable = lib.mkForce false;` -> no unit, no package.
generate_diceware_password() built the password from 3 words out of a 96
word list plus a single digit: 96^3 x 10 = 8,847,360 combinations, about
23 bits.
That one password is the desktop login, the 'free' account password, and
the only thing standing in front of the Hub, which runs as root and
displays the root password, the SSH passphrase, the RTL password and the
Vaultwarden admin token. 23 bits is thin for something that valuable, and
the rate limiting in front of it was weaker than intended (see "hub: make
the login lockout that LOGIN_FAIL_MAX described").
Now 4 words plus 2 digits: 96^4 x 100 = 8,493,465,600, about 33 bits,
for the cost of one more word to write down.
- iso/installer.py: generate_diceware_password().
- modules/credentials.nix: the three fallback generators in
root-password-setup, free-password-setup and free-password-migration,
so a machine provisioned without the installer gets the same strength.
Affects new installs only; existing passwords are untouched.
Checked by running the real thing. The installer function was exercised
2000 times: 96 words in the list, always word-word-word-word-NN, 33.0
bits. For the three services, the generator lines were taken from the
script the evaluated module really produces (nix eval on the nixpkgs
revision flake.lock pins) and run 1500 times each: 96 words in each
list, always word-word-word-word-NN, every two-digit suffix from 00 to 99
seen, and no repeated password.
Server + Desktop publishes services under the operator's own domain, and
the DNS record for that domain points at the home connection, so anyone
can look up the home IP address. None of the places that offer Server +
Desktop said so.
- README: new section "Server + Desktop and your home IP address" (what
becomes public, what does not, the alternatives, and what happens
technically), plus a note on the role table and in the security
overview.
- SECURITY.md: a matching section, the consequence noted next to "Public
web services exposed only when enabled by the operator", and the
supported versions row no longer pins 1.0.x.
- ISO installer: the Server + Desktop role card ends with the warning.
- Hub: the domain setup text (onboarding, feature setup and domain
reconfiguration share renderDomainNeedsHtml) and the upgrade dialog
carry the same notice.
- Add tests/test_exposure_guards.py. It fails if one of these places
loses the notice or the README anchor stops resolving.
- Replace all "Sovran SystemsOS" (with space) with "Sovran_SystemsOS"
- Line 241: landing page title
- Line 262: internet notice text
- Line 328: welcome/role-selection hero title (was "Sovran Systems")
- Line 910: install progress title
- Replace push_complete method: remove credentials screen (username,
password, first-boot note, reboot button) and replace with a simple
status page that says "Rebooting…" then auto-reboots after 3 seconds
via GLib.timeout_add_seconds
Agent-Logs-Url: https://github.com/naturallaw777/staging_alpha/sessions/2a39f2d5-6aef-42cf-a94a-e1db5c6a601a
Co-authored-by: naturallaw777 <99053422+naturallaw777@users.noreply.github.com>