Skip to content

Understanding permissions

vinceskahan edited this page Mar 7, 2024 · 60 revisions

Working with permissions in a Unix environment

This is an introduction to how permissions work in a Unix environment, with functional examples that you might encounter with WeeWX.

Sometimes permissions and/or ownership get mixed up, typically when attaching USB and/or serial devices, upgrading from a pre-V5 installation, or when you copy files or backups from one machine to another.

There are two general classes of users in a Unix environment: (1) privileged and (2) unprivileged. A privileged user has the ability to do things to the system that affect how the system operates and could break the system if applied incorrectly. For example, administrative privileges are typically required to upgrade the operating system or to install system software. An unprivileged user can run software and save data, but only in ways that would not break the system. Usually you login to a computer as an unprivileged user, then you only escalate privilege when you do specific, administrative activities. This helps prevent silly mistakes, and it provides a layer of protection against malicious behavior.

For each file and directory, there is a set of permissions that define who can read and write that file or directory. The permissions are defined by owner, group, and world. This lets you say "only bill can write to file X, but anyone can read it", or "anyone in the weewx group can write to this directory, and no one else can even read it".

Since USB and serial devices are also just files (a special kind of file, but still just files), the same permissions system applies to them.

The following sections explain how permissions affect different parts of WeeWX.

sudo vs su

How does an unprivileged user get permission to do system administration things? There are two approaches:

  1. temporary escalation using sudo, or
  2. extended escalation by becoming root.

For temporary escalation, prefix a command with sudo. For example, instead of nano /etc/weewx/weewx.conf you would do sudo nano /etc/weewx/weewx.conf. For extended escalation, you login as the root user. For example, you can become root by doing su or su --login.

Which approach is better? It depends. See the Debian article about sudo for pros and cons of each approach.

Beware that sudo may not be on your system, depending on how you installed/configured the operating system. If there is no sudo, use your system's package manager to install it.

Note that BSD systems have the command doas as well as or instead of sudo, depending on how you installed/configured the operating system.

Privilege escalation usually affects you when you need to view or modify a file. It will also affect you when you try to start and stop certain processes.

System files and directories are usually protected, so that only users with administrative privileges can modify them. In some cases, administrative privileges are necessary even to view them.

Files and directories in your HOME directory do not have these restrictions.

Here are some situations where permissions matter when you are using WeeWX.

The WeeWX user

Before V5, WeeWX ran as the user root. When WeeWX runs as the root user, runtime permissions are not an issue — root has permission to do anything. However, any user other than root would have to become root in order to make changes to the configuration.

Starting with V5, WeeWX runs as a non-root user, either the dedicated weewx user (DEB/RPM installs), or the user who installed WeeWX (pip installs). Running as a non-root user is considered best practice — it minimizes the damage to the system should something go awry, and it is more secure against nefarious attacks. However, it requires that permissions are configured for reading data from the weather station (typically USB or serial devices, or perhaps network interfaces), saving data to the database, and saving data to the files and directories that constitute the reports.

You can see who is running the weewxd process using ps. In this example, the weewxd process is running as the user root.

$ ps aux | grep weewxd
root      3670  8.5  3.6  62528 34728 ?        Sl    2023 5738:19 /usr/bin/python /opt/weewx/bin/weewxd --daemon --log-label weewx-gem --pidfile=/var/run/weewx-gem.pid /etc/weewx/gem.conf

On Linux systems with systemd, the WeeWX unit file determines which user runs weewxd. You can check it like this:

# for a DEB/RPM installation
grep User /usr/lib/systemd/system/weewx.service
# for a pip installation
grep User /etc/systemd/system/weewx.service

For DEB/RPM installations, the WeeWX configuration files and skins are owned by the weewx user, and the weewxd application runs as the weewx user. The files are also in a group called weewx, so anyone in the weewx group will also have permission to modify the files. For DEB/RPM installations, the installer puts you into the weewx group. When you are in the weewx group, you do not have to sudo to modify the WeeWX files in /etc/weewx, but you do need sudo to start/stop the weewxd daemon.

Verify that you are in the weewx group using the groups command:

groups

If somehow you were not added to the weewx group, you can add yourself. Note that you must create a new shell/terminal to see the group change. Or you can log out then log back in.

sudo usermod -a -G weewx $USER

Modifying a configuration file or skin

If you installed WeeWX using pip, then all of the station settings and skins should be owned by you, so you can simply edit them:

nano ~/weewx-data/weewx.conf

If you installed WeeWX from a DEB/RPM package, then the station settings and skins are owned by the weewx user. As long as you are in the weewx group, you can modify them:

nano /etc/weewx/weewx.conf

Installing an extension

You must have read/write permissions on the WeeWX "user" directory in order to install or remove extensions. If you installed using pip, then you should be the owner of the weewx-data directory, so you can just invoke weectl extension and everything should work.

$ weectl extension install /var/tmp/gw1000-0.3.1.tar.gz
Request to install '/var/tmp/gw1000-0.3.1.tar.gz'
Extracting from tar archive /var/tmp/gw1000-0.3.1.tar.gz
Saving installer file to /home/jackhandy/weewx-data/bin/user/installer/GW1000
Saved configuration dictionary. Backup copy at /home/jackhandy/weewx-data/weewx.conf.20210426101025
Finished installing extension '/var/tmp/gw1000-0.3.1.tar.gz'

