Typo fixes and grammar improvements, h/t Claude
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-02-21 16:24:09 +00:00
parent 4d8f3a42e8
commit c645550081
3 changed files with 38 additions and 38 deletions

View File

@@ -29,8 +29,8 @@ audit the certificate logs themselves. The intent is that eventually clients wo
certificates that do not appear in a log, effectively forcing CAs to add all issued certificates to
the logs.
In the first two articles of this series, I explored [[Sunlight]({{< ref 2025-07-26-ctlog-1 >}})]
and [[TesseraCT]({{< ref 2025-08-10-ctlog-2 >}})], two open source implementations of the Static CT
In the first two articles of this series, I explored [[TesseraCT]({{< ref 2025-07-26-ctlog-1 >}})]
and [[Sunlight]({{< ref 2025-08-10-ctlog-2 >}})], two open source implementations of the Static CT
protocol. In this final article, I'll share the details on how I created the environment and
production instances for four logs that IPng will be providing: Rennet and Lipase are two
ingredients to make cheese and will serve as our staging/testing logs. Gouda and Halloumi are two
@@ -74,7 +74,7 @@ ctlog1:~$ for log in lipase; do \
```
The hypervisor will use PCI passthrough for the NVMe drives, and we'll handle ZFS directly on the
VM. The first command creates a ZFS raidz2 pool using 4kB blocks, turns of _atime_ (which avoids one
VM. The first command creates a ZFS raidz2 pool using 4kB blocks, turns off _atime_ (which avoids one
metadata write for each read!), and turns on SSD trimming in ZFS, a very useful feature.
Then I'll create an encrypted volume for the configuration and key material. This way, if the
@@ -87,12 +87,12 @@ _Rennet_ for the testing log and _Gouda_ for the production log.
{{< image width="10em" float="right" src="/assets/ctlog/sunlight-logo.png" alt="Sunlight logo" >}}
I set up Sunlight first. as its authors have extensive operational notes both in terms of the
I set up Sunlight first, as its authors have extensive operational notes both in terms of the
[[config](https://config.sunlight.geomys.org/)] of Geomys' _Tuscolo_ log, as well as on the
[[Sunlight](https://sunlight.dev)] homepage. I really appreciate that Filippo added some
[[Gists](https://gist.github.com/FiloSottile/989338e6ba8e03f2c699590ce83f537b)] and
[[Doc](https://docs.google.com/document/d/1ID8dX5VuvvrgJrM0Re-jt6Wjhx1eZp-trbpSIYtOhRE/edit?tab=t.0#heading=h.y3yghdo4mdij)]
with pretty much all I need to know to run one too. Our Rennet and Gouda logs use very similar
with pretty much all I need to know to run one too. Our Rennet and Gouda logs use a very similar
approach for their configuration, with one notable exception: the VMs do not have a public IP
address, and are tucked away in a private network called IPng Site Local. I'll get back to that
later.
@@ -136,8 +136,8 @@ the automatic certificate renewals, and will handle SSL upstream. A few notes on
1. Most importantly, I will be using a common frontend pool with a wildcard certificate for
`*.ct.ipng.ch`. I wrote about [[DNS-01]({{< ref 2023-03-24-lego-dns01 >}})] before, it's a very
convenient way for IPng to do certificate pool management. I will be sharing certificate for all log
types under this certificate.
convenient way for IPng to do certificate pool management. I will be sharing a certificate for all log
types.
1. ACME/HTTP-01 could be made to work with a bit of effort; plumbing through the `/.well-known/`
URIs on the frontend and pointing them to these instances. But then the cert would have to be copied
from Sunlight back to the frontends.
@@ -165,7 +165,7 @@ us going in a public `tesseract-posix` instance.
One thing I liked about Sunlight is its compact YAML file that described the pertinent bits of the
system, and that I can serve any number of logs with the same process. On the other hand, TesseraCT
can serve only one log per process. Both have pro's and con's, notably if any poisonous submission
can serve only one log per process. Both have pros and cons, notably if any poisonous submission
would be offered, Sunlight might take down all logs, while TesseraCT would only take down the log
receiving the offensive submission. On the other hand, maintaining separate processes is cumbersome,
and all log instances need to be meticulously configured.
@@ -198,7 +198,7 @@ logs:
EOF
```
With this snippet, I have all the information I need. Here's the steps I take to construct the log
With this snippet, I have all the information I need. Here are the steps I take to construct the log
itself:
***1. Generate keys***
@@ -245,7 +245,7 @@ Creating /ssd-vol0/logs/lipase2027h2/data/log.v3.json
{{< image width="60%" src="/assets/ctlog/lipase.png" alt="TesseraCT Lipase Log" >}}
It's nice to see a familiar look-and-feel for these logs appear in those `index.html` (which all
cross-link to each other within the logs specificied in `tesseract-staging.yaml`, which is dope.
cross-link to each other within the logs specified in `tesseract-staging.yaml`, which is dope.
***3. Generate Roots***
@@ -347,7 +347,7 @@ read path. Filippo explained that the HTTP headers matter in the Static CT speci
Issuers, and Checkpoint must all have specific caching and content type headers set. This is what
makes Skylight such a gem - I get to read it (and the spec!) to see what I'm supposed to be serving.
And thus, `gen-nginx` command is born, and listens on port `:8080` for requests:
And thus, the `gen-nginx` command is born, and listens on port `:8080` for requests:
```
ctlog@ctlog1:/ssd-vol0/enc/tesseract$ tesseract-genconf -c tesseract-staging.yaml gen-nginx
@@ -487,14 +487,14 @@ server {
}
```
Taking _Lipase_ shard 2025h2 as an example, The submission path (on `*.log.ct.ipng.ch`) will show
Taking _Lipase_ shard 2025h2 as an example, the submission path (on `*.log.ct.ipng.ch`) will show
the same `index.html` as the monitoring path (on `*.mon.ct.ipng.ch`), to provide some consistency
with Sunlight logs. Otherwise, the `/metrics` endpoint is forwarded to the `otelcol` running on port
`:9464`, and the rest (the `/ct/v1/` and so on) are sent to the first port `:16900` of the
TesseraCT.
Then the read-path makes a special-case of the `/checkpoint` endpoint, which it does not cache. That
request (as all others) are forwarded to port `:8080` which is where NGINX is running. Other
request (as all others) is forwarded to port `:8080` which is where NGINX is running. Other
requests (notably `/tile` and `/issuer`) are cacheable, so I'll cache these on the upstream NGINX
servers, both for resilience as well as for performance. Having four of these NGINX upstream will
allow the Static CT logs (regardless of being Sunlight or TesseraCT) to serve very high read-rates.