BSDCan Gifts

This was my last year as BSDCan chair. The committee worked hard make the con happen. That’s not to my credit, though I am slightly proud of myself in selecting as potential members “people likely to complete tasks” and persuading them to volunteer. I am notably proud of arranging matters so that Kristof Provost felt compelled to scream my name in rage during the closing auction. I’d link to the video, but the sound of everyone else laughing drowns him out. KP is no Bob Beck.

But this post isn’t about that.

Two people gave me gifts. Gifts that I had no idea existed.

From Patrick McEvoy, assistant con chair, video lead, and next year’s con chair: a Laserblast alien figurine. If you’ve read the book, this closely resembles Bert.

Tiny? Yes. Silly? Absolutely? Surprisingly motivational? Yep! I’ve added Bert to my Inspirational Triptych, to remind myself that anything goes. (For the youthful, the others are Rosebud the basselope, Bullwinkle’s Fearless Leader, and the Big Man himself, Cthulhu.) I have no idea where my ideas come from, but these are my literary moral compass. I guess it’s a quadtych now?

The second gift was presented a little more publicly, at the very end of the closing session (video). Warner Losh commissioned my portrait from Frank Pryor. Warner didn’t merely hand him a photo of me to work from. Pryor went through my publicly available media and assembled a complete inventory of my public persona.

Beaver Tails? What do Beaver Tails have to do with anything? There’s a photo from a BSDCan maybe ten, eleven years ago where about twenty of us converged on the Ottawa Beaver Tail hut for deep-fried sweet bread covered in Nutella or peanut butter and chocolate or cinnamon sugar or any other decadence you can imagine. (It’s basically an Instant Diabetes Kit, and it’s fantastic.)

Warner liked the look so much, he even made me a one-of-a-kind T-shirt.

In keeping with BSDCan tradition of course, immediately after this unique T-shirt was presented to me, they proceeded to auction off three more just like it.

I am left with one question, though. You see, right when I was starting to write $ git commit murder Warner joked that he wished someone would write fanfiction about him. That gave me a name, although I changed it slightly to maintain plausible deniability for when in case the real Warner gets killed at a Unix con. (If you’ve ever met Warner, you’d understand this is a legitimate risk.) I am wondering how he knew about the tombstone, though? I mean, mine has an ending date on it, but still, it’s a stunningly good guess.

May’s Mandriarchal Sausage

This post went to Patronizers at the beginning of April, and to the public at the beginning of May. Yes, I know, everyone already patronizes me, but if you want me to pay attention sign up here.

As expected, the economy is in an unforced crash. Yippee! Buckle in folks, it’s gonna be a wild ride. I wish to thank all of y’all for backing me. Those folks who signed up to See the Sausage Being Made for $12 a year add up. The whole Patronizer thing often makes me feel like the founder of the world’s most useless cult, but you do keep the bank from taking the house and I am grateful.

I spent some time this month going through my bills. We’ve had the same cable company for almost twenty years and two different houses. (No TV, just a bit pipe.) Every few years, I’d get a letter that they were upgrading my plan. Fine. I gave them a call and told them to cut my bill or lose me. They cut the bill and upgraded my service again. I really need to put “negotiate with cable company” on my calendar for every two years.

Next up: the cell phone. We had Sprint because it worked here, which means we became T-Mobile, which means our bill had gone up. Probably switching to Consumer Cellular. It’s time to stretch those dollars!

Happier news: all active Tilted Windmill Press titles are in Bookvault, which means I will be able to sell them from my bookstore. Yay! I have a box of 21 proofs coming. If they are okay I’ll get them in the store.

I’m already offering the FreeBSD Storage Bundle in print at $24 off. I’m afraid to look at what I’ll have to charge for The Full Michael in print, but it’ll happen.

Okay, fine. Let me build a spreadsheet and add it up.

34 print books, $785. If I give a 20% discount that makes it $628. Call it $629.99. Nobody’s that insane, but if I don’t offer it one of you is gonna ask me why not. Plus, being able to offer it all feels correct. Like the bookstore is truly complete. You want it, I can send it!

Why do a 20% discount? When you buy direct from me, I don’t have to pay a bookstore or a distributor. 20% splits the difference with the reader, which seems fair. I do have paperwork and financial overhead on direct sales, though, so I’m compromising by offering the split on larger orders. Larger orders also save on shipping. Eventually I want to say “buy 4 or more get 20% off” but I implement only one headache at a time.

