Projects

An automation server, and the access policy that wasn't

A workflow automation server at home, published to the internet through a tunnel. The part worth reading is the access policy: the configuration screen said one address, and testing it with an address that was not mine said anyone.

The n8n editor on a laptop and on a phone, a site health check workflow from its two triggers through the check to a healthy path and a recheck before any alert.

n8n in Docker on an Ubuntu 24.04 virtual machine under VMware, with a cloudflared container beside it, reached from outside over a tunnel.

The architecture decision is a split, and it is the sort of thing that reads as obvious once stated and is easy to get wrong in practice: the control interface sits behind an identity check and the webhook endpoint does not. A webhook that requires a human to log in is not a webhook. So two paths into the same service carry different policies, and the open one is open deliberately and scoped to exactly what has to be reachable.

The part worth telling is what happened next. I put the identity check in place naming my own address, and it looked correct on the configuration screen. Then I tested it properly, from outside, with an address that was not mine. It sent that address a code and let it in. The policy had not been restricting anything at all.

Nobody finds that by reading the configuration, because the configuration says what you intended. It was found by trying the thing I was trying to prevent.

The fix was to make the rule name one exact address and nothing broader. Tested again the same way: any address can still be typed in, and only mine is ever sent a code. Every other address gets no code and no error, nothing that tells a stranger which address would work. And behind that gate, n8n still asks for its own username and password.

What I would do differently: settle the encryption key and both hostnames before the first launch. Adding the key to an instance that had already made its own took the service down, and the way back was the last command that had worked.