Skip to content
Small team, full backlog, zero orders dropped. Support replies are slower than we’d like. Read our status update → Zero orders dropped. Status → 📬 Check your spam folder — most of our replies land there. We do answer. Status update → 📬 Check your spam folder. Status →

Build DCENT_OS From Source

The Rust daemon, dashboard and Buildroot integration are public under GPL-3.0 and build from the repository. A full flashable Antminer image is a different boundary: it reuses boot-critical vendor components that D-Central cannot redistribute in the source repository. Those are two different jobs with two different answers, and most of the confusion here comes from treating them as one.

What is open and what is not redistributed

Open-source and non-redistributed DCENT_OS build inputs
ComponentRepository statusBuild/audit path
dcentrald Rust mining daemonGPL-3.0 sourceBuilds from a fresh clone for ARMv7 and AArch64 targets
React/TypeScript dashboardGPL-3.0 sourceBuilds from the repository toolchain (Node and npm)
Host-side test suitesGPL-3.0 sourceRun on your machine with no miner attached
Buildroot external tree and configurationGPL-3.0 project source/configurationDefines the minimal Linux userspace and integration
SoC kernel, FPGA bitstream, FSBL/U-BootBoot-critical vendor/upstream artifacts; not redistributed in the source repoMust be supplied locally from firmware the operator is authorized to use and must match pinned hashes
Signed release packagePrebuilt guarded artifactContains SHA-256 manifests, Ed25519 public key and signed manifest

Build the open daemon

The workspace pins its own Rust toolchain, so you do not pick a version. A rust-toolchain.toml at the daemon workspace root names channel 1.90.0, the rustfmt and clippy components, and both cross targets — armv7-unknown-linux-musleabihf for Zynq control boards and aarch64-unknown-linux-musl for Amlogic. Install rustup and it provisions all of that on the first build. The pin exists because the primary daemon workspace previously did not have one, so a fresh clone built with whatever toolchain the contributor happened to have.

The prerequisite that stops most first builds

Read this before you run anything, because the error message does not point at the fix. The daemon's dependency tree includes ring, which compiles C and assembly. Rust's own cross-linking needs no external GCC — rust-lld handles it, and the repository's cargo config says so. C compilation is a separate matter. On a host with no ARM C cross-compiler, the build stops here:

error occurred in cc-rs: failed to find tool "arm-linux-musleabihf-gcc": program not found
warning: build failed, waiting for other jobs to finish...

Exit code 101, on ring v0.17.14. If you already have an ARM C cross-toolchain on your PATH you will never see it. If you do not, this is where you stop, and nothing in the message tells you why. The fix is to point the cc crate at a C cross-compiler through its per-target environment variables:

# Linux or CI - real musl-cross-make tools
export CC_armv7_unknown_linux_musleabihf=arm-linux-musleabihf-gcc
export AR_armv7_unknown_linux_musleabihf=arm-linux-musleabihf-ar

# Windows - the wrappers the repository already ships (needs Zig 0.13.0)
set CC_armv7_unknown_linux_musleabihf=%CD%\zig-cc-arm.bat
set AR_armv7_unknown_linux_musleabihf=%CD%\zig-ar-arm.bat

The AArch64 equivalents are CC_aarch64_unknown_linux_musl and AR_aarch64_unknown_linux_musl, with zig-cc-aarch64.bat and zig-ar-aarch64.bat. Those four wrapper scripts are in the public tree under dcentrald/; they strip the --target flag cc-rs adds and hand the compile to zig cc. The deploy helper exports the same variables for you when you have not set your own, which is why a deploy sometimes builds cleanly on a machine where a bare cargo build did not. The reason the repository does not simply put a default in a cargo [env] block is documented in dcentrald/.cargo/config.toml: cargo resolves the path to absolute form first, and cc-rs on Windows can mis-split an absolute path containing spaces.

Then the build itself

git clone https://github.com/DCentralTech/DCENT_OS.git
cd DCENT_OS/DCENT_OS_Antminer/dcentrald
cargo build --release --target armv7-unknown-linux-musleabihf   # Zynq
cargo build --release --target aarch64-unknown-linux-musl       # Amlogic

With the C cross-compiler in place, that produces an ARM dcentrald binary at target/<triple>/release/dcentrald. It does not by itself produce a complete bootable image, and it is not a statement about any particular miner — what happens when that binary reaches hardware is a separate question with a separate answer.

The dashboard and the host-side tests need no cross-compiler at all:

cd dashboard && npm install && npm run build

cd dcentrald
cargo test
cargo fmt --all --check
cargo clippy --all-targets

The repository also carries a Docker wrapper, scripts/build-dcentrald.sh, which builds a pinned cross image that supplies the C toolchain. It is the lane our own build environment uses; from a fresh public clone it currently stops on missing tracked inputs, so use the host-toolchain route above until that is fixed.

The build environment, concretely

  • Default workspace build. A bare cargo build compiles the daemon stack through the workspace's default-members. It deliberately excludes the optional pic-recovery package, which is diagnostic-only and needs no vendor bitstream. Build it explicitly with cargo build -p pic-recovery if you want it.
  • Host OS for the image lane: Ubuntu 22.04, in a container. The build image installs build-essential, device-tree-compiler, u-boot-tools, squashfs-tools, libncurses-dev, libssl-dev, cpio, bc and rsync among others.
  • Windows hosts: use WSL or Docker for anything beyond the daemon build. Several crates carry Linux-only hardware-abstraction code and are validated on the target rather than on a Windows host.