If you installed using a DEB or RPM package, then the user directory will be owned by weewx. The installer should have put you into the weewx group, so you can just install the extension.

If somehow you are not in the weewx group, or the permissions are set incorrectly, you will see permission failure:

$ weectl extension install /var/tmp/gw1000-0.3.1.tar.gz
Request to install '/var/tmp/gw1000-0.3.1.tar.gz'
Extracting from tar archive /var/tmp/gw1000-0.3.1.tar.gz
Traceback (most recent call last):
   [...]
PermissionError: [Errno 13] Permission denied: '/etc/weewx/bin/user/gw1000.py'

Reading/writing to a database

In a default configuration, the WeeWX database is world-readable, but writable only by the owner. So you should be able to read the WeeWX database no matter how you installed WeeWX.

# pip install
sqlite3 ~/weewx-data/archive/weewx.sdb

# deb/rpm install
sqlite3 /var/lib/weewx/weewx.sdb

If you see messages about "database locked", then the problem is probably not because of permissions or ownership.

Writing reports

The WeeWX process must have write permission on the report directory, HTML_ROOT. If you put HTML_ROOT in a location other than the default, you must ensure that the user running WeeWX has write permission to that location. If you run a web server on the same machine that WeeWX saves reports, then the contents of HTML_ROOT must be readable to the web server process.

For DEB/RPM installations, the default HTML_ROOT directory is /var/www/html/weewx. This directory will be created with correct permissions when you install WeeWX. The files and directories should be owned by weewx:weewx and should be read/write for owner and group, and read-only for world.

For pip installations, the HTML_ROOT directory is typically weewx-data/public_html in the home directory of the user running WeeWX.

If you see "no permission" messages in the log when WeeWX is generating reports, check the directory and file permissions. If the user running WeeWX is not the owner and not in a file/directory group with write permissions, then it will not be able to write reports.

ls -la /var/www/html/weewx

Viewing the log

Most systems require administrative privileges to view the system log, so you must use sudo or become root before you can view the log messages.

# systems that use syslog
sudo tail /var/log/syslog
sudo tail /var/log/messages

# systems that use systemd-journald
sudo journalctl -u weewx

How to fix file permissions

The user running weewxd must have permissions to read and write the database files (for sqlite) and the report files. Files should be 664 and directories should be 775. The owner should be the user running weewxd.

The following instructions are for user weewx, configuration directory WEEWX_ROOT of /etc/weewx, report directory HTML_ROOT of /var/www/html/weewx, and database directory SQLITE_ROOT of /var/lib/weewx. This is typical for a DEB/RPM installation.

For the WEEWX_ROOT directory (configuration file, skins, and other extensions):

# set the permissions
sudo find /etc/weewx -type d -exec chmod 2775 {} \;
sudo find /etc/weewx -type f -exec chmod 664 {} \;
# set the owner and group
sudo chown -R weewx /etc/weewx
sudo chgrp -R weewx /etc/weewx

For the HTML_ROOT directory (location of reports):

# set the permissions
sudo find /var/www/html/weewx -type d -exec chmod 2775 {} \;
sudo find /var/www/html/weewx -type f -exec chmod 664 {} \;
# set the owner and group
sudo chown -R weewx /var/www/html/weewx
sudo chgrp -R weewx /var/www/html/weewx

For the SQLITE_ROOT directory (location of sqlite databases):

