gentoo-zsh-completions for oh-my-zsh

gentoo-zsh-completions plugin for oh-my-zsh. forked from gentoo-zsh-completions main repository, and modified for Oh-my-zsh.


$ git clone ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/gentoo-zsh-completions

To use it, add 'gentoo-zsh-completions' to the plugins array in your zshrc file:

plugins=(... gentoo-zsh-completions)

Gentoo kernel build script

Automating the kernel compile, configuration copying, systemd-boot and grub2 configuration updating, old kernel cleaning script for Gentoo Linux.


  • First, clone this repository and change directory:

git clone
cd kernel-build
  • Change script permissons:

chmod +x
  • If you are using systemd-boot you should first learn rootfs disk UUID or LVM partition and then add it to the script:


Optional: You can add specific kernel parameters to ROOTFLAGS.

  • Now you execute the script like so:

./ systemd-boot
  • If you are using grub2:

./ grub2

Vim Tips: Channel

Vim supported channels for inter-process communication and job channels communicate with other processes. Also, The vim packages contains the demo channel server( You can find script in "$VIMRUNTIME/tools/". "$VIMRUNTIME" path, may change according to your distro:

My path, "/usr/share/vim/vim82/tools/" on Gentoo Linux.

  • First, run the demo server in a terminal.

$ python /usr/share/vim/vim82/tools/
  • And then, run Vim in another terminal.

  • For detailed information, I am quoting from the script:

    # Server that will accept connections from a Vim channel.
    # Run this server and then in Vim you can open the channel:
    #  :let handle = ch_open('localhost:8765')
    # Then Vim can send requests to the server:
    #  :let response = ch_sendexpr(handle, 'hello!')
    # And you can control Vim by typing a JSON message here, e.g.:
    #   ["ex","echo 'hi there'"]
    # There is no prompt, just type a line and press Enter.
    # To exit cleanly type "quit<Enter>".
    # See ":help channel-demo" in Vim.
    # This requires Python 2.6 or later.

systemd-boot update script

systemd-boot does not automatically regenerate entry configuration files like update-grup or grub-mkconfig. So you can use below script for Gentoo Linux.

# This is a simple kernel hook to populate the systemd-boot entries
# whenever kernels are added or removed.

# The UUID of your disk.
# Note: if using LVM, this should be the LVM partition.

# Intel microcode file name

# Any rootflags you wish to set. For example, mine are currently
# "subvol=@ quiet splash intel_pstate=enable".

# Our kernels.
FIND="find /boot -maxdepth 1 -name 'vmlinuz-*' -type f -not -name '*.old' -print0 | sort -Vrz"
while IFS= read -r -u3 -d $'\0' LINE; do
        KERNEL=$(basename "${LINE}")
done 3< <(eval "${FIND}")

# There has to be at least one kernel.
if [ ${#KERNELS[@]} -lt 1 ]; then
        echo -e "\e[2msystemd-boot\e[0m \e[1;31mNo kernels found.\e[0m"
        exit 1

# Copy the latest kernel files to a consistent place so we can
# keep using the same loader configuration.
echo -e "\e[2msystemd-boot\e[0m \e[1;32m${LATEST}\e[0m"
cat << EOF > /boot/loader/entries/gentoo.conf
title   Gentoo Linux
linux   /vmlinuz-${LATEST}
initrd  /${MCODE}
initrd  /initramfs-${LATEST}.img
options root=UUID=${UUID} rw ${ROOTFLAGS}

# Copy any legacy kernels over too, but maintain their version-
# based names to avoid collisions.
if [ ${#KERNELS[@]} -gt 1 ]; then
        for VERSION in "${LEGACY[@]}"; do
            echo -e "\e[2msystemd-boot\e[0m \e[1;32m${VERSION}\e[0m"
            cat << EOF > /boot/loader/entries/gentoo-${VERSION}.conf
title   Gentoo Linux ${VERSION}
linux   /vmlinuz-${VERSION}
initrd  /${MCODE}
initrd  /initramfs-${VERSION}.img
options root=UUID=${UUID} rw ${ROOTFLAGS}

printf "\n"
printf "Updating systemd-boot firmware \n"
bootctl update

# Success!
echo -e "\e[2m---\e[0m"
exit 0

This script forked from here.

Basic Timezone API

timezone-api is lightweight Flask app with TimezoneFinder(L) python library and provides a simple interface. Your request the timezone information for specific latitude and longtitude pair.

Request Parameters

Parameters are separated using the ampersand(&) character.

  • lat: latitude (eg. lat=39.6034810) (Required)
  • lng: longtitude (eg. lng=-119.6822510) (Required)
  • timestamp: timestamp (eg. timestamp=1331161200) (Required)

Example Request


API urls must follow this format:



- tzname: Timezone name
- dstoffset: the offset for daylight-savings time in seconds.
This will be zero if the time zone is not in Daylight Savings Time during the specified timestamp.
- rawoffset: the offset from UTC (in seconds) for the given location.
This does not take into effect daylight savings.
- status: response code
    - 200: the request was successful
    - 400: missing parameter(s)
    - 422: out of bounds error

API Health

To check the API status or health


Response: OK

API Info

For information about API




- debug: APP debug status
- running-since: API start time
- version: API version


I. Method: From Docker Hub

$ docker run -d -p 8080:8000 --name timezone-35 mofm/timezone-api
  • Test
$ curl --request GET  ""
  "dstoffset": 3600.0,
  "rawoffset": -28800.0,
  "status": 200,
  "tzname": "America/Los_Angeles"

II. Method: Build Docker image

  • Clone this repostory
$ git clone
  • Build Docker image (slim image with Google Distroless)
docker build -t timezone-img .
  • Running Docker image
$ docker run -d -p 8080:8000 --name timezone-api ti
  • Test
$ curl --request GET  ""
  "dstoffset": 3600.0,
  "rawoffset": -28800.0,
  "status": 200,
  "tzname": "America/Los_Angeles"

Unbound DoH behind Nginx

Unbound DoH is waiting HTTP/2 requests. But Nginx proxy module doesn't support HTTP/2 on the upstream connections. So you can use grpc proxy:

location /dns-query {
     grpc_pass grpc://unbound-host;

and disable TLS for DNS-over-HTTP downstream service in unbound.conf:

http-notls-downstream: yes

URLs of Blacklists

Free, up-to-date and large blacklist databases for those who want to set up DNS firewall:



Energized Protection



Adguard List



NoCoin List

PornTop1M List

Simple Ad List

Simple Tracker List



YoYo List

Block ads and malware via BIND9 RPZ

Installation on Ubuntu 20.04 LTS

  • Run following command to install BIND 9 on Ubuntu 20.04
$ sudo apt update
$ sudo apt install bind9 bind9utils bind9-dnsutils

Configurations for recursive DNS resolver with RPZ(response policy zone)

  • To enable recursion service, edit /etc/bind/named.conf.options :
    // hide version number from clients for security reasons.
    version "not currently available";

    // optional - BIND default behavior is recursion
    recursion yes;

    // provide recursion service to trusted clients only
    allow-recursion {;;; };

    // disallow zone transfer
    allow-transfer { none; };

    // enable the query log
    querylog yes;

    //enable response policy zone.
    response-policy {
        zone "blocked.local";
  • Add RPZ zone in /etc/bind/named.conf.local :
    zone "blocked.local" {
        type master;
        file "/etc/bind/db.blocked.local";
        allow-query { localhost; };
        allow-transfer { localhost; };
  • add following lines in /etc/bind/named.conf to use separate log file for RPZ(recommended):
    logging {
        channel blockedlog {
            file "/var/log/named/blocked-zone.log" versions unlimited size 100m;
            print-time yes;
            print-category yes;
            print-severity yes;
            severity info;
        category rpz { blockedlog; };
  • If /var/log/named/ directory doesn't exist, create it and make bind as the owner:
$ sudo mkdir /var/log/named/
$ sudo chown bind:bind /var/log/named/ -R

Creating Zone File

  • first, clone this repository:
$ git clone
  • If there is domain(s) you want to block, you can add it to the blacklist file.

  • execute the script(this script downloads StevenBlack host file and then creates RPZ zone file):

$ sudo bash

Check configurations and service:

$ sudo named-checkconf
$ sudo named-checkzone rpz /etc/bind/db.blocked.local

If no problem, restart and enable bind9 service;

$ sudo systemctl restart bind9
$ sudo systemctl enable bind9


  • You can run the dig command on the BIND server to see if RPZ is working:
$ dig A @
  • You can also check '/var/log/named/blocked-zone.log' for query log:
$ sudo tail /var/log/named/blocked-zone.log
  • READY, you can add this BIND9 host IP address to your host(s).


Ingress path redirection appends port

Ingress bazi URL isteklerine container port'u ile redirect etmeye calistigi gibi bir sorunla karsilasabilirsiniz. Ornek olarak biraz daha acmak gerekirse;

$ curl -I

HTTP/1.1 200 OK
Date: Mon, 07 Dec 2020 23:47:21 GMT
Content-Type: text/html
Content-Length: 87466
Connection: keep-alive
Last-Modified: Mon, 07 Dec 2020 20:48:36 GMT
ETag: "5fce9524-155aa"
Accept-Ranges: bytes

Yukarida goruldugu "" adresine gonderdigimiz istek saglikli sekilde "200" kodunu cevap olarak donuyor. Birde "" seklinde istekte bulunarak test edelim:

$ curl -I

HTTP/1.1 301 Moved Permanently
Date: Sun, 07 Dec 2020 23:52:48 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

Bu ornek ise goruldugu gibi "http://hostname:cointainer_port/paths" seklinde container portunu da ekleyerek sayfayi yanlis sekilde redirect etmeye calisiyor ve sayfa ulasilamaz oluyor. Buradaki '8080' portu ingress'in arka tarafindaki nginx container'in yayin yapmakta olan portu.

Sorunun sebebine gelince, bu sorunun ingress ile hic bir alakasi yok. Hem kubernetes/ingress-nginx hem de nginxinc/nginx-ingress ingress controller'larinda nginx konfigurasyonu uzerindeki port_in_redirect degeri default olarak 'off' olarak. Fakat arka tarafta calisan nginx container uzerindeki bu konfigurasyonu 'on' yapilmissa bu durumla karsilasabilirsiniz. Bunu nginx.conf uzerinde 'port_in_redirect off;' seklinde kapatarak yasanmasini engelleyebilirsiniz.

Asagidaki sekilde nginx.conf'u configmap'e ekleyerek nginx pod'un bu configmap'i kullanmasini saglayarak deployment yapabilirsiniz.

apiVersion: v1
kind: ConfigMap
  name: nginx-conf
  nginx.conf: |
    worker_processes  1;

    error_log  /var/log/nginx/error.log warn;
    pid        /tmp/;

    events {
        worker_connections  1024;

    http {
        proxy_temp_path /tmp/proxy_temp;
        client_body_temp_path /tmp/client_temp;
        fastcgi_temp_path /tmp/fastcgi_temp;
        uwsgi_temp_path /tmp/uwsgi_temp;
        scgi_temp_path /tmp/scgi_temp;

        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

        access_log  /var/log/nginx/access.log  main;

        sendfile        on;
        #tcp_nopush     on;

        port_in_redirect off;

        keepalive_timeout  65;

        #gzip  on;

        include /etc/nginx/conf.d/*.conf;


apiVersion: apps/v1
kind: Deployment
  name: coffee
  replicas: 3
      app: coffee
        app: coffee
      - name: www
        image: nginxinc/nginx-unprivileged
        - containerPort: 8080
        - name: nginx-conf
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
          readOnly: true


apiVersion: v1
kind: Service
  name: coffee-svc
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
    app: coffee