# Quicly implements QUIC in C as a library H2O embeds in its HTTP server

> Quicly is the H2O project's from-scratch QUIC implementation, written in C and meant to be linked into an existing server rather than deployed on its own. It suits people building an HTTP/3 stack who want to own the QUIC code path, and it is not a standalone proxy you can point at traffic.

**h2o/quicly** — A modular QUIC stack designed primarily for H2O

- Repository: https://github.com/h2o/quicly
- Stars: 664 · Forks: 133
- Language: C
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/h2o-quicly

## Quicly is a library for QUIC, not a proxy you deploy

The first thing to understand is what Quicly is not. It is not a standalone QUIC proxy, and there is no daemon to run and no config file to edit. It is an implementation of the IETF QUIC protocol, written from the ground up, and the README says it is designed to be used primarily within the H2O HTTP server. That single sentence sets the expectations. You link it into a server you already own, you provide the TLS credentials, and you get QUIC handling for your own traffic. The alternative model, where a separate component terminates QUIC and forwards to your origin over TCP, is easier to bolt onto an existing deployment, and Quicly is deliberately not that. Its audience is the maintainer of an HTTP server or of a network-facing daemon in C who wants QUIC to be part of the program rather than a dependency of the program. The MIT licence and the C implementation are consistent with that audience, since a library you link has to be readable in a language you already maintain.

## A submodule-driven cmake build against OpenSSL

The build is short, which usually means the dependencies do the work. The repository uses git submodules, so the first step is a recursive submodule update, then cmake configures and make builds.

```bash
% git submodule update --init --recursive
% cmake .
% make
```

Building the software requires OpenSSL 1.0.2 or above. If OpenSSL lives in a non-standard directory, the location is passed through the PKG_CONFIG_PATH environment variable at configure time, which is the conventional way to point a pkg-config based build at a private OpenSSL.

```bash
% PKG_CONFIG_PATH=/path/to/openssl/lib/pkgconfig cmake .
```

That single environment variable is the whole configuration surface described in the documentation, which tells you something about the shape of the project. The top level of the tree carries a CMakeLists.txt, a .gitmodules file, an include directory that is presumably the public header surface, lib/ and src/ for the implementation, a cpanfile describing the Perl dependencies, a deps/ directory, an examples directory, a fuzz/ directory, a corpus/ directory and a t/ directory for tests. The presence of a fuzz directory and a corpus of test data is the kind of detail that distinguishes a protocol implementation meant to survive contact with the internet from a demonstration.

## The test suite runs on Perl, and the dependency step is the part that bites

Testing is not the quick part. The instructions are to install dependencies first, and the way to do that depends on whether you use the system Perl, in which case the tool wants --sudo, or a local Perl, where you are told to omit it. In both cases cpanm is used with --installdeps --notest against the cpanfile in the repository root.

```bash
# If you use system perl, use --sudo
% curl -sL https://cpanmin.us | perl - --sudo --self-upgrade
% cpanm --installdeps --notest --sudo .

# Otherwise, you'd better omit --sudo
% curl -sL https://cpanmin.us | perl - --self-upgrade
% cpanm --installdeps --notest .
```

The tests themselves are then run with make check, which drives the t/ directory through the Perl tooling. The practical implication is that a contributor needs a working Perl toolchain with network access to CPAN before any protocol behaviour can be verified, which is a heavier setup than the C build itself. It also means the test harness is not a separate framework you can run piecemeal, so a change to the QUIC state machine is verified through the same suite every time, which is the arrangement you want in code that handles untrusted input.

## The cli binary is how you see QUIC without writing a server

For learning the stack, the repository provides a command-line program named cli that runs either as a server or as a client, and the documentation explains both modes in a few lines. As a client you give the peer hostname and port as arguments. As a server you give the certificate and private key files, the hostname, and the port to bind to.

```bash
% ./cli host port
```

```bash
% ./cli -c server.crt -k server.key 0.0.0.0 4433
```

For anything else, the documentation points at ./cli --help. The value of this binary is that it is the same implementation the server uses, not a separate test harness, so a connection established against it exercises the real protocol code. The examples directory holds a separate echo.c program, which is a useful contrast: a minimal server written against the public headers, showing what a program that embeds Quicly actually looks like. The interface style also tells you about the library, because the certificate and key are passed as file paths on the command line rather than being discovered through a system store, so TLS configuration is left to the caller.