Sadly no, I can’t include No Starch titles. They are not print-on-demand. I would have to touch them and compute shipping. Not happening.

The question I’m still struggling with is the default format. I have to choose either “print/epub bundle” or “just epub.” Yes, people can change it with the “Format” drop-down. But defaults do impact people. Is it more ethical to set it to the less expensive option? How many people won’t see the “Format” option?

Clearly I need to pivot to “just give me all your money and I’ll decide what you get,” sigh.

I discovered a complication on direct print sales to Europe, though. The printer does not include commercial invoices. Bookvault does not know how much I charged you, or if I charged VAT. You can download an invoice with your order. I had one European customer who had trouble with this, but other Europeans say that’s fairly standard. I need to go through the print store and add that warning to every print version.

The good news is, I have the hard part of the networking book done. Sort of. I sent the TLS chapter to Bob Beck for review, and it went horribly wrong. The good news is, I get to do some new sysadmin stuff and set up QUIC on my web site. Then I get to do some netflow analysis and see how much of the traffic is QUIC versus everything else. Good fun times, for a strange value of good and stranger value of fun.

The good news is, the second half of the rest of N4SA2e requires very little in the way of updates. Some of the warnings need to be louder, but traceroute hasn’t changed, nor netcat.

Laserblasted is due back from copyedit on 15 May, and I’m wondering: if I can crank hard for two weeks, can I finish this draft and get it to tech review by then? I don’t know, but it’s a worthy goal. If nothing else, I’ll have two weeks of cramming on it.

Speaking of Laserblasted: as an experiment, it’ll be exclusive to my store for a few weeks before I release it on other bookstores. It’s a weird book so it’s not a real test of windowing, but I’ve heard from a few folks who missed the Kickstarter and maybe I’ll scoop them up that way.

Laserblasted also taught me a lesson. I had so much fun ranting about the film that I forgot to describe what the book is. Or: I spent so much time saying what it isn’t that I forgot to say what it is.

Meaning that I broke my own rule, and didn’t write the jacket copy before writing the book.

I still am struggling with the jacket copy. I might just steal my pal ZZ Claybourne’s description:

“What would happen if Gomer Pyle got turned into a scathing indictment of the military patriarchal industrial complex but with way more aliens and laser-inflicted explosions than the sitcom managed to achieve? Starring Brad Pitt as Gomer, directed by Sam Raimi.”

I’m scathing? When did this happen?

Er, uh–yeah. I meant to write that. What that says. I planned that. Yep.

Now to get back cover text that means that.

Maybe I’ll just put that on the back.

I really do need to get a Prohibition Orcs Christmas story written for my Christmas collection. Ideally I’ll launch the Twisted Presents Kickstarter on 25 July and be ready to fulfill immediately upon payment, so I can do the N4SA2e Kickstarter right after. Wait–does that work? Let’s sketch this out.

Let’s be pessimistic and say I finish end of May. I want a month for tech review, which means end of June.

I’ll have Laserblasted proofs ready and hard copies ordered before BSDCan, and order the books for delivery when I get home. Fulfill that by the end of June, no problem.

The copyeditor will have N4SA2e in July. She’s usually about six weeks on a tech book. I haven’t checked with her, of course, and she might blow up my entire schedule.

So if I launch Twisted Presents on 21 July and let it run for two weeks, it ends 4 August. I order books 5 August. Yes, I don’t have the money yet, but I’m assuming Kickstarter coughs up the dough on 18 August, like they do. I can ship them that week. It’s only a handful of copies, it’ll only take a day.

So I get the N4SA2e copyedits about 15 August and spend about a week doing corrections and laying out the print and indexing, all that crap. Launch that Kickstarter early September, let it run for three weeks. (Tech book campaigns should run longer than fiction ones.)

Now to work backwards.

Launching Twisted Presents on 21 July means I must have a print proof in hand by that date. I’ll need everything finalized by 7 July. I need the final manuscript end of June. Most of this book was previously published, but the orc tale needs copyediting and everything needs a final proofreading. I might have to use an alternate editor for that, someone less expensive at speed. That’ll take a couple weeks at best, which brings us up to the end of BSDCan. I’m not working on books during BSDCan. The book must go to copyedit by 9 June.

I need a few first readers to read the orc story. That takes two weeks.

