Across locationsThree places, one routineSecurity and accessBruno

Your remote access works — but you have not proved it

Three flats, three answers. Why a successful request from home proves nothing, why bans never expire — and why one location has nothing at all.

The most honest reason for looking into my own flat from outside is not a technical one: Bruno stays there. What he does once the door closes was a mystery for a long time — and that is what made me not only set up remote access but actually trust it.

Because a camera you cannot reach when it matters reassures nobody.

Three flats, three answers to the same question:

Remote access
Kapfenberg running since 29.08.2026
Vienna since 08.09.2026, after an evening of fault-finding
Merano not documented at all

The third entry is the most honest one, and I come back to it at the end.

The setup that exists in two houses

internet --443--> router --forwarding--> Pi --> proxy --> Home Assistant

Plus a dynamic DNS name. That is not a luxury: in Kapfenberg the public address changed within three weeks. That is exactly what the name is for — and exactly why, from that day on, the documentation carries the name and no longer the number.

How remote access cannot be proved

This is the part I value most, because I walked into both dead ends myself.

First dead end: the request from inside your own house. Fetching the public name from the home network returns 200 OK. It looks like proof and is not: the request goes to the router, which hands it back through its own forwarding rule. It was never on the internet. This is called NAT hairpinning.

Second dead end: a fetch by a tool that “runs in the cloud.” The thought was obvious — if the fetch runs on somebody else’s infrastructure it comes from outside.

It ran locally. The proof was in the ban log: the recorded sender was the home’s own public address, complete with the tool’s user agent. Hairpinning again, just with a different label on the envelope.

What both do show: the forwarding rule exists and points at the right machine. What neither shows: whether the provider lets incoming connections through at all.

Exactly two routes are valid:

  1. From a phone over mobile data, Wi-Fi switched off.
  2. From a machine outside, a rented server for instance.

The trick with the failed attempt

The counter-check in the log only works on a failed attempt — the ban log records rejected logins only. So log in wrongly on purpose; then the real sender address is there.

Count along while doing it: after five failed attempts the address lands in the ban list. Tolerable for a mobile address, annoying for your own line.

Bans never expire by themselves

Read in the source: the ban list is loaded from the file at start-up, after which it lives in memory and is only added to. There is no expiry time.

From that follows something easily overlooked: cleaning the file is not enough. Without a restart the ban stays active in memory.

Two things belong cleanly apart:

lives where survives a restart?
counter of failed attempts memory no — zero after every start
completed ban (5 failures) file yes, permanently

So you cannot stumble into a ban over several days. It takes five failures in one run.

The cleanup runs daily at four in the morning: remove entries older than 24 hours — and restart only if something was actually removed. On most days nothing happens at all.

I tested it with an artificial list from the address range reserved for documentation:

Entry Age Result
first 30 h removed
second 2 h kept
third date unreadable kept

The third case is deliberate. Lifting a ban because you cannot read its date would be the wrong direction in which to err.

The correction that makes documentation worthless

For eight lines my own documentation said that only “the proxy on 443” is exposed.

Measured from the office, so genuinely from outside:

port 22     answers   <- the SSH add-on
port 443    answers   <- the proxy
port 2222   timeout
port 22222  timeout

Port 22 is exposed as well. Claude had relied on that documentation and claimed on its basis that packages could not be deployed from here. Wrong — I noticed it myself.

Documentation that does not know about an exposed port is worse than none: it sounds like a verified statement.

I then looked up how that open gate is secured:

password login off
keyboard-interactive off
login as main user yes
stored keys exactly one

So: main user yes, but with exactly one key. Whoever does not have it gets nowhere on port 22, however often they try. The exposure is defensible — it just had not been written down.

Two factors and an objection that does not hold

The objection to two-factor login was: with only one phone it is tedious to enter a second factor every time you log in.

That does not hold. Home Assistant issues a refresh token per device and browser. Tick “stay signed in” and you enter the second factor once per device, not once per session.

What I did reject was the obvious shortcut of declaring the home network blanket trustworthy and skipping the login there. It shifts security onto the assumption that only authorised people are on your Wi-Fi — and that holds exactly until one device on the network is compromised.

And the third location

For Merano there is no remote-access file. Not a short one, not an incomplete one — none.

That is not an omission of this article, it is the state of things. And a second open item hangs off it: the same ineffective configuration section that cost me an evening in Vienna is probably sitting there too. It has not been checked.

The most honest entry in a comparison between locations is the one where nothing is written.

What I’d suggest

  1. Test from outside, not from inside. Phone on mobile data, Wi-Fi off. Everything else may be hairpinning and still looks like success.
  2. Trust no tool you believe runs elsewhere. Check the log for the sender address that actually arrived.
  3. Use a name, not the address. It changes, and it does so without notice.
  4. Write down every exposed port, including the convenient one. An incomplete list of open gates is more dangerous than none.
  5. Clean the ban list — with a restart. Without one the ban stays in memory whatever the file says.
  6. Set up the second factor before you open the port. Afterwards it becomes a task that gets left lying around.

So what?

Remote access is the one point in these three flats where a mistake means more than inconvenience. Everything else costs data or comfort at worst. Here there is a door.

Which makes it all the more unpleasant how easily you talk yourself into success. Twice I believed I had proved access from outside, and both times the request had never left the house. Each time it looked like proof — green status, 200 OK, all good.

The difference between “it works” and “I checked it” is not academic where remote access is concerned. In one case you know the door opens. In the other you only know you are standing on the right side of it.