# set the permissions
sudo chmod 2775 /var/lib/weewx
sudo chmod 644 /var/lib/weewx/*.sdb
# set the owner and group
sudo chown -R weewx /var/lib/weewx
sudo chgrp -R weewx /var/lib/weewx

How to fix device permissions

First of all, most USB and serial devices are accessible to only one process at a time. For example, if weewxd is running and communicating with the device /dev/ttyUSB0, then you will not be able to read/write to the device /dev/ttyUSB0 even if you have sufficient permissions.

By default, only a privileged user can write to USB or serial devices. If you want someone other than root to read/write a USB or serial device, then you must change the permissions on that device. Usually it is best to define read/write access to a group, then put individual users into that group to grant them permission.

Linux has a mechanism called udev that will automatically detect certain types of devices, and automatically apply permissions to those devices. There are udev rules for USB and serial devices included with WeeWX. These are installed as /usr/lib/udev/rules.d/60-weewx.rules for a DEB/RPM installation, or /etc/udev/rules.d/60-weewx.rules for a pip installation. If you are using a USB or serial device that is not in the WeeWX core, you will probably have to add a udev rule for your device.

Changes to group membership require a logout/login, or a restart of the WeeWX daemon.

Changes to the udev rules are recognized immediately on modern systems, but on older systems you might have to unplug-then-replug the device.

Example: install a udev rule

For the WH23xx weather station, a USB-connected device with idVendor=10c4, idProduct=8486, put this rule in /etc/udev/rules.d/60-weewx.rules to give permission to the weewx user :

SUBSYSTEM=="usb",ATTRS{idVendor}=="10c4",ATTRS{idProduct}=="8468",MODE="0664",GROUP="weewx"

Thanks to WeeWX user Michael Waldor

Example: add the weewx user to group in a udev rule

The SDR (software-defined radio) software, rtl-sdr, typically installs its udev rules with permissions granted to a dedicated group. This might be plugdev or plughw - look at the rules in /etc/udev/rules.d to find out. In this case, the rules are installed, but you must put the user who runs weewxd into the group specified in the rules.

This is one of the udev rules from the file /etc/udev/rules.d/rtl-sdr.rules that was installed by the rtl-sdr package when compiled from source. It defines read/write permissions for anyone in the plugdev group.

SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", ENV{ID_SOFTWARE_RADIO}="1", MODE="0660", GROUP="plugdev"

Use usermod to grant permissions. For example, this would grant permissions by putting the weewx user into the group plugdev:

sudo usermod -aG plugdev weewx

Example: add the weewx user to group defined on a device

The serial port on many systems is configured so that anyone in the dialout group can read/write the serial ports. So if you use a weather station connected to a serial port (e.g., a Davis station connected by serial or USB-to-serial), you must ensure that the user running WeeWX is in the group that can read/write the serial port.

There are a few names you might encounter for serial ports, including:

  • /dev/ttyUSB0 - serial port when using a USB-to-serial adapter on a Linux system
  • /dev/ttyS0 - first physical serial port on a x86-based Linux system
  • /dev/ttyAMA0 - first physical serial port on an ARM-based Linux system
  • /dev/cuaU0.0 - serial port on a BSD system
  • /dev/tty.PL2303-* - USB-to-serial adapter on a macOS system

You can check the device permissions using the ls command:

ls -l /dev/ttyS0
crw-rw---- 1 root dialout 4, 64 Dec 31 11:51 /dev/ttyS0

Use usermod to grant permissions. For example, this would grant permissions by putting the weewx user into the group dialout:

sudo usermod -aG dialout weewx

How to fix network permissions

If you use the interceptor driver to listen on port 80, you might have problems when you run weewxd as a non-root user. This is because only root is allowed to bind to ports lower than 1024.

For Linux systems, your options include:

  • run nginx with a reverse proxy rule to send traffic to weewxd
  • use authbind to let weewx:weewx bind to port 80
  • use CAP_NET_BIND_SERVICE
  • use iptables to redirect traffic from port 80 to a high port
  • run weewxd as root:root
  • listen on a higher port (this only works if you can change the port on whatever is sending data)

reverse proxy

The reverse proxy is perhaps the most robust approach. If you make interceptor listen on port 8080, then install a reverse proxy configuration so that requests on port 80 are redirected to port 8080. The reverse proxy configuration for nginx looks something like this:

location / { 
  proxy_set_header X-Is-Reverse-Proxy "true";
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-Host $host;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $remote_addr;
  proxy_pass http://localhost:8080;
}

authbind

The following recipe will permit the weewxd process to listen on port 80.

Thanks to WeeWX user Graham Knights

# Install authbind
sudo apt install authbind

# Configure authbind to allow weewx
sudo touch /etc/authbind/byport/80
sudo chown weewx /etc/authbind/byport/80
sudo chmod 755 /etc/authbind/byport/80

# Modifiy the systemd unit file - add 'authbind --deep' before 'weewxd'
ExecStart=authbind --deep weewxd /etc/weewx/weewx.conf

# Reload the systemd configuration then restart weewxd
sudo systemctl daemon-reload
sudo systemctl stop weewx
sudo systemctl start weewx

Here is the man page for authbind:

https://manpages.ubuntu.com/manpages/noble/en/man1/authbind.1.html

CAP_NET_BIND_SERVICE

Stack overflow and superuser have details about CAP_NET_BIND_SERVICE:

https://stackoverflow.com/questions/413807/is-there-a-way-for-non-root-processes-to-bind-to-privileged-ports-on-linux

https://superuser.com/questions/710253/allow-non-root-process-to-bind-to-port-80-and-443

re-routing using iptables

Serverfault shows how to do the iptables redirect:

https://serverfault.com/questions/112795/how-to-run-a-server-on-port-80-as-a-normal-user-on-linux

More details about which groups can do what

It is not always self-evident which groups the weewx user needs to be in and the answer might vary slightly among the possible operating systems and versions. Depending on your hardware configuration and connected devices, you might need to provide the weewx user membership in one or more of the following groups:

  • adm: allows use of the command journalctl to read systemd log files as well being able to access log files under /var/log

  • dialout: allows access to serial/usb devices, for example a Davis Datalogger connected via USB or serial interface

  • plugdev: allows access to 'pluggable' external storage devices, such as external USB disks

  • gpio: allows access to pi-specific GPIO pin type interfaces

  • i2c: similarly for the I2C bus on a pi

  • spi: similarly for the SPI bus on a pi

Just as a point of reference, the default 'pi' user is a member of the following groups in a recent raspi os:

  • pi adm dialout cdrom sudo audio video plugdev games users input render netdev gpio i2c spi
Clone this wiki locally