Satnogs-client docker can't see any hardware devices

Edit: I’m seeing now in the Wiki that the new software doesn’t support serial device access from within the container. I’ll have to try the workarounds I suppose.

So I’ve run the satnogs client install and satnogs-setup on a Raspberry pi 4 without any issues following the instructions here: Raspberry Pi - SatNOGS Wiki.

dev@raspberrypi:~ $ sudo docker ps -f 'name=^satnogs_' --format "table {{.Names}}\t{{.Status}}"
NAMES                    STATUS
satnogs_satnogs-client   Up 2 hours
satnogs_rigctld          Up 17 hours

I can see my site online and I can schedule observations just fine. However, the docker container can’t access any of my devices. It’s not an issue with the host setup:

dev@raspberrypi:~ $ hackrf_info
hackrf_info version: 2022.09.1
libhackrf version: 2022.09.1 (0.7)
Found HackRF
Index: 0
Serial number: 0000000000000000088869dc2940ba1b
Board ID Number: 2 (HackRF One)
Firmware Version: 2021.03.1 (API:1.04)
Part ID Number: 0xa000cb3c 0x006a4757
[ 3092.572214] usb 1-1.4: new full-speed USB device number 6 using xhci_hcd
[ 3092.676419] usb 1-1.4: New USB device found, idVendor=0403, idProduct=6001, bcdDevice= 6.00
[ 3092.676429] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 3092.676434] usb 1-1.4: Product: FT232R USB UART
[ 3092.676437] usb 1-1.4: Manufacturer: FTDI
[ 3092.676441] usb 1-1.4: SerialNumber: AB0KPC11
[ 3092.683051] ftdi_sio 1-1.4:1.0: FTDI USB Serial Device converter detected
[ 3092.683125] usb 1-1.4: Detected FT232R
[ 3092.687198] usb 1-1.4: FTDI USB Serial Device converter now attached to ttyUSB0
dev@raspberrypi:~ $ ls /dev/ttyUSB-rotator
/dev/ttyUSB-rotator

As you can see, my HackRF and rotator interfaces are detected just fine. I can also run rotctld and control it with rotctl or with gpredict from another computer no issue. However, during an observation, no devices:

