How I used a docker container to adjust the fans from the hdd temp

Hello, everyone,
I recently found a great docker container based on a well-known script for dynamically cooling hard drives.
Below I explain the steps that I took:

First we need to configure “lm-sensors” by running the following shell command

sudo sensors-detect

Always press enter, up to “Do you want to add these lines automatically to /etc/modules?”
At this point write yes and press enter again.

Now run:

sudo /etc/init.d/kmod restart

At this point we run the following command, and look for the fans we want to use to cool the hdds. You can slow them down with your finger.

watch sensors 


Mine are fan1 and fan5.

In order to make this container work, we need to create a symbolic link to /lib/modules. Here is mine (you have to adapt it to your case).

sudo ln -s /mnt/tank/VM/k3s/hddfanmonitor/lib-modules /lib/modules

Now we can finally create our app, adapting it to the docker compose

version: "3"
services:
hddfancontrol:
image: ghcr.io/fightforlife/docker_hddfancontrol:master
restart: unless-stopped
volumes:
- /lib/modules:/lib/modules:ro
privileged: true
cap_add:
- SYS_MODULE
environment:
- DRIVE_FILEPATHS=/dev/sdb1 /dev/sdc1 /dev/sdd1
- FAN_PWM_FILEPATH=/sys/class/hwmon/hwmon2/pwm1 /sys/class/hwmon/hwmon2/pwm2
- FAN_START_VALUE=70 80
- FAN_STOP_VALUE=20 30
- MIN_TEMP=40
- MAX_TEMP=60
- MIN_FAN_SPEED_PRCT=0
- INTERVAL_S=60
- CPU_PROBE_FILEPATH=/sys/devices/platform/coretemp.0/hwmon/hwmon0/tempY_input
- CPU_TEMP_RANGE=50 70
- SPIN_DOWN_TIME_S=900
- VERBOSITY=debug
- LOG_FILEPATH=/var/log/hddfancontrol.log
- TEMP_QUERY_MODE=smartctl #hddtemp,hdparm,drivetemp,smartctl

You can get an idea from these pictures.







I hope I have been helpful :slight_smile:

UPDATE 16/08/2024
You can safely skip the sym-link trick (/lib/modules) by externally loading the module for your PWM controller. To make it automatic and persistent to updates, adapt this code to your motherboard.

UPDATE 26/06/2023
The container has been updated. If you have an error in the logs referring to “hddtemp,” know that it has been deprecated.
Use an alternative, such as smartctl. Set it as environment variable.

TEMP_QUERY_MODE=smartctl #hddtemp,hdparm,drivetemp,smartctl

Note TrueNAS Scale 23.10+
If you get the error “OSError: [Errno 30] Read-only file system: ‘/sys/class/hwmon/hwmon2/pwm1_enable’”, please enable ‘Provide access to node network namespace for the workload’

UPDATE 13/03/2024
If you wish to use the disk name ‘/dev/disk/’ instead of '/dev/sd’, create a symbolic link to ‘/dev’ as you did before with ‘/lib/modules’

variables6
example: /dev/disk/by-id/wwn-0x50014ee2c03f0711

3 Likes

Thank you so much for this, I got about 50% of the way there but was still struggling until I found you to hold my hand. :slight_smile:

1 Like

An alternative to using your fingers to slow the fans down to identify them is to bring up the container, shell into it, and run pwmconfig which iterates thru the available fan headers and adjusts the speed of each to help you learn which is which

1 Like

Hi Everyone,

i’m currently trying to get the hddfancontrol docker container to work with Electric Eel.
After many tries i’ve figured out the correct variables for everything, but now i’m stuck.

The container crashes after a fraction of a second, when i take a look at the logs (which also took long to get working) i can see that the script tries to set the fan speed but i get the error message: “ERRNO 13: Permission denied”

when i open the path through shell i can see that every item is read only, how should the container set the fan speed if everything is read only?

