...
1# Boulder - An ACME CA
2
3[](https://github.com/letsencrypt/boulder/actions/workflows/boulder-ci.yml?query=branch%3Amain)
4
5This is an implementation of an ACME-based CA. The [ACME
6protocol](https://github.com/ietf-wg-acme/acme/) allows the CA to
7automatically verify that an applicant for a certificate actually controls an
8identifier, and allows domain holders to issue and revoke certificates for
9their domains. Boulder is the software that runs [Let's
10Encrypt](https://letsencrypt.org).
11
12## Contents
13
14* [Overview](#overview)
15* [Setting up Boulder](#setting-up-boulder)
16 * [Development](#development)
17 * [Working with Certbot](#working-with-certbot)
18 * [Working with another ACME Client](#working-with-another-acme-client)
19 * [Production](#production)
20* [Contributing](#contributing)
21* [License](#license)
22
23## Overview
24
25Boulder is divided into the following main components:
26
271. Web Front Ends (one per API version)
282. Registration Authority
293. Validation Authority
304. Certificate Authority
315. Storage Authority
326. Publisher
337. OCSP Responder
348. CRL Updater
35
36This component model lets us separate the function of the CA by security
37context. The Web Front End, Validation Authority, OCSP Responder and
38Publisher need access to the Internet, which puts them at greater risk of
39compromise. The Registration Authority can live without Internet
40connectivity, but still needs to talk to the Web Front End and Validation
41Authority. The Certificate Authority need only receive instructions from the
42Registration Authority. All components talk to the SA for storage, so most
43lines indicating SA RPCs are not shown here.
44
45```text
46 CA ---------> Publisher
47 ^
48 |
49 Subscriber -> WFE --> RA --> SA --> MariaDB
50 | ^
51Subscriber server <- VA <----+ |
52 |
53 Browser -------------------> OCSP Responder
54```
55
56Internally, the logic of the system is based around five types of objects:
57accounts, authorizations, challenges, orders and certificates, mapping directly
58to the resources of the same name in ACME. Requests from ACME clients result in
59new objects and changes to objects. The Storage Authority maintains persistent
60copies of the current set of objects.
61
62Boulder uses gRPC for inter-component communication. For components that you
63want to be remote, it is necessary to instantiate a "client" and "server" for
64that component. The client implements the component's Go interface, while the
65server has the actual logic for the component. A high level overview for this
66communication model can be found in the [gRPC
67documentation](https://www.grpc.io/docs/).
68
69The full details of how the various ACME operations happen in Boulder are
70laid out in
71[DESIGN.md](https://github.com/letsencrypt/boulder/blob/main/docs/DESIGN.md).
72
73## Setting up Boulder
74
75### Development
76
77Boulder has a Dockerfile and uses Docker Compose to make it easy to install
78and set up all its dependencies. This is how the maintainers work on Boulder,
79and is our main recommended way to run it for development/experimentation. It
80is not suitable for use as a production environment.
81
82While we aim to make Boulder easy to setup ACME client developers may find
83[Pebble](https://github.com/letsencrypt/pebble), a miniature version of
84Boulder, to be better suited for continuous integration and quick
85experimentation.
86
87We recommend setting git's [fsckObjects
88setting](https://groups.google.com/forum/#!topic/binary-transparency/f-BI4o8HZW0/discussion)
89before getting a copy of Boulder to have better integrity guarantees for
90updates.
91
92Clone the boulder repository:
93
94```shell
95git clone https://github.com/letsencrypt/boulder/
96cd boulder
97```
98
99Additionally, make sure you have Docker Engine 1.13.0+ and Docker Compose
1001.10.0+ installed. If you do not, you can follow Docker's [installation
101instructions](https://docs.docker.com/compose/install/).
102
103We recommend having **at least 2GB of RAM** available on your Docker host. In
104practice using less RAM may result in the MariaDB container failing in
105non-obvious ways.
106
107To start Boulder in a Docker container, run:
108
109```shell
110docker compose up
111```
112
113To run our standard battery of tests (lints, unit, integration):
114
115```shell
116docker compose run --use-aliases boulder ./test.sh
117```
118
119To run all unit tests:
120
121```shell
122docker compose run --use-aliases boulder ./test.sh --unit
123```
124
125To run specific unit tests (example is of the ./va directory):
126
127```shell
128docker compose run --use-aliases boulder ./test.sh --unit --filter=./va
129```
130
131To run all integration tests:
132
133```shell
134docker compose run --use-aliases boulder ./test.sh --integration
135```
136
137To run specific integration tests (example runs TestAkamaiPurgerDrainQueueFails and TestWFECORS):
138
139```shell
140docker compose run --use-aliases boulder ./test.sh --filter TestAkamaiPurgerDrainQueueFails/TestWFECORS
141```
142
143To get a list of available integration tests:
144
145```shell
146docker compose run --use-aliases boulder ./test.sh --list-integration-tests
147```
148
149The configuration in docker-compose.yml mounts your boulder checkout at
150/boulder so you can edit code on your host and it will be immediately
151reflected inside the Docker containers run with `docker compose`.
152
153If you have problems with Docker, you may want to try [removing all
154containers and
155volumes](https://www.digitalocean.com/community/tutorials/how-to-remove-docker-images-containers-and-volumes).
156
157By default, Boulder uses a fake DNS resolver that resolves all hostnames to
158127.0.0.1. This is suitable for running integration tests inside the Docker
159container. If you want Boulder to be able to communicate with a client
160running on your host instead, you should find your host's Docker IP with:
161
162```shell
163ifconfig docker0 | grep "inet addr:" | cut -d: -f2 | awk '{ print $1}'
164```
165
166And edit docker-compose.yml to change the `FAKE_DNS` environment variable to
167match. This will cause Boulder's stubbed-out DNS resolver (`sd-test-srv`) to
168respond to all A queries with the address in `FAKE_DNS`.
169
170If you use a host-based firewall (e.g. `ufw` or `iptables`) make sure you allow
171connections from the Docker instance to your host on the required validation
172ports to your ACME client.
173
174Alternatively, you can override the docker-compose.yml default with an
175environmental variable using -e (replace 172.17.0.1 with the host IPv4
176address found in the command above)
177
178```shell
179docker compose run --use-aliases -e FAKE_DNS=172.17.0.1 --service-ports boulder ./start.py
180```
181
182Running tests without the `./test.sh` wrapper:
183
184Run all unit tests
185
186```shell
187docker compose run --use-aliases boulder go test -p 1 ./...
188```
189
190Run unit tests for a specific directory:
191
192```shell
193docker compose run --use-aliases boulder go test <DIRECTORY>
194```
195
196Run integration tests (omit `--filter <REGEX>` to run all):
197
198```shell
199docker compose run --use-aliases boulder python3 test/integration-test.py --chisel --gotest --filter <REGEX>
200```
201
202### Working with Certbot
203
204Check out the Certbot client from https://github.com/certbot/certbot and
205follow their setup instructions. Once you've got the client set up, you'll
206probably want to run it against your local Boulder. There are a number of
207command line flags that are necessary to run the client against a local
208Boulder, and without root access. The simplest way to run the client locally
209is to use a convenient alias for certbot (`certbot_test`) with a custom
210`SERVER` environment variable:
211
212```shell
213SERVER=http://localhost:4001/directory certbot_test certonly --standalone -d test.example.com
214```
215
216Your local Boulder instance uses a fake DNS resolver that returns 127.0.0.1
217for any query, so you can use any value for the -d flag. To return an answer
218other than `127.0.0.1` change the Boulder `FAKE_DNS` environment variable to
219another IP address.
220
221### Working with another ACME Client
222
223Once you have followed the Boulder development environment instructions and have
224started the containers you will find the ACME endpoints exposed to your host at
225the following URLs:
226
227* ACME v2, HTTP: `http://localhost:4001/directory`
228* ACME v2, HTTPS: `https://localhost:4431/directory`
229
230To access the HTTPS versions of the endpoints you will need to configure your
231ACME client software to use a CA truststore that contains the
232`test/wfe-tls/minica.pem` CA certificate. See
233[`test/PKI.md`](https://github.com/letsencrypt/boulder/blob/main/test/PKI.md)
234for more information.
235
236Your local Boulder instance uses a fake DNS resolver that returns 127.0.0.1
237for any query, allowing you to issue certificates for any domain as if it
238resolved to your localhost. To return an answer other than `127.0.0.1` change
239the Boulder `FAKE_DNS` environment variable to another IP address.
240
241Most often you will want to configure `FAKE_DNS` to point to your host
242machine where you run an ACME client.
243
244### Production
245
246Boulder is custom built for Let's Encrypt and is intended only to support the
247Web PKI and the CA/Browser forum's baseline requirements. In our experience
248often Boulder is not the right fit for organizations that are evaluating it for
249production usage. In most cases a centrally managed PKI that doesn't require
250domain-authorization with ACME is a better choice. For this environment we
251recommend evaluating a project other than Boulder.
252
253We offer a brief [deployment and implementation
254guide](https://github.com/letsencrypt/boulder/wiki/Deployment-&-Implementation-Guide)
255that describes some of the required work and security considerations involved in
256using Boulder in a production environment. As-is the docker based Boulder
257development environment is **not suitable for
258production usage**. It uses private key material that is publicly available,
259exposes debug ports and is brittle to component failure.
260
261While we are supportive of other organization's deploying Boulder in
262a production setting we prioritize support and development work that favors
263Let's Encrypt's mission. This means we may not be able to provide timely support
264or accept pull-requests that deviate significantly from our first line goals. If
265you've thoroughly evaluated the alternatives and Boulder is definitely the best
266fit we're happy to answer questions to the best of our ability.
267
268## Contributing
269
270Please take a look at
271[CONTRIBUTING.md](https://github.com/letsencrypt/boulder/blob/main/docs/CONTRIBUTING.md)
272for our guidelines on submitting patches, code review process, code of conduct,
273and various other tips related to working on the codebase.
274
275## Code of Conduct
276
277The code of conduct for everyone participating in this community in any capacity
278is available for reference
279[on the community forum](https://community.letsencrypt.org/guidelines).
280
281## License
282
283This project is licensed under the Mozilla Public License 2.0, the full text
284of which can be found in the
285[LICENSE.txt](https://github.com/letsencrypt/boulder/blob/main/LICENSE.txt)
286file.
View as plain text