nix the Rust crate: safe bindings to Unix and Linux system calls
Rust friendly bindings to *nix APIs
At a glance
- What is it?
- A Rust library that wraps the platform APIs the libc crate leaves unsafe, organised behind around forty feature flags, with a three-tier support policy for targets.
- Who is it for?
- The nix crate is for Rust programs that need to talk to the operating system directly: files, sockets, signals, processes, mounts, terminal control. Its value is that unsafe blocks and errno handling disappear from your code without the API becoming unidiomatic, and its support policy is unusually explicit, with CI enforcement tiers and a stated MSRV of 1.69 that will not move without a version bump.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 12 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.
Editorial analysis
First, the name means Unix, not NixOS
The repository description is `Rust friendly bindings to *nix APIs`, and that asterisk is the whole point. In the library's own README, *nix refers to the Nix family of Unix-like platforms, Linux, Darwin and the BSDs. It has nothing to do with NixOS, the Nix package manager, or flakes. The search results for this project are dominated by NixOS questions for exactly that reason, which makes the naming collision worth stating before anything else.
So this is a library, not a tool you install. You add it to `Cargo.toml`, enable the feature flags for the syscalls you want, and call safe Rust functions instead of raw libc bindings. The repository topics back this up: `libc`, `rust`, `rust-bindings`, `unix`.
The value proposition is narrow and concrete. The `libc` crate exposes the operating system as `unsafe extern` functions taking raw pointers and returning `c_int` codes. The nix crate wraps those in types that make illegal usage impossible to express, and turns the return code convention into a `Result`. The README makes the comparison with `gethostname` directly, and it is the clearest statement of intent in the project:
// libc api (unsafe, requires handling return code/errno)
pub unsafe extern fn gethostname(name: *mut c_char, len: size_t) -> c_int;
// nix api (returns a nix::Result<OsString>)
pub fn gethostname() -> Result<OsString>;No buffer to size, no return code to check by hand, and the error case lands in the type system rather than in a comment reminding you to check `errno`.
Forty feature flags are the real API surface
The `Cargo.toml` lists roughly forty feature flags, and each one maps to an area of the operating system rather than to a single function. `fs` for the filesystem, `net` and `socket` for networking, `signal` and `process` for control flow, `mount`, `mman` and `uio` for memory and mounting, `term` for terminal attributes, `ptrace` for process inspection, `sched` and `resource` for limits, `syslog`, `personality`, `fanotify`, `inotify`, `quota`, `reboot`.
Some flags are dependency declarations rather than namespaces. `dir` expands to `fs`, `event` to `poll`, `mqueue` to `fs`, `uio` is pulled in by `mount`, and `zerocopy` pulls both `fs` and `uio`. That structure is worth reading before you pick flags, because enabling `mount` quietly enables `uio`, which enables the `zerocopy` machinery.
This design has a real consequence for compile times and for your dependency tree, and it is a deliberate one. You enable only what you call, so a program that never touches `ptrace` does not compile that code. The cost is that the crate's documentation is genuinely large, spread across docs.rs with every feature turned on, which is configured in `Cargo.toml` through `all-features = true` and a `--cfg docsrs` rustdoc flag.
The default feature set is empty. Nothing is enabled unless you ask for it, which is the right default for a bindings crate but means a first build with no features will not do anything useful.
Three tiers of platform support, enforced by CI
Rather than claiming to support everything `libc` supports, the project splits its targets into three tiers and says exactly what each one means for you. Tier 1 targets are built and tested in CI, and a failure of either blocks the inclusion of new code. Tier 2 targets are built in CI, where a build failure blocks new code but a test failure does not. Tier 3 targets are built in CI where build failures do not necessarily block anything, and the README says plainly that a tier 3 target may be dropped at any time at the project's discretion.
That is an unusually honest way to describe platform support, and it converts an abstract promise into something you can check. If your target is tier 1, regressions get caught. If it is tier 3, you are depending on goodwill.
The tier 1 list covers the mainstream targets: `aarch64-apple-darwin`, `aarch64-unknown-linux-gnu`, `arm-unknown-linux-gnueabi`, `armv7-unknown-linux-gnueabihf`, `i686-unknown-freebsd`, `i686-unknown-linux-gnu`, `i686-unknown-linux-musl`, the mips and mips64 families, `powerpc64le-unknown-linux-gnu`, and `x86_64-unknown-linux-musl`. Tier 2 adds Android, iOS, OHOS, loongarch64, s390x, illumos and NetBSD. Tier 3 contains the long tail: uclibc, powerpc64, Fuchsia, Dragonfly, Haiku, gnux32, OpenBSD, Redox and Hurd.
Platforms not listed at all are supported best-effort, relying on users to report problems. The `docs.rs` target list in `Cargo.toml` is a third, shorter list of what gets prebuilt for documentation, which is not the same as the support policy.
MSRV 1.69 with an explicit promise attached
The crate states it is supported on Rust 1.69 and higher, and adds a commitment that is rarer than the number itself: the MSRV will not be changed in the future without bumping the major or minor version. Since the current version is `0.31.3`, that promise is binding for every 0.x release, because a semver minor bump on a 0.x crate is a breaking change.
`Cargo.toml` enforces this mechanically with `rust-version = "1.69"`, so a build on an older toolchain fails with a clear error rather than mysterious compilation failures deeper in the dependency graph. For a library used by applications that upgrade slowly, this is the guarantee that actually matters, more than any feature.
The dependency floor is similarly conservative in a way that suggests age-consciousness. `libc` is pinned at `0.2.186` with the `extra_traits` feature, `bitflags` at `2.3.3`, `cfg-if` at `1.0`, and the optional `memoffset` and `pin-utils` are held at older versions as well.
Release mechanics that never touch GitHub releases
The repository has no GitHub releases. That is not an oversight, it is the release path. A `RELEASE_PROCEDURE.md` documents the process, `CHANGELOG.md` is the accumulated history, and a `changelog/` directory alongside `towncrier.toml` means changelog entries are written as fragments and assembled at release time rather than edited by hand into the file.
The version lives in exactly one place. `Cargo.toml` says `version = "0.31.3"`, and the crate is published to crates.io from there. So the authoritative statement of what version you are using is the dependency you resolved, and the GitHub tags play no part in it.
Two other entries describe how the project works day to day. `Cross.toml` at the root is a `cross-rs` configuration, which is how a library supporting arm, musl and BSD targets runs its test suite on hardware it does not own. The `justfile` is the task runner, and it contains a single real task, the docs build:
RUSTDOCFLAGS='--cfg docsrs' cargo +nightly doc --all-features --no-depsThat one line explains the `docsrs` cfg you see in `Cargo.toml`, and it needs nightly Rust because that is what docs.rs runs. The default target of the justfile is `just --list`.
`CONVENTIONS.md`, `CONTRIBUTING.md` and the `test/` directory complete a repository that has clearly thought about how it wants to be worked on.
Where nix is the wrong choice
The clearest case against is that the crate does not hide the operating system, it renames it. If your program's difficulty is that the syscall is awkward rather than that the Rust wrapper is unsafe, nix does not help, because the awkwardness is the platform's. The README is explicit that the goal is not a fully unified interface but to unify what can be unified while still exposing platform-specific APIs, which means you will still hit `cfg` branches in your own code.
The second case is dependency weight in a different sense. Around forty feature flags is good engineering for a bindings library and a real cost for anyone who wanted one logging call to stay simple. If you need a small thing from the operating system, `std` covers a surprising amount of it, and a bindings crate is the heavier answer.
The third is tier 3. If you deploy to Fuchsia, Redox, Dragonfly or a uclibc arm board, the README has already told you the target may be dropped without a major version bump. That is not a defect, it is an accurate statement of what one volunteer-maintained crate can promise, but it does mean your support question has to be asked out loud rather than answered by the version number.
The alternative to weigh is writing the `libc` call directly with `unsafe` and handling the return code. For a single call in a codebase that already depends on `libc`, that is often the lighter choice. nix earns its place when the count of operating system calls is high enough that hand-written errno handling becomes a recurring source of bugs.
Editorial conclusion
The nix crate is for Rust programs that need to talk to the operating system directly: files, sockets, signals, processes, mounts, terminal control. Its value is that unsafe blocks and errno handling disappear from your code without the API becoming unidiomatic, and its support policy is unusually explicit, with CI enforcement tiers and a stated MSRV of 1.69 that will not move without a version bump. Before adopting it, check two things: whether the feature flags you need exist and are listed in Cargo.toml, and whether your target sits in tier 1 where failures block new code, or in tier 3 where it may be dropped. Neither is the NixOS package manager despite the name, so if you reached this repository looking for Rust on NixOS, this is not the crate you want.
Frequently asked questions
Is the nix crate related to NixOS?
No. The name refers to the Nix family of Unix-like platforms, Linux, Darwin and the BSDs, and the repository description is Rust friendly bindings to *nix APIs. It is a library you add to Cargo.toml, not a package manager and not an operating system. The search results that suggest otherwise are matching on the name.
How does nix differ from using the libc crate directly?
libc exposes system calls as unsafe extern functions with raw pointers and integer return codes, so the caller handles errno. nix wraps the same calls in types that make illegal usage hard to express and returns a Result, which is why the README compares gethostname's two-argument unsafe form against a zero-argument function returning Result<OsString>.
Which platforms does the nix crate support?
Targets are split into three tiers with different CI consequences. Tier 1 is built and tested and a failure blocks new code, tier 2 is built where a build failure blocks but a test failure does not, and tier 3 is built where failures may be ignored and the target may be dropped at any time. Anything unlisted is best-effort.
Does enabling a feature flag in nix pull in others?
Some do. The feature list in Cargo.toml is not flat: dir expands to fs, event expands to poll, mqueue expands to fs, mount pulls in uio, and zerocopy pulls both fs and uio. The default feature set is empty, so nothing is enabled unless you name it.
How do I build the nix crate documentation?
The justfile has a doc task that sets RUSTDOCFLAGS to the docsrs cfg and runs cargo +nightly doc with all features and no dependencies. It requires a nightly toolchain because that is the configuration docs.rs uses, and Cargo.toml enables all-features for that same build.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nix-rust-nix)