I must have a completed orc story by 26 May. Achievable.

Except I’m cramming to finish N4SA2e by then.

Have I ever mentioned that I’m terrible at scheduling?

All of this is built on the very slender reed of finishing N4SA2e by the end of May. Which means I get QUIC on my web server.

I think I better go get to work.

Buy Your Paperbacks Directly From Me

All Tilted Windmill Press titles are now available directly from me in paperback and ebook at https://tiltedwindmillpress.com. All paperback purchases include the ebook. You’ll get the ebook immediately1, and the print will arrive in a week or so.

Books will be printed in the US, Canada, UK, and Australia. This reduces both shipping costs and environmental impact. Books aren’t exactly green, but local printing makes them less brown. (Are ebooks greener? That’s a great argument over a drink.)

I am excited beyond words. I have been working towards this ever since my first book came out in 1992.

Benefits to you? Those bundles I offer, like the FreeBSD Storage Mastery bundle? There’s now a discount print version. That ridiculous The Full Michael bundle that includes everything I’ve indie published? You can now buy the whole thing in paperback.

Do I expect anyone to drop $624 on a stack of books? No. But I am delighted to have that degree of control.

Books from No Starch Press (Absolute FreeBSD, Absolute OpenBSD, and Network Flow Analysis) are not included. Sorry. I don’t have the access to ship those touch-free on demand. The ILUVMICHAEL coupon code still gets you 30% off at their site and gives me a couple bucks extra, though!

Completing this was a huge amount of work, but the publishing industry is doing its best to eat writers alive. The only way to survive is disintermediation.

I haven’t made hardcovers available yet. Hardcover sales are minuscule next to paperbacks. Some books present challenges, and I’m not sure selling them direct is worth it. I’m doing the easy hardcovers first in the hope that inspiration strikes.

Future books will be released in on my site a month before they’re available at retailers. If they’re trying to eat my career, I see no reason to prioritize them.

“Networking for System Administrators” sponsorships closing and schedule.

Yesterday I finished a raw draft of the new Networking for System Administrators. It’s not ready for technical review yet; the engine has all the pieces, but there are loose bolts everywhere and a couple of the belts are repurposed nylons. I’ll get it out for tech review this weekend.

On 1 June 2025, I close sponsorships. If you want to sponsor it, this week is your last chance. I promised to do a challenge coin for print sponsors and Patronizers so I will, but the next one probably won’t. I’ll happily absorb $10 per sponsor to do something daft, but not the $25 the US’ Wheel of Tariffs threatens. (Regardless of your politics, unpredictability is death to business.)

The tentative schedule for N4SA2e is:

  • June: Technical Review
  • July-August: Copyedit
  • September: Kickstarter
  • October: ship sponsor and Patronizer copies, both print and ebook exclusive to tiltedwindmillpress.com
  • November: standard retail release

The print version will come in a special backer-exclusive edition available only to print sponsors, Patronizers, and Kickstarter backers. (Kickstarter backers can’t get the challenge coin; that’s exclusive to early backers.) I can’t say it’ll be as daft as Ruin Your Mail By Running It Yourself or the Networknomicon, but it will exist.

Then again, I always think my special editions are lame. You can make your own opinion.

“Networking for System Administrators” restructuring

No, not the book this time. The product. Previously you picked a format, print or ebook. If you sponsored for print, Woocommerce used your address to calculate shipping. Cool. It took me a couple iterations to get that working, but it’s the way the rest of the world works.

Then I added print books via BookVault.

Turns out that Woocommerce does not like multiple shipping systems. It says it’s fine. It is not. After months of fighting with this, I realized that my attachment to sponsor shipping autocalculation was causing pain. I have restructured the product so that you choose a destination and pay accordingly.

The total price has not changed. The list price is now shipping-inclusive to avoid Woo’s clunky shipping system, that’s all. While sponsorship is an especially terrible deal for my Australian backers, it is no more terrible than before.

I’m still pushing to get the first draft of this book finished by the end of the month.

Also: attachment is the source of all pain. Well, that and blunt instruments. Those hurt, too.

Laserblasted Update

My copyeditor got the manuscript back to me last weekend. I’ll be getting it into production this week and next, amidst finishing the new Networking for Systems Administrators. Once the book can be purchased both print and ebook will be exclusive to my store for a month or so, then I’ll release it to the wider public.

