Models of offline Rust programming

With my move to Qubes I want to leverage its compartmentalization capabilities to adopt a mostly offline programming model. Something like one qube per project, no NetVM. This is ready to go were my project dependencies all available in Debian/Fedora package repositories: assemble a template with everything I need installing through the updates proxy.

But Rust has its own repositories: Cargo for libraries and binaries and rustup for toolchains; and in the standard workflow installed dependencies are writable, semi-ephemeral, and stored locally to the project code. So, less suited to installation into a persistent readonly FHS-respecting template, at least at first blush.

More pragmatically I think I could install everything within my offline project app qube/s by enabling the updates-proxy-setup service and configuring Cargo and rustup to use that proxy, as it is permissive by default.

https://doc.rust-lang.org/cargo/reference/config.html#httpproxy

https://rust-lang.github.io/rustup/network-proxies.html

Well, this is likely what I’ll do… but halfheartedly. The presence of the open proxy will mean the qube is no longer offline, there is no true network gap between my project code and the wild. I could toggle the proxy on/off as needed, but that is security/privacy theater. I could attenuate the permissiveness of the proxy, and- maybe. What is my threat model? I don’t really have one, it’s just I like the “hygiene” of a full separation, philosophically.

If there are other programmers here who use Rust, what’s your workflow? Do you have a better development model?

updates-proxy-setup works with the qubes.UpdatesProxy qrexec policy.
This means that you can control when the qube should have access to this proxy with a dom0 confirmation window.

In dom0, create a new policy file in /etc/qubes/policy.d/50-config-user.policy with:

qubes.UpdatesProxy * rust-qube-name @default ask target=proxyqube
1 Like

This is a little bit of a “use my favorite thing” post, but it is actually applicable to the situation. I tinker with Rust code on occasion but I’ve never done significantly complex work in Rust.

Guix (https://guix.gnu.org) has package definitions for some (though not all) cargo crates, and a build system that configures the Rust toolchain to use local copies of the crates instead of fetching from the server. The crates are fetched from the server when building the package for the crate itself (in the template) and dependent crates use this copy. Adding new packages is pretty painless with guix import (Invoking guix import (GNU Guix Reference Manual)). The main caveat is that the importer is not recursive, so if you depend on one package which depends on 5 other package then you will need to run the tool 6 times.

You can install Guix on top of a base distribution (Binary Installation (GNU Guix Reference Manual)). From a brief glance at the code it looks like the http_proxy and https_proxy environment variables are supported (as long as they are defined in the daemon’s environment), but I haven’t tried using them myself.

1 Like