{"id":13493494,"url":"https://github.com/letsencrypt/boulder","last_synced_at":"2026-03-03T20:11:52.506Z","repository":{"id":24867965,"uuid":"28283593","full_name":"letsencrypt/boulder","owner":"letsencrypt","description":"An ACME-based certificate authority, written in Go. ","archived":false,"fork":false,"pushed_at":"2025-05-04T20:12:25.000Z","size":27271,"stargazers_count":5394,"open_issues_count":186,"forks_count":614,"subscribers_count":138,"default_branch":"main","last_synced_at":"2025-05-05T14:53:57.782Z","etag":null,"topics":["acme","boulder","ca","certificate-authority","go","lets-encrypt","pki","rfc8555","tls"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/letsencrypt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"docs/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":"docs/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"custom":"https://letsencrypt.org/donate/"}},"created_at":"2014-12-21T00:29:54.000Z","updated_at":"2025-05-03T06:18:24.000Z","dependencies_parsed_at":"2023-12-18T22:19:58.928Z","dependency_job_id":"efe327df-9c77-4bea-aed7-bc1bf82c6d95","html_url":"https://github.com/letsencrypt/boulder","commit_stats":{"total_commits":4768,"total_committers":139,"mean_commits":"34.302158273381295","dds":0.7594379194630873,"last_synced_commit":"97aa50977fb55c859342c9fabc636fc35a388aac"},"previous_names":[],"tags_count":401,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letsencrypt%2Fboulder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letsencrypt%2Fboulder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letsencrypt%2Fboulder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letsencrypt%2Fboulder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/letsencrypt","download_url":"https://codeload.github.com/letsencrypt/boulder/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253777228,"owners_count":21962644,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acme","boulder","ca","certificate-authority","go","lets-encrypt","pki","rfc8555","tls"],"created_at":"2024-07-31T19:01:15.860Z","updated_at":"2026-01-06T03:20:10.114Z","avatar_url":"https://github.com/letsencrypt.png","language":"Go","readme":"# Boulder - An ACME CA\n\n[![Build Status](https://github.com/letsencrypt/boulder/actions/workflows/boulder-ci.yml/badge.svg?branch=main)](https://github.com/letsencrypt/boulder/actions/workflows/boulder-ci.yml?query=branch%3Amain)\n\nThis is an implementation of an ACME-based CA. The [ACME\nprotocol](https://github.com/ietf-wg-acme/acme/) allows the CA to automatically\nverify that an applicant for a certificate actually controls an identifier, and\nallows subscribers to issue and revoke certificates for the identifiers they\ncontrol. Boulder is the software that runs [Let's\nEncrypt](https://letsencrypt.org).\n\n## Contents\n\n* [Overview](#overview)\n* [Setting up Boulder](#setting-up-boulder)\n  * [Development](#development)\n  * [Working with Certbot](#working-with-certbot)\n  * [Working with another ACME Client](#working-with-another-acme-client)\n  * [Production](#production)\n* [Contributing](#contributing)\n* [License](#license)\n\n## Overview\n\nBoulder is divided into the following main components:\n\n1. Web Front Ends (one per API version)\n2. Registration Authority\n3. Validation Authority\n4. Certificate Authority\n5. Storage Authority\n6. Publisher\n7. CRL Updater\n\nThis component model lets us separate the function of the CA by security\ncontext. The Web Front End, Validation Authority, CRL Storer, and\nPublisher need access to the Internet, which puts them at greater risk of\ncompromise. The Registration Authority can live without Internet\nconnectivity, but still needs to talk to the Web Front End and Validation\nAuthority. The Certificate Authority need only receive instructions from the\nRegistration Authority. All components talk to the SA for storage, so most\nlines indicating SA RPCs are not shown here.\n\n```text\n                            CA ---------\u003e Publisher\n                             ^\n                             |\n       Subscriber -\u003e WFE --\u003e RA --\u003e SA --\u003e MariaDB\n                             |               ^\nSubscriber server \u003c- VA \u003c----+               |\n                                             |\n          Browser -----\u003e S3 \u003c----- CRL Storer/Updater\n```\n\nInternally, the logic of the system is based around five types of objects:\naccounts, authorizations, challenges, orders and certificates, mapping directly\nto the resources of the same name in ACME. Requests from ACME clients result in\nnew objects and changes to objects. The Storage Authority maintains persistent\ncopies of the current set of objects.\n\nBoulder uses gRPC for inter-component communication. For components that you\nwant to be remote, it is necessary to instantiate a \"client\" and \"server\" for\nthat component. The client implements the component's Go interface, while the\nserver has the actual logic for the component. A high level overview for this\ncommunication model can be found in the [gRPC\ndocumentation](https://www.grpc.io/docs/).\n\nThe full details of how the various ACME operations happen in Boulder are\nlaid out in\n[DESIGN.md](https://github.com/letsencrypt/boulder/blob/main/docs/DESIGN.md).\n\n## Setting up Boulder\n\n### Development\n\nBoulder has a Dockerfile and uses Docker Compose to make it easy to install\nand set up all its dependencies. This is how the maintainers work on Boulder,\nand is our main recommended way to run it for development/experimentation. It\nis not suitable for use as a production environment.\n\nWhile we aim to make Boulder easy to setup ACME client developers may find\n[Pebble](https://github.com/letsencrypt/pebble), a miniature version of\nBoulder, to be better suited for continuous integration and quick\nexperimentation.\n\nWe recommend setting git's [fsckObjects\nsetting](https://groups.google.com/forum/#!topic/binary-transparency/f-BI4o8HZW0/discussion)\nbefore getting a copy of Boulder to have better integrity guarantees for\nupdates.\n\nClone the boulder repository:\n\n```shell\ngit clone https://github.com/letsencrypt/boulder/\ncd boulder\n```\n\nAdditionally, make sure you have Docker Engine 1.13.0+ and Docker Compose\n1.10.0+ installed. If you do not, you can follow Docker's [installation\ninstructions](https://docs.docker.com/compose/install/).\n\nWe recommend having **at least 2GB of RAM** available on your Docker host. In\npractice using less RAM may result in the MariaDB container failing in\nnon-obvious ways.\n\nTo run our standard battery of tests (lints, unit, integration):\n\n```shell\n./t.sh\n```\n\nTo run all unit tests:\n\n```shell\n./t.sh -u\n```\n\nTo run specific unit tests (example is of the ./va directory):\n\n```shell\n./t.sh -u -p ./va\n```\n\nTo run all integration tests:\n\n```shell\n./t.sh -i\n```\n\nTo run unit tests and integration tests with coverage:\n\n```shell\n./t.sh -ui -c --coverage-dir=./test/coverage/mytestrun\n```\n\nTo run specific integration tests (example runs TestGenerateValidity and TestWFECORS):\n\n```shell\n./t.sh -i -f TestGenerateValidity/TestWFECORS\n```\n\nTo do any of the above, but using the \"config-next\" configuration, which\nrepresents a likely future state (e.g. including new feature flags):\n\n```shell\n./tn.sh -your -options -here\n```\n\nTo start Boulder in a Docker container, first run:\n\n```shell\ndocker compose run bsetup\n```\nthis will write the necessary certificates into `test/certs/[.softhsm-tokens,ipki,webpki]`;\nYou only need to run this once to create the certificates. If you\nneed to remove all of the certificates and start over, you can remove\nthe directories `./test/certs/.softhsm-tokens`, `./test/certs/ipki`,\nand `./test/certs/webpki` and re-run `docker compose run bsetup`.\n\nThen run:\n\n```shell\ndocker compose up\n```\n\n\n\nThe configuration in docker-compose.yml mounts your boulder checkout at\n/boulder so you can edit code on your host and it will be immediately\nreflected inside the Docker containers run with `docker compose`.\n\nIf you have problems with Docker, you may want to try [removing all\ncontainers and\nvolumes](https://www.digitalocean.com/community/tutorials/how-to-remove-docker-images-containers-and-volumes).\n\nBy default, Boulder uses a fake DNS resolver that resolves all hostnames to\n127.0.0.1. This is suitable for running integration tests inside the Docker\ncontainer. If you want Boulder to be able to communicate with a client\nrunning on your host instead, you should find your host's Docker IP with:\n\n```shell\nifconfig docker0 | grep \"inet addr:\" | cut -d: -f2 | awk '{ print $1}'\n```\n\nAnd edit docker-compose.yml to change the `FAKE_DNS` environment variable to\nmatch. This will cause Boulder's stubbed-out DNS resolver (`sd-test-srv`) to\nrespond to all A queries with the address in `FAKE_DNS`.\n\nIf you use a host-based firewall (e.g. `ufw` or `iptables`) make sure you allow\nconnections from the Docker instance to your host on the required validation\nports to your ACME client.\n\nAlternatively, you can override the docker-compose.yml default with an\nenvironmental variable using -e (replace 172.17.0.1 with the host IPv4\naddress found in the command above)\n\n```shell\ndocker compose run --use-aliases -e FAKE_DNS=172.17.0.1 --service-ports boulder ./start.py\n```\n\nRunning tests without the `./test.sh` wrapper:\n\nRun unit tests locally, without docker (only works for some directories):\n\n```shell\ngo test ./issuance/...\n```\n\nRun all unit tests:\n\n```shell\ndocker compose run --use-aliases boulder go test -p 1 ./...\n```\n\nRun unit tests for a specific directory:\n\n```shell\ndocker compose run --use-aliases boulder go test \u003cDIRECTORY\u003e\n```\n\nRun integration tests (omit `--filter \u003cREGEX\u003e` to run all):\n\n```shell\ndocker compose run --use-aliases boulder python3 test/integration-test.py --chisel --gotest --filter \u003cREGEX\u003e\n```\n\n### Working with Certbot\n\nCheck out the Certbot client from https://github.com/certbot/certbot and\nfollow their setup instructions. Once you've got the client set up, you'll\nprobably want to run it against your local Boulder. There are a number of\ncommand line flags that are necessary to run the client against a local\nBoulder, and without root access. The simplest way to run the client locally\nis to use a convenient alias for certbot (`certbot_test`) with a custom\n`SERVER` environment variable:\n\n```shell\nSERVER=http://localhost:4001/directory certbot_test certonly --standalone -d test.example.com\n```\n\nYour local Boulder instance uses a fake DNS resolver that returns 127.0.0.1\nfor any query, so you can use any value for the -d flag. To return an answer\nother than `127.0.0.1` change the Boulder `FAKE_DNS` environment variable to\nanother IP address.\n\n### Working with another ACME Client\n\nOnce you have followed the Boulder development environment instructions and have\nstarted the containers you will find the ACME endpoints exposed to your host at\nthe following URLs:\n\n* ACME v2, HTTP: `http://localhost:4001/directory`\n* ACME v2, HTTPS: `https://localhost:4431/directory`\n\nTo access the HTTPS versions of the endpoints you will need to configure your\nACME client software to use a CA truststore that contains the\n`test/certs/ipki/minica.pem` CA certificate. See\n[`test/certs/README.md`](https://github.com/letsencrypt/boulder/blob/main/test/certs/README.md)\nfor more information.\n\nYour local Boulder instance uses a fake DNS resolver that returns 127.0.0.1\nfor any query, allowing you to issue certificates for any domain as if it\nresolved to your localhost. To return an answer other than `127.0.0.1` change\nthe Boulder `FAKE_DNS` environment variable to another IP address.\n\nMost often you will want to configure `FAKE_DNS` to point to your host\nmachine where you run an ACME client.\n\n### Production\n\nBoulder is custom built for Let's Encrypt and is intended only to support the\nWeb PKI and the CA/Browser forum's baseline requirements. In our experience\noften Boulder is not the right fit for organizations that are evaluating it for\nproduction usage. In most cases a centrally managed PKI that doesn't require\ndomain-authorization with ACME is a better choice. For this environment we\nrecommend evaluating a project other than Boulder.\n\nWe offer a brief [deployment and implementation\nguide](https://github.com/letsencrypt/boulder/wiki/Deployment-\u0026-Implementation-Guide)\nthat describes some of the required work and security considerations involved in\nusing Boulder in a production environment. As-is the docker based Boulder\ndevelopment environment is **not suitable for\nproduction usage**. It uses private key material that is publicly available,\nexposes debug ports and is brittle to component failure.\n\nWhile we are supportive of other organization's deploying Boulder in\na production setting we prioritize support and development work that favors\nLet's Encrypt's mission. This means we may not be able to provide timely support\nor accept pull-requests that deviate significantly from our first line goals. If\nyou've thoroughly evaluated the alternatives and Boulder is definitely the best\nfit we're happy to answer questions to the best of our ability.\n\n## Contributing\n\nPlease take a look at\n[CONTRIBUTING.md](https://github.com/letsencrypt/boulder/blob/main/docs/CONTRIBUTING.md)\nfor our guidelines on submitting patches, code review process, code of conduct,\nand various other tips related to working on the codebase.\n\n## Code of Conduct\n\nThe code of conduct for everyone participating in this community in any capacity\nis available for reference\n[on the community forum](https://community.letsencrypt.org/guidelines).\n\n## License\n\nThis project is licensed under the Mozilla Public License 2.0, the full text\nof which can be found in the\n[LICENSE.txt](https://github.com/letsencrypt/boulder/blob/main/LICENSE.txt)\nfile.\n","funding_links":["https://letsencrypt.org/donate/"],"categories":["Go","Go (134)","go","Repositories","Cryptography"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fletsencrypt%2Fboulder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fletsencrypt%2Fboulder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fletsencrypt%2Fboulder/lists"}