Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Installation

acme-proxy is a Rust application, published on crates.io. There are four ways to get it: cargo install, a source build, the published container image, or a container image you build yourself. Only the published image comes prebuilt; no standalone prebuilt binaries are published.

The result is a single binary carrying both the server and the admin CLI, so a deployment never needs a second tool.

Prerequisites

  • Rust toolchain: the crate is edition 2024 and declares a rust-version in Cargo.toml (currently 1.97). That file is the source of truth; cargo refuses to build with anything older.
  • Cargo: the Rust package manager.

SQLite is not a prerequisite: the driver is bundled with sqlx, the database file is created automatically, and DATABASE_URL is not needed to compile. The PostgreSQL driver is bundled the same way, so the same binary speaks both — what it does need is a server and a database that already exist. A sqlite3 binary is only useful if you want to inspect the database by hand.

You can install Rust via rustup:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

From crates.io

cargo install acme-proxy

This fetches the published crate, compiles it, and puts the binary in ~/.cargo/bin — which needs to be on your PATH. Confirm it with:

acme-proxy --version

Tab completion and a man page come out of the binary itself, so there is nothing extra to download:

acme-proxy completions zsh > ~/.zfunc/_acme-proxy
acme-proxy man | sudo tee /usr/share/man/man1/acme-proxy.1 > /dev/null

Both are generated from the command tree, so regenerate them when you upgrade. The per-shell paths are in the admin CLI chapter.

To pin a version, or to move to a specific one later, name it:

cargo install acme-proxy --version 0.6.0

Upgrading is cargo install acme-proxy --force. Before doing so across a minor version, read the ### Breaking section of the changelog. Before 1.0.0 the database schema is the only compatibility guarantee, so the data survives an upgrade but a configuration key may have been renamed.

Building from source

Prefer this if you intend to change anything, or want the test suite and the book sources alongside the binary.

  1. Clone the repository:

    git clone https://github.com/acme-proxy/acme-proxy.git
    cd acme-proxy
    
  2. Build the project in release mode for production use:

    cargo build --release
    

The binary will be located at target/release/acme-proxy.

Optional features

The default build has no optional features. One is available:

FeatureWhat it adds
hsmPKCS#11 support for the Local CA’s issuing key, so it can live in a YubiKey or an HSM instead of a file — see Hardware Keys.
cargo install acme-proxy --features hsm    # or, from a clone:
cargo build --release --features hsm

It is off by default because it pulls in cryptoki and its bindings, which a deployment signing with an on-disk key does not need. The PKCS#11 module itself is loaded at runtime, so enabling this adds no build-time C toolchain requirement. Configuring signer.local_ca.key_source = "pkcs11" on a binary built without it is a startup error naming the feature, never a silent fallback to the file key.

The published container image is the default build, without hsm. A deployment that needs it builds its own binary.

Container (Docker / Podman)

Every release is published to the GitHub Container Registry as a multi-architecture image, for linux/amd64 and linux/arm64:

podman pull ghcr.io/acme-proxy/acme-proxy:0.6.0
TagPoints at
0.6.0That release. It never moves.
0.6The newest 0.6.x release: its fixes, never a new minor.
latestThe highest release, whatever its minor.
edgeThe head of main, rebuilt on every merge. Not a release.
sha-…One commit of main, as edge was when it was built.

Run a version tag, or 0.6 to take patch releases without a change on your side. Avoid latest for an unattended deployment. Before 1.0.0 a minor release may rename a configuration key, so a pull of latest can stop a server from starting; the ### Breaking sections of the changelog list every such change. edge is for trying what the next release will hold, never for a certificate authority anyone depends on.

Every image holds the release build with the default features: the binary cargo install acme-proxy produces.

To build the image yourself instead, use the Containerfile in a clone of the repository:

podman build -t acme-proxy .

That is the same release build as the published image, fat LTO included, so it takes tens of minutes.

The image’s working directory is /data and its entrypoint is the acme-proxy binary, so mount a volume there for the SQLite database, the configuration and the CA key material — all of which default to paths relative to the working directory. The image runs as a non-root user, so the mounted directory must be writable by it — the :U flag below is the rootless-Podman way; see Deployment for Docker.

podman run -d \
  -p 3000:3000 \
  -v ./data:/data:U \
  ghcr.io/acme-proxy/acme-proxy:0.6.0

Drop a config.toml into ./data (it must define at least one profile — see the Quick Start), or configure the container entirely through ACME_PROXY_* environment variables:

podman run -d \
  -p 3000:3000 \
  -v ./data:/data:U \
  -e ACME_PROXY_PROFILES__DEFAULT__ENABLED=true \
  -e ACME_PROXY_SERVER__BASE_URL=https://acme.example.com \
  ghcr.io/acme-proxy/acme-proxy:0.6.0

Verifying the image

Each published image carries a signed build provenance attestation. It records the repository, the commit and the workflow run that built the image. Check it with the GitHub CLI before you run the image:

gh attestation verify oci://ghcr.io/acme-proxy/acme-proxy:0.6.0 \
  --repo acme-proxy/acme-proxy

The attestation is on the multi-architecture index, the object a tag resolves to. The digest of one architecture’s image, on its own, has no attestation to find.