Category Archives: IT

Funkwhale: installation

Funkwhale is a very nice audio hosting platform. We’ll install it using docker-compose in Portainer.

services:
  funkwhale:
    image: funkwhale/all-in-one:latest
    container_name: funkwhale2 #I have 2 instances of funkwhale on this docker host
    restart: unless-stopped
    depends_on:
      - postgres
      - redis
    environment:
      - FUNKWHALE_HOSTNAME=audio.MYSITE.COM
      - FUNKWHALE_PROTOCOL=https
      - FUNKWHALE_PROTOCOL_HEADER=TRUE
      - FUNKWHALE_PROXY_BODY_SIZE=200M
      - FUNKWHALE_MAX_UPLOAD_SIZE=200M
      - DATABASE_URL=postgresql://funkwhale:XXX_MY_DB_PWD_XXX@postgres:5432/funkwhale
      - REDIS_URL=redis://redis:6379/0
      - DJANGO_SECRET_KEY=XXXXX_MYSECRET_XXXXX
      - FUNKWHALE_ENABLE_FEDERATION=false
      - FUNKWHALE_DISABLE_REGISTRATION=true
      # Email Configuration (for GMAIL)
      - EMAIL_CONFIG=smtp+tls://MY_GMAIL_ADDRESS@gmail.com:XX_MY_APP_PASSWORD_XX@smtp.gmail.com:587
      - DEFAULT_FROM_EMAIL=MY_GMAIL_ADDRESS@gmail.com
    volumes:
      - /mnt/funkwhale2-data/media:/data/media
      - /mnt/funkwhale2-data/static:/data/static
      - /mnt/funkwhale2-data/music:/music
    networks:
      - funkwhale2
    ports:
      - "5001:80"  # Choose e free host port; default is 5000
      
  postgres:
    image: postgres:14
    container_name: funkwhale2_postgres
    restart: unless-stopped
    environment:
      - POSTGRES_USER=funkwhale
      - POSTGRES_PASSWORD=XXX_MY_DB_PWD_XXX
      - POSTGRES_DB=funkwhale
    volumes:
      - ./postgres2:/var/lib/postgresql/data  # Different volume!
    networks:
      - funkwhale2
      
  redis:
    image: redis:7-alpine
    container_name: funkwhale2_redis
    restart: unless-stopped
    networks:
      - funkwhale2
      
networks:
  funkwhale2:  # I run 2 instances of Funkwhale on my docker.
    external: false

Create your Django secret (or passwords) with this:

openssl rand -base64 48

Funkwhale user admin

To check if users are active in database, or if they confirmed the registration email, start by connecting to the postgres database on your docker host:

docker exec -it funkwhale2_postgres psql -U funkwhale -d funkwhale

Confirm registration & confirmation status:

SELECT
  id,
  username,
  email,
  is_active,
  date_joined,
  last_login
FROM users_user
ORDER BY date_joined DESC;

will output something like:

 id | username |          email          | is_active |          date_joined          |          last_login           
----+----------+-------------------------+-----------+-------------------------------+-------------------------------
  4 | Paul     | paulXXX@domain.com      | t         | 2025-12-14 11:18:31.248306+00 | 2025-12-14 11:18:32.49417+00
  3 | Mary     | maryXYZ@domain.com      | t         | 2025-12-13 23:33:18.022068+00 | 2025-12-13 23:33:20.309663+00
  1 | admin    | siteadmin@domain.com    | t         | 2025-12-13 23:13:51.537683+00 | 2025-12-13 23:32:35.71689+00
(3 rows)

Find users who registered but never logged in:

SELECT username, email
FROM users_user
WHERE last_login IS NULL;

Find users who registered but never confirmed:

SELECT username, email
FROM users_user
WHERE is_active = false;

Proxmox rotating network interfaces

It sometimes happens that when I shutdown Proxmox for some hours, that after restart, the network interface does not work. I figured that Proxmox is rotating the network interface numbers which leads to the Linux network bridges to not map to the correct network interface and thus leads to no network connectivity. The only thing that helps is to adapt the /etc/network/interfaces file.

Some commands that can help:

brctl show
ifconfig vmbr0
dmesg
lspci | grep -i ethernet

Increase size of disk partition in Ubuntu

If you try to upgrade your system and you lack disk space, here is a solution that might help.

Run “df -h” to check how much space your system is using.

df -h

If it is at 100%, check if the partition still has some spare space left to be used.

lsblk

If the size of the partition your Ubuntu system is living on (f.ex. sda3) is bigger thant the allocated space for “ubuntu–vg-ubuntu–lv”, then you can add space to the system partition.

Result of lsblk (15GB remaining to be added)

You need to extend the logical volume to the maximum free space available:

sudo lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv

Then you need to expand the filesystem:

sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv

Check with df -h ig the additional space has been allocated.

Set up SSH keys on Ubuntu 24.04

Login to your Ubuntu client with the username for which you want to create a key pair. Create the key with the following command:

ssh-keygen

The keys will be saved in your home directory under: /.ssh/id_rsa

Now copy your public key to the server that you want to connect to crom your client without using a password:

ssh-copy-id myusername@remote_host

That’s it. Now try to connect to your server with that username. If all works fine, no password will be asked for.

For a more comprehensive tutorial with more explanations, please consult this excellent page.

Install and configure AWSTATS

General configuration

Using awstats to analyse your web usage statistics if your Apache webserver is running behind an Nginx reverse proxy server, needs some special configuration steps.

Install awstats on your system:

sudo apt install awstats

Enable the awstats apache configuration (and cgi if it is not enabled yet):

