Listing a connection in strongSwan configuration proves only that a definition loaded. It does not mean the peer was contacted, that an IKE SA exists, or that any traffic is protected. The daemon treats definitions and live associations as separate objects, and the distance between them is a deliberate design choice. Knowing which object you are inspecting turns a vague failure into a specific next command.

Loading is not connecting

A loaded connection is a statement of what may be negotiated later: peer addresses, credentials, proposals, and traffic selectors. Nothing in that statement requires the daemon to have dialed anyone. A gateway can wait for the other side, initiate at startup, or wait for matching traffic to wake it. All three are valid, and all three look identical in the configuration file until you read the start policy.

Operators get into trouble by reading the definition list as a status list. The profile is there, so the tunnel is assumed up, and the next hour goes into debugging routes for an association that was never built.

The opposite mistake is just as common. A missing profile sends people hunting for a network fault when the configuration never loaded. Name the object, then run the command that observes it.

Three objects, three observations

strongSwan keeps a loaded definition, an IKE SA, and a CHILD SA. The first is configuration, the second is an authenticated control relationship, and the third is negotiated protection for selected traffic. They even have separate names, so a profile called hq can own a child called hq-lan.

The table maps each layer to the command that shows it. Read the row before reading the log.

LayerWhat it containsCommand
DefinitionPeer addresses, credentials, proposals, and traffic selectorsswanctl --list-conns
IKE SAOne authenticated control channel to the peerswanctl --list-sas
CHILD SAKeys and selectors for the traffic being protectedChild rows under the IKE SA

Requesting the child builds its parent IKE SA first when none exists. Requesting the IKE SA alone is a different call. A control channel that authenticates fine does not guarantee the child you asked for.

That difference matters during a partial failure. An IKE SA can be healthy while the child fails on a selector mismatch or a proposal the peer will not accept. The two objects fail for different reasons, so they deserve separate observations.

Pick the start action deliberately

In swanctl.conf, a child's start_action decides behavior after loading. The default none leaves the definition for manual initiation or responder use. start dials it, while trap leaves a policy that negotiates as soon as matching traffic shows up.

So loading never starts a tunnel and loading always starts one are both wrong. The action is part of the profile, and it should match the peer's role. Two gateways that both wait for the other side produce silence, not a tunnel.

With trap, the traffic has to match the selectors, so an unrelated ping will not wake anything. With start, the peer address must be usable and both sides must agree on authentication and proposals. Neither action substitutes for checking those preconditions.

Recovery is a separate policy

Startup is not a keepalive. Dead-peer detection, explicit peer closure, rekeying, and a process restart are different lifecycle events with their own settings. Configure each one deliberately instead of expecting an initial start to cover all of them.

A tunnel that comes up at boot and dies an hour later is a recovery question. The start policy did its job and then stopped mattering. Look at DPD and rekey settings before blaming the initial negotiation.

Replacing loaded definitions is its own operation. Non-default start policies have documented inverse actions, and a reload is an operational change rather than an assumption that every association was updated in place. Stage reloads where a reconnect is acceptable. Keep the old configuration until the new one is proven.

Check what exists before you debug routing

Run the three observations in order: loaded definitions, active IKE SAs, and child entries. Each answer narrows the next question. Skip a step and you end up debugging a layer that was never built.

Start with what is loaded and what is actually established:

swanctl --list-conns
swanctl --list-sas

If the child is missing while the profile is correct, initiate it by name and watch what happens. The output usually says whether the parent came up first.

swanctl --initiate --child hq-lan

An active CHILD SA is not the finish line. Forwarding rules, routes, and the application's own authorization still have to line up. The lifecycle answers what was negotiated; it cannot decide who may use the service.

Nsɛm a ɛfa ho