This post has a nice solution for using GPIO (and I2C) without root-privileges. This is useful if you're running an (web) app in a virtual environment as some ve-user, so as to shield off your whole Pi from that ve-user. But let's not digress.

The solution is basically that your ve-user must be member of gpio, and that root:gpio (not root:root) owns /dev/gpio.

pi@RPi2a ~ $ ls -l /dev/gpiomem  
crw------- 1 root root 245, 0 Jan  1  1970 /dev/gpiomem   # BEFORE  
pi@RPi2a ~ $ sudo chown root.gpio /dev/gpiomem && sudo chmod g+rw /dev/gpiomem  
pi@RPi2a ~ $ ls -l /dev/gpiomem  
crw-rw---- 1 root gpio 245, 0 Jan  1  1970 /dev/gpiomem   # AFTER  

The thing is: after a reboot, it's all back to the BEFORE situation. So how do you make it stick? Googling some, I found it's ruled by /etc/udev/rules.d/99-com.rules.
I guess (correctly?) root executes this at boot time. In it, there is:

PROGRAM="/bin/sh -c 'chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio; chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio'"  
SUBSYSTEM=="input", GROUP="input", MODE="0660"  
SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660"  
SUBSYSTEM=="spidev", GROUP="spi", MODE="0660"  

So I inserted this into the first line, just before the closing '":

; chown root.gpio /dev/gpiomem && chmod g+rw /dev/gpiomem  

But that didn't work, nor did this variation: chown root:gpio /dev/gpiomem && chmod 660 /dev/gpiomem). So I've added that line to root's crontab (sudo crontab -e) like this:

@reboot chown root.gpio /dev/gpiomem && chmod g+rw /dev/gpiomem  

This works, but it looks to me like fighting the symptom rather than the cause. So I tried to find what resets the ownership on /dev/gpiomem:

sudo grep -rnw /etc/ -e "/dev/gpio"  

to no avail. Grepping the entire disk (/ instead of /etc/udev) breaks with grep: memory exhausted. It's a 256 MB Pi. I'm using, and want to stick to, Adafruit's Wheezy.

So the question is: what, where, how & why manipulates /dev/gpiomem?

  • Why do you want to stick to Adafruit's distribution? I didn't realise it still existed.
    – joan
    Jan 11, 2017 at 15:01
  • @joan I think the TFT driver that was added to the mainline kernel doesn't cover some of their smaller displays.
    – goldilocks
    Jan 11, 2017 at 15:36
  • @joan I started out with Adafruit's Wheezy because at the time, it had a bunch of stuff pre-installed (i2c, smbus, and more) that 'normal' Wheezy had not. Later on, I had to work around out-of-memory errors compiling lxml, which I need for my project. I'm hesitating to move to Jessie, because I don't want to go through all those motions again. That's the reason.
    – RolfBly
    Jan 11, 2017 at 15:54
  • If you have a spare SD card I'd try a mainstream distribution. Adafruit's is now a dead end.
    – joan
    Jan 11, 2017 at 16:09
  • @joan It's just Wheezy and some. Still updates and upgrades. I do see advantages in Jessie, but there are some 30 non-standard libraries, packages and countless evenings of configuration and tweaking in my current set-up. That I don't want to do all over again. With a new Pi, I certainly will, tho'.
    – RolfBly
    Jan 11, 2017 at 16:19

1 Answer 1


what, where, how & why manipulates /dev/gpiomem?

Anything that has the correct permissions, so without the udev adjustment, any privileged process.

The adjustment is made by udevd, an init service daemon.

So I tried two add this to the first line

Beware those .rules files are not shell scripts. However, you can change this:

PROGRAM="/bin/sh -c 'chown -R root:gpio ....`

To the path to a shell script:


Which will make things a little tidier. I just made that path up (there is no /etc/udev/local_scripts directory); you can put it anywhere, but you must include an appropriate shebang and set $PATH in the script:



However, the reason this will not work:

chown root.gpio /dev/gpiomem && chmod g+rw /dev/gpiomem

Is because when the PROGRAM= entry is run, the device node does not exist yet (see here, and also scroll up to see the previous section). But, as per that, what's indicated by RUN is executed after the device node is created (also note "PROGRAM is used for running programs which produce device names (and they shouldn't do anything other than that)"). So you could instead try:

RUN+="/bin/sh -c 'chown root.gpio /dev/gpiomem && chmod g+rw /dev/gpiomem'"

Or, as just explained, put whatever you want to do in a script and execute it via the same parameter.

  • Thanks! I've corrected and (hopefully) clarified the question. Do I understand right that (1) the PROGRAM=.. clause sets the device node up, and (2) it gets root:root because that's simply what the setting up does?
    – RolfBly
    Jan 11, 2017 at 15:45
  • The whole thing doesn't actually need to exist; if not, the kernel will create the node anyway with whatever default settings it uses (almost certainly, root access only). The point of udev is to inject changes, etc., into the process. So you can do stuff before the node is created via PROGRAM, including control the name of the node (as explained in that link), and after via RUN.
    – goldilocks
    Jan 11, 2017 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.