Tuesday, March 11, 2025

Installing TexLive Packages Using tlmgr from a Non-default Repository

From time to time, the default TexLive repository does not work for me when I try to install a package using tlmgr. One method to get around this is to use a non-default repository, e.g., to install the listings package, we can


tlmgr -repository https://mirrors.ibiblio.org/pub/mirrors/CTAN/systems/texlive/tlnet install listings

Perhaps, the trick part is not to find a mirror, rather it is to write the correct URL. This example serves as a template for that

Monday, March 3, 2025

Selecting CUDA Devices

I observed that when I run a Pytorch program on a system with GPUs, the Pytorch runner dispatches the computational tasks to both GPUs. Since the program is not optimized for using multiple GPUs, the performance using the two GPU is worse than just using one. A simple method to address this turns out to be that we inform Pytorch to use a designated GPU via environmental variable CUDA_VISIBLE_DEVICES.

For instance, to run a task run_task.sh, we can 

 CUDA_VISIBLE_DEVICES=0 ./run_task.sh SEED=1234

which results in running the task on a single GPU. 

For the non-optimized program, I got much better computational efficiency by doing than letting each run on two GPUs:

 CUDA_VISIBLE_DEVICES=0 ./run_task.sh SEED=1234

 CUDA_VISIBLE_DEVICES=1 ./run_task.sh SEED=4321




 


 

Friday, February 21, 2025

Enabling NAT and IP Masquerading on Rocky Linux 9

This is a note about enabling NAT (SNAT, more precisely) and IP masquerading on a Linux host that runs Rocky Linux 9. The host has two network interfaces: eth0 and wg0.  Interface eth0 connects to the outside network and is assigned an public IP address while interface wg0 is on a private network. The objective is to make the Linux host as router for the private network so that the traffic originated from the private network can go to the outside network. The steps to achieve this objective using firewalld are as follows:

  1. Enable IPv4 forwarding
          echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
          sudo sysctl -p
        
  2. Assign interface eth0 to the external zone
         firewall-cmd --permanent --zone=external --change-interface=eth0
        
  3. Assign interface wg0 to the internal zone
         firewall-cmd --permanent --zone=internal --change-interface=wg0
        
  4. Set the zone target of the internal zone to ACCEPT
         firewall-cmd --permanent --zone=internal --set-target=ACCEPT
        
  5. Finally, reload firewalld's configuration.
         firewall-cmd --reload
        

There is no need to meddle with anything else, such as adding nftables rules and set masquerading for the outward facing network interface. This is because the external zone is by default with masqerading enabled. This can be verified by

firewall-cmd --zone=external --query-masquerade
    

or by looking at the zone definition file at /usr/lib/firewalld/zones/external.xml.

In addition, the external zone's is also enabled to forward packets. We can examine this by looking at the zone definition file at /usr/lib/firewalld/zones/external.xml or by

firewall-cmd --zone=external --query-forward
    

The issue seems to lie at the zones' targets. First, let's view the zones' configuaration::

firewall-cmd --zone=external --list-all
    

Of course, we can also just check the target:

firewall-cmd --permanent --zone=external --get-target
    
firewall-cmd --zone=internal --list-all
    

Of course, we can also just check the target:

firewall-cmd --permanent --zone=internal --get-target
    

The targets of the both external and internal zones are both originally default. The internal zone's default target is in fact interpreted as reject, thus, preventing from packet forwarding to the outside network. This is explained as

For a forwarded packet that ingresses zoneA and egresses zoneB:
  • if zoneA's target is ACCEPT, DROP, or REJECT then the packet is accepted, dropped, or rejected respectively.
  • if zoneA's target is default, then the packet is accepted, dropped, or rejected based on zoneB's target. If zoneB's target is also default, then the packet will be rejected by firewalld's catchall reject.

Since both ingress (internal) and egress (external) are both "default", the result is that the internal zone's target becomes REJECT".

