Is it impossible for now to run Wireguard VPN server container on BalenaOS?

I may be wrong, but it seems that for now it is impossible to run wireguard container provided by because of some missing linux kernel headers in balenaOS.

I am running balena-pihole project on Raspberry Pi 3 (64bit) whith Adafruit PiTFT 2.8" using balenaOS 2.38.0+rev1 because of this and this issue, which does not allow to show the PADD on the higher BalenaOS versions for some reason.

Recently I have decided to add Wireguard to this setup using the mentioned above container, and found out that the container can not create the network interface saying the following:

16.06.20 20:47:34 (+0300)  wireguard  No kernel headers found in the Ubuntu or Debian repos!! Will try the headers from host (if mapped), may or may not work


16.06.20 18:33:14 (+0300)  wireguard  [#] ip link add wg0 type wireguard
16.06.20 18:33:14 (+0300)  wireguard  RTNETLINK answers: Operation not supported
16.06.20 18:33:14 (+0300)  wireguard  Unable to access interface: Protocol not supported
16.06.20 18:33:14 (+0300)  wireguard  [#] ip link delete dev wg0
16.06.20 18:33:14 (+0300)  wireguard  Cannot find device "wg0"

I tried doing it manually with the same results. Fast google-fu, lead me here which hints (but may not be right), that newer kernel (>4.17) should work.

I alse tried the newest atm balenaOS 2.51.1+rev1 (32bit), which has the kernel 4.19.75, but the errors are still the same and the wireguard container still can not create the network interface needed…

Anyway, because PiTFT does not work with Balena versions higher then 2.38.1(the issue, mentioned above is still open) I would not want to use higher version, as I love the look of my PADD…

Therefore do you guys have any ideas how can I install linux kernel headers on my 2.38.1 BalenaOS, needed to successfully run Wireguard VPN? I know, I could just buy another device and use PiVPN project, which now supports Wireguard, but I love the idea of Balena and containerized application setup, so posting this here, hoping for your expertise.


We have a project template for compiling kernel drivers and loading them from a container - 6. It compiles a simple “hello world” type of module, but you can adapt it for usage with Wireguard.

As for configuring the networking interface, you will probably need to run the container that sets up Wireguard in privileged mode and with network mode set to “host”.

Of course I am doing this…

  version: '2.1'


      image: linuxserver/wireguard
      container_name: wireguard
      - 'NET_ADMIN'
      - 'SYS_MODULE'
        - 'PUID=1000'
        - 'PGID=1000'
        - 'TZ=UTC'
        - '' #optional
        - 'SERVERPORT=51820' #optional
        - 'PEERS=1' #optional
        - 'PEERDNS=auto' #optional
        - 'INTERNAL_SUBNET=' #optional
        - 'wireguard_config:/config'
        - 'wireguard_lib_modules:/lib/modules'
        - '51820:51820/udp'
        - 'net.ipv4.conf.all.src_valid_mark=1'
      restart: unless-stopped
      network_mode: host

but changing cap_add to priviledged: true changed nothing…
Obviously the problem is with the lack of needed linux kernel headers, which I have no clue how to add manually to my BalenaOS… Is there any detailed info about this (Although, I believe it is not supposed to be that difficult…) Any ideas why them should not be included in the BalenaOS by default?

I mean seriously? No one runs wireguard on balena?

Found Wireguard client in container?, which basically contains the answer above (obviously copied…) So I guess the right (and the most efficient) way to run Wireguard on raspberry pi is using PiVPN project… :frowning: That’s unfortunate…

needed linux kernel headers

The script in the repo linked above has a step where is pulls in the kernel headers for the given balenaOS version. It uses the AWS CLI to interrogate the bucket and then pulls down the archive. You should be able to do the same, or reverse it to get a link to the archive manually. You should then make a multistage build Dockerfile to first pull the headers and build the module, then copy from that stage into your final image just the module without the build tools/headers etc.

Any ideas why them should not be included in the BalenaOS by default?

Size. BalenaOS is built for embedded/small-spec machines, so wasting space on headers which aren’t needed at runtime wouldn’t make sense.

I mean seriously? No one runs wireguard on balena?

Not that I am aware of. I appreciate your frustration but let’s try and keep it constructive :+1:

Wow, thanks, that’s something… Sorry for being stupid, I am not a Docker pro, but It’s still not clear…

Let’s summarize what we’ve got here:

First Stage of my Dockerfile should be based on balenalib/%%BALENA_MACHINE_NAME%%-debian (so it pulls the headers and builds the needed kernel module). I guess HERE they explain where to get the code needed and how to build it.

Second Stage should be based on official linuxserver/wireguard docker image, but will also contain the needed by wireguard linux kernel module (I will copy it from shared filesystem between docker stages during second stage execution)? Therefore, the kernel module will be located in the resulted wireguard container instead of Host OS? Will it work at all?

Please let me know if I get it wrong or right.

Thank you

Hi there – thanks for your question. The procedure you’ve outlined is broadly correct, and you can read more about multi-stage docker builds at As you say, the intent is to copy the kernel module to the second stage container (in your case, built on linuxserver/wireguard). This is the same procedure that’s used to support things like different Raspberry Pi Hats, so it should work here as well.

Hope that helps, and please let us know how you get on!

All the best,

Ok, so I tried to figure this out, and this is what I ended up with so far (and honestly, I doubt that it’s gonna go further without other people’s help, lol)…


FROM balenalib/%%BALENA_MACHINE_NAME%%-debian

# Shouldn't this be ARG though? (Not sure)
ENV VERSION 'balenaOS 2.38.0+rev1'

WORKDIR /usr/src/app

RUN apt-get update && apt-get install -y curl wget build-essential \
    libelf-dev awscli bc flex libssl-dev python bison git pkg-config


# get wireguard kernel module source code (as described here
RUN git clone

      --device %%BALENA_MACHINE_NAME%% \
      --os-version "$VERSION" \
      --src wireguard-linux-compat/src

FROM linuxserver/wireguard
COPY --from=0 "/usr/src/app/wireguard-linux-compat/src/${AND_WHAT_DO_I_EXPECT_TO_COPY?}" /lib/modules/

Even if I knew the last piece of puzzle, which is this variable: "${AND_WHAT_DO_I_EXPECT_TO_COPY?}", I doubt it would work, as the wireguard instruction tells to install the module this way:

$ make -C wireguard-linux-compat/src -j$(nproc)
$ sudo make -C wireguard-linux-compat/src install

But I am trying the blackbox(to me lol) called

The problem here is that I honestly have never built any kernel modules, no clue what this kernel module is. Is it just a binary? Where the makefile will put it then? Does the makefile do anything else for it to work… I think this “simplistic wireguard VPN” setup (as it’s being advertised) should definitely not be such a hassle (hehe)…

Just leaving this here in case me, or more likely, someone smarter, becomes bored or inspired one day to finish this…

I found a working fork for raspberry pi 3/4 (and I don’t think I see the author’s name in this thread yet).

I’m working on something similar and will post it once I finish.

As promised, here’s my working project with links and acknowledgements for the scripts I borrowed.

1 Like