Server helpers configure a subnet and then fill it with a dynamic pool of their own choosing. That default is convenient until some addresses must stay out of allocation, whether they are reserved for fixed assignments or held back for a future segment. Suppressing the automatic pool and declaring the range yourself takes two lines and one deliberate decision about which addresses are not for allocation. The rest is operational discipline: inventory, apply, verify, roll back.

This is a change to a working service, so treat it as an operational task: inventory first, apply through the normal lifecycle, verify with a fresh client, and keep a rollback.

Start from the subnet you already have

Read the current server configuration and the addresses clients actually hold. The pool change only makes sense against that baseline, and the baseline is not always what the file suggests, because a managed product or a configuration generator may own the file you are reading.

grep -nE '^(topology|server|ifconfig-pool|max-clients|client-config-dir)' /etc/openvpn/server/lab.conf
ip -4 addr show tun0

Confirm the topology in force. Under subnet topology each client takes one address from the pool; older net30 layouts allocate a small block per client and the arithmetic is completely different. If the server is still on net30, this page is the wrong migration guide and the pool numbers will not mean what you expect. Check that line before copying address arithmetic from anywhere else.

Write down the server's own address, every fixed assignment in the client-config directory, and any address that a route or an access rule depends on. Those are the addresses that must stay outside the dynamic range. Writing them down first is what makes the range a decision instead of a guess. It also gives a rollback something concrete to restore.

Add nopool and declare the range

The helper keyword accepts nopool, which keeps the subnet configuration and suppresses the automatic dynamic pool, as the OpenVPN 2.6 manual describes. The explicit ifconfig-pool line then supplies the inclusive range you intend, and its netmask matches the subnet. Both lines belong in the same server block, because a pool without its subnet has no meaning. Order between them matters only for readability, since the helper expands the pair when the service starts.

topology subnet
server 10.70.0.0 255.255.255.0 nopool
ifconfig-pool 10.70.0.50 10.70.0.120 255.255.255.0

Both bounds are inclusive, so the example offers seventy-one addresses. Keep the server address and every fixed assignment outside that span; a fixed assignment that lands inside the dynamic range produces a collision that depends on connection order, which is the worst kind to debug. Keep a margin between the reserved set and the range if fixed assignments are likely to grow.

Range size and concurrency are separate limits. A hundred addresses do not mean a hundred simultaneous clients if max-clients says otherwise, and a pool larger than the concurrency limit is normal rather than wasteful. What matters is that the two limits are chosen deliberately rather than inherited from a default.

Keep fixed assignments out of the dynamic range

A client-specific ifconfig-push is a different mechanism from pool allocation, and it must use parameters appropriate to the active topology. In subnet mode that is a single address and netmask; carrying over a net30 pair because it appeared in an old example is a common error.

Allocation history is a hint, not an authority. A persist file remembers which client had which address so reconnecting clients tend to receive the same one, and it does not reserve addresses, free them, or replace a fixed assignment. If a specific device must always hold a specific address, use a fixed assignment rather than relying on the persist file.

Then check the paths that depend on addresses. A route pushed to clients, a firewall rule that admits a subnet, or a monitoring check that expects a particular host may all assume the old range. Changing the pool without reading them moves the failure to a place that looks unrelated.

Apply through the lifecycle, then verify

Apply the change the way the service normally receives configuration, whether that is a direct file plus a restart or a management layer that regenerates the file. A manual edit to a generated file survives until the next generation, and no longer. Record which mechanism owns the file, because the next operator will need to know where to make the same change. Then restart once and read the log before you invite a client.

systemctl restart openvpn-server@lab
journalctl -u openvpn-server@lab -n 30 --no-pager
# on a fresh client
ip -4 addr show tun0

Connect a client that was not previously connected and confirm the address falls inside the declared range and outside the reserved set. Then confirm the return path: the client should reach what the policy permits and nothing more. An address that matches the plan but has no working route is not a successful change.

Reconnect a client that held an address from the old range. It should receive an address from the new range, and any session-scoped state tied to the old address should be gone. If it keeps the old address, something else is assigning it and the pool is not the owner you think it is.

Rolling back a range change

Keep the previous three lines in your change record, not just the previous file. Restoring them and restarting returns allocation to the old behaviour, and clients reconnecting afterwards will receive addresses from it.

Two cautions belong in the record. Clients already connected when you roll back keep their current addresses until they reconnect, so a rollback is not instant across the fleet. And if the old range overlapped a fixed assignment, restoring it restores the collision too; that overlap is the reason the change was made, and it needs a different fix than a rollback.

A pool change is finished when a fresh client receives an in-range address, a reserved address is never handed out, and the routes and rules that consume those addresses still behave as intended. Anything less leaves the next person to discover which of the three is untrue.

متعلقہ مضامین