Hi Willy,

thank you for the insightful explanation. We did not initially consider setting 
the precedence of the state file IP via init-add last.

It is however interesting to us that this only affects the IP address and that 
the port seems to always be taken from the state file. Is there also some 
option or workaround to control where the port is read from?

Anyways, it seems confusing to us that the default behavior is to read the IP 
address from the config and the port from the state file. Does this not lead to 
confusion and possibly even corrupt states?

Best regards,

Benedict

Von: Willy Tarreau <[email protected]>
Datum: Montag, 16. Februar 2026 um 18:50
An: Weis, Benedict <[email protected]>
Cc: [email protected] <[email protected]>, Stephan, Alexander 
<[email protected]>, [email protected] <[email protected]>
Betreff: Re: [PATCH] BUG/MINOR: server: fix server-state-file servers ip address

[You don't often get email from [email protected]. Learn why this is important at 
https://aka.ms/LearnAboutSenderIdentification ]

Hi Benedict,

On Fri, Feb 13, 2026 at 12:21:16PM +0000, Weis, Benedict wrote:
> Hi everyone,
>
> first of all, thank you all for your amazing work on HAProxy!
>
> I am writing to you today because my colleague Alexander and I am
> experiencing a bug in our HAProxy deployment for which we hope to present an
> acceptable patch.
>
> The bug seems to be a regression introduced by
> 5e5152<https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fhaproxy%2Fhaproxy%2Fcommit%2F25e515235a8ddd7590b222980990baab764680ec&data=05%7C02%7Cbenedict.weis01%40sap.com%7C8c7f843dadbd42ac436308de6d83ecb8%7C42f7676cf455423c82f6dc2d99791af7%7C0%7C0%7C639068610549689787%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C40000%7C%7C%7C&sdata=ZfT3PjkKTa7x%2BDkEvSp%2FAeV%2BJtp%2BTdwsb8k3JrLgD6s%3D&reserved=0<https://github.com/haproxy/haproxy/commit/25e515235a8ddd7590b222980990baab764680ec>>
> targeting the server IP address initialization path. When a server-state-file
> is used during HAProxy reload and the server-state-file contains a valid IP
> address for a server, the original server IP address from the HAProxy config
> takes precedence. The same is not the case for the server's port.
>
> This leads to the situation that when a servers IP address has been altered
> during operation, for example by issuing ,,set server b1/s1 addr 1.1.1.1" to
> the socket API and HAProxy is reloaded with the server-state-file enabled,
> the servers IP address is reset its original IP address.

It is unfortunately much more complex. There is a design flaw in the
server-state-file feature in that it only contains the latest values but
not the initial ones. This means that upon reload, haproxy checks for
differences between the config and the contents of the state-file, and
chooses based on common sense. It's easy for all non-initialized stuff
such as server address that is not set when dealing with resolution, or
with a server's status (up/down) etc. But for things that can be changed
on the fly, there's no simple rule.

There has been a long period where picking too much from the state-file
would result in people not being able to change their configuration
anymore. Because, it's important to remember, the sole reason of a reload
is to apply a config change. And when the config change is ignored and
the previous state is preferred, there is a big problem! We've had
complaints of users having to manually delete entries from their state
files to allow to take config changes into account again.

I'm well aware that the current situation is far from being perfect, but
it remains the one giving the least surprises. That doesn't mean that it
cannot be improved though.

My understanding is that you're having an explicit server address in the
config, you're changing it from the CLI and upon reload it's back to the
one of the config. I agree this can be surprising, but now imagine with
the "fix": you set server addresses in the config, you figure that one
is wrong, you edit it in your config and you reload, and it continues to
use the wrong one, forever, because that's the one in the state file and
it now has precedence over the configuration. It's even worse.

There's normally a way to work around this using init-addr. init-addr
defines the order in which servers addresses are resolved among:
  - "last" (last known value from server-state-file)
  - "libc" (uses gethostbyname at boot)
  - "none" (no address, uses DNS resolutions once booted)
  - an explicit address.

In my opinion, you could choose which one has precedence over the other
in the config by adjusting the declaration, for example:

    server srv1 ip-srv1:80 init-addr last,10.20.30.40

=> will look for "srv1" in the state-file, use its IP if found,
   otherwise 10.20.30.40

In case of force manual change, just place "last" at the end, or
drop it:

    server srv1 ip-srv1:80 init-addr 10.20.30.40,last

In this case it should use that IP primarily. One just needs to remember
to switch back to last,10.20.30.40 once the forced change is applied so
as to preserve the manually managed ones.

In case your addresses are never pre-filled in the config, you could
even simplify the approach with this:

    server srv1 ip-srv1:80 init-addr last,none

But please keep in mind that all of this (i.e. ignoring config changes
and preferring to use the previous setting) is quite rare and generally
not welcome among ops people, and that the state-file was really designed
to preserve naturally changing info (IP when none set, etc), not to serve
as a way to bypass the configuration.

Maybe we could imagine making an exception for address 0, though. While
it *is* a valid address (route everything to the same destination), it
makes no sense usually to combine it with init-addr, and we could maybe
imagine that a server declared this way:

    server srv1 0.0.0.0:80 init-addr last

Would automatically pick its address from the state file. Then along
the same logic, that one:

    server srv1 0.0.0.0:80 init-addr last,10.20.30.40

Would take it there otherwise fall back to 10.20.30.40. But note that
we're very close to the "ip-srv1" above in that, after all "ip-srv1"
is just a placeholder to say "no address known yet, use init-addr".

What do you think ?

Willy

Reply via email to