# certes: a .NET client for ACME, with a CLI that dropped Azure on the way to v5

> certes implements the ACME protocol from RFC 8555 in C#, covering v2 accounts, orders, wildcard certificates, the three challenge types, external account binding, key rollover and revocation, plus a command line tool. Version 4 is in maintenance mode, and the v5 work is a breaking change to the CLI's runtime and parser.

**fszlin/certes** — A client implementation for the Automated Certificate Management Environment (ACME) protocol

- Repository: https://github.com/fszlin/certes
- Stars: 574 · Forks: 128
- Language: C#
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/fszlin-certes

## An ACME client that stops at the protocol boundary

certes is a .NET client for the Automated Certificate Management Environment protocol, which the README links to RFC 8555. It provides an API for obtaining and managing certificates, plus a certes command line tool. What the library implements is specific: ACME v2 accounts, orders, wildcard certificates, HTTP-01, DNS-01 and TLS-ALPN-01 challenge support, external account binding, account-key rollover, revocation, and PEM and PFX export. Then comes the sentence that defines the boundary of the project, and it is a deliberate one. Applications are responsible for provisioning challenge responses and scheduling renewals. In other words, certes speaks the protocol and the certificate cryptography, and it does not run your web server, point a DNS record, or put a renewal on a calendar. That is the right division for a library, and it also means that adopting it is not one package but a workflow.

## The target matrix, and what the .NET 10 move cost

The project status section is unusually precise about versions, which is helpful when you are deciding whether to adopt it. The library targets net10.0, net8.0 and netstandard2.0. The CLI targets net10.0 only. The unit and integration tests target net10.0 and net462. The library keeps .NET Standard 2.0 compatibility assets so consumers on .NET 8 or 9 select net8.0, while .NET 6 and 7 consumers fall back to netstandard2.0 rather than getting a dedicated net6.0 build. Two changes are called out as breaking. The v4 CLI package requires .NET 10, which the README describes as a runtime requirement change for pre-v4 CLI users, and Azure deployment commands were removed from the CLI entirely, so the az command group with az set, az dns and az app is gone, and the README says to use dedicated Azure tooling for DNS and app deployment workflows. The library on .NET 8 remains supported by Microsoft until November 10, 2026, with .NET 10 as the development and CLI baseline.

## What changed in v5, and why a CLI migration is a breaking change

The upgrade guide covers three things, and the third is the one that will bite an automated pipeline. Development toward v5 introduces optional cancellation tokens on the core async APIs, which the README states is a binary and interface breaking change. If you automate dotnet-certes, the CLI runtime now requires .NET 10, the az command group was removed, and the CLI parser migration is complete, with legacy System.CommandLine command paths removed in favour of the Spectre runtime path. For anyone building or extending Certes from source there is a dependency change, moving from Portable.BouncyCastle to BouncyCastle.Cryptography, and the tests and helper code follow the newer BouncyCastle APIs and stricter DN validation semantics. The v5 development CLI uses Spectre 0.55.0 and supports Ctrl+C cancellation with exit code 130, and the README notes that routine Spectre version updates require deliberate review while security updates stay enabled.

## Installing the library and the CLI, and the staging CA advice

The library goes into an application as a package reference.

```sh
dotnet add package Certes
```

The command line tool is a dotnet tool, installed globally and then invoked.

```sh
dotnet tool install --global dotnet-certes
certes --help
```

The README notes that you should check the package's runtime requirements when installing a published tool version, because the requirement moved to.NET 10 in v4. One piece of operational advice stands out and is easy to miss: use a staging CA while developing an issuance workflow. Because the whole point of the library is to obtain real certificates, and developing against a staging certificate authority is the difference between a debugging session and an outage. The documentation is split into a library getting-started guide, an ACME API guide, a CLI guide, a release guide, a historical changelog and a contributing guide, and the README warns that the usage guides are being refreshed as part of the revival, so their historical examples and implementation-status claims should be checked against the code.

## CI that runs against a local Pebble instead of a live CA

