How About Ordinary Middleware?
With v0.8, we’ve added initial support for Ordinary Middleware. For this first release we’ve kept narrowly focused on validation operations that can be delegated to external services via HTTP request.
Example Case#
One tool that we’re excited about and is well-aligned with our #NoAI agenda is Iocaine—a service which runs as a separate daemon that filters out requests from ‘AI’ scrapers based on request headers.
Building on the proxy functionality that we introduced last week (v0.7.0), we’ll be using an Ordinary Proxy to front our very own GoToSocial instance and run validation of all proxied requests against Iocaine before forwarding.
Setup#
I won’t go into explicit detail on setting up Iocaine and GoToSocial—as they both have super helpful guides themselves—other than to say that I have them both setup and running with systemd on the same Debian VPS (Hetzner CX11) where ordinaryd was already running.
External Services#
- Iocaine setup guide
- GoToSocial setup guide
At this point we have Iocaine running at http://localhost:42069 and GoToSocial running at http://localhost:6020 (I left Iocaine’s port as the default and made GTS’s 6020 because 60 -> GO and 20 -> TO *shrug*).
Ordinary Proxy & Middleware#
The DNS has already been configured for ordinary.so to point it at the Hetzner floating IP address, so now we need to create the ordinary_so account for the domain in api.ordinary.host’s system.
Signed in as the root Ordinary user:
# retrieve an invite token
# user: ordinary_so
# domain: ordinary.so
# role: admin
ordinary accounts invite ordinary_so ordinary.so admin
With invite token in hand:
# register account
# api: https://api.ordinary.host
# account: ordinary_so
# password: 'supersecret123!'
# invite token: 'BASE_64_ENCODED_INVITE_TOKEN'
ordinary accounts register https://api.ordinary.host ordinary_so \
--password 'supersecret123!' \
--invite 'BASE_64_ENCODED_INVITE_TOKEN'
With the QR code / MFA secret and recovery codes stored we can log in as the ordinary_so account:
# login to account
# api: https://api.ordinary.host
# account: ordinary_so
# password: 'supersecret123!'
# MFA code: 123456
ordinary accounts login https://api.ordinary.host ordinary_so \
--password 'supersecret123!' \
--mfa 123456
And then let’s create an ordinary.json with the basic config:
// ordinary.json
{
"domain": "ordinary.so",
"contacts": ["support@ordinarylabs.io"],
"version": "0.1.0",
"storage_size": 10000000
}
Reverse Proxy#
The first phase of integrating the external services is setting up the GoToSocial proxy.
Because we want ordinary.so to behave fully as a reverse proxy for GoToSocial, we are going to use a path-based proxy without a subpath, pointing at http://localhost:6020.
// ordinary.json
{
"domain": "ordinary.so",
// ...
"proxies": [
{
"path": "/{*path}",
"target": "http://localhost:6020" // gotosocial endpoint
}
]
}
Validation Middleware#
Next we’re going to add a Validate middleware, that will forward headers to the Iocaine daemon as a check, before forwarding to the GoToSocial instance.
// ordinary.json
{
"domain": "ordinary.so",
// ...
"middlewares": [
{
"name": "iocaine",
"operation": {
"Validate": {
"rule": {
"StatusCode": 421 // if status code == 421 { continue } else { reject }
},
"components": ["Headers"] // only forward the headers
}
},
"mechanism": {
"Request": {
"endpoint": "http://localhost:42069" // iocaine endpoint
}
}
}
]
}
Update the proxy to include the newly created middleware.
// ordinary.json
{
"domain": "ordinary.so",
// ...
"proxies": [
{
"path": "/{*path}",
"target": "http://localhost:6020",
"middlewares": ["iocaine"] // add this line
}
]
}
Publish#
Logged in as the ordinary_so account:
ordinary publish -v
Testing it Out#
Now I’ve already migrated the Ordinary ActivityPub account over to this instance so we’ll use it to test out the Iocaine middleware. If you navigate to https://ordinary.so/@ordinary in a conventional browser you should be able to see the account unadulterated.
To test that we’re filtering out ‘AI’ scrapers we can curl with a junk user agent:
# should get back some garbled source code
curl https://ordinary.so -v -A Perplexity
Conclusion#
To see the config that is actually running https://ordinary.so, you can look here.
Right now the middleware setup is somewhat limited and primarily useful for filtering and auth delegation. In the future, request mapping, overrides, etc. will all be configurable, and in the slightly further future, WebAssembly module middleware, much like we already have WASM templates and actions.