I was hanging out with ZZ Claybourne and a couple friends, so we picked the movie we’re going to watch and review for the Kickstarter stretch goal. It is… drum roll, please…

Evil Brain from Outer Space.

I see no way this will end well.

Migrating from Apache 2.4 to Caddy

I’ve been using Apache since the 1990s. The networking book requires information about QUIC, so I need experience with QUIC, so I need HTTP/3, so I can’t use Apache.

I experimented with Caddy on my test host. It worked well as a reverse proxy, so I began putting it in place in production this weekend. (If you deploy Caddy, definitely have it run as a user other than root!)

As I went through the docs to prepare, though, I realized that not only would it would be less complex and more robust to drop Apache and use Caddy, it would also be easier.

My Apache configuration files are large and complex because Apache can do anything. I don’t need a web server that can do anything. I need a web server that serves static files, talks to php-fpm, and supports TLS. The Caddy docs are complete, but I didn’t find a simple guide for what I wanted to do, so I’m posting this. I suspect that guide exists but is buried beneath pages of search engine poison.

This uses Caddy 2.9.1 on FreeBSD 14. My config files are in /usr/local/etc/caddy, symlinked to /etc/caddy.

The main config file, /etc/caddy/Caddyfile contains only:

import sites/*conf

The /etc/caddy/sites directory contains each of my sites in its own file. Mostly.

Here’s one of my old sites in blackhelicopters.org.conf:

blackhelicopters.org www.blackhelicopters.org {
        root * /var/www/bh
        file_server

        log {
                output file /var/log/bh/bh-caddy.log
                format json
        }
}

The first entry on the first line is the server’s main name, blackhelicopters.org. (I could probably let that domain go, but my oldest friends have that email in their address books and it’s worth a couple bucks a year to not inconvenience them.) The following hostnames are what Apache would call ServerAlias entries: other names this host responds to. Every name here goes into the X.509 certificate.

The root statement tells Caddy where to find the files for this site. Every URL goes under here. If I had Apache Directory statements, I could put them here.

The file_server statement means “hand out files.”

Last, there’s a logging statement. Caddy logs are written in JSON, making them harder to eyeball but easier to mechanically parse. Pipe the logs through jq(1) to read the parts you want.

Several of my domains exist only as legacy redirects. While https://michaelwlucas.com and https://michaelwarrenlucas.com made sense in a keyboard-centric era, they’re a pain to type on a phone.

blather.michaelwlucas.com www.michaelwarrenlucas.com michaelwarrenlucas.com www.michaelwlucas.com michaelwlucas.com mwlucas.org www.mwlucas.org {
        redir https://mwl.io
        }

This config doesn’t even serve files. It’s like setting DocumentRoot to /var/empty. Any traffic to these hostnames should be redirected to my current web site.

So what about that all-important main web site?

mwl.io  www.mwl.io {
        tls mwl@mwl.io

        log {
                output file /var/log/mwl/io-caddy.log
                format json
        }

        root * /var/www/io
        file_server
        php_fastcgi localhost:9000

        @disallowed {
                path /xmlrpc.php
                path *.sql
                path /wp-content/uploads/*.php
                path *~
        }

        rewrite @disallowed 'index.php'

        redir "/ks" https://www.kickstarter.com/projects/mwlucas/mwls-next-1-april-book"
...
}

the tls statement puts my email address in the Let’s Encrypt certificate request. I should probably go back and add that to the sites I did earlier.

The php_fastcgi option tells Caddy where to find the php-fpm engine.

The @disallowed statement defines a list named “disallowed.” The following rewrite statement transforms requests to files with those names, redirecting them to the index.

Finally, I have several redirect statements for my convenience.

Test a configuration by going to /etc/caddy and running caddy validate, much like apachectl configtest. The configuration files are JSON, so the parser isn’t quite as straightforward as you might expect.

# caddy validate
2025/05/05 15:02:38.489 INFO using adjacent Caddyfile
2025/05/05 15:02:38.489 INFO using config from file {"file": "Caddyfile"}
Error: adapting config using caddyfile: /usr/local/etc/caddy/sites/test-twp.conf:1: unrecognized directive: test.tiltedwindmillpress.com
Did you mean to define a second site? If so, you must use curly braces around each site to separate their configurations.

Here’s the problem: the error is not where it says the error is. The error is before the cited point. The sensible thing to do is to test after creating each site’s configuration file. If you get bored and do all your sites while watching reruns of Adam and Jamie welding JATO units to a hamster ball so they can replicate that urban legend about the Syria-Guam War, you’ll have to do a binary search of your files to see where the problem is. Test each one as you finish it.

Once you have a parseable configuration, shut off Apache and start Caddy. Watch /var/log/caddy/caddy.log for errors. Test all of your sites.

Am I happy with Caddy? Yes, so far. Am I keeping my known-working Apache configuration around? Also yes, so far. If I suffer an attack of the AI scrapers, I might need to fall back to a Caddy reverse proxy so that I can implement Anubis. Yes, there’s an Anubis Caddy module but it’s a proof-of-concept.

What kind of impact has Caddy had on my site? It seems faster, but that might be QUIC aka HTTP/3 rather than any difference between Caddy and Apache. Of course, QUIC is a difference between the two. How much of my traffic is QUIC now? QUIC runs on UDP port 443. First, let’s check how much traffic went to and from port 443 yesterday, on all protocols.

# nfdump -R . -B ip 23.139.82.3 and port 443
...
Summary: total flows: 58605, total bytes: 6.9 G, total packets: 7.0 M, avg bps: 1.0 M, avg pps: 127, avg bpp: 990
Time window: 2025-05-04 00:00:00 - 2025-05-04 23:59:59

6.9 GB. How much of that is UDP?

# nfdump -R . -B ip 23.139.82.3 and port 443 and proto udp | tail -4
Summary: total flows: 1620, total bytes: 428.4 M, total packets: 412444, avg bps: 62756, avg pps: 7, avg bpp: 1038
Time window: 2025-05-04 00:00:00 - 2025-05-04 23:59:59
Total flows processed: 750342, passed: 1620, Blocks skipped: 0, Bytes read: 66537172
Sys: 0.0209s User: 0.0209s Wall: 0.0399s flows/second: 18806544.9 Runtime: 0.0423s

428.4 Mb of my traffic is QUIC? Firefox and Chrome derivatives both use QUIC if available. The only clients that should be using TCP are stupid bots and crawlers–

Oh. Maybe I do need to implement Anubis. Dammit.

BSDCan Travel Fund Auction in honor of Mike Karels

Mike Karels has been around the BSD community since the last century, and was integral to our projects. How integral? If your name is on the definitive book on the topic, you’re integral.

On his way home from BSDCan 2024, Mike passed away.

I could go on and on about what a humble guy he was, and how he helped many folks. Or I can tell you that he backed Run Your Own Mail Server. He had no need for my book, but thought it was worthwhile? I was stunned. And appreciative.

With his family’s permission, I am auctioning off his reward in his honor. And something extra.

Here’s a copy of the backers-only edition of RYOMS, Ruin Your Mail By Running It Yourself, with a sponsors-only challenge coin. After fulfilling sponsor gifts, I have a scant handful of coins left. I don’t sell them, despite repeated requests, the occasional threat, and one ham-fisted blackmail attempt. The only way to get one today is by winning this auction.

Bid on the set by leaving a comment on this page.

The auction runs from now until 5PM EDT 12 May. If the bidding goes nuts in the last few minutes, I’ll leave it open until it settles down. There’s no sniping this auction at the last moment, as I want bids to escalate beyond all sensible limits.

Mike was a cool dude. Honor him by giving the next generation a chance to join us.

April’s Abjurational Sausage

This post went to Patronizers at the beginning of April, and to the public at the beginning of May. Not a Patronizer? You could be. It’s a terrible deal, but you could be.

I’ve considered myself well-prepared for personal financial disaster, but we’re not headed into personal financial disaster. We’re headed into a global one. I would say that I’m conservative–I save money, look after my family, mind my own business–but the reactionaries have stolen that term from me. Plus, I’m not conservative enough to cope with this economy. Nobody could be.

Last year was an all-time writing income peak, thanks to the Run Your Own Mail Server Kickstarter.

This year? Well, the Laserblasted Kickstarter is concerning. Yes, this is something of a gag book–but it’s a real novel. Folks who would normally take a $200 leather-cased book are backing for $6 ebooks. Several folks wrote me to say that they wanted to support the book, but simply couldn’t right now. I’ve also lost Patronizers.

I don’t blame them. But the upshot is, I’m expecting this year to be ugly.

Plus, this month I’m writing checks for taxes and retirement fund. Because of RYOMS, those checks are large. While I understand the logic of “feed the IRA while the stock market is low,” it definitely feels like I should just set the money on fire instead. The IRS would let me record that as a business loss.

From the latest happenings, I think it’s clear that I need to start increasing my overseas business. I need my books to become more accessible to European and Asian markets. That means dealing with VAT. Even with the RYOMS Kickstarter, I didn’t quite make enough in Europe to qualify for IOSS. I suspect that if I can include VAT in my book prices more Europeans will buy them. If I get an IOSS number I can have my books printed inside the EU, which would make them still more accessible. To get there, I need to sell more.

Chicken, meet egg.

I need to ask folks who run businesses in the EU for their thoughts. Fortunately, there’ll be a bunch at BSDCan.

Anyway. Money sucks.

The good news is, my readers seem to like ordering print books through my store! Each week there’s a handful of print sales from my bookstore. While I still have no idea what my best-selling titles are, I used a couple months of Amazon print sales as a proxy and have started working my way down that list. I’ve set up PAM Mastery, the two versions of TLS Mastery, and FreeBSD Mastery: Jails with the new printer and ordered the proofs. If they come out okay, I’ll have them on the store as print/ebook bundles straight away.

When converting books to the new printer, my titles are either simple or disastrous. I plan to focus on the simple ones first, but ideally I want to offer “The Full Michael” in print. I don’t know that anyone will actually buy that stack, but being able to offer that makes me as independent as possible.

The other good news about direct print sales? Bookvault recently added printers in Australia and Canada. Cracking Canada has long been a goal. Yes, I can ship from the States, but for two countries right next to each other, shipping to Canada sure is expensive and annoying. Printing and shipping from Canada also lets me skip the annoyance of customs.

The funny thing about this exercise is: chapbooks. When Amazon shifted their prices, I stopped putting short stories in print. I might bring short stories into print again, but make them exclusive to my store. If I was smart, I’d put them in a series like William Meikle did. Number them. Make them seem collectible. Brand them like a unit. See if I can trigger that completist urge in collectors.

Oh, wait. My hardcore collectors are mostly Patronizers. I’d just have to ship them copies. Huh. Well, I might do it anyway just for the laughs.

On the writing front: Project IDGAF, aka Laserblasted, survived first readers. People like the stupid thing. Many Patronizers will get a copy as part of their benefits, but if you’re not one of them you might take a look at the first chapter as see if it interests you. First reader reaction was universally positive, which was quite a shock. I wanted to write something that I had no stakes in, that people were not expecting or demanding, so I’d be free to stretch myself and be a little daft. (More daft. Whatever.) It seems to have worked, which is nice.

Which leaves me grinding on the new Networking for Systems Administrators. Writing a cross-platform book is weird. We pretend that TCP/IP is a universal standard, but everybody made different decisions regarding that standard. Sigh. Still, it’s starting to coalesce into something resembling a book.

Hopefully I’ll get N4SA2e to Kickstarter this summer, along with the Twisted Presents Christmas story collection. Most of the stories exist for that one. I still need to write an exclusive Prohibition Orcs tale for it, but I’m hoping that doesn’t go horribly wrong. Last thing I need to do is accidentally write a Christmas novel about a cranky little old lady orc (no matter how much JG would like that).

Anyway, I better get back to these edits. Thank you for your support. I appreciate every one of you, especially in these troubled times.

Notes on caddy as QUIC reverse proxy with mac_portacl

As I wrote yesterday, I need QUIC for my web sites. The servers I have data on run FreeBSD, because ZFS. I use Apache everywhere, because it’s what I learned back in the 486 Age. My web site is critical to my business, so I must minimize downtime. I chose to implement a Caddy reverse proxy, because it looked easier than Envoy or migrating to nginx. (Nothing against either tool, of course.)

These are my notes, not a tutorial. If they help you, that’s grand. I pillaged Thomas Hurt’s post for this.

QUIC for HTTPS runs on UDP port 443. I suggest you start by opening UDP port 443 on your packet filter. Or you can follow my example, not open it, and spend half an hour staring at the screen shrieking why doesn’t this work? Up to you.

Caddy defaults to running as root, so it can bind to privileged ports. I played “run servers as root” in 1995 and have no desire to get rooted again, so I need to allow an unprivileged user to bind to privileged ports. That’s where FreeBSD’s mac_portacl comes in. It allows unprivileged users to bind to privileged ports according to a policy you set.

I’ve written about mac_portacl before, but my hosting architecture has changed. Instead of VMs scattered around the world, I now rent a single dedicated machine and use VNET jails. It saved me some money and gave me flexibility.

But mac_portacl is not jail-aware. You set rules per UID, but those rules apply across all jails. Individual jails can declare if they use mac_portacl or if they use the traditional scheme. You need to use consistent UIDs across all your jails, meaning that the user www must run whatever’s on port 80 and 443. All services need to run as different unprivileged users, so I’ll need to create a separate user for Apache.

Start on the host.

# pkg install portacl-rc

This gives /etc/rc.conf integration into mac_portacl. So go into /etc/rc.conf.

portacl_users="www"
portacl_user_www_tcp="http https"
portacl_user_www_udp="https"
portacl_enable=yes

Reboot the system and verify that portacl is working.

# sysctl security.mac.portacl
security.mac.portacl.rules: uid:80:tcp:443,uid:80:tcp:80,uid:80:udp:443,uid:80:udp:80
security.mac.portacl.port_high: 1023
security.mac.portacl.autoport_exempt: 1
security.mac.portacl.suser_exempt: 1
security.mac.portacl.enabled: 1

Looks good. Now go to the jail.

Control traditional privileged ports with the net.inet.ip.portrange.reservedhigh sysctl. By setting it to 0, you disable privileged ports.

# sysctl net.inet.ip.portrange.reservedhigh=0
net.inet.ip.portrange.reservedhigh: 1023 -> 0

Make the change permanent in sysctl.conf
net.inet.ip.portrange.reservedhigh=0

mac_portacl now controls access to ports 1 through 1023.

I need a separate user for Apache. Yes, I could run both as www but I survived the “run everything as nobody” era and learned my lesson.

# pw groupadd -n apache -g 81
# pw useradd -n apache -u 81 -g 81 -d /nonexistent -w no -s /usr/sbin/nologin

In theory, I can switch apache to run as this user and it’ll be fine. Reality will have a short sharp shock for me, I’m sure.

Now go to httpd.conf. Bind it to 127.0.0.1 port 8080

Listen 127.0.0.1:8080
User apache
Group apache

I also commented out mod_ssl. Apache will provide everything unencrypted, but only on localhost.

Go into the virtual host config. All those VirtualHost *:443 entries? They need changing to VirtualHost 127.0.0.1:8080

I also comment out all of the TLS entries. We’ll have Caddy manage TLS for us.

Restart Apache. Watch the error logs. It’ll gripe about a few files being owned by www. Change their owner.

Now configure caddy in /usr/local/etc/Caddyfile.

Permit me to put on my old sysadmin hat and shriek: “Don’t start config files with capital letters, people! You know better! WHYYY.” Yes, I know the world has moved on. Come closer so I can smack you with my cane.

Caddy does nothing except get X.509 certificates and forward connections to Apache.

test.mwl.io {
  reverse_proxy localhost:8080

  # Enable logging:
  log {
    output file /var/log/caddy/access.log
    format json
  }
}

That’s it.

Start Caddy. Point the browser at the HTTP site and it gets redirected to the HTTPS site. All this work, and I have replicated what I started with!

So let’s turn on QUIC and HTTP/3.

Sites must inform clients that QUIC is available through an HTTP header. The client makes an initial connection of HTTP/2, sees the header, and switches to HTTP/3 and QUIC. Add the header in the virtual host configuration.

Header set alt-svc "h3=\":443\"; ma=3600, h3-29=\":443\"; ma=3600

Reload Apache. Set up your packet sniffer to watch UDP port 443. Point your browser at the web page.

So far, I like Caddy. It seems simpler than Apache. It is owned and backed by a commercial firm (ZeroSSL). I am careful going all-in on commercially-backed tools because the Internet’s business model is betrayal. I have other options if that happens.

I’ll deploy this on my main site to get some QUIC experience for the new Networking for System Administrators. QUIC isn’t essential today, but I want to future-proof it. I would be remiss if I didn’t mention that the book is open for sponsorships, for a little while longer at least.

Future path: do I need Apache? For some stuff, probably. But can I serve simple sites straight out of Caddy? Yes.