One question, I have in mind is, why do I not assign the internal facing interface to the trusted zone? That might be for another day.

Reference

This note benefited tremendously from the following resources:

  1. https://askubuntu.com/questions/1463093/what-is-target-default-of-a-zones-configuration-in-firewalld
  2. https://github.com/firewalld/firewalld/issues/590#issuecomment-605200548
  3. man firewall-cmd
  4. man firewalld.zone
  5. man firewalld

 

Wednesday, February 19, 2025

Runing dnf package manager on Linux with small memory

Running dnf package manager can sometimes be difficult on Linux hosts with small memory. I observed on a Rocky Linux 9 with 1 GB RAM after enabled epel, and dnf install would sometimes be killed due to OOM.

To address this issue, we can create and enable a swap space:

$ sudo dd if=/dev/zero of=/swapfile count=1024 bs=1MiB
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile
$ sudo dnf update

Once done, we then turn off the swap space:

$ sudo swapoff /swapfile

Reference

This idea come from this Stackoverflow post

 

 

 

 

 

Thursday, December 12, 2024

Solution for problem: rootless Docker container cannot ping outside networks

I am running a rootless docker container on a Ubuntu host (24.04 LTS). However, I cannot ping the host where the container is running and the outside network. The workaround I created are two steps:

  1. Run the container with the --privileged option, as in
    docker container run --privileged 
  2. On the host where the container is running, set Linux kernel parameber `net.ipv4.ping_group_range` to include the group id that runs the container. For instance, if the group id of the user that runs the container is 3000, we can set the parameter as follows:
    echo "3000 3000" > /proc/sys/net/ipv4/ping_group_range

If tests indicate that pings are successful in the container, we can set the kernel parameter through a configuration file so that the setting can survive reboot, e.g.,

  • On the host that the container is running, create a file, e.g., /etc/sysctl.d/99-ping-group-range.conf as in:
    echo "net.ipv4.ping_group_range=3000 3000" \
           > /etc/sysctl.d/99-ping-group-range.conf

The idea of these is from

  1. https://github.com/containers/podman/issues/2488
  2. https://opennms.discourse.group/t/how-to-allow-unprivileged-users-to-use-icmp-ping/1573

Wednesday, October 2, 2024

SSH Publication Key Authentication Fails When Home is on NFS

As the title stated, regardless how I try, I couldn't get SSH publication key authentication to work for a Linux host. It turns out that the Linux host that runs the SSH server has SELinux enabled. To make public key authnentication work for SSH, we simply need to configure SELinux, i.e.,


sudo setsebool -P use_nfs_home_dirs 1

Thursday, May 16, 2024

Signing Git Commits: Inappropriate ioctl for device

When I attempted to sign a Git commit, I encountered the following error:


$ git commit -S -m "important change"
error: gpg failed to sign the data:
[GNUPG:] KEY_CONSIDERED AAAABBBBCCCCDDDD00000 2
[GNUPG:] BEGIN_SIGNING H8
[GNUPG:] PINENTRY_LAUNCHED 583247 curses 1.2.1 - xterm localhost:10.0 - 1000/2001 0
gpg: signing failed: Inappropriate ioctl for device
[GNUPG:] FAILURE sign 83918950
gpg: signing failed: Inappropriate ioctl for device

fatal: failed to write commit object

After an investigation, I learned that the problem could be somethign with gpg itself. To gauge whether it is the problem with gpg, we could sign a message with gpg, e.g.,


$ echo "test" | gpg --clearsign
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

test
gpg: signing failed: Inappropriate ioctl for device
gpg: [stdin]: clear-sign failed: Inappropriate ioctl for device

Clearly, we observe the same error message. We can conclude it is the issue with gpg. It turns out that one reason of this is that tty is not set properly. To fix this, we set tty for gpg using


export GPG_TTY=$(tty)

This can be added to shell script's profiles