i can’t start the container without setting the path for the fan i want to control because the container then stops without me even being able to access the logs.

My container runs privileged mode an also as user root just to be safe… anything else i can do?

There are some “limits” depending on motherboard? Because i have tried first steps, but when i use the watch sensors command, only CPU and nvme temp is displayed

Did you configure lm-sensors correctly? Try to see on a distro, maybe Ubuntu, if it detects the sensors.
It is rare, but sometimes the necessary modules for some motherboards are not present.

1 Like

I think to have done It correctly, just going on with default except on adding those rows in the /etc/modules as mentioned.
Posting output of process can help somehow?

Running something like Alpine Linux in a VM will be ok? (I don’t have GPU :upside_down_face: )

Thanks

Since EE release, you can use the built-in docker composer.
Just adapt the script and go.

No, you can’t use a VM. Only the host os has the direct access to the hw controller.

I can’t get this to work, am I doing it right?

I should copy the YAML into Apps - Discover apps - Install via YAML (hamburger menu), correct?

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/middlewared/job.py", line 509, in run
    await self.future
  File "/usr/lib/python3/dist-packages/middlewared/job.py", line 556, in __run_body
    rv = await self.middleware.run_in_thread(self.method, *args)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/main.py", line 1367, in run_in_thread
    return await self.run_in_executor(io_thread_pool_executor, method, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/main.py", line 1364, in run_in_executor
    return await loop.run_in_executor(pool, functools.partial(method, *args, **kwargs))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/service/crud_service.py", line 268, in nf
    rv = func(*args, **kwargs)
         ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/schema/processor.py", line 55, in nf
    res = f(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/schema/processor.py", line 183, in nf
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/plugins/apps/crud.py", line 185, in do_create
    return self.middleware.call_sync('app.custom.create', data, job)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/main.py", line 1665, in call_sync
    return methodobj(*prepared_call.args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/plugins/apps/custom_app.py", line 88, in create
    raise e from None
  File "/usr/lib/python3/dist-packages/middlewared/plugins/apps/custom_app.py", line 78, in create
    compose_action(app_name, version, 'up', force_recreate=True, remove_orphans=True)
  File "/usr/lib/python3/dist-packages/middlewared/plugins/apps/compose_utils.py", line 36, in compose_action
    compose_action(app_name, app_version, 'down', remove_orphans=True)
  File "/usr/lib/python3/dist-packages/middlewared/plugins/apps/compose_utils.py", line 61, in compose_action
    raise CallError(err_msg)
middlewared.service_exception.CallError: [EFAULT] Failed 'down' action for 'test' app. Please check /var/log/app_lifecycle.log for more details

You can use the following docker compose configuration (YAML, the one you just mentioned). Do not forget the modprobe of the fan driver, and the correct pwm / sata/sas addresses.

services:
  hddfancontrol:
    cap_add:
      - SYS_MODULE
    environment:
      - >-
        DRIVE_FILEPATHS= /dev/sda
        /dev/sdb
      - >-
        FAN_PWM_FILEPATH=/sys/class/hwmon/hwmon3/pwm1
        /sys/class/hwmon/hwmon3/pwm5
      - FAN_START_VALUE=64 64
      - FAN_STOP_VALUE=0 0
      - MIN_TEMP=35
      - MAX_TEMP=50
      - INTERVAL_S=60
      - TEMP_QUERY_MODE=smartctl
    image: ghcr.io/fightforlife/docker_hddfancontrol:master
    privileged: True
    restart: unless-stopped
    volumes:
      - /dev:/dev:ro

Thanks, now it installed, but it just autoquits immidiately:

https://github.com/user-attachments/assets/e121267a-202e-4cd0-904c-3996fbcd3ebd

try restarting the system, also check the container logs.

Nice, I managed to get it working.

It had to do with the YAML. Since I only have one PWM fan I had removed the two PWM filepaths, but not the duplicate fan start/stop value numbers. Once I removed the duplicate numbers it started working! :slight_smile:

1 Like