The Buildroot layer

The image lane wraps Buildroot with an external tree at br2_external_dcentos/. Buildroot is not vendored — the setup target clones it and pins it to a specific commit for repeatability. Buildroot's own manual is better than anything we would write and we are not going to reproduce it; what follows is only the part that is specific to this repository.

make setup          # clone Buildroot at the pinned commit, apply the merged defconfig
make                # build
make menuconfig     # adjust Buildroot config
make savedefconfig  # write your changes back

Defconfigs are merged, not monolithic. The tree carries 15 defconfigs — S9, three AM2 Zynq boards, two BeagleBone variants, and nine Amlogic boards — plus two fragments. The merge step concatenates a workspace-wide common fragment, then an architecture-specific fragment where one applies, then the per-product defconfig last so its overrides win. The merged file is generated and git-ignored; edit the fragments or the per-product defconfig, never the merged output.

The default target is the S9. Any other board needs both variables on the command line:

make DEFCONFIG=dcentos_am3_s21_defconfig \
     DEFCONFIG_FRAGMENTS="dcentos-common.fragment dcentos_am3_aml_common.fragment" \
     setup

Pass the defconfig without its fragments and you get a config missing everything the common layer provides. This is the single most common way to waste an afternoon here.

That a defconfig exists for a board is not a statement that an image for it can be packaged. Fifteen defconfigs exist; one target is admitted by the release capsule. The gap between those two numbers is the vendor-artifact boundary described below, not a to-do list.

Verifying your build

make test                 # compile-gate every workspace test for armv7 musl, in Docker
make test RUN_TESTS=1     # compile and execute on the container host target
make test-host            # the no-hardware crate tests, no container
make verify               # the local gate that `make release` runs before building
make install-hooks        # install the commit/push gates once per checkout

make release runs make verify itself, and the hook-only skip variable does not bypass release verification. None of these need a miner.

Build a full image

The repository's production capsule currently admits the S9 target. It expects restricted boot inputs, release keys and a digest-pinned builder described in the release-candidate runbook. Direct development packaging fails closed when it cannot satisfy the release receipt.

make release RELEASE_TARGET=s9

Two variables gate that command: a manifest public-key pin and a release signing key. Neither is a secret you have to be given — scripts/generate_release_keypair.sh is in the public tree, it generates an Ed25519 keypair with openssl, and the Makefile's own error message names it. What a public cloner cannot supply is the boot-critical vendor material: the SoC kernel, the FPGA bitstream and the FSBL/U-Boot chain, which come from each miner's stock or BraiinsOS firmware, are not ours to redistribute, and must hash-match a recorded manifest. Producing your own S9 image means extracting those artifacts from firmware you are authorized to use — in practice, from a unit you own. We can describe the boundary. We cannot hand you the artifacts, and you should be suspicious of anyone who does. Calling the surrounding stack open source does not make third-party redistribution rights appear.

Three lanes refuse before they do any work, so nobody burns an afternoon on them:

  • make dev image packaging is fail-closed and exits with an error. It cannot satisfy the invocation-bound build-receipt contract the release lane depends on.
  • Direct Buildroot packaging through the inner Docker driver is likewise disabled until a separate lab capsule exists; it refuses before doing any build work.
  • make release is S9 only and rejects any other release target.

So the buildable, useful, genuinely supported artifact from this repository is the daemon. That is what most contributors need, and it is enough to get a running process on real hardware.

Reproducibility status

We do not claim byte-for-byte reproducible firmware. The release lane pins a Buildroot commit, a digest-pinned builder image and a toolchain SHA-256, and it records a build receipt — but a third party cannot currently reproduce a signed image bit-for-bit from the public tree alone, because of the same non-redistributable boot inputs described above. A reproducibility claim needs a published environment, hashes from independent rebuilds, and a documented comparison of any differences. Stating otherwise would be a claim we cannot back.

Upstream we lean on

The build is Buildroot with a BR2_EXTERNAL tree, and Buildroot's own manual is the right place to understand the underlying system rather than just drive ours. Same for the Rust project's cross-compilation model and Xilinx's Zynq boot documentation — all three publish better documentation for their own layers than we could write, so we link them instead of cloning them. Braiins made the Antminer control board an open, scriptable Linux target years before we shipped anything. We credit the 256 Foundation's Mujina, ESP-Miner and Skot's reverse-engineering work as references studied during design; no code was forked from them.

You have a binary. Now what?

A compiled dcentrald is not a running miner, and for most boards it will never become a flashable image — the release capsule admits one target. The route from binary to running daemon is a warm deployment over the Linux already on the control board: a script that cross-compiles, copies, takes over from the incumbent mining process and starts the daemon. On every board family except the S9 it writes only to /tmp, so a power cycle undoes it completely — and a daemon that starts is still not a daemon that mines.

That route, its per-board recovery paths and the guardrails it will stop you at are documented in Run DCENT_OS from your own build. Read it before you point anything at hardware. If you first want to know what your machine actually is, install routes by control board is the per-board lookup: one model badge maps to several control boards and most of them cannot mine.

Audit trail

Boundary reviewed 2026-08-29. Checked against the public GPL-3.0 tree at commit 6f61603. This page distinguishes buildable source from a complete redistributable boot image, and every command on it was executed before it was published.


Companion tool — DCENT_Toolbox: Install DCENT_Toolbox from source.