Editing a line in ipp.txt feels like reserving an address, and it is not one. That file, named by ifconfig-pool-persist, records which address a common name had last time so the pool can hand the same one back when that is convenient. Nothing in it binds the next connection to that number.

Run the checks below in order. Each one either confirms the mechanism or tells you to stop and repair an input.

What the persistence file is for

The file exists to keep addresses stable across restarts, which makes reconnects friendlier and logs easier to read. It is read as history and written as history, and the allocation path stays free to choose another address when the hint does not fit: a different pool, a conflicting assignment, or a client that arrived after the pool filled. That is why a manual edit can look perfect in the file and change nothing about the connection. Treat it as a cache of past decisions rather than a source of policy.

If you need a specific address for a specific client, the documented mechanism is ifconfig-push, and it belongs in the configuration that owns that client.

Check that the right client is selected

An explicit assignment is looked up by the client's common name, so a file named for the wrong identity is simply never read. Confirm what the server considers that client's name, especially where username-as-common-name changes it after authentication. Then confirm the file name matches that value exactly, including case.

Consider concurrency while you are here. If duplicate-cn is allowed, several devices can present the same identity, and one fixed address cannot be unique to all of them. Decide whether the fixed address is worth refusing concurrent sessions for that identity, because those two requirements cannot both be satisfied.

Check that the numbers match the topology

The meaning of the arguments depends on the tunnel topology, and this is where a copied example does the most damage. In the older net30 arrangement each client occupies a four-address block, so the push supplies a pair of addresses. In subnet topology the client receives one address plus the pool's mask, and the pair form is wrong. Read the topology from the running configuration before writing the line.

# /etc/openvpn/ccd/partner-a   (subnet topology)
ifconfig-push 10.44.0.61 255.255.255.0

Check the address against everything else that could own it: another explicit assignment, the dynamic pool range, and any static route that assumes a fixed host. An address that overlaps the pool will work until the pool hands it to somebody else, and that failure will look random.

Check the result on a fresh connection

An existing session keeps the address it was given, so the only meaningful test is a new connection. Disconnect the client, reconnect, and read the address it actually received together with the routes that arrived with it. If the address is still dynamic, the assignment was not applied, and the next step is the configuration lookup rather than another edit to the history file.

Keep the evidence together: the client name, the file that matched, the address assigned and the pool it came from.

Finally, a fixed tunnel address is not a device credential. It identifies a place in the address plan, while authentication still rests on the certificate and the account. Confusing the two turns an address conflict into a security assumption that nobody wrote down.

འབྲེལ་བའི་རྩོམ་ཡིག