## Where Quicly is the wrong choice

The first and largest limitation is the one already stated: this is a library, so somebody has to own the server. If your goal is to add HTTP/3 to a deployment you do not control the code of, Quicly is the wrong answer and a reverse proxy that terminates QUIC is the right one. The second limitation is language and platform. The implementation is C, and the build assumes a Unix-style environment with cmake, make, pkg-config and OpenSSL, so a Windows or Windows Server deployment of a QUIC front end is a considerably different project. The third limitation is that the documentation is thin. The README covers the build, the tests and the cli binary, and says nothing about which QUIC versions or draft revisions are implemented, which extensions are supported, or how the library negotiates ALPN with an application that speaks more than one protocol. Anyone evaluating this needs to read the headers in include/ and the source in src/ rather than expect a feature matrix. The fourth limit is that quicly-probes.d and the corpus directory suggest interoperability testing against other implementations, which is exactly the kind of evidence you would want, but the results are not summarised anywhere in the documentation.

## How Quicly differs from a proxy-based QUIC terminator

The two architectures produce different operational outcomes. A proxy terminates QUIC in a separate process, forwards plain HTTP or TCP to the origin, and can be introduced without touching the origin code, which is why it dominates in the common case of putting HTTP/3 in front of an existing application. Quicly inverts that: the protocol handling lives in the same process as the application, so there is no extra hop, no proxy configuration, and no separate deployment to monitor, but every deployment requires a build of the server itself. The proxy also wins on one practical point that is easy to overlook, since it can be a single well-known binary you install and configure, while Quicly is a source dependency whose behaviour is fixed at the moment you link it. The library wins on control, because the same process can make protocol decisions based on the connection it is serving, and on the deployment surface, because there is one less network hop between the client and the application logic.

## Conclusion

Engineers who maintain a server of their own and want QUIC under their control, and who are already working in C, are the people Quicly serves. It is the wrong tool for a team that wants to turn on HTTP/3 by configuration, since Quicly is a library with no configuration file and no daemon, and it is the wrong tool for a project that needs ALPN-driven protocol negotiation across a large application stack, because the stated purpose is to be used primarily within H2O. Check three things before you start: that you can satisfy the build, which needs OpenSSL 1.0.2 or above, cmake and a recursive submodule update, that you can supply the Perl dependencies for the test suite, since the tests are run with make check after cpanm installs them, and that the module boundaries suit your use, since the source tree is split into lib/ and src/ with a public include/ tree. The licence is MIT, the repository publishes no GitHub releases, and the last push was on 2026-10-20.

## FAQ

### How do I build Quicly from source?

Run git submodule update --init --recursive, then cmake . and make. The build requires OpenSSL 1.0.2 or above, and if OpenSSL is in a non-standard directory you pass its pkgconfig path through PKG_CONFIG_PATH when running cmake.

### How do I run the Quicly test suite?

Install the Perl dependencies first with cpanm --installdeps --notest against the repository, using --sudo only if you rely on the system Perl, and then run make check. The cpanm tool itself is installed with the curl command shown in the documentation.

### What is the cli program in Quicly?

It is a command-line program that runs either as a server or a client. As a client you pass the peer hostname and port, and as a server you pass the certificate and private key files along with the hostname and port to bind, with more options listed by ./cli --help.

### Is Quicly a standalone QUIC proxy?

No. It is an implementation of the IETF QUIC protocol written from the ground up, and the documentation says it is designed to be used primarily within the H2O HTTP server, so it is linked into a server you own rather than deployed on its own.

### What licence is Quicly released under?

The MIT License, as stated in the documentation. The repository publishes no GitHub releases, and the last push was on 2026-10-20.

## Sources

- [h2o/quicly on GitHub](https://github.com/h2o/quicly)
- [Issues](https://github.com/h2o/quicly/issues)
- [License: MIT](https://github.com/h2o/quicly/blob/master/LICENSE)
- [README](https://github.com/h2o/quicly/blob/master/README.md)

---

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