Understanding permissions
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.
- How to fix permissions on files/directories
- How to fix permissions on USB and/or serial devices
- How to fix permissions when binding to a network port
- More details about which groups can do what
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.
- modifying the configuration file and skins
- installing and removing extensions
- reading the database
- ownership of the files and directories for reports
- access to the log files
How does an unprivileged user get permission to do system administration things? There are two approaches:
- temporary escalation using
sudo
, or - 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.
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
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
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'
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.
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
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
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
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.
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
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
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
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 toweewxd
- use
authbind
to letweewx:weewx
bind to port 80 - use
CAP_NET_BIND_SERVICE
- use
iptables
to redirect traffic from port 80 to a high port - run
weewxd
asroot:root
- listen on a higher port (this only works if you can change the port on whatever is sending data)
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;
}
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
Stack overflow and superuser have details about CAP_NET_BIND_SERVICE:
https://superuser.com/questions/710253/allow-non-root-process-to-bind-to-port-80-and-443
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
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