systemd Integration

Proper systemd integration ensures 802.1X authentication starts automatically at boot and handles failures gracefully. This guide covers service templates, dependencies, and network ordering.

Service Architecture

systemd Service Dependencies
Figure 1. systemd Boot Order for 802.1X Authentication

The boot sequence ensures proper ordering:

  1. Hardware layer — Interface device must exist

  2. Authentication layer — wpa_supplicant authenticates via 802.1X

  3. Network layer — DHCP requests IP after port authorization

  4. Targets — network.target and network-online.target for dependent services

The iwd service conflicts with wpa_supplicant. It must be masked to prevent WiFi management conflicts.

Wired 802.1X Service

Template Service

Create the template at /etc/systemd/system/[email protected]:

[Unit]
Description=WPA supplicant for wired 802.1X (%I)
Documentation=man:wpa_supplicant(8)
Requires=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
Before=network.target
Wants=network.target

[Service]
Type=simple
ExecStart=/usr/bin/wpa_supplicant \
    -c /etc/wpa_supplicant/wpa_supplicant-wired-%I.conf \
    -i %I \
    -D wired
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Enable for Interface

# Reload systemd
sudo systemctl daemon-reload

# Enable for specific interface
sudo systemctl enable wpa_supplicant-wired@<interface>.service

# Start immediately
sudo systemctl start wpa_supplicant-wired@<interface>.service

WiFi 802.1X Service

Template Service

Create the template at /etc/systemd/system/[email protected]:

[Unit]
Description=WPA supplicant for WiFi 802.1X (%I)
Documentation=man:wpa_supplicant(8)
Requires=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
Before=network.target
Wants=network.target

# Prevent iwd conflict
Conflicts=iwd.service

[Service]
Type=simple
ExecStart=/usr/bin/wpa_supplicant \
    -c /etc/wpa_supplicant/wpa_supplicant-wifi-%I.conf \
    -i %I \
    -D nl80211,wext
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Enable for Interface

sudo systemctl daemon-reload
sudo systemctl enable [email protected]
sudo systemctl start [email protected]

DHCP Integration

Authentication must complete before DHCP requests IP. Configure DHCP to wait for port authorization.

dhcpcd with wpa_supplicant

Create /etc/systemd/system/[email protected]/wpa-supplicant.conf:

[Unit]
# Wait for wpa_supplicant to authenticate
After=wpa_supplicant-wired@%i.service
Wants=wpa_supplicant-wired@%i.service

NetworkManager

If using NetworkManager, ensure it doesn’t conflict:

# /etc/NetworkManager/conf.d/unmanaged.conf
[keyfile]
unmanaged-devices=interface-name:eth0

Then reload:

sudo systemctl restart NetworkManager

Service Status

Check Running Services

# Check wpa_supplicant status
systemctl status wpa_supplicant-wired@<interface>

# Check if enabled at boot
systemctl is-enabled wpa_supplicant-wired@<interface>

# List all wpa_supplicant services
systemctl list-units 'wpa_supplicant*'

View Logs

# Follow logs in real-time
sudo journalctl -u wpa_supplicant-wired@<interface> -f

# View boot logs
sudo journalctl -u wpa_supplicant-wired@<interface> -b

# Filter for EAP events
sudo journalctl -u wpa_supplicant-wired@<interface> | grep -iE 'eap|tls|auth'

Debug Mode

Temporary Debug Service

For troubleshooting, run with maximum verbosity:

# Stop the service
sudo systemctl stop wpa_supplicant-wired@<interface>

# Run manually with debug
sudo wpa_supplicant \
    -c /etc/wpa_supplicant/wpa_supplicant-wired-<interface>.conf \
    -i <interface> \
    -D wired \
    -dd

# When done, restart service
sudo systemctl start wpa_supplicant-wired@<interface>

Persistent Debug Logging

Create override for persistent debug:

sudo systemctl edit wpa_supplicant-wired@<interface>

Add:

[Service]
ExecStart=
ExecStart=/usr/bin/wpa_supplicant \
    -c /etc/wpa_supplicant/wpa_supplicant-wired-%I.conf \
    -i %I \
    -D wired \
    -dd

Boot Order

Network Dependencies

The correct boot sequence:

  1. sys-subsystem-net-devices-%i.device — interface exists

  2. wpa_supplicant-wired@%i.service — authenticates

  3. dhcpcd@%i.service or NetworkManager — gets IP

  4. network-online.target — network fully ready

Verify Order

# Show service dependencies
systemctl list-dependencies wpa_supplicant-wired@<interface>

# Show what requires this service
systemctl list-dependencies --reverse wpa_supplicant-wired@<interface>

Handling Failures

Automatic Restart

The service template includes:

Restart=on-failure
RestartSec=5

This restarts wpa_supplicant 5 seconds after failure.

Custom Failure Actions

For notifications on failure, create /etc/systemd/system/[email protected]/notify.conf:

[Unit]
OnFailure=wpa-failure-notify@%i.service

With corresponding notification service:

# /etc/systemd/system/[email protected]
[Unit]
Description=Notify on wpa_supplicant failure for %I

[Service]
Type=oneshot
ExecStart=/usr/local/bin/notify-failure.sh wpa_supplicant %I

Multiple Interfaces

For systems with multiple wired interfaces requiring 802.1X:

# Create config for each interface
sudo cp /etc/wpa_supplicant/wpa_supplicant-wired-eth0.conf \
       /etc/wpa_supplicant/wpa_supplicant-wired-eth1.conf

# Enable service for each
sudo systemctl enable wpa_supplicant-wired@eth0
sudo systemctl enable wpa_supplicant-wired@eth1

# Start all
sudo systemctl start wpa_supplicant-wired@eth0
sudo systemctl start wpa_supplicant-wired@eth1

Disable Default Services

Some distributions ship default wpa_supplicant services. Disable conflicts:

# Check for default services
systemctl list-unit-files 'wpa_supplicant*'

# Disable conflicting services
sudo systemctl disable wpa_supplicant.service
sudo systemctl mask wpa_supplicant.service

# Disable iwd (conflicts with wpa_supplicant)
sudo systemctl disable iwd
sudo systemctl mask iwd

Verification Checklist

  • Service template created at /etc/systemd/system/[email protected]

  • Configuration file exists at /etc/wpa_supplicant/wpa_supplicant-wired-.conf

  • Service enabled: systemctl is-enabled wpa_supplicant-wired@

  • Service running: systemctl is-active wpa_supplicant-wired@

  • No conflicting services (iwd masked)

  • DHCP integration configured

  • Logs show successful authentication