How to do systemd like ExecStartPost in procd?

I want to do a couple things after the main command executes:

  1. set up some iptables rules
  2. change some routing info with ip
  3. change some other service configs that are conflicting

What's the correct place to run these commands?

My first thought is to directly run these after procd_close_instance, but then I realize procd_set_param command is probably async.

I tried searching in the openwrt source, but couldn't find useful example that illustrates this use case. It's be great if someone could point me in the right direction.

BTW, once the service is stopped, I'd like to revert the config changes I've made to other services to their original values. Does uci or procd scripts provide any tools to help with that?

1 Like

I half-assed it by creating two init scripts with different start value, one for the main program, the other post stuff. It works, but brittlely.

I check both OpenVPN and StrongSwan, which are very similar in nature to my program, on how they package. It seems they don’t deal with iptables at all. Users are expected to set up their own firewall rules.

Is that the norm in OpenWRT? Am I on the wrong path?

Not answering your initial question but both OpenVPN and Strongswan use hooks that you can customise to set up your own routes/firewall when connections are established and closed.

OpenVPN uses route-up and route-pre-down hooks which call whatever script you want (

Strongswan uses an updown script (

1 Like

If what you are looking for is to run specific commands when an interface comes up/down (managed by a third party tool which doesn't have hooks), you could look into triggering your scripts with something like:

1 Like

Thanks for the heads-up.

Unfortunately my program doesn't support ifup/ifdown script, but indeed it would have solved the problem perfectly if it did. Maybe I should submit a feature request to the author.

As for procd_add_interface_trigger, I tried it, but it seems to only take effect when the interface is specified in /etc/config/network. In my case, the program creates the interface automatically, and with this in the init script

service_triggers() {
    procd_add_interface_trigger "interface.*" ifname /bin/sh -c "/usr/bin/env >/tmp/iflog"

where ifname was the interface name, the command didn't seem to be called at all, yet ifname was in ip link.

Maybe I need to register the program a custom protocol and then create the interface in /etc/config/network?

My improved approach is to create a subshell before the program runs, and wait for the interface to be up in that subshell, after which iptables and stuff are called. I was able to use only one init script with this approach.