The development setup is worth a close look because it tells you how the project validates itself. The GitHub Actions workflow checks cross-platform compilation, the full offline unit suite, package smoke consumption, and a local Pebble integration, with the tests running directly on .NET 10. The Linux build also reports unit-test coverage in its job summary and produces a downloadable artifact with Cobertura XML and browsable HTML reports. There is a separate CodeQL workflow adding static security analysis for C#, running on pull requests, pushes to main, and weekly. The legacy Azure Functions test helper has been retired and the integration tests use a local Pebble instance, and the README is explicit that unit tests need no certificate authority service or containers while the separate integration suite uses the local Pebble container stack. That distinction is the important one, because a unit test that passes proves nothing about interoperability with a real CA, and the README says so directly: passing unit tests do not establish current CA interoperability.

## A revival with a maintenance baseline and no committed date

The project is being brought back, and the documentation reflects that state honestly. There is a revival baseline in the AGENTS.md file that maintains the dated build and test results along with the known blockers, and AGENTS.md itself is the recommended starting point for both human contributors and LLM coding agents, containing the project map, development rules, verification commands and known blockers. The branching and release strategy is documented there too, and you are pointed at it before preparing a contribution. The build and test commands run from the repository root.

```sh
dotnet build src/Certes/Certes.csproj
dotnet test test/Certes.Tests/Certes.Tests.csproj -f net10.0 -p:SkipSigning=true
```

The roadmap has three lines. The v4.x maintenance track covers security fixes and reported regressions, and no planned feature work remains for v4. The v5 track covers cancellation support and the coordinated Spectre CLI migration. Unscheduled work includes native AOT support, which is pending investigation. The 5.0.0 milestone tracks the next major release, and the README states that no release date is committed. The last push was on 2026-10-19 and the licence is MIT.

## Conclusion

certes fits a .NET team that needs to issue and renew certificates programmatically and wants to keep that in process rather than shelling out to a separate binary, and that is comfortable owning the challenge provisioning and the renewal scheduling itself. It does not fit a team that wants a hosted service, and it does not fit a team on .NET 6 or 7 that needs the CLI, since the v4 CLI package requires .NET 10. Verify first that you can meet the runtime requirements, read the v5 migration guide if you automate the command line tool, and remember that the library deliberately stops at the ACME API: proving control of a domain and timing the renewal stay your responsibility.

## FAQ

### What does the certes .NET library implement?

It implements the ACME protocol from RFC 8555: v2 accounts and orders, wildcard certificates, HTTP-01, DNS-01 and TLS-ALPN-01 challenges, external account binding, account-key rollover, revocation, and PEM and PFX export. Provisioning the challenge responses and scheduling renewals are left to the application.

### How do I install the certes library and CLI?

Add the library with dotnet add package Certes, and install the command line tool with dotnet tool install --global dotnet-certes, then run certes --help. The v4 CLI package requires .NET 10, so check the runtime requirements of the published tool version before installing.

### What breaks when moving from v4 to v5?

The core async APIs gain optional cancellation tokens, which is a binary and interface breaking change. The CLI now requires .NET 10, the az command group for Azure DNS and app deployment was removed, and the legacy System.CommandLine paths were replaced by the Spectre runtime path. The library dependency also moved from Portable.BouncyCastle to BouncyCastle.Cryptography.

### How does the project test certificate issuance?

The GitHub Actions workflow checks cross-platform compilation, the offline unit suite, package smoke consumption and a local Pebble integration, with CodeQL adding static analysis for C#. Unit tests need no certificate authority service or containers, and the README is explicit that passing unit tests do not establish current CA interoperability.

## Sources

- [fszlin/certes on GitHub](https://github.com/fszlin/certes)
- [Issues](https://github.com/fszlin/certes/issues)
- [License: MIT](https://github.com/fszlin/certes/blob/main/LICENSE)
- [README](https://github.com/fszlin/certes/blob/main/README.md)
- [Releases](https://github.com/fszlin/certes/releases)

---

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