Refusing to start, the client complains that it cannot bind a local address, and the obvious fix looks like pointing it at the tunnel address it expects to receive. That cannot work, and the reason is worth understanding: before the tunnel exists there is no inside address, and the socket that contacts the server has to exist first. Two different addresses are involved, and only one of them can be chosen locally.

The bind error names a local address

When OpenVPN reports that it cannot bind a local address, it is talking about the transport socket: the UDP or TCP endpoint that carries the encrypted connection to the peer.

An explicit local directive asks the daemon to bind that socket to a specific local address. The address must exist in the network namespace where the process runs, and it must be assignable at the moment the client starts.

A public address translated at a router or a cloud edge is not a local address the daemon can bind, even though it is the address the server sees. That distinction explains why one profile works at home and fails on a cloud instance. It also explains why adding the public address to a loopback interface does not help, since the transport would then source from an address the network cannot return to. Read the interface list before editing the profile.

What local and remote actually select

remote names the peer to contact. local binds the near end of the same socket. nobind lets the operating system pick both the local address and port, which is why clients behind home routers normally work without either directive.

Neither directive has anything to do with the address inside the tunnel.

In a container or a network namespace the same rule applies with narrower boundaries: the host's addresses are not present inside, so a local line copied from the host configuration fails for a completely different reason than a wrong address would.

ip -brief address show
ip route get 203.0.113.10

The inner address comes from the server

The address inside the tunnel is negotiated or assigned after the control channel is established. With a dynamic pool the server decides it at connect time, and with client-specific configuration it may be fixed per identity.

Writing local with an inner address does not ask the server to allocate that address. In the best case the bind fails; in the worst case the client finds an unrelated host address with the same value and starts using it for the transport.

The interfaces to read are different too. ifconfig parameters and pool configuration describe the inside, while remote, local, proto and nobind describe the outside. Keeping the two lists apart explains almost every confusing example you will find on a forum. The OpenVPN 2.6 manual documents them in separate sections for that reason.

The trap: a full tunnel that captures its own transport

Once the tunnel is up and carrying the default route, the packets that sustain it must not be routed into it. That is a routing problem rather than an addressing one, and the daemon handles it by installing a more specific route to the server's own address through the original gateway.

If you pin the transport to a specific local address and later change the path that address uses, the outer connection can lose its way while the inside stays configured. The tunnel keeps reporting connected because the inside is fine. Only the transport is broken, which is why the logs read as contradictions.

Symptoms then look like a tunnel that connects and freezes, or one that reconnects in a loop with no useful error. Check the route for the peer's address before you check anything inside the tunnel, and confirm that the local address you bound still belongs to the interface you expected.

A habit that prevents the confusion

Read every address in a profile and decide which layer it belongs to before editing it.

If it names the far end of the transport or binds the near end of it, it is an outside address and must exist before startup. If it describes what happens inside the tunnel, it comes from the server or from the topology, and no local directive can substitute for it.

Write the two lists into the deployment notes next to the profile. The next troubleshooting session then starts with the layer rather than with a guess.

פֿאַרבונדענע אַרטיקלען