Watch a file for changes and copy/sync it to a remote host


  • works on Linux and Mac OS
  • install entr
ls -b [file]... | entr -p scp /_ targethost:/destination/folder/


  • works only on Linux
  • it does not work if the file is replaced rather than changed.
  • install inotify-tools
F="filename" eval 'inotifywait -m -e close_write $F | while read E; do echo -e $(date +"%F %T") $E; scp $F root@targethost:/destination/folder/; done;'

Resize root partition on UEFI/GPT machines

It assumes you want to resize root partition (/) on a virtual machine and the partition you want to resize is the last one that has data. Swap would be ok if it’s last.

Example (disk already resized from 5GB to 20GB):

Disk /dev/sda: 41943040 sectors, 20.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 7DCC138E-820C-42FA-AFB4-3E9A89946AFB
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 10485726
Partitions will be aligned on 2048-sector boundaries
Total free space is 4029 sectors (2.0 MiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048          194559   94.0 MiB    EF00
   2          194560         6639615   3.1 GiB     8300  root
   3         6639616        10483711   1.8 GiB     8200  swap
  1. resize the disk
  2. reboot?
  3. swapoff -a
  4. gdisk /dev/sda
  5. make all new sectors usable
    • go to expert mode with command ‘x’
    • use command ‘e’ to relocate backup data structures to the end of the disk
    • go back to menu (‘m’)
  6. delete partitions sda3 and sda2
  7. re-create partition sda2, type 8300
    • it should start from the same sector to preserve the data
    • leave some space at the end for the swap
  8. re-create sda3, type 8200
  9. optional: rename the partitions with the old (or new) names
  10. write parition table to disk
  11. mkswap /dev/sda3
  12. edit /ets/fstab and update UUID of the swap partition, it probably changed
  13. reboot
  14. resize2fs /dev/sda2

Ranger Cheatsheet

ranger is a console file manager with vim key bindings

Most Used Keyboard Shortcuts

ttag toggle
g nnew tab
TABnext tab
qquit tab
d Ddelete
d dcut
y yyank / copy
p ppaste
p opaste overwrite
g hgo home
Sopen shell
ropen with …
d ccount the size
[move up in the parent directory
]move down in the parent directory
``last directory bookmark
z htoggle show hidden files
o rsort reverse
o msort by mtime
o nsort natural / by name
Rreload this directory
SPACEselect under cursor
vinvert selection / select all

Convert to mp3 Using FFMPEG

In this example we will convert m4a audio files to mp3. But you can convert virtually any audio format.

$ mkdir converted
$ for f in *.m4a; do ffmpeg -i "$f" -codec:v copy -codec:a libmp3lame -q:a 2 converted/"${f%.m4a}.mp3"; done;
  • -q:a 2 means LAME’s option -V 2, which gives us a VBR MP3 audio stream with an average stereo bitrate of 170-210 kBit/s. See for more options.
  • make sure you convert to equal or lower quality (it would not make much sense to convert to better quality than the source)

Raspberry Pi (rpi) – Disable WiFi and/or Bluetooth

Open /boot/config.txt and add to the end of the file:

# disable wifi

# disable bt


Alternatively you can blacklist kernel modules for wifi and/or bluetooth

Create /etc/modprobe.d/raspi-blacklist.conf and copy this:

## wifi
blacklist brcmfmac
blacklist brcmutil

## bt
blacklist btbcm
blacklist hci_uart


Mail Tracking

It seems there is growing trend of tracking emails one sends. As an example, using a browser add-on – take a look at MAILTAG

They track you and your recipients and they share the collected information with you. That’s it!

What you usually get

You’ll know when your recipients will open your email and, optionally, if they clicked any link in that email you sent.

First when I heard about it, promoted by a Youtube channel that teaches web programming, it just sounded gross to me.

So I decided to write about it. I will try to describe the technique so you’ll understand what you are doing when you use such service.

How it generally works

The technique used is by inserting tracking code into sent emails. For example they would insert a transparent one pixel image with and ID parameter representing the email you are sending. This invisible image loads from their servers and they can tell when the mail was open and how many times. They’ll share that information with you.

To track links they would need to alter all of them in your sent email to point somewhere else where they can count clicks and later redirect to the original link.

They’ll know all the links from all email you sent and when your recipients clicked on them. The latter info they’ll share with you. The former you know already.

How to prevent being tracked

  • disable loading external images in all your email clients
  • don’t click on links unless you checked where they point
  • (most probably) ad blockers like uBlock Origin will block such links. This is not effective for standalone email clients
  • block mail client outgoing connections, but to the mail server
  • use mutt or alpine

Next available IP or Subnetwork with PostgreSQL

Calculates next available IPs or subnetworks.
You’ll need to have a table with used IPs and subnetworks defined similar to the one bellow.

    remote_addr CIDR NOT NULL CONSTRAINT ip_remote_addr UNIQUE

How it works

  • generates series of networks of length new_ip_mask_len inside the given ip_address/mask network and checks if they are available. This means there is no other (sub)network from the generated ones inside the ip table AND there is no network with the same prefix (even a bigger one) @see last where clause
  • hardcoded vars are as example, use ? bind variables from your ORM instead
  • for a single IP set the mask new_ip_mask_len to 32, duh

The SQL code

SELECT new.addr FROM ( 
    WITH vars AS (
            ''::varchar ip_address, 
            '24'::integer mask, 
            '29'::integer new_ip_mask_len
    ),   vals AS (
            ( host(network((vars.ip_address || '/' || vars.mask)::inet)) || '/' || vars.mask )::cidr AS subnet,
            ( 2 ^ ( 32 - mask ) )::integer - 2  AS max,
            ( 2 ^ ( 32 - new_ip_mask_len ) )::integer AS step
        FROM vars
    SELECT set_masklen(
        (generate_series(0, max, step) + subnet)::inet,
    ) AS addr FROM vals
) AS new
    SELECT FROM ip ip 
    WHERE new.addr >>= ip.remote_addr OR host(new.addr) = host(ip.remote_addr)

AC Power Wiring Colors

According to International Electrical Commission standard IEC60445:2017, for AC power the following color codes should be used.

Check if the country where you are adheres to the standard!

See also outdated IEC60446.

  • Grounding symbol = protective conductor = green/yellow
  • N = Neutral conductor = blue
  • L = AC Phase conductors
    • L1 = brown (or just L for single AC phase)
    • L2 = black
    • L3 = grey

Clean URLs with Apache httpd

a la Caddy

Caddy server let’s you easily define implicit extensions for your server URLs. Check ext directive in it’s documentation.

Get the same result in apache httpd using rewrite rules

Configuration snippet
RewriteEngine On
# Auto ext, clean URLs
# -----
# .html
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !.*\.html$
RewriteRule ^(.*)$ $1.html [NC,L]
# .php
RewriteRule ^(.*)$ $1.php [NC,L]

The story: If (1) the URI does not already end with the extension and (2) if it is not a folder with the same name and (3) if the file with the added extension actually exists, then it adds the extension

Later edit:  If the folder exists the rewriting is not done and therefore the index.html or index.php in the folder is served. If you want the file plus the added extention to have precedence over folder, comment out out the 2nd condition.

flag L|last stop processing rules after match. If you have other rules you need applied, remove it!

flag NC|nocase case-insensitive matching

Use the config snippet per VirtualHost. Or add it to your server global rewrite rules. Usually it’s the /etc/apache2/mods-enabled/rewrite.conf file. Don’t forget about RewriteOptions Inherit in your VirtualHost if you use the global configuration.

— tried and works with Apache 2.4

Byobu / Tmux / Screen


Function keys work by default only in byobu.

ctrl-a cF2create new window
ctrl-a pF3previous window
ctrl-a nF4next window
ctrl-a ctrl-aprevious window
F5refresh all status notifications
ctrl-a dF6detach from session / leave
ctrl-a [F7scrollback / search mode
ctrl-a AF8rename current window

Tell byobu to not set the terminal window title


Set the title of your terminal window by running

echo -ne "\033]0;${HOSTNAME%%.*}\007"

This will set your terminal title to the hostname your are on (without domain part). Add this to your $PROMPT_COMMAND to set it automatically with every command you run.