Dead Software Walking: The ongoing evolution of relayd(8) and httpd(8) · rsadowski.de
↓<br>Skip to main content
rsadowski.de
Table of Contents
Table of Contents
Start with WHY
As I mentioned in my OpenBSD 7.8<br>highlights post,<br>development of relayd(8) and httpd(8) had stalled. Many diffs appeared on<br>the tech@ mailing list from different contributors, but few were committed<br>into the repository. The main reason was simple: Established OpenBSD developers<br>weren’t interested in these daemons anymore. Call it momentum, or timing.
Around the same time, kirill@ and I started working<br>on these daemons more actively. We both use them regularly and have real-world<br>use cases. I support customers with OpenBSD setups that often involve complex<br>httpd(8) and relayd(8) configurations. This practical need motivated me on<br>many levels.
But the biggest motivation is and was LLMs.
For many years, I wrote modern C++ code professionally. Eventually, I moved away<br>from development work and focused on solution architecture, platform<br>engineering, and building teams. I wrote little actual code, mostly declarative<br>YAML. The only coding I did was reading and porting code for OpenBSD ports(7).
Then LLMs arrived. As tech bros<br>claimed “coding is solved”. I realized something: I wanted to challenge myself<br>to code again. I think that at a time when this knowledge is being outsourced,<br>it’s more important than ever to have it! C has always been the language<br>that intimidated me most. C++ and Rust handle the hard thinking for you. C<br>doesn’t. That’s exactly what I wanted: that kind of challenge.
So I decided to start contributing to relayd(8) and httpd(8)().
It is better to conquer self than to win a thousand battles.<br>– Buddha
Discipline beats motivation
I wrote this section with this title intentionally. We’re talking about open<br>source. Even though I made the decision to contribute, it could have ended in<br>frustration weeks later. “Why am I doing this to myself?“But I think I’m past<br>that point now. The pain actually feels good.
At first, I read through the codebase passively and was discouraged by many<br>parts. Maybe it’s just how C code is written. Maybe it’s the lack of comments.<br>Maybe it’s poor design in places. Real spaghetti code. Or maybe it’s just me.<br>Time will tell.
I talked to the some OpenBSD daemon maintainers and decided to start modernizing<br>the handcrafted imsg message system. I’m focusing on relayd(8) first. httpd(8) will<br>follow. Working on this is a great way to understand the codebase.
My next step was to go through the tech@ mailing list archives from 2024 to<br>2026. I collected all open diffs and issues. I think I’ve addressed most of<br>them. If anyone has something pending, please reach out.
relayd and httpd(8) were originally developed by Reyk Floeter (reyk@). He is now<br>retired from OpenBSD. I wish him all the best. Reyk also maintained a GitHub<br>mirror: https://github.com/reyk/relayd. I went through the old issues there too.<br>Everything can be closed, fixed, or is no longer relevant.
That mirror inspired me to create my own. I wanted to make it easier for new and<br>young contributors. I also wanted to reach the community beyond the OpenBSD<br>mailing lists. Also, I work on a git mirror of the CVS tree. (CVS and I will<br>never be friends. I started my career with SVN, which was painful enough. No<br>more version control pain.)
Development happens primarily on the Gothub instance. The other locations are<br>kept in sync:
Primary: https://rsadowski.gothub.org/<br>Mirror: https://codeberg.org/rsadowski/relayd<br>Mirror: https://github.com/sizeofvoid/relayd
The same goes for httpd(8). I wrote a detailed README.md that covers everything you<br>need to know.
Achievements in httpd(8) and relayd(8)
Everything should end on a positive note. Let’s look at what the OpenBSD team<br>has accomplished in httpd(8) and relayd(8):
relayd(8)
Modernization and Code Quality
Converted the imsg system to use new safer getters (imsg_get_data, imsg_get_type, imsgbuf_get)
Added proper error handling throughout imsg payload reading
Standardized logging and comments with bgpd for consistency
Moved HTTP start line logic into dedicated functions for better code organization
Added proper knfmt formatting
Security Improvements
Switched default TLS cipher set from “HIGH:!aNULL” to “secure”
Added ECDSA support to the CA privsep engine
Reject duplicate Content-Length headers with HTTP 400 response
Reject obs-fold headers to prevent parser differentials (RFC 9112 5.2)
Restrict IMSG_CTL_PROCFD to parent process with ID checks
Use explicit_bzero for sensitive password data
Bug Fixes and Stability
Fixed relayd reload race condition that caused crashes
Removed multiple memory leaks (X509_dup, config_purge, tls_cfg)
Fixed NULL checks and bounds tests
Added proper error handling for OpenSSL failures
Drain OpenSSL error queue...