My Privacy and Security Setup on NixOS
OpenSnitch blocking every outbound connection by default, Mullvad with SOCKS proxies, encrypted Firefox vaults, firejailed apps and a full pentesting toolkit. All declarative.
I take privacy and security pretty seriously. Not in a tinfoil hat way but in a "I want to know exactly what's leaving my machine and where it's going" way. And running NixOS makes this significantly easier than it would be on any other distro because I can declare my entire security posture in config files that I version control.
Let me walk through what my actual setup looks like.
OpenSnitch - application firewall
This is probably the most important piece and the reason I set it up is actually quite specific. So there was the whole Axiom npm supply chain attack where a compromised package was downloading malicious payloads through curl in postinstall scripts. Downstream attacks like that are becoming way more common and when you think about it, we're running AI agents that install packages and pull dependencies constantly. It's only a matter of time before Claude accidentally installs something from a polluted repo right. That thought genuinely concerned me so I decided to get ahead of it.
I run OpenSnitch as an application-level firewall with the default action set to deny. Every single process that tries to make an outbound connection gets blocked unless I've explicitly allowed it. It uses eBPF for process monitoring and nftables for the actual filtering.
I've got rules for the stuff that obviously needs network access. Firefox, Claude Code, git, the nix daemon, Protonmail Bridge, Syncthing, Spotify. But here's the key part right. Curl is intentionally NOT whitelisted. It's the number one tool used by supply chain attacks to download payloads. So every curl request that happens on my system prompts me through OpenSnitch and I can see exactly where it's trying to go. If some random npm package tries to phone home or download something suspicious I'll know about it immediately. That's the whole point. When you've got AI agents running npm install and pulling packages you've never heard of you need that visibility.
Mullvad VPN
I use Mullvad and the reason is pretty simple. It's a fixed price, no accounts, no email required to sign up and they haven't enshittified their product. They're one of the few VPN providers that has genuinely stayed true to what they are. You can literally send them cash in the mail to pay for it if you want. No card details, no identity, just a code and an envelope. That gives me a lot of peace of mind.
On the technical side I've got some specific hardening around it. When Mullvad is enabled on a machine my NixOS config automatically disables IPv6 system-wide. The reason is that Mullvad's tunnel has IPv6 turned off so any IPv6 traffic would bypass the tunnel and leak my real address. The config also forces Docker containers to use the host's systemd-resolved stub instead of falling back to Google DNS during Mullvad transitions.
I've built custom Go tools for managing Mullvad too. A TUI for quick relay switching and a relay selector. Both compiled as Go modules in my nix config. I also use SOCKS proxies through Mullvad for routing specific applications through different exit nodes which gives me more granular control over what traffic goes where.
I've also got Tailscale set up with Mullvad as my exit node. So all my devices including my phone are connected to my infrastructure through Tailscale but the traffic exits through Mullvad. That means I can access any of my servers from anywhere, even from my phone on mobile data, and I've still got the privacy of a VPN. It's the best of both worlds right. Private mesh networking for my fleet and encrypted tunnelling for everything going out to the internet.
Protonmail for private email
All my email runs through Protonmail with Proton Bridge locally. End-to-end encryption, zero-access encryption on their servers, Swiss privacy laws, no ads, no data mining. For about £4 a month I get custom domain support with unlimited addresses which means every project gets its own email identity without paying per mailbox.
The privacy side is obvious but it's also really practical for running AI agents across multiple projects. One Proton Bridge connection, one MCP server, and my agents can send and receive email as any of my custom domain addresses. Compare that to Google Workspace where you'd be paying £5 per user per month per mailbox and setting up separate OAuth for each one. The cost and complexity difference is massive.
Firejail sandboxing
Every application that doesn't need full system access runs in a firejail sandbox. I've got custom profiles for Spotify, Telegram and Steam. Each profile explicitly blacklists sensitive directories like .ssh, .gnupg, .mozilla and my nix-config. They whitelist only what the app actually needs and drop all capabilities, disable printers and USB, restrict namespaces and filter D-Bus access.
The Spotify profile for example can only see its own cache and config directories plus the nix store. It can't see my home directory, it can't see my SSH keys and it can't see any of my projects. If Spotify gets compromised the blast radius is basically zero.
Secrets management with agenix
All my secrets are managed through agenix. API keys, tokens, passwords, they're all encrypted with age and only decrypted at build time on the machines that need them. They never sit on disk in plaintext outside of the nix store.
But here's the thing right. By default if Claude runs as your user and agenix decrypts a secret owned by your user then Claude can just read it. It can cat /run/agenix/api-key and see the raw key. That's a problem because if a compromised package gets code execution through Claude it could dump every secret on the system.
So I built a custom MCP secrets server that sits between Claude and the actual keys. It runs as a completely separate system user called mcp-secrets that owns the secrets. Claude never sees the raw API keys. It calls a tool like "authenticate with this service" and the MCP server uses the key on Claude's behalf and just gives back the result. The key never enters Claude's process memory or environment variables.
The server also verifies callers by walking the process tree and matching against the exact Claude Code nix store path. So even if something malicious is running as my user it can't connect to the secrets server because it's not Claude. And it can't read the secrets directly because they're owned by a different user. Two layers of protection.
This is really important when you think about it. I've got agents running npm install and pulling packages I've never reviewed. If one of those packages is compromised and tries to exfiltrate my API keys it hits a wall. The keys aren't in env vars, they're not readable by my user and the only thing that can access them is verified Claude processes through a unix socket. That's the kind of setup you need when AI agents are making real changes to your infrastructure.
GnuPG
GPG is enabled with SSH support through the agent so I can use my GPG keys for both signing and SSH authentication. Kleopatra is installed for key management.
Why NixOS makes this work
The thing about all of this is that it's declarative. My entire security setup is in version-controlled nix files. If I set up a new machine it gets the same OpenSnitch rules, the same Mullvad hardening, the same firejail profiles, the same pentesting tools. I don't have to remember what I installed or configured. It's just there.
And because it's all code I can review changes, roll back if something breaks and know exactly what's running on every machine in my fleet. That's the kind of confidence you don't get from manually installing security tools and hoping you didn't forget anything.