I had zero Linux experience. Zero. Didn’t know what a terminal was, couldn’t use the command line, never touched a single Linux distribution.
But I built a transparent proxy gateway for Qubes OS that helped users in restricted regions get online — users who couldn’t even update their Qubes systems.
Here’s how I got there.
When I Knew Nothing
When I first started using Qubes, I couldn’t do the most basic things. How do you transfer files between VMs? Why does software installed in an AppVM disappear after a reboot? What do all those Qubes Manager options mean?
ChatGPT kept me alive. Whenever I hit a problem, I’d describe it in Chinese, it gave me commands, I copy-pasted. Combined with community tutorials and official docs, I figured things out bit by bit.
Eventually I got the basics: install software in the template, use it in the AppVM. qvm-copy moves files between VMs. qvm-prefs changes VM settings. Foundation stuff.
But the real trouble was ahead.
The qrexec Wall
When I started trying to do more complex things, I kept hitting the same wall: qrexec.
It’s Qubes’ inter-VM communication mechanism. The docs are thorough enough, but I had no systems programming background. RPC services, policy files, source/destination matching rules… I read through it multiple times and the pieces just wouldn’t click.
That was a rough stretch. I felt like this system was designed for people who already knew Linux, and I was forcing my way into a world that didn’t want me.
The Turning Point — Installing an AI Agent into a Qube
Then I found a different way to use AI: not chatting in a browser, but installing an AI agent directly into a Qube and letting it actually do things — read files, run commands, write code, test, fix, repeat.
I set up a dedicated Qube for the agent, installed Hermes Agent, then fed it all of Qubes OS’s official docs, community tutorials, and every forum post I could find. Started telling it what I wanted in Chinese.
Completely different from using ChatGPT. ChatGPT gives you advice, then you go type the commands yourself. The agent lives inside your system — it can see your actual configuration, run commands itself, read its own errors and fix them. One approach doesn’t work, try ten. Ten don’t work, try twenty. It doesn’t fear failure. But the token burn hurts.
The Proxy Gateway
I live in a region with network restrictions. Not just “slow internet” — Qubes templates won’t update, packages won’t install, community resources are unreachable, can’t even download the ISO.
There have to be others in the same situation. Running a proxy client in every AppVM is exhausting. Setting it up in the template is inflexible. You need a gateway-level solution.
I didn’t mess with my real setup. I created two test Qubes: one as the proxy gateway, one as a browser, connected to each other. Something breaks? Destroy and rebuild, no harm done.
Then I had the agent SSH into both test Qubes — write code, deploy, test connectivity, check logs, fix bugs, go again.
Round after round. Token consumption was massive. But each failure taught me (and the agent) more about how Qubes networking flows, how nftables rules work, how DNS hijacking kicks in.
Once the test environment was stable, I packaged it into install scripts, wrote docs, and published it to GitHub and the Qubes forum.
What came out of it is qubes-clash-gateway — a transparent proxy gateway for Qubes OS based on mihomo. How it works:
Any AppVM → NetVM (sys-proxy)
↓ all traffic arrives on vif* interface
mihomo transparent proxy
├→ CN domains/IPs → direct
└→ Foreign → proxy nodes → internet
Zero config on the AppVM side — just assign the NetVM and go. TCP/UDP on all ports, DNS fake-ip to prevent pollution, GeoIP-based routing, subscription parsing, plus a terminal controller and web UI.
After I posted it on the forum, someone told me they hadn’t been able to update Qubes at all before, and now they finally could. That meant more than anything.
Security — Let’s Be Real
Using an AI agent to operate a system — especially a security-focused one like Qubes — carries real risks.
A few rules I stick to:
Default deny, allow on request. No broad whitelisting for the agent. If it needs something, you open that specific thing.
Least privilege. If the current task only needs file read access, don’t give it network access.
Test in disposable VMs first. Qubes gives you isolation for free — break a test VM, just destroy it.
Audit. Regularly check what the agent has been doing, read logs, review its code. It’s a tool, not an authority. It makes mistakes. It suggests insecure configurations. It misunderstands the Qubes security model. You have to verify.
Qubes’ architecture has a natural advantage here — every Qube is isolated, qrexec policies control communication, and disposable Qubes are there to throw away.
Lessons Learned
Looking back, a few things that mattered.
Start from a real problem. I didn’t “learn Qubes” first and then build something. I hit a specific problem and figured out Qubes while solving it.
Feed the agent enough docs. Don’t give it a few sentences and hope for the best. Give it all the official docs, all the community posts. The more it knows, the better the solutions.
Don’t just copy-paste. I read every line of code the agent wrote. Didn’t understand something? Asked it to explain. Over time, I started spotting problems myself.
Every time we solved a hard problem, I saved the solution as a skill. Next time something similar comes up, no need to start from scratch.
The Qubes community has excellent documentation. AI agents don’t replace it — they make it accessible to people like me with zero background. The docs tell you what things are. The agent helps you actually do them.
If you’re in a restricted region using Qubes, don’t give up.