Matthew Weier O'PhinneyCaddy as a Secure Reverse Proxy (6.12.2021, 22:03 UTC)

I've been using Caddy as a front-end reverse proxy for several years now, on the advice of Marco Pivetta. Somewhere along the line version 2 was released, and I updated at some point, but evidently didn't quite understand some of its configuration options, particularly around HSTS support and providing your proxied application information about how the client tried to connect.

Caddy has always had a fairly declarative syntax, and tended towards sane defaults. The syntax is like a hybrid of YAML and HCL, for better or worse, and includes placeholders for substituting in request or block-specific values. Fortunately, you don't have to write much to get the most common scenarios to work correctly. And v2 now provides a JSON syntax as well. The JSON syntax gives full access to all configuration options, and is particularly useful to learn if you want to be able to update the configuration on the fly via Caddy 2's configuration API. That said, the JSON syntax is incredibly verbose, and has quite a large set of nested members; I've found that for the bulk of my usage, the declarative HCL-like syntax tends to be easier to read and implement.

For instance, the documented way to create a reverse proxy to a service running on port 9000 of another machine, and that uses HTTPS by default is simply: {
  reverse_proxy machine-running-actual-service:9000

Boom, done.

Even better: Caddy can serve local IPs and addresses over HTTPS as well. It will generate self-signed certificates using its own root certificate, which you then install into your system trust store. The benefit is you can test your sites locally using TLS, which can help when testing JavaScript interactions, and reduce behavior differences with production.

Securing reverse proxies

That said, I've run into some small issues when running reverse proxies:

  • I assumed HSTS headers were in place. They were not. (This is true of any Caddy-served site, though, and not specific to reverse proxies.)
  • I assumed things like the X-Forwarded-Host and X-Real-IP request headers were in place. They were not. That said: by default, Caddy:
    • Passes the Host header intact to the proxy. This is actually quite handy, as most application frameworks will prefer the Host header when present anyways.
    • Adds the X-Forwarded-Proto header; this is the one most standardly consumed by other web servers and web application frameworks.
    • Adds or updates the X-Forwarded-For header, which is used by load balancers.

Fortunately, adding configuration for these are relatively straight-forward {
  reverse_proxy machine-running-actual-service:9000 {
    header_up X-Real-IP {remote}
    header_down Strict-Transport-Security max-age=31536000

If you have quite a number of reverse proxies, you likely don't want to copy-paste those. Caddy to the rescue again: configuration supports snippets. These look like your host blocks, but the name will be in parentheses. When a configuration block can re-use it, it can import it by name.

(reverseproxyheaders) {
    header_up X-Real-IP {remote}
    header_down Strict-Transport-Security max-age=31536000
} {
  reverse_proxy machine-running-actual-service:9000 {
    import reverseproxyheaders

With these changes, my applications now:

  • can resolve the client IP correctly
  • provide HSTS headers to the client, helping protect users from MITM attacks

My own configuration defines three reverse proxies, two subdomains that redirect elsewhere, and defines one static site. All in a total of 34 lines of configuration.

I'll take it.


Why use Caddy, particularly if you're comfortable and/or knowledgable with Apache or nginx?

For me, the decision comes down to sane defaults and ease of setup. Setting up ACME with Apache or nginx, while it has become simpler, is not turn-key. Caddy, however, assumes TLS by default, uses ACME to marshal a TLS certificate, and redirects non-TLS requests to TLS, all without requiring any additional configuration whatsoever. Similarly, the fact that setting up a reverse proxy can often be as simple as pointing it to the proxy, and not require remembering to pass on common headers, sets it apart from the traditional web servers. Finally, it's built for speed, and I've found that the performance overhead of running it as a reverse proxy is essentially negligible.

Truncated by Planet PHP, read more at the original (another 816 bytes)

Larry GarfieldAdvent of Functional PHP: Day 6 (6.12.2021, 18:43 UTC)
Advent of Functional PHP: Day 6

Day 6's challenge is a little fishy. Given what we've already done so far, it's pretty simple. The only catch is making sure you do it in an efficient way.

Specifically, we're asked to model the growth patterns of fictional lantern fish. In this silly model, we start with a list of fish at various ages. Each fish spawns a new fish every 7 days, and a newborn fish takes an extra 2 days before it starts spawning new fish. Fish also never die. (Someone warn the AI people that we've found the paperclip optimizer.)

Part 1 asks us how many fish there are after 80 days, all around the world, given the start data. Let's find out, but let's do so efficiently.

Continue reading this post on PeakD.

Larry 6 December 2021 - 12:43pm
Larry GarfieldAdvent of Functional PHP: Day 5 (6.12.2021, 03:23 UTC)

Advent of Functional PHP: Day 5

Submitted by Larry on 5 December 2021 - 9:23pm

After the last two days, Day 5 of Advent of Code is almost mundane in comparison. Today we're asked to read in the definition for a series of lines and compute how many times they intersect.

The process is much the same as the previous days: Parse the incoming data into some sort of data model, then run some computations on it. And both parts will consist primarily of `pipe()` operations, since we're really just shuffling data from one form to another.

Our input data looks like this (albeit with a much larger range of coordinates):

Continue reading this post on PeakD.

Larry GarfieldAdvent of Functional PHP: Day 4 (5.12.2021, 01:41 UTC)

Advent of Functional PHP: Day 4

Submitted by Larry on 4 December 2021 - 7:41pm

Day 4 of Advent of Code has us playing bingo against a giant squid. (Don't ask; I don't understand it either.) More specifically, we want to take an input file that consists of a series of numbers that will get called, followed by a series of boards. We then need to compute which board will be the first to win, following the standard rules of bingo (although with no free space in the middle, the cheating squid...).

This sort of problem is inherently very stateful, and thus, frankly, not a good fit for functional code. It absolutely can be done in a functional way, but it's not the best fit. We're not interested in the best fit in this series, though, just how it could be done functional-style. So let's do it functional style just to say we did. Along the way we will really exercise the function composition concept, and show a few other tricks along the way.


Larry GarfieldAdvent of Functional PHP: Day 3 (5.12.2021, 00:15 UTC)

Advent of Functional PHP: Day 3

Submitted by Larry on 4 December 2021 - 6:15pm

The third challenge in this year's Advent of Code is all about bit manipulation. We're asked to read in a series of binary numbers and interpret them in various entirely illogical ways as a form of diagnostics. (Incidentally, if you ever write a system that requires this kind of logic to debug its output, you're fired.)

In any case, we're given a file with a list of 12 digit binary numbers and asked to compute various values. In the first part, we are asked to find the most common bit (0 or 1) in each position, and the result is known as "gamma." Then we have to find the least common bit in each position, and the result is known as "epsilon." (I don't know why you would want to do this; it's all Greek to me.)

Larry GarfieldAdvent of Functional PHP: Day 2 (2.12.2021, 17:46 UTC)

Advent of Functional PHP: Day 2

Submitted by Larry on 2 December 2021 - 11:46am

In today's challenge, we're asked to interpret a series of basic command lines from a file and update the position of our submarine accordingly. It's basically a graph walk of sorts, with instructions of up, down, and forward. (Apparently you cannot go backward, as in life.)

As with yesterday's challenge, we could do it imperatively with a foreach() loop and a couple of state variables floating around, but that conflates a whole bunch of different behaviors into one blob of code. We don't want to do that, so let's step back and consider the problem more clearly.

Larry GarfieldAdvent of Functional PHP: Day 1 (1.12.2021, 17:24 UTC)
Advent of Functional PHP: Day 1

today's challenge asks us to interpret a list of numbers. In the first part, our goal is to determine how many elements in the list are larger than their immediate predecessor.

The imperative way would be to toss it in a `foreach()` loop and track some state along the way. But we want to be functional and avoid "track some state," because the whole point of functional programming is to avoid tracking state, as tracking state is error prone.

When looking at a foreach-style operation that has some state, my first inclination is to look at a reduce operation. A reduce operation walks over a list and performs the same operation (function) on each item, using the output of the previous iteration as an input. That is, each step takes the output of the previous operation and the next element, and produces an output. It's quite elegant.

Larry 1 December 2021 - 11:24am
Larry GarfieldAdvent of Code 2021: Functional PHP (30.11.2021, 00:45 UTC)
Advent of Code 2021: Functional PHP

I am planning to participate in Advent of Code this year. For those not familiar with it, it's a daily coding challenge that runs through December, until Christmas. Mostly it's just for fun, but some people take it as an opportunity to either push themselves (by solving the puzzles in a language they're unfamiliar with) or to show off some feature of a language they like, which they then blog about.

In my case, I'll be solving puzzles in PHP, of course, but specifically using functional techniques. My goal is to demonstrate how functional programming in PHP is not just viable but creates really nice solutions. At least, I hope it works out that way; I haven't seen any of the challenges yet. :-)

Larry 29 November 2021 - 6:45pm
Larry GarfieldEvolving PHP safely (27.11.2021, 18:37 UTC)

Evolving PHP safely

Submitted by Larry on 27 November 2021 - 12:37pm

This past week, the latest PHP RFC, Deprecate Dynamic Properties, passed 2:1. It just barely met the 2/3 vote threshold for passing, which of course can and has been spun in various pro-and-con ways. The RFC covers the change itself fairly well so I won't go into detail about it here.

The main argument people had against it was that it involves triggering deprecation warnings. Which... is kind of the point. That's kind of all it does.

This is not the first time that debate has come up, but it's been coming up more frequently and we, as PHP, need to improve the answer.

(Continue reading this post on PeakD.)

Derick RethansPHP Internals News: Episode 95: PHP 8.1 Celebrations (25.11.2021, 09:23 UTC)

PHP Internals News: Episode 95: PHP 8.1 Celebrations

In this episode of "PHP Internals News" we're looking back at all the RFCs that we discussed on this podcast for PHP 8.1. In their own words, the RFC authors explain what these features are, with your host interjecting his own comments on the state of affairs.

The RSS feed for this podcast is, you can download this episode's MP3 file, and it's available on Spotify and iTunes. There is a dedicated website:


Derick Rethans 0:14

Hi, I'm Derick, and this is PHP internals news, a weekly podcast dedicated to demystifying the development of the PHP language.

Derick Rethans 0:23

This is episode 95. I've been absent on the podcast for the last few months due to other commitments. It takes approximately four hours to make each episode. And I can now unfortunately not really justify spending the time to work on it. I have yet to decide whether I will continue with it next year to bring you all the exciting development news for PHP 8.2.

Derick Rethans 0:44

However, back to today, PHP eight one is going to be released today, November 25. In this episode, I'll look back at the previous episodes this year to highlight a new features that are being introduced in PHP 8.1. I am not revisiting the proposals that did not end up making it into PHP 8.1 feature two features I will let my original interview speak. I think you will hear Nikita Popov a lot as he's been so prolific, proposing and implementing many of the features of this new release. However, in the first episode of the year, I spoke with Larry about enumerations, which he was proposing together with Ilija Tovilo. I asked him what enumerations are.

Larry Garfield 1:26

Enumerations, or enums, are a feature of a lot of programming languages. What they look like varies a lot depending on the language, but the basic concept is creating a type that has a fixed finite set of possible values. The classic example is booleans. Boolean is a type that has two and only two possible values true and false. Enumerations are way to let you define your own types like that, to say this type has two values Sort Ascending or Sort Descending. This type has four values for the four different card suits, and a standard card deck. Or a user can be in one of four states pending, approved, cancelled or active. And so those are the four possible values that this variable type can have. What that looks like varies widely depending on the language. In a language like C or C++, it's just a thin layer on top of integer constants, which means they get compiled away to introduce at compile time, and they don't actually do all that much they're a little bit to help for reading. On the other end of the spectrum, you have languages like rust or Swift, where enumerations are a robust, advanced data type and data construct of their own. That also supports algebraic data types. We'll get into that a bit more later. And is a core part of how a lot of the system actually works in practice, and a lot of other languages are somewhere in the middle. Our goal with this RFC is to give PHP more towards the advanced end of enumerations. Because there are perfectly good use cases for it, so let's not cheap out on it.

Derick Rethans 3:14

In the next episode, I spoke with Aaron Piotrowski about another big new feature: fibres.

Aaron Piotrowski 3:20

A few other languages already have Fibers like Ruby. And they're sort of similar to threads in that they contain a separate call stack and a separate memory stack. But they differ from threads in that they exist only within a single process and that they have to be switched to cooperatively by that process rather than pre-emptively by the OS like threads. And so the main motivat

Truncated by Planet PHP, read more at the original (another 16365 bytes)

LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP