# Boulder: the ACME CA that runs Let's Encrypt, and how to run it locally

> Boulder is Let's Encrypt's ACME certificate authority, written in Go and split into seven components by security context. This article covers what it does, how to bring it up with Docker Compose, and where it stops being the right tool.

**letsencrypt/boulder** — An ACME-based certificate authority, written in Go. 

- Repository: https://github.com/letsencrypt/boulder
- Stars: 5,760 · Forks: 648
- Language: Go
- License: MPL-2.0
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/letsencrypt-boulder

## What Boulder is, and who ends up running it

Boulder is an implementation of an ACME-based certificate authority. The protocol it speaks, ACME, lets a CA verify automatically that an applicant controls an identifier, and lets subscribers issue and revoke certificates for the identifiers they control. The README states plainly that Boulder is the software that runs Let's Encrypt.

That sentence sets the audience. This is not a general-purpose CA you drop into a homelab to sign internal certificates. It is the reference implementation behind a public CA that has to survive hostile input at internet scale. The people who get value from it are engineers building or testing ACME clients, teams operating a CA that needs the same separation of duties, and researchers who want to read how issuance, validation and revocation are actually wired together. If you only need certificates for a handful of internal services, the README points you elsewhere, and that pointer is worth taking seriously.

## Seven components split by security context

Boulder's architecture is its main design decision. The README lists seven parts: Web Front Ends (one per API version), Registration Authority, Validation Authority, Certificate Authority, Storage Authority, Publisher, and CRL Updater. The split is not about scaling. It is about which components are allowed to touch the internet.

The Web Front End, Validation Authority, CRL Storer and Publisher need internet access, which the README says puts them at greater risk of compromise. The Registration Authority can live without internet connectivity but still talks to the Web Front End and Validation Authority. The Certificate Authority only receives instructions from the Registration Authority. Everything reaches storage through the Storage Authority, so most SA RPC lines are omitted from the README's diagram.

The data flow is short and readable. A subscriber talks to the WFE, which calls the RA, which calls the SA, which persists to MariaDB. The VA reaches out to the subscriber's server to check a challenge, and the CA hands certificates to the Publisher. Browsers fetch CRLs from S3, written by the CRL Storer and Updater. Internally the system is built around five object types (accounts, authorizations, challenges, orders and certificates) that map directly onto the ACME resources of the same names. Components talk over gRPC: for a remote component you instantiate a client that implements the Go interface and a server that holds the logic.

That last detail is the practical cost. You cannot run Boulder as one process and expect the isolation the design is for. You get the isolation by deploying the pieces separately, which means you own service discovery, certificates between components, and the operational surface of seven moving parts.

## Installing Boulder with Docker Compose for development

Boulder ships a Dockerfile and a Docker Compose setup that installs all its dependencies. The README calls this the maintainers' own working method and the main recommended way to run it for development or experimentation, and says explicitly that it is not suitable as a production environment. The README also suggests enabling git's fsckObjects setting before cloning, for better integrity guarantees on updates.

Start by cloning the repository and entering it. You need Docker Engine 1.13.0+ and Docker Compose 1.10.0+, and the README recommends at least 2GB of RAM on the Docker host because the MariaDB container can otherwise fail in non-obvious ways.

```bash
git clone https://github.com/letsencrypt/boulder/
cd boulder
```

Before the stack can start, the certificates the components use have to exist. This one-off command writes them into test/certs/[.softhsm-tokens,ipki,webpki]:

```bash
docker compose run bsetup
```

You only need to run it once. If you want to start over, remove ./test/certs/.softhsm-tokens, ./test/certs/ipki and ./test/certs/webpki and run the same command again. Then bring the stack up:

```bash
docker compose up
```

The Compose file mounts your checkout at /boulder, so edits on the host appear inside the containers immediately. By default Boulder uses a stubbed DNS resolver, sd-test-srv, that answers every A query with the address in FAKE_DNS. That is fine for integration tests inside the container. To point an ACME client running on your host at Boulder, find your host's Docker IP and change FAKE_DNS in docker-compose.yml to match:

```bash
ifconfig docker0 | grep "inet addr:" | cut -d: -f2 | awk '{ print $1}'
```

You can also override the default in one shot, replacing the address with the one the command above returned:

```bash
docker compose run --use-aliases -e FAKE_DNS=172.17.0.1 --service-ports boulder ./start.py
```

If you run a host firewall such as ufw or iptables, allow connections from the Docker instance to your host on the validation ports your ACME client's solver is listening on. Otherwise challenges fail and the failure looks like a validation bug rather than a network rule.

## Running the test suite before you change anything

Boulder's t.sh is the entry point for the standard battery of lints, unit tests and integration tests, and tn.sh runs the same with the config-next configuration, which the README describes as a likely future state including new feature flags. That distinction matters if you are modifying the CA: config-next is where new behaviour shows up first.

```bash
./t.sh
./t.sh -u
./t.sh -u -p ./va
./t.sh -i
./t.sh -ui -c --coverage-dir=./test/coverage/mytestrun
./t.sh -i -f TestGenerateValidity/TestWFECORS
```

