Skip to content

6th February 2023

Life Management

Computer configuration management

  • New: Introduce configuration management.

    Configuring your devices is boring, disgusting and complex. Specially when your device dies and you need to reinstall. You usually don't have the time or energy to deal with it, you just want it to work.

    To have a system that allows you to recover from a disaster it's expensive in both time and knowledge, and many people have different solutions.

    This article shows the latest step of how I'm doing it.




  • New: How to encrypt a file.

    gpg.encrypt_file('path/to/file', recipients)

    Where recipients is a List[str] of gpg Key IDs.

Configure Docker to host the application

  • New: Troubleshoot Docker python not showning prints.

    Use CMD ["python","-u",""] instead of CMD ["python",""].

  • New: [Get the difference of two lists.](../coding/python/python_project_template/







If we want to substract the elements of one list from the other you can use:

for x in b:
  if x in a:


  • New: Split stdout from stderr in tests.

    By default the runner is configured to mix stdout and stderr, if you wish to tell apart both sources use:

    def test(runner: CliRunner):
      runner.mix_stderr = False


  • New: Add basic operations.

    Selecting series:

    • Select latest sample for series with a given metric name:
    • Select 5-minute range of samples for series with a given metric name:
    • Only series with given label values:
    • Complex label matchers (=: equality, !=: non-equality, =~: regex match, !~: negative regex match):
    • Select data from one day ago and shift it to the current time:
    process_resident_memory_bytes offset 1d

    Rates of increase for counters:

    • Per-second rate of increase, averaged over last 5 minutes:
    • Per-second rate of increase, calculated over last two samples in a 1-minute time window:
    • Absolute increase over last hour:

    Aggregating over multiple series:

    • Sum over all series:
    • Preserve the instance and job label dimensions:
    sum by(job, instance) (node_filesystem_size_bytes)
    • Aggregate away the instance and job label dimensions:
    sum without(instance, job) (node_filesystem_size_bytes)

    Available aggregation operators: sum(), min(), max(), avg(), stddev(), stdvar(), count(), count_values(), group(), bottomk(), topk(), quantile().


    • Get the Unix time in seconds at each resolution step:
    • Get the age of the last successful batch job run:
    time() - demo_batch_last_success_timestamp_seconds
    • Find batch jobs which haven't succeeded in an hour:
    time() - demo_batch_last_success_timestamp_seconds > 3600


  • New: Passing environmental variables to commands.

    The _env special kwarg allows you to pass a dictionary of environment variables and their corresponding values:

    import sh
    sh.google_chrome(_env={"SOCKS_SERVER": "localhost:1234"})

    _env replaces your process’s environment completely. Only the key-value pairs in _env will be used for its environment. If you want to add new environment variables for a process in addition to your existing environment, try something like this:

    import os
    import sh
    new_env = os.environ.copy()
    new_env["SOCKS_SERVER"] = "localhost:1234"
  • New: Use commands that return a SyntaxError.

    pass is a reserved python word so sh fails when calling the password store command pass.

    pass_command = sh.Command('pass')
    pass_command('show', 'new_file')


  • New: Print to stderr.

    You can print to "standard error" with a Rich Console(stderr=True)

    from rich.console import Console
    err_console = Console(stderr=True)
    err_console.print("error message")


Infrastructure as Code




  • New: Troubleshoot Yaml templates in go templates.

    If you are using a values.yaml.gotmpl file you won't be able to use {{ whatever }}. The solution is to extract that part to a yaml file and include it in the go template. For example:

    • values.yaml.gotmpl:
      enabled: true
        release: prometheus-operator
    {{ readFile "prometheus_rules.yaml" }}
    • prometheus_rules.yaml
      enabled: true
        release: prometheus-operator
        - alert: VeleroBackupPartialFailures
            message: Velero backup {{ $labels.schedule }} has {{ $value | humanizePercentage }} partialy failed backups.
          expr: increase(velero_backup_partial_failure_total{schedule!=""}[1h]) > 0
          for: 15m
            severity: warning
  • New: Introduce dotdrop.

    The main idea of Dotdropis to have the ability to store each dotfile only once and deploy them with a different content on different hosts/setups. To achieve this, it uses a templating engine that allows to specify, during the dotfile installation with dotdrop, based on a selected profile, how (with what content) each dotfile will be installed.

    What I like:

    • Popular
    • Actively maintained
    • Written in Python
    • Uses jinja2
    • Has a nice to read config file

    What I don't like:



Infrastructure Solutions


Automating Processes


  • New: Introduce letsencrypt.

    Letsencrypt is a free, automated, and open certificate authority brought to you by the nonprofit Internet Security Research Group (ISRG). Basically it gives away SSL certificates, which are required to configure webservers to use HTTPS instead of HTTP for example.

    In the article you can also find:



Operating Systems


Linux Snippets

  • New: Use a pass password in a Makefile.

    TOKEN ?= $(shell bash -c '/usr/bin/pass show path/to/token')
        @AUTHENTIK_TOKEN=$(TOKEN) terraform plan
  • New: Install a new font.

    Install a font manually by downloading the appropriate .ttf or otf files and placing them into /usr/local/share/fonts (system-wide), ~/.local/share/fonts (user-specific) or ~/.fonts (user-specific). These files should have the permission 644 (-rw-r--r--), otherwise they may not be usable.

  • New: Get VPN password from pass.

    To be able to retrieve the user and password from pass you need to run the openvpn command with the next flags:

    sudo bash -c "openvpn --config config.ovpn  --auth-user-pass <(echo -e 'user_name\n$(pass show vpn)')"

    Assuming that vpn is an entry of your pass password store.


  • New: How to install the latest version.

    Install the dependencies:

    sudo apt-get install zstd

    Download the latest release package.

    Open a terminal and run the following commands, replacing the filename as appropriate:

    tar xaf Downloads/anki-2.1.XX-linux-qt6.tar.zst
    cd anki-2.1.XX-linux-qt6
    sudo ./


google chrome

  • Correction: Update the installation steps.

    • Import the GPG key, and use the following command.

      sudo wget -O- | gpg --dearmor > /usr/share/keyrings/google-chrome.gpg

    • Once the GPG import is complete, you will need to import the Google Chrome repository.

    echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] stable main' | sudo tee /etc/apt/sources.list.d/google-chrome.list
    • Install the program:
      apt-get update
      apt-get install google-chrome-stable


  • New: How to add fonts to kitty.

    • Add your fonts to the ~/.local/share/fonts directory
    • Check they are available when you run kitty +list-fonts
    • Add them to your config:

    font_family      Operator Mono Book
    bold_font        Operator Mono Medium
    italic_font      Operator Mono Book Italic
    bold_italic_font Operator Mono Medium Italic
    feat(kitty#Screen not working on server with sudo): Troubleshoot the Screen not working on server with sudo issue

    Make sure you're using the ssh alias below

    alias ssh="kitty +kitten ssh"

    And then copy the ~/.terminfo into /root

    sudo copy -r ~/.terminfo /root




  • New: Introduce seedvault.

    Seedvault is an open-source encrypted backup app for inclusion in Android-based operating systems.

    While every smartphone user wants to be prepared with comprehensive data backups in case their phone is lost or stolen, not every Android user wants to entrust their sensitive data to Google's cloud-based storage. By storing data outside Google's reach, and by using client-side encryption to protect all backed-up data, Seedvault offers users maximum data privacy with minimal hassle.

    Seedvault allows Android users to store their phone data without relying on Google's proprietary cloud storage. Users can decide where their phone's backup will be stored, with options ranging from a USB flash drive to a remote self-hosted cloud storage alternative such as NextCloud. Seedvault also offers an Auto-Restore feature: instead of permanently losing all data for an app when it is uninstalled, Seedvault's Auto-Restore will restore all backed-up data for the app upon reinstallation.

    Seedvault protects users' private data by encrypting it on the device with a key known only to the user. Each Seedvault account is protected by client-side encryption (AES/GCM/NoPadding). This encryption is unlockable only with a 12-word randomly-generated key.

    With Seedvault, backups run automatically in the background of the phone's operating system, ensuring that no data will be left behind if the device is lost or stolen. The Seedvault application requires no technical knowledge to operate, and does not require a rooted device.

    In the article you'll also find:

    • How to install it
    • How to store the backup remotely
    • How to restore a backup


  • New: Add installation steps.

    These instructions only work for 64 bit Debian-based Linux distributions such as Ubuntu, Mint etc.

    • Install our official public software signing key
    wget -O- | gpg --dearmor > signal-desktop-keyring.gpg
    cat signal-desktop-keyring.gpg | sudo tee -a /usr/share/keyrings/signal-desktop-keyring.gpg > /dev/null
    • Add our repository to your list of repositories
    echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/signal-desktop-keyring.gpg] xenial main' |\
      sudo tee -a /etc/apt/sources.list.d/signal-xenial.list
    • Update your package database and install signal

    bash sudo apt update && sudo apt install signal-desktop