Libreswan IKEv2 With A Pre-Shared Key, IKE On One Address

Libreswan from AppStream: IPsec connections authenticated by a pre-shared key made on the host, negotiated with IKEv2 under the system crypto policy, IKE kept to one address, each connection checked by its keywords and again by pluto. The live test brings a peer in a namespace up, sees the ping cross as ESP only, and is refused with a different key. Original role, live-tested on Rocky Linux 10.

ansibleNetworking & VPC

Verification

Live-tested

Really deployed to a container sandbox, proven idempotent (a second run changes nothing), verified against the role’s assertions, then torn down.

Conformance

  • Static validation (yamllint · ansible-lint)

Provenance

  • SHA-256 checksum
  • Signature (pending)

Functional

  • Live-tested - applied, verified, destroyed

Last verified 2026-10-08 · podman 4.9.3 · ansible 2.21.4 · how we verify

Cite it in your README

badge · attribution

Paste this beside the module in the repository that uses it. The badge is rendered from this artifact's verification record, so it reads live-tested because the record says so, and the link lands on this page.

README.md, GitLab, Gitea
[![IaC Bazaar: live-tested](https://www.iac-bazaar.com/api/artifacts/ansible-libreswan/badge)](https://www.iac-bazaar.com/catalog/ansible-libreswan?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)

Ansible role 1.0.0, live-tested on IaC Bazaar: [Libreswan IKEv2 With A Pre-Shared Key, IKE On One Address](https://www.iac-bazaar.com/catalog/ansible-libreswan?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)

```yaml
# Libreswan IKEv2 With A Pre-Shared Key, IKE On One Address: https://www.iac-bazaar.com/catalog/ansible-libreswan (download from your IaC Bazaar account)
```

Preview:IaC Bazaar: live-tested

Documentation

libreswan

Libreswan from AppStream: IPsec connections authenticated by a pre-shared key, negotiated with IKEv2 under the system's crypto policy, a key made on the host for each connection that is given none, IKE kept to one address, and every connection checked twice - its keywords before the file lands and its values by pluto itself. Original role for EL 10, live-tested with podman on Rocky Linux 10.

No download, and no version to pin. EL 10 packages ipsec, so the role installs it by name and takes what the distribution ships: a security update arrives through dnf, not through a new release of this role. What the role owns is the configuration and the proof that the service works.

The distribution's unit, our configuration. The package's unit is Type=notify and runs ipsec checknss first, which makes pluto's NSS database when there is none. The role writes /etc/ipsec.d/iacbazaar.conf (root 0644) and /etc/ipsec.d/iacbazaar.secrets (root 0600), both picked up by the package's /etc/ipsec.conf, which keeps including the system crypto policy's libreswan settings; the one line it changes there is listen=.

IKE on one address. Without listen=, pluto takes UDP 500 and 4500 on every address the host has (measured: the container's own address, loopback and ::1). The role sets it from libreswan_listen_address; the example's is 192.0.2.1 (TEST-NET-1), so on a host without that address pluto listens on nothing until you configure it. The live test reads the sockets and finds IKE on that address and no other.

Two checks, because one is not enough. ipsec addconn --checkconfig refuses an unknown keyword with the file and the line, but passes a bad value - authby=nonsense, an IKE key length of 999, a /99 subnet (measured); pluto refuses those only when it adds the connection ("failed to add connection: authby=nonsense is unknown"). So the template's validate is the checkconfig, and after every start the role asks pluto for each connection (ipsec connectionstatus) and fails if one is missing.

A key per connection, made on the host. A connection given no psk gets 48 hexadecimal characters from Python's secrets, kept in /etc/ipsec.d/iacbazaar-psk/<name> (root 0600); give the peer the same key.

Proven by a peer. tests/pre-converge.yml gives the example connection a home: a veth pair into a network namespace, the host end 192.0.2.1, the peer 192.0.2.2 - made before pluto starts, because pluto orients a connection only to an address it found when it scanned. The live test starts a second pluto in that namespace with the key the role made, brings the connection up (IKEv2, a transport-mode Child SA), and pings the peer while counting what crosses the link: ESP only, no plain ICMP, and the SA's byte counters move. Then the peer is given a different key, and the host's attempt fails with AUTHENTICATION_FAILED. The lane needs the WSL host's xfrm_user and esp4 modules and --cap-add=NET_ADMIN --cap-add=NET_RAW.

License

Commercial - IaC Bazaar EULA. (c) IaC Bazaar.

Usage code & full reference need an account

The complete copy-paste usage, the full input/output reference, and operational notes are free with an account - shown here and bundled in the download. Sign in and this section fills in.

  • Variables
  • Test

Related modules

Live-tested

ansible-squid

The stock squid.conf allows localhost before it denies loopback destinations, so a local client can proxy into loopback services. This role puts every deny first and binds loopback. The live test fetches a page through it, then sees squid itself refuse loopback, 169.254.169.254, an unsafe port, CONNECT to 25 and a non-loopback client. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-consul-server

HashiCorp Consul as a single-node server from the upstream release (sha256-verified), as a hardened system service with HTTP, DNS, RPC and both serf listeners on loopback and its configuration checked by consul validate before it lands. The live test waits for a leader, writes a KV key through the API, reads it back and reads the member alive. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-frr

FRR from AppStream: BGP that announces only your prefixes, accepts from each neighbour only what you list for it, signs sessions with TCP MD5, and applies a change without dropping them. The live test peers with a real BGP speaker in its own namespace; a filtered prefix stays out of the kernel and a wrong password keeps the session down. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-headscale

Headscale, the self-hosted Tailscale control server, from the upstream release binary (sha256-verified) as a hardened system service on loopback with sqlite; configtest runs as the service user (it opens the database). The live test creates a user over the unix socket, issues a reusable pre-auth key for it, reads the user back from the key, destroys it. Original role, live-tested on Rocky 10.

View module
Live-tested

ansible-kea-dhcp4

Kea DHCPv4 from AppStream: your subnets, pools, options and reservations in Kea's own keys, checked with kea-dhcp4 -t and applied by reload, leases on disk. The live test runs a raw-socket DHCP client in a namespace: an address with router, DNS and lease time, the reserved address for its MAC, and nothing on a segment no subnet covers. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-wireguard

WireGuard from AppStream: a wg-quick interface whose private key is generated once and kept in its own file, never in the config, peers from a variable, and each config loaded into a throwaway interface first. The live test pings through the tunnel from a peer in another network namespace while an unlisted key gets no reply. Original role, live-tested on Rocky Linux 10.

View module