hostapd on two interfaces (two configuration files)

I have two wireless interfaces and I want to run different APs on each. (Neither hardware supports multiple SSIDs.)

I have a .conf file for each interface. How do I get hostapd to use them both automatically?

This works fine:

# hostapd -dd /etd/hostapd/hostapd.wlan0.conf /etc/hostapd/hostapd.wlan1.conf

The problem is getting it to work automatically.

One claim is to set in /etc/default/hostapd

DAEMON_CONF="/etc/hostapd/hostapd.wlan0.conf /etc/hostapd/hostapd.wlan1.conf"

but this doesn’t work because the whole string is interpreted as being one file — which doesn’t exist.

I see this is used by /usr/lib/systemd/system/hostapd.service as

ExecStart=/usr/sbin/hostapd -B -P /run/hostapd.pid -B $DAEMON_OPTS ${DAEMON_CONF}

However, I also see something called /usr/lib/systemd/system/hostapd@.service which does something different:

ExecStart=/usr/sbin/hostapd -B -P /run/hostapd.%i.pid $DAEMON_OPTS /etc/hostapd/%i.conf

(what does %i mean?)
However, systemctl seems only to know about hostapd and not about hostapd@.

I have edited /usr/lib/systemd/system/hostapd.service to hard-code the two configuration files.

After editing it appears to be necessary to run

# systemctl daemon-reload

Seems like an unpleasant hack, but it works.

Answered By: Richard Barraclough

You were almost there at the end of the question. %i is used for instanced services. Here’s an excerpt of the role of instances described in the systemd.unit(5):

Unit files can be parameterized by a single argument called the
"instance name". The unit is then constructed based on a "template
file" which serves as the definition of multiple services or other
units. A template unit must have a single "@" at the end of the name
(right before the type suffix). The name of the full unit is formed by
inserting the instance name between "@" and the unit type suffix. In
the unit file itself, the instance parameter may be referred to using
"%i" and other specifiers, see below.

Or in the specifiers list:

├─────────┼───────────────┼───────────────────────────────────────────────────┤
│         │               │For instantiated units this is the string between  │
│"%i"     │Instance name  │the first "@" character and the type suffix. Empty │
│         │               │for non-instantiated units.                        │
├─────────┼───────────────┼───────────────────────────────────────────────────┤

Using instanced services will run one independent hostapd daemon per interface. This allows for example to alter or kill one instance with the assurance the other instance, and thus the other interface won’t be affected.

You can do this for using instances:

  • revert to default settings everywhere and disable and stop hostapd.service

  • rename your configurations to accommodate an unmodified hostapd instanced service which expects with %i.conf only the interface name followed by .conf:

    mv -i /etd/hostapd/hostapd.wlan0.conf /etd/hostapd/wlan0.conf
    mv -i /etd/hostapd/hostapd.wlan1.conf /etd/hostapd/wlan1.conf
    
  • use the instanced version of the hostapd service, distinguished by the @ character and which is configured differently from the normal instance as already written in OP. Once per interface:

    systemctl enable --now hostapd@wlan0
    systemctl enable --now hostapd@wlan1
    

In the end the daemon will be running twice as these:

/usr/sbin/hostapd -B -P /run/hostapd.wlan0.pid   /etc/hostapd/wlan0.conf
/usr/sbin/hostapd -B -P /run/hostapd.wlan1.pid   /etc/hostapd/wlan1.conf

(unless there was something in $DAEMON_OPTS).

Answered By: A.B
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.