sudo a2enmod cgi
sudo a2enconf awstats

Restart the apache service:

sudo systemctl restart apache2

Edit the configuration awstats configuration file or create a configuration file for each virtual host. We are using combined log formats and need to configure this.

sudo cp /etc/awstats/awstats.conf /etc/awstats/awstats.www.mysite.com.conf 
sudo nano /etc/awstats/awstats.www.mysite.com.conf

Configure the virtual host log file path in your awstats configuration file. Make sure you select the correct one (might be the SSL log file).

LogFile="/var/log/apache2/www.mysite.com.access_log"
LogFormat=1

Configure the domain name and domain aliases:

SiteDomain="www.mysite.com"
HostAliases="mysite.com XYZ.mysite.com"

Optionally, if you want DNS lookup (conversing of IP’s into hostnames):

DNSLookup=1

Now update the awstats statistics folder by running the following command:

sudo /usr/lib/cgi-bin/awstats.pl -config=www.mysite.com -update 

Go to your awstats page:

https://www.mysite.com/cgi-bin/awstats.pl?config=www.mysite.com

Depending on your configuration, cgi-bin might need to be replaced by awstats.

Note on security: Make sure that your awstats statistics page is not visible from outside, even more if you are allowing your statistics to be updated through the web interface. I am forcing an htaccess realm through the Nginx reverse proxy on these directory.

If you want to update your statistics through the web interface, set the corresponding flag.

AllowToUpdateStatsFromBrowser=1

The following files have to be readable or writable by the apache service (www-data) user:

/var/lib/awstats (read & write)
/var/log/apache2/www.mysite.com.access_log (read)

Alternatively, add a crontab (edit /etc/crontab) entry:

* */15 * * * root /usr/lib/cgi-bin/awstats.pl -config=www.mysite.com -update > /dev/null

Configuration when running your web server behind an NGINX reverse proxy

Configure your reverse proxy correctly

In the NGINX reverse proxy configuration for your website, make sure you send the real IP-address of the client requesting your page through the header information to the web server. Add the following lines to the root location of your NGINX reverse proxy configuration for your web site (sudo nano /etc/nginx/sites-available/www.mysite.com). For more information on this, check here.

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;

Configure your web server to write the correct IP of the client into the log file (instead of the reverse proxy IP). Add the following to your apache virtual host file (sudo nano /etc/apache2/sites-available/www.mysite.com.conf):

RemoteIPHeader X-Real-IP
RemoteIPInternalProxy IP.PROXY.SERVER
RemoteIPTrustedProxy IP.PROXY.SERVER
RemoteIPHeader X-Forwarded-For
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

%{X-Forwarded-For}i replaces the first parameter in the combined log format, which normally is %h or %a. So if the LogFormat is set in your configuration file, make sure it has the above format.

Apache needs the remoteip module to be enabled in order to treat this information:

sudo a2enmod remoteip

To load the following module in the main Apache configuration file (sudo nano /etc/apache2/apache2.conf), delete the hash sign (#) before the following line:

LoadModule remoteip_module modules/mod_remoteip.so

Test the configuration and reload the apache service.

apache2ctl configtest
service apache2 restart

If you believe you have header issues and don’t know if the bug is on the level of the reverse proxy or the web server, check what header information is arriving at the web server.

Display the received headers (from reverse proxy) in html file

If you are running a reverse proxy server in front of your webserver, it might sometimes be useful to see which header variables are reaching your webserver. To achieve this, create the following headers.php file in the root of your webserver documents folder:

<?php
echo "<h1>Received Headers</h1>";
$headers =  getallheaders();
foreach($headers as $key=>$val){
  echo $key . ': ' . $val . '<br>';
}
echo "======================"
//echo '<pre>'; print_r($_SERVER); echo '</pre>';

?>

openHAB gauge for car fuel tank status

I need a gauge style widget that shows the percentage of fuel left in the tank. The item delivers a number between 0 and 1 and I wanted to display a percentage number between 0 and 100. Here is the functioning code that modifies an item value in the valueText component.

component: oh-gauge-card
config:
  action: navigate
  actionPage: page:cars
  actionPageTransition: f7-dive
  borderColor: =(items.myCar_FuelLevel.state<0.26)?"orange":"red"
  item: myCar_FuelLevel
  max: 1
  min: 0
  title: My car
  type: semicircle
  valueText: =(items.myCar_FuelLevel.state*100) + " %"
  valueTextColor: white
slots: null

renders to:

It might be more interesting to show the remaining mileage in the text though:

component: oh-gauge-card
config:
  action: navigate
  actionPage: page:cars
  actionPageTransition: f7-dive
  borderColor: =(items.myCar_FuelLevel.state<0.26)?"orange":"red"
  item: myCar_FuelLevel
  max: 1
  min: 0
  title: My car
  type: semicircle
  valueText: =(items.MyCar_DistanceLeft.state)
  valueTextColor: white
slots: null

which renders to:

openHAB Command Line Interface commands

  backup [--full] [filename]   -- Stores the current configuration of openHAB.
  clean-cache                  -- Cleans the openHAB temporary folders.
  console                      -- Opens the openHAB console.
  info                         -- Displays distribution information.
  reset-ownership              -- Gives openHAB control of its own directories.
  restore [--textconfig] [--uiconfig] filename
                               -- Restores openHAB configuration from a backup.
  showlogs                     -- Displays the log messages of openHAB.
  start [--debug]              -- Starts openHAB in the terminal.
  status                       -- Checks to see if openHAB is running.
  stop                         -- Stops any running instance of openHAB.