The flags compose: -u for unit tests, -i for integration tests, -p to narrow unit tests to a package such as ./va, -c to collect coverage into a directory you name, and -f to select specific integration tests. Run the full suite once on a clean checkout before touching code. If it fails there, the problem is your environment, not your patch, and the RAM warning above is the first thing to check.

## Where Boulder is the wrong tool

The README is unusually direct about this. It says that while the project aims to make Boulder easy to set up, ACME client developers may find Pebble, described as a miniature version of Boulder, better suited for continuous integration and quick experimentation. If your goal is to exercise an ACME client against a server that issues certificates, Pebble gets you there with far less machinery.

The second limitation is the Compose path itself. The README states the development setup is not suitable for use as a production environment. Treating it as one means running a CA whose threat model has been collapsed: the component separation that justifies Boulder's complexity is exactly what a single Compose stack does not give you.

The third is the dependency floor. MariaDB, S3 for CRL storage, and a PKCS#11 token directory under test/certs/.softhsm-tokens are all part of the picture. That is a real infrastructure commitment for a tool whose value is concentrated in studying or extending a public CA's implementation. If you wanted a small CA for a private network, this is a large answer to a small question.

## Pebble and Boulder: two sizes of the same protocol

The honest alternative is Pebble, from the same organisation. The difference is scope, not protocol. Pebble is a miniature Boulder aimed at CI and quick experimentation, so it gives you an ACME server to talk to without the seven-component deployment. Boulder gives you the production architecture: separate security contexts, gRPC between components, the SA as the single path to storage, and the object model that maps onto ACME resources.

If you are writing an ACME client, start with Pebble and move to Boulder when you need to test behaviour that only the full implementation exercises. If you are designing a CA, read Boulder's component split and the implementation details document under docs/, because the design is the part worth copying, and Pebble does not contain it.

## Licence, maintenance and the cost of tracking upstream

Boulder is licensed under MPL-2.0. That is a file-level copyleft licence: modifications to covered files carry obligations when distributed. This is not legal advice, and if you plan to redistribute a modified Boulder, get your own reading of the licence and of LICENSE.txt in the repository.

Maintenance signals are concrete. The repository is not archived, and the last push was on 2026-09-22. Releases are frequent and date-stamped rather than semantic: v0.20260921.0, v0.20260908.0, v0.20260901.0. A version number that encodes a date tells you the project does not promise API stability across releases, and the Makefile's VERSION default of 1.0.0 is a packaging placeholder, not a compatibility statement.

Upgrade cost therefore lands on you. Pinning a release and reading the diff between two date-stamped tags is the realistic workflow. Note also that the Makefile carries TODO comments pointing at removing the Makefile itself and at retiring pardot-test-srv in favour of salesforce-test-srv, so the build and test tooling is itself in motion. Budget for that churn if you fork.

## Conclusion

Adopt Boulder if you need to study, test against, or modify the CA that actually issues for Let's Encrypt: the Docker Compose development path is the maintainers' recommended way in, and the component split is the reason to prefer it over a single-binary CA. Do not adopt it as the public CA for a small internal PKI, and do not treat the Compose setup as a production deployment, because the README says it is not suitable for that. Before committing, verify that your host has at least 2GB of RAM for the MariaDB container, that Docker Engine 1.13.0+ and Docker Compose 1.10.0+ are present, and that the FAKE_DNS value in docker-compose.yml points at the address where your ACME client's solver listens.

## FAQ

### What is Boulder in the context of Let's Encrypt?

Boulder is an implementation of an ACME-based certificate authority written in Go, and the README states it is the software that runs Let's Encrypt. It handles verifying that an applicant controls an identifier and lets subscribers issue and revoke certificates for identifiers they control.

### How do I install Boulder for local development?

Clone the repository, run docker compose run bsetup once to write the certificates into test/certs, then run docker compose up. You need Docker Engine 1.13.0+ and Docker Compose 1.10.0+, and the README recommends at least 2GB of RAM on the Docker host.

### Is Boulder suitable for production use?

The README says the Docker Compose development setup is not suitable for use as a production environment. Production means deploying the components separately so the security-context separation the architecture is built around actually holds.

### Is Boulder the same as Pebble?

No. The README describes Pebble as a miniature version of Boulder and suggests ACME client developers may find it better suited for continuous integration and quick experimentation. Boulder is the full component architecture that runs Let's Encrypt.

### What licence does Boulder use?

Boulder is licensed under MPL-2.0, per the repository. That is a file-level copyleft licence, so modifications to covered files carry obligations on distribution; check LICENSE.txt in the repository for the terms that apply to you.

## Sources

- [Issues](https://github.com/letsencrypt/boulder/issues)
- [letsencrypt/boulder on GitHub](https://github.com/letsencrypt/boulder)
- [License: MPL-2.0](https://github.com/letsencrypt/boulder/blob/main/LICENSE)
- [README](https://github.com/letsencrypt/boulder/blob/main/README.md)
- [Releases](https://github.com/letsencrypt/boulder/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/letsencrypt-boulder