INFO     satnogsclient.scheduler.tasks   Received job for observation 11929961, starting at 2025-07-10T17:44:04+00:00
INFO     satnogsclient.observer.observer Begin observation 11929961 ...
rot_init called
initrots4_easycomm called
rot_register (201)
rot_register (202)
rot_register (204)
rot_open called
serial_open called
serial_open: Unable to open /dev/ttyUSB-rotator - No such file or directory
rot_get_position called
rot_set_position called az=0.33 el=8.07
rig_init: rig does not have rx_range!!
network_open: hoststr=rigctld, portstr=4532
INFO     satnogsclient.observer.observer Start gnuradio thread.
Traceback (most recent call last):
  File "/usr/bin/satnogs_fm.py", line 476, in <module>
    main()
  File "/usr/bin/satnogs_fm.py", line 459, in main
    tb = top_block_cls(antenna=options.antenna, bb_freq=options.bb_freq, bw=options.bw, dc_removal=options.dc_removal, decoded_data_file_path=options.decoded_data_file_path, dev_args=options.dev_args, deviation=options.deviation, doppler_correction_per_sec=options.doppler_correction_per_sec, enable_iq_dump=options.enable_iq_dump, file_path=options.file_path, gain=options.gain, gain_mode=options.gain_mode, iq_file_path=options.iq_file_path, lo_offset=options.lo_offset, max_modulation_freq=options.max_modulation_freq, other_settings=options.other_settings, ppm=options.ppm, rigctl_host=options.rigctl_host, rigctl_port=options.rigctl_port, rx_freq=options.rx_freq, samp_rate_rx=options.samp_rate_rx, soapy_rx_device=options.soapy_rx_device, stream_args=options.stream_args, tune_args=options.tune_args, udp_IP=options.udp_IP, udp_dump_host=options.udp_dump_host, udp_dump_port=options.udp_dump_port, udp_port=options.udp_port, waterfall_file_path=options.waterfall_file_path)
  File "/usr/bin/satnogs_fm.py", line 92, in __init__
    self.soapy_source_0_0 = soapy.source(1, dev, dev_args, stream_args,
  File "/usr/lib/python3/dist-packages/soapy/soapy_swig.py", line 131, in make
    return _soapy_swig.source_make(nchan, device, dev_args, stream_args, tune_args, other_settings, sampling_rate, type)
RuntimeError: no hackrf device matches
netrigctl_close: done status=Command completed successfully
INFO     satnogsclient.observer.observer Observation 11929961 finished.
ERROR    satnogsclient.observer.observer No waterfall data file found

Checking from within the container, sure enough there are no devices:

dev@raspberrypi:~ $ sudo docker exec -it satnogs_satnogs-client bash
satnogs-client@0f6edb9f1b24:/$ SoapySDRUtil --find="driver=hackrf"
######################################################
##     Soapy SDR -- the SDR abstraction library     ##
######################################################

No devices found!
satnogs-client@0f6edb9f1b24:/$ ls /dev/tty*
/dev/tty

I believe my configuration is correct:

------------[ copy here ]------------
{
    "versions": {
        "satnogs-client": "unknown",
        "satnogs-ansible": "unknown",
        "satnogs-flowgraphs": "unknown",
        "gr-satnogs": "unknown",
        "gr-soapy": "unknown",
        "gnuradio": "unknown",
        "satnogs-config": "1.0"
    },
    "state": {
        "is-applied": false,
        "pending-tags": null
    },
    "system": {
        "date": "2025-07-10T19:48:48.183028+00:00",
        "platform": {
            "system": "Linux",
            "node": "satnogs-config",
            "release": "6.12.34+rpt-rpi-v8",
            "version": "#1 SMP PREEMPT Debian 1:6.12.34-1+rpt1~bookworm (2025-06-26)",
            "machine": "aarch64",
            "processor": ""
        },
        "memory": {
            "total": 3981369344,
            "available": 3430019072,
            "percent": 13.8,
            "used": 457207808,
            "free": 2031718400,
            "active": 985976832,
            "inactive": 677175296,
            "buffers": 223854592,
            "cached": 1268588544,
            "shared": 22478848,
            "slab": 194625536
        },
        "disk": {
            "total": 30890590208,
            "used": 10667376640,
            "free": 18633166848,
            "percent": 36.4
        }
    },
    "configuration": {
        "satnogs_antenna": "TX/RX",
        "satnogs_api_token": "[redacted]",
        "satnogs_log_level": "INFO",
        "satnogs_rf_gain": "64",
        "satnogs_rot_enabled": true,
        "satnogs_rot_model": "ROT_MODEL_EASYCOMM2",
        "satnogs_rot_port": "/dev/ttyUSB-rotator",
        "satnogs_rx_samp_rate": "8e6",
        "satnogs_soapy_rx_device": "driver=hackrf",
        "satnogs_station_elev": "1941",
        "satnogs_station_id": "3494",
        "satnogs_station_lat": "38.901",
        "satnogs_station_lon": "-104.851"
    }
}
------------[ copy end ]-------------```

I've rerun satnogs-setup and restarted the container many times following troubleshooting guides to no effect. What can I do here?

Welcome and good evening,

I haven’t used the hackrf on the new docker based client, so wondering:

Does the following command SoapySDRUtil --find="driver=hackrf" run on the host not inside the container produce output.

And is there a 53-hackrf.rules or similar in /etc/udev/rules.d on the host ?

I am also interested to see what the mode and group ownership is in the rules file on your system.

Jan | PE0SAT

Here is output on the host:

dev@raspberrypi:~ $ SoapySDRUtil --find="driver=hackrf"
######################################################
##     Soapy SDR -- the SDR abstraction library     ##
######################################################

Found device 0
  device = HackRF One
  driver = hackrf
  label = HackRF One #0 88869dc2940ba1b
  part_id = a000cb3c006a4757
  serial = 0000000000000000088869dc2940ba1b
  version = 2021.03.1

dev@raspberrypi:~ $ sudo cat /etc/udev/rules.d/99-rotator.rules
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="AB0KPC11", SYMLINK+="ttyUSB-rotator"
dev@raspberrypi:~ $ sudo cat /etc/udev/rules.d/99-serial.rules
KERNEL=="ttyUSB[0-9]*", GROUP="dialout", MODE="0660"
dev@raspberrypi:~ $ sudo cat /etc/udev/rules.d/52-hackrf.rules
ATTR{idVendor}=="1d50", ATTR{idProduct}=="604b", MODE="660", GROUP="plugdev"
ATTR{idVendor}=="1d50", ATTR{idProduct}=="6089", MODE="660", GROUP="plugdev"
ATTR{idVendor}=="1fc9", ATTR{idProduct}=="000c", MODE="660", GROUP="plugdev"

dev@raspberrypi:~ $ ls -l /dev/ttyUSB-rotator
lrwxrwxrwx 1 root root 7 Jul 10 14:41 /dev/ttyUSB-rotator -> ttyUSB0
dev@raspberrypi:~ $ ls -l /dev/ttyUSB0
crw-rw----+ 1 root dialout 188, 0 Jul 10 14:41 /dev/ttyUSB0

Hi,
The sdr issue looks to be related to conflicting udev rules.
This is the one that should be in the udev rules dir.
I suspect this is due to packages installed directly on the host and what ansible (satnogs-setup) is trying to install.
With the docker stack, we don’t need gnuradio, soapy, or the sdr packages on the host.

Regarding the rotator, this is a known limitation (for now and for way too long), here’s my workaround.

1 Like

The MODE:=660, GROUP="plugdev" where the satnogs client isn’t a member of plugdev on the host system will be the reason for the failure.

The satnogs user inside the container has uid=999(satnogs-client) gid=999(satnogs-client) groups=999(satnogs-client)

On my system I also have this user on the host, but I can’t remember if I created this user manual or if it was part of the installation.

You can also change the /etc/udev/rules.d/52-hackrf.rules and change MODE:=660 with MODE:=666

The easy way is to reboot the system after this change, and after the reboot run the SoapySDRUtil --find="driver=hackrf" inside the contianer.

Jan | PE0SAT

Good call, it was the group permission issue. I can now see the hackrf inside the container. Two things for posterity - I did have to update my udev rule to MODE=“0666”. But also, there was a system-wide default rule in /lib/udev with priority 60, so I needed to change my custom hackrf rule file in /etc/udev/ to be over 60 to override that (instead of editing the default one).

Will work on the rotator work arounds now.

3 Likes

For the rotator, I set up rotctld outside of the Docker. I wasn’t really comfortable using the ansible approach. I can confirm that satnogs can connect to rotctld and is at least sending the read position command, although for now it doesn’t seem to be sending any actual movement commands. For anyone that needs it, I did the following:

  1. (Optional) Created a file at /etc/default/rotctl_env that contains:
ROT_OPTS="-m 202 -r /dev/ttyUSB-rotator -s 19200 -t 4533"
  1. Created /etc/systemd/system/user_rotctld.service:
[Unit]
Description=rotctld server

[Service]
EnvironmentFile=-/etc/default/hamlib-utils
ExecStart=/usr/bin/rotctld $ROT_OPTS
Restart=on-failure
User=dev
Group=dev

[Install]
WantedBy=multi-user.target

User/group are whatever your user is. I named the file user_roctld.service because when satnogs install or setup runs, it seems to want to clean out the /etc/systemd/system/roctld.service file. I’m guessing this is because of the push towards containerized services. Containers have always caused me more grief than not, but I’m guessing I’m in the minority here.

Then of course

sudo systemctl daemon-reload
sudo systemctl enable user_rotctld
  1. Set the following options in satnogs_setup:
satnogs_rot_enabled: true
satnogs_rot_model: ROT_MODEL_NETROTCTL
satnogs_rot_port: 172.17.0.1:4533

That IP address is the address of the host as seen from inside the container.

That’s it so far. Will update if I figure out what I’m missing to get satnogs to actually issue position commands during a pass.

Edit:

I think this is related to this issue: Upgrade Hamlib to 4.5+ (#484) · Issue · librespacefoundation/satnogs/satnogs-client

My install has hamlib 4.0 and I seem to have the same log messages as in the issue where they claim max az and el get set to 0:

0000    6d 69 6e 5f 61 7a 3d 30 2e 30 30 30 30 30 30 0a     min_az=0.000000.
read_string called, rxmax=64
read_string(): RX 18 characters
0000    6d 61 78 5f 61 7a 3d 33 36 30 2e 30 30 30 30 30     max_az=360.00000
0010    30 0a                                               0.
read_string called, rxmax=64
read_string(): RX 16 characters
0000    6d 69 6e 5f 65 6c 3d 30 2e 30 30 30 30 30 30 0a     min_el=0.000000.
read_string called, rxmax=64
read_string(): RX 18 characters
0000    6d 61 78 5f 65 6c 3d 31 38 30 2e 30 30 30 30 30     max_el=180.00000
0010    30 0a                                               0.

Edit:
I am trying out the unstable docker container which does have hamlib 4.5, but getting the exact same behavior, except now some additional warnings about invalid dumpcaps lines. I think I’m out of ideas for tonight.

Hi,
libhamlib4 in debian stable is 4.5.4, in the latest librespace/hamlib image is also 4.5.4, which is incompatible with all current satnogs-client. It needs to be the 4.0 version, as was shown in my example.
the possibility to easily control software versions was one of the big points with moving to docker.
I know it can be frustrating changing a lot of things at once and not knowing what is causing problems, been there, done that.
that is why I’m here, I like developing, helping and building.

1 Like

Ok, I reverted back to the stable version, and tried your suggestion to use docker compose to get a rotctld container, and actually it works. Everything is resolved now, much appreciated all. I’m curious though why the container version would work but running rotctld outside of the container didn’t, even though it was able to establish communication with the daemon.

1 Like

I’m just guessing it was the same version mismatch with the latest image, ie v4.5.4