Using DNS over HTTPS aka DoH is fairly easy with the latest version of firefox. To use libredns is just a few settings in your browser, see here. In libredns’ site, there are also instructions for DNS over TLS aka DoT.
In this blog post, I am going to present how to use dnscrypt-proxy as a local dns proxy resolver using DoH the LibreDNS noAds (tracking) endpoint. With this setup, your entire operating system can use this endpoint for everything.
Disclaimer: This blog post is about dnscrypt-proxy version 2.
dnscrypt-proxy 2 - A flexible DNS proxy, with support for modern encrypted DNS protocols such as DNSCrypt v2, DNS-over-HTTPS and Anonymized DNSCrypt.
sudo pacman -S dnscrypt-proxy
$ pacman -Qi dnscrypt-proxy Name : dnscrypt-proxy Version : 2.0.39-3 Description : DNS proxy, supporting encrypted DNS protocols such as DNSCrypt v2 and DNS-over-HTTPS Architecture : x86_64 URL : https://dnscrypt.info Licenses : custom:ISC Groups : None Provides : None Depends On : glibc Optional Deps : python-urllib3: for generate-domains-blacklist [installed] Required By : None Optional For : None Conflicts With : None Replaces : None Installed Size : 12.13 MiB Packager : David Runge <email@example.com> Build Date : Sat 07 Mar 2020 08:10:14 PM EET Install Date : Fri 20 Mar 2020 10:46:56 PM EET Install Reason : Explicitly installed Install Script : Yes Validated By : Signature
$ ps -e fuwww | grep re[s]olv systemd+ 525 0.0 0.1 30944 21804 ? Ss 10:00 0:01 /usr/lib/systemd/systemd-resolved $ sudo systemctl stop systemd-resolved.service $ sudo systemctl disable systemd-resolved.service Removed /etc/systemd/system/multi-user.target.wants/systemd-resolved.service. Removed /etc/systemd/system/dbus-org.freedesktop.resolve1.service.
It is time to configure dnscrypt-proxy to use libredns
sudo vim /etc/dnscrypt-proxy/dnscrypt-proxy.toml
In the top of the file, there is a server_names section
server_names = ['libredns-noads']
We can now change our resolv.conf to use our local IP address.
echo -e "nameserver 127.0.0.1noptions edns0 single-request-reopen" | sudo tee /etc/resolv.conf
$ cat /etc/resolv.conf nameserver 127.0.0.1 options edns0 single-request-reopen
start & enable dnscrypt service
sudo systemctl start dnscrypt-proxy.service sudo systemctl enable dnscrypt-proxy.service
$ sudo ss -lntup '( sport = :domain )' Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process udp UNCONN 0 0 127.0.0.1:53 0.0.0.0:* users:(("dnscrypt-proxy",pid=55795,fd=6)) tcp LISTEN 0 4096 127.0.0.1:53 0.0.0.0:* users:(("dnscrypt-proxy",pid=55795,fd=7))
$ dnscrypt-proxy -config /etc/dnscrypt-proxy/dnscrypt-proxy.toml -list libredns-noads
$ dnscrypt-proxy -config /etc/dnscrypt-proxy/dnscrypt-proxy.toml -resolve balaskas.gr Resolving [balaskas.gr] Domain exists: yes, 2 name servers found Canonical name: balaskas.gr. IP addresses: 126.96.36.199, 2a03:f80:49:158:255:214:14:80 TXT records: v=spf1 ip4:188.8.131.52/31 ip6:2a03:f80:49:158:255:214:14:0/112 -all Resolver IP: 184.108.40.206 (libredns.gr.)
asking our local dns (proxy)
dig @localhost balaskas.gr
; <<>> DiG 9.16.1 <<>> @localhost balaskas.gr ; (2 servers found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2449 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;balaskas.gr. IN A ;; ANSWER SECTION: balaskas.gr. 7167 IN A 220.127.116.11 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Sat Mar 21 19:48:53 EET 2020 ;; MSG SIZE rcvd: 56
That’s it !
Yoursystem is now using LibreDNS DoH noads endpoint.
If your operating system does not yet support dnscrypt-proxy-2 then:
You can always download the latest version from github:
To view the files
curl -sLo - $(curl -sL https://api.github.com/repos/DNSCrypt/dnscrypt-proxy/releases/latest | jq -r '.assets.browser_download_url | select( contains("linux_x86_64"))') | tar tzf - linux-x86_64/ linux-x86_64/dnscrypt-proxy linux-x86_64/LICENSE linux-x86_64/example-cloaking-rules.txt linux-x86_64/example-dnscrypt-proxy.toml linux-x86_64/example-blacklist.txt linux-x86_64/example-whitelist.txt linux-x86_64/localhost.pem linux-x86_64/example-ip-blacklist.txt linux-x86_64/example-forwarding-rules.txt
To extrace the files
$ curl -sLo - $(curl -sL https://api.github.com/repos/DNSCrypt/dnscrypt-proxy/releases/latest | jq -r '.assets.browser_download_url | select( contains("linux_x86_64"))') | tar xzf - $ ls -l linux-x86_64/ total 9932 -rwxr-xr-x 1 ebal ebal 10117120 Μαρ 21 13:56 dnscrypt-proxy -rw-r--r-- 1 ebal ebal 897 Μαρ 21 13:50 example-blacklist.txt -rw-r--r-- 1 ebal ebal 1277 Μαρ 21 13:50 example-cloaking-rules.txt -rw-r--r-- 1 ebal ebal 20965 Μαρ 21 13:50 example-dnscrypt-proxy.toml -rw-r--r-- 1 ebal ebal 970 Μαρ 21 13:50 example-forwarding-rules.txt -rw-r--r-- 1 ebal ebal 439 Μαρ 21 13:50 example-ip-blacklist.txt -rw-r--r-- 1 ebal ebal 743 Μαρ 21 13:50 example-whitelist.txt -rw-r--r-- 1 ebal ebal 823 Μαρ 21 13:50 LICENSE -rw-r--r-- 1 ebal ebal 2807 Μαρ 21 13:50 localhost.pem $ cd linux-x86_64/
Prepare the configuration
$ cp example-dnscrypt-proxy.toml dnscrypt-proxy.toml $ $ vim dnscrypt-proxy.toml
In the top of the file, there is a server_names section
server_names = ['libredns-noads']
$ ./dnscrypt-proxy -config dnscrypt-proxy.toml --list [2020-03-21 19:27:20] [NOTICE] dnscrypt-proxy 2.0.40 [2020-03-21 19:27:20] [NOTICE] Network connectivity detected [2020-03-21 19:27:22] [NOTICE] Source [public-resolvers] loaded [2020-03-21 19:27:23] [NOTICE] Source [relays] loaded libredns-noads
Run as root
$ sudo ./dnscrypt-proxy -config ./dnscrypt-proxy.toml [sudo] password for ebal: ******* [2020-03-21 20:11:04] [NOTICE] dnscrypt-proxy 2.0.40 [2020-03-21 20:11:04] [NOTICE] Network connectivity detected [2020-03-21 20:11:04] [NOTICE] Source [public-resolvers] loaded [2020-03-21 20:11:04] [NOTICE] Source [relays] loaded [2020-03-21 20:11:04] [NOTICE] Firefox workaround initialized [2020-03-21 20:11:04] [NOTICE] Now listening to 127.0.0.1:53 [UDP] [2020-03-21 20:11:04] [NOTICE] Now listening to 127.0.0.1:53 [TCP] [2020-03-21 20:11:04] [NOTICE] [libredns-noads] OK (DoH) - rtt: 65ms [2020-03-21 20:11:04] [NOTICE] Server with the lowest initial latency: libredns-noads (rtt: 65ms) [2020-03-21 20:11:04] [NOTICE] dnscrypt-proxy is ready - live servers: 1
Interesting enough, first time is 250ms , second time is zero!
$ dig libredns.gr ; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> libredns.gr ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53609 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;libredns.gr. IN A ;; ANSWER SECTION: libredns.gr. 2399 IN A 18.104.22.168 libredns.gr. 2399 IN A 22.214.171.124 ;; Query time: 295 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Sat Mar 21 20:12:52 EET 2020 ;; MSG SIZE rcvd: 72 $ dig libredns.gr ; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> libredns.gr ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31159 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;libredns.gr. IN A ;; ANSWER SECTION: libredns.gr. 2395 IN A 126.96.36.199 libredns.gr. 2395 IN A 188.8.131.52 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Sat Mar 21 20:12:56 EET 2020 ;; MSG SIZE rcvd: 72
almost three (3) years ago I wrote an article about the Tools I use daily. But for the last 18 months (or so), I am partial using windows 10 due to my new job role, thus I would like to write an updated version on that article.
I’ ll try to use the same structure for comparison as the previous article, keep in mind this a nine to five setup (work related). So here it goes.
NOTICE beer is just for decor ;)
I use Win10 as my primary operating system in my worklaptop. I have a couple of impediments that can not work on a linux distribution but I am not going to bother you with them (it’s webex and some internal internet-explorer only sites).
We used to use webex as our primary communication tool. We are sharing our screen and have our video camera on, so that everybody can see each other.Working with remote teams, it’s kind of nice to see the faces of your coworkers. A lot of meetings are integrated with the company’s outlook. I use OWA (webmail) as an alternative but in fact it is still difficult to use both of them with a linux desktop.
We successful switched to slack for text communications, video calls and screen sharing. This choice gave us a boost in productivity as we are now daily using slack calls to align with each other. Although still webex is in the mix. Company is now using a newer webex version that works even better with browser support so that is a plus. It’s not always easy to get everybody with a webex license but as long as we are using slack it is okay. Only problem with slack in linux is when working with multiple monitors, you can not choose which monitor to share.
I have considered to use a VM (virtual machine) but a win10 vm needs more than 4G of RAM and a couple of CPUs just to boot up. In that case, it means that I have to reduce my work laptop resources for half the day, every day. So for the time being I am staying with Win10 as the primary operating system. I have to use the winVM for some other internal works but it is limited time.
Default Win10 desktop
I daily use these OpenSource Tools:
- AutoHotkey for keyboard shortcut (I like switching languages by pressing capslock)
- Ditto as clipboard manager
- Greenshot for screenshot tool
and from time to time, I also use:
- X-Mouse Controls (window focus with mouse)
- Always on Top to Keep Any Window Visible Always
- Plumb a Tiling Window Manager
except plumb, everything else is opensource!
So I am trying to have the same user desktop experience as in my Linux desktop, like my language swith is capslock (authotkey), I dont even think about it.
Disk / Filesystem
Default Win10 filesystem with bitlocker. Every HW change will lock the entire system. In the past this happened twice with a windows firmware device upgrade. Twice!
(same setup as linux, except bitlocker is luks)
OWA for calendar purposes and … still Thunderbird for primary reading mails.
Thunderbird 68.6.0 AddOns:
- Provider for CalDAV & CardDAV
- ExQuilla for Exchange
- Toggle Headers
- Duplicate Contacts Manager
- Remove Duplicates
- Expression Search / GMailUI
- Mail Redirect
- Markdown Here
- Open With
(same setup as linux)
Windows Subsystem for Linux aka WSL … waiting for the official WSLv2 ! This is a huge HUGE upgrade for windows. I have setup an Arch Linux WSL environment to continue work on a linux environment, I mean bash. I use my WSL archlinux as a jumphost to my VMs.
- Mintty The best terminal emulator for WSL. Small, not to fancy, just works, beautiful, love it.
(same setup as linux)
Primary Browser: Firefox
Primary Private Browsing: Brave
(same setup as linux)
(same setup as linux - minus the Viber client)
(same setup as linux)
I have switched to a majority of electron applications. I use the same applications on my Linux boxes. Encrypted notes on boostnote, synced over syncthing. Same browsers, same bash/shell, the only thing I dont have on my linux boxes are webex and outlook. Consider everything else, I think it is a decent setup across every distro.
Thanks for reading my post.
restic is a fast, secure & efficient backup program.
I wanted to test restic for some time now. It is a go backup solution, I would say similar to rclone but it has a unique/different design. I prefer having an isolated clean environment when testing software, so I usually go with a VΜ. For this case, I installed elementary OS v5.1, an ubuntu LTS based distro focus on user experience. As backup storage solution, I used MinIO an S3 compatible object storage on the same VM. So here are my notes on restic and in the end of this article you will find how I setup minion.
Be aware this is a technical post!
Most probably your distro package manager has already restic in their repositories.
pacman -S restic or apt -y install restic
download latest version
But just in case you want to install the latest binary version, you can use this command
curl -sLo - $(curl -sL https://api.github.com/repos/restic/restic/releases/latest | jq -r '.assets.browser_download_url | select( contains("linux_amd64"))') \ | bunzip2 - | sudo tee /usr/local/bin/restic > /dev/null sudo chmod +x /usr/local/bin/restic
or if you are already root
curl -sLo - $(curl -sL https://api.github.com/repos/restic/restic/releases/latest | jq -r '.assets.browser_download_url | select( contains("linux_amd64"))') \ | bunzip2 - > /usr/local/bin/restic chmod +x /usr/local/bin/restic
we can see the latest version
$ restic version restic 0.9.6 compiled with go1.13.4 on linux/amd64
sudo restic generate --bash-completion /etc/bash_completion.d/restic
restart your shell.
Prepare your repo
We need to prepare our destination repository. This is our backup endpoint. restic can save multiple snapshots for multiple hosts on the same endpoint (repo).
Apart from the files stored within the keys directory, all files are encrypted with AES-256 in counter mode (CTR). The integrity of the encrypted data is secured by a Poly1305-AES message authentication code (sometimes also referred to as a “signature”).
To access a restic repo, we need a key. We will use this key as password (or passphrase) and it is really important NOT to lose this key.
For automated backups (or scripts) we can use the environmental variables of our SHELL to export the password. It is best to export the password through a script or even better through a password file.
export -p RESTIC_PASSWORD=<our key> or export -p RESTIC_PASSWORD_FILE=<full path of 0400 file>
export -p RESTIC_PASSWORD=55C9225pXNK3s3f7624un
We can also declare the restic repository through an environmental variable
export -p RESTIC_REPOSITORY=<our repo>
An example of local backup repo should be something like this:
$ cat restic.local.conf export -p RESTIC_PASSWORD=55C9225pXNK3s3f7624un export -p RESTIC_REPOSITORY="/mnt/backup/"
We are going to use minio as an S3 object storage, so we need to export the Access & Sercet Key in a similar way as for amazon S3.
AccessKey <~> AWS_ACCESS_KEY_ID SecretKey <~> AWS_SECRET_ACCESS_KEY
export -p AWS_ACCESS_KEY_ID=minioadmin export -p AWS_SECRET_ACCESS_KEY=minioadmin
The S3 endpoint is
http://localhost:9000/demo so a full example should be:
$ cat restic.S3.conf export -p AWS_ACCESS_KEY_ID=minioadmin export -p AWS_SECRET_ACCESS_KEY=minioadmin export -p RESTIC_PASSWORD=55C9225pXNK3s3f7624un export -p RESTIC_REPOSITORY="s3:http://localhost:9000/demo"
source the config file into your shell:
We are ready to initialise the remote repo
$ restic init created restic repository f968b51633 at s3:http://localhost:9000/demo Please note that knowledge of your password is required to access the repository. Losing your password means that your data is irrecoverably lost.
Be Careful if you asked to type a password, that means that you did not use a shell environmental variable to export a password. That is fine, but only if that was your purpose. Then you will see something like that:
$ restic init enter password for new repository: <type your password here> enter password again: <type your password here, again> created restic repository ea97171d56 at s3:http://localhost:9000/demo Please note that knowledge of your password is required to access the repository. Losing your password means that your data is irrecoverably lost. enter password for new repository: enter password again: created restic repository ea97171d56 at s3:http://localhost:9000/demo Please note that knowledge of your password is required to access the repository. Losing your password means that your data is irrecoverably lost.
We are ready to take our first snapshot.
$ restic -v backup /home/ebal/ open repository repository c8d9898b opened successfully, password is correct created new cache in /home/ebal/.cache/restic lock repository load index files start scan on [/home/ebal/] start backup on [/home/ebal/] scan finished in 0.567s: 2295 files, 307.823 MiB Files: 2295 new, 0 changed, 0 unmodified Dirs: 1 new, 0 changed, 0 unmodified Data Blobs: 2383 new Tree Blobs: 2 new Added to the repo: 263.685 MiB processed 2295 files, 307.823 MiB in 0:28 snapshot 33e8ae0d saved
You can exclude or include files with restic, but I will not get into this right now.
For more info, read Restic Documentation
restic can also take for backup:
mysqldump --all-databases -uroot -ppassword | xz - | restic --stdin --stdin-filename mysqldump.sql.bz2
$ restic -v check using temporary cache in /tmp/restic-check-cache-528400534 repository c8d9898b opened successfully, password is correct created new cache in /tmp/restic-check-cache-528400534 create exclusive lock for repository load indexes check all packs check snapshots, trees and blobs no errors were found
Take another snapshot
$ restic -v backup /home/ebal/ --one-file-system --cleanup-cache open repository repository c8d9898b opened successfully, password is correct lock repository load index files using parent snapshot 33e8ae0d start scan on [/home/ebal/] start backup on [/home/ebal/] scan finished in 0.389s: 2295 files, 307.824 MiB Files: 0 new, 4 changed, 2291 unmodified Dirs: 0 new, 1 changed, 0 unmodified Data Blobs: 4 new Tree Blobs: 2 new Added to the repo: 154.549 KiB processed 2295 files, 307.824 MiB in 0:01 snapshot 280468f6 saved
$ restic -v snapshots repository c8d9898b opened successfully, password is correct ID Time Host Tags Paths ----------------------------------------------------------------- 6988dda7 2020-03-14 23:32:55 elementary /etc 33e8ae0d 2020-03-15 21:05:55 elementary /home/ebal 280468f6 2020-03-15 21:08:38 elementary /home/ebal ----------------------------------------------------------------- 3 snapshots
as you can see, I had one more snapshot before my home dir and I want to remove it
$ restic -v forget 6988dda7 repository c8d9898b opened successfully, password is correct removed snapshot 6988dda7
$ restic -v snapshots repository c8d9898b opened successfully, password is correct ID Time Host Tags Paths ----------------------------------------------------------------- 33e8ae0d 2020-03-15 21:05:55 elementary /home/ebal 280468f6 2020-03-15 21:08:38 elementary /home/ebal ----------------------------------------------------------------- 2 snapshots
$ restic -v diff 33e8ae0d 280468f6 repository c8d9898b opened successfully, password is correct comparing snapshot 33e8ae0d to 280468f6: M /home/ebal/.config/dconf/user M /home/ebal/.mozilla/firefox/pw9z9f9z.default-release/SiteSecurityServiceState.txt M /home/ebal/.mozilla/firefox/pw9z9f9z.default-release/datareporting/aborted-session-ping M /home/ebal/.mozilla/firefox/pw9z9f9z.default-release/storage/default/moz-extension+++62b23386-279d-4791-8ae7-66ab3d69d07d^userContextId=4294967295/idb/3647222921wleabcEoxlt-eengsairo.sqlite Files: 0 new, 0 removed, 4 changed Dirs: 0 new, 0 removed Others: 0 new, 0 removed Data Blobs: 4 new, 4 removed Tree Blobs: 14 new, 14 removed Added: 199.385 KiB Removed: 197.990 KiB
Mount a snapshot
$ mkdir -p backup $ restic -v mount backup/ repository c8d9898b opened successfully, password is correct Now serving the repository at backup/ When finished, quit with Ctrl-c or umount the mountpoint.
open another terminal
$ cd backup/ $ ls -l total 0 dr-xr-xr-x 1 ebal ebal 0 Μαρ 15 21:12 hosts dr-xr-xr-x 1 ebal ebal 0 Μαρ 15 21:12 ids dr-xr-xr-x 1 ebal ebal 0 Μαρ 15 21:12 snapshots dr-xr-xr-x 1 ebal ebal 0 Μαρ 15 21:12 tags $ ls -l hosts/ total 0 dr-xr-xr-x 1 ebal ebal 0 Μαρ 15 21:12 elementary $ ls -l snapshots/ total 0 dr-xr-xr-x 3 ebal ebal 0 Μαρ 15 21:05 2020-03-15T21:05:55+02:00 dr-xr-xr-x 3 ebal ebal 0 Μαρ 15 21:08 2020-03-15T21:08:38+02:00 lrwxrwxrwx 1 ebal ebal 0 Μαρ 15 21:08 latest -> 2020-03-15T21:08:38+02:00 $ ls -l tags total 0
So as we can see, snapshots are based on time.
$ du -sh snapshots/* 309M snapshots/2020-03-15T21:05:55+02:00 309M snapshots/2020-03-15T21:08:38+02:00 0 snapshots/latest
be aware as far as we have mounted the restic backup, there is a lock on the repo.
Do NOT forget to close the mount point when finished.
When finished, quit with Ctrl-c or umount the mountpoint. signal interrupt received, cleaning up
you may need to re-check to see if there is a lock on the repo
$ restic check using temporary cache in /tmp/restic-check-cache-524606775 repository c8d9898b opened successfully, password is correct created new cache in /tmp/restic-check-cache-524606775 create exclusive lock for repository load indexes check all packs check snapshots, trees and blobs no errors were found
Restore a snapshot
Identify which snapshot you want to restore
$ restic snapshots repository c8d9898b opened successfully, password is correct ID Time Host Tags Paths ----------------------------------------------------------------- 33e8ae0d 2020-03-15 21:05:55 elementary /home/ebal 280468f6 2020-03-15 21:08:38 elementary /home/ebal ----------------------------------------------------------------- 2 snapshots
create a folder and restore the snapshot
$ mkdir -p restore $ restic -v restore 280468f6 --target restore/ repository c8d9898b opened successfully, password is correct restoring <Snapshot 280468f6 of [/home/ebal] at 2020-03-15 21:08:38.10445053 +0200 EET by ebal@elementary> to restore/
$ ls -l restore/ total 4 drwxr-xr-x 3 ebal ebal 4096 Μαρ 14 13:56 home $ ls -l restore/home/ total 4 drwxr-xr-x 17 ebal ebal 4096 Μαρ 15 20:13 ebal $ du -sh restore/home/ebal/ 287M restore/home/ebal/
List files from snapshot
$ restic -v ls 280468f6 | head snapshot 280468f6 of [/home/ebal] filtered by  at 2020-03-15 21:08:38.10445053 +0200 EET): /home /home/ebal /home/ebal/.ICEauthority /home/ebal/.Xauthority /home/ebal/.bash_history /home/ebal/.bash_logout /home/ebal/.bashrc /home/ebal/.cache /home/ebal/.cache/.notifications.session
$ restic key list repository ea97171d opened successfully, password is correct ID User Host Created ------------------------------------------------ *8c112442 ebal elementary 2020-03-14 23:22:49 ------------------------------------------------
restic rotate snapshot policy
a few more words about forget
Forget mode has a feature of keep last
TIME snapshots, where
time can be
- number of snapshots
and makes restic with local feature an ideally replacement for rsnapshot!
$ restic help forget The "forget" command removes snapshots according to a policy. Please note that this command really only deletes the snapshot object in the repository, which is a reference to data stored there. In order to remove this (now unreferenced) data after 'forget' was run successfully, see the 'prune' command. Flags: -l, --keep-last n keep the last n snapshots -H, --keep-hourly n keep the last n hourly snapshots -d, --keep-daily n keep the last n daily snapshots -w, --keep-weekly n keep the last n weekly snapshots -m, --keep-monthly n keep the last n monthly snapshots -y, --keep-yearly n keep the last n yearly snapshots
Appendix - minio
MinIO is a s3 compatible object storage.
sudo curl -sLo /usr/local/bin/minio \ https://dl.min.io/server/minio/release/linux-amd64/minio sudo chmod +x /usr/local/bin/minio minio --version minio version RELEASE.2020-03-14T02-21-58Z
minio server ./data
create demo bucket
sudo curl -sLo /usr/local/bin/mc https://dl.min.io/client/mc/release/linux-amd64/mc sudo chmod +x /usr/local/bin/mc mc -v mc version RELEASE.2020-03-14T01-23-37Z
mc config host add myminio http://192.168.122.31:9000 minioadmin minioadmin
run mc client
$ mc ls myminio [2020-03-14 19:01:25 EET] 0B demo/ $ mc tree myminio/demo $
you need to restart your shell.
$ mc ls myminio/demo/ [2020-03-15 21:03:15 EET] 155B config [2020-03-15 21:34:13 EET] 0B data/ [2020-03-15 21:34:13 EET] 0B index/ [2020-03-15 21:34:13 EET] 0B keys/ [2020-03-15 21:34:13 EET] 0B snapshots/
The other day I was thinking about my first ever job in this industry as a junior software engineer at the age of 20. I was doing okay with my studies at the Athens university of applied sciences but I was working outside of this industry. I had to gain some working experience in the field, so I made a decision to find part time work in a small software house. The (bad) experience and lessons learned in those couple weeks are still with me till this day … almost 20 years after!
I got a flyer from the job board at school and I walked a couple of kilometers to the address of the place. I didn’t have a car back then (or for the next 7 years), so I had to use public transportation (bus) or walk wherever I wanted to go. I rang the doorbell around noon and went up on the second floor. There I introduced myself and asked for an opportunity to work with them. The owner/head of software team asked me a few things and got to the technical parts of the job.
- We are working with visual studio, but we are using HTML pages as forms for our product. In a sense we have copied the Amazon model!
Impressed, that I was going to work with the next amazon, I immediately said Yes to the offer.
- Do you know HTML ?
- No, but I am a quick study.
He smiled at me and gave me (I think) this 800 pages book to read about HTML4.
He then told me:
- Read this book and come back when you finished it.
That was Friday noon.
I spent 10 hours quickly reading the book and keeping notes. Then I made a static demo site about Milos Island, where I had spent two weeks in the summer with my girlfriend. I had photos and material to write about, so I did that as an exercise.
Monday morning, I was presenting him with my homework. He didn’t believe me and spent a couple of hours talking about HTML4, just to prove that I had made the site, reading the book he gave me. In the end he was convinced.
My next assignment was to learn about Visual Basic and Visual Studio. I had a basic idea about this but I had never worked as a professional programmer, so he prepared a few coding exercises to get familiar with the codebase. This was my onboarding period.
- Take this exercise and come back when you finish it. It will take you about a week.
Next day, I was again first in the office.
- So you came back to ask for help. That is okay. You should ask for help but you need to make an effort to do it yourself.
- I finished it, it was easy.
- Really? Then here is your next assignment. This is more difficult. Come back when you finished it.
Next day … I was back in the office.
- I finished it, what is next ?
- Okay, read this today and come back tomorrow.
Read it, returned the next day.
- Okay, I need you to sit here and work on the next assignments. I want to see how you are working on these coding exercises for myself.
Next two days, worked there on coding exercises to get familiar with their codebase. He was impressed and I was very happy.
Next day (Friday):
- You now have access to our production code. Here are your tasks, whenever your finish something I want to see it. But before all that, here is a copy of our product. Today you will test it and report any bugs that you think we need to fix.
I took this task as my personal goal to prove myself. Worked ten hours that day and made a few comments on how to improve customer experience.
I asked if I can take the CD back with me at home and tested it on my personal computer.
It was a windows executable and the installer was pretty decent.
Next, next, install, done.
My windows 98 second edition didn’t have enough free space on my hard disk, and I needed to also install oracle to work on my semester lab exercises. My 8G hard disk and the gazillion of floppy disks around my home office on my Pentium III was my entire kingdom back then. So I uninstalled the application and rebooted my computer.
Then something horrible happened. My computer could not start the operating system. There were indications of missing DLLs.
I re-installed (repair) windows and was curious about what happened.
I re-installed the application and re-uninstalled it once more.
Reboot Windows and again missing DLLs.
I returned on Monday morning at the office and explained in details the extreme bug I had found. When a customer removes our software, they would corrupt their operating system. The majority of our customers didn’t have the technical experience to fix this problem. So I made it very clear that this is something we need to fix ASAP and we should inform every customer not to remove our application and reboot their machine. I was really proud that I had found this super bug and that we were going to save our company.
And then the owner told me:
- Our customers are paying us for installation of our software application. They are not paying us for fixing their computer problems.
- But this is something we introduced.
- Do not be silly, we are professionals, we do not make mistakes.
- But …
- No butts, this is not our problem.
First business lesson was:
- We do not make mistakes, customers should pay us for fixing our bugs!
The next thing was to check the installer. We’ve noticed that they had marked a few windows DLLs as important to be there for our application to run. To avoid any mistakes we copied these DLLs from the application’s CD to our customer’s windows. The uninstallation process, was removing everything that installed so … the windows DLLs were gone! It was a simple mistake and easy to fix. Click on the correct checkbox for those files, not to be removed during the uninstallation process.
We needed to distribute our application to all 2.000 customers all over Greece. We had to burn 2.000 physical CD’s, print 2.000 CD covers, compile 2.000 CD cases and put them in 2.000 envelopes and write 2.000 addresses on the envelopes. Then visit the local post office, pay for stamps etc and mail 2.000 CDs to our customer’s snail addresses.
We also had to provide letters of instructions:
- Uninstall the previous version
- Install the new version
in any circumstance do not reboot your PC till the new version is up and running. Then copy your license key into the program and connect to the internet to upload your contracts/data or sync your data from the central database to your laptop/desktop.
For every patch (that meant a new CD to sent) our business model was to get money from our customers for our work and any expenses for distributing these CDs around Greece. That was the business deal with our customers. Customers were paying us, for our mistakes and could also take a week or so to get the fix. Depending on the post office delays. License keys were valid (I am not sure but I believe) for a year and then there was a subscription model for the patches. If customers wanted to subscribe. then they should pay us for every CD, for every patch, for every mistake. Our business model depended on that.
For some reasons I had opinions about this effort. I made a suggestion to use our web server (web site) to provide the patch, so the customers can download from the internet and install it immediately without waiting for weeks till we sent the next CD with the latest version. Also ,no need of extra money for the post office or CDs or burning 2.000 CDs through the weekend. Customers should pay for the patch (our work) so this way would be best for everybody.
The owner replied to me, that they made more money with the current system, so no need of making things easier or cheaper for customers and I should keep this innovated ideas to myself.
At that point, the thought that I wasn’t working for the next amazon came in mind. They would put this extra profit on top of their customer’s needs.
Finally, after my first week as an employee, I was now writing code as a software engineer. I did an impressive work of fixing bugs and refactoring code and in a sense made our product better, faster and safer. I had ideas and worked closely with the senior programmer on a few things. I was doing good, working fast, learning and providing value.
I’ve noticed a specific coding style so I kept it. The senior programmer could read my code and comments (I wrote a lot of comments) and vice versa. Finally I had joy from my work as a programmer.
I vividly remember a specific coding issue, even 20 years after it happened. There was a form with 10 buttons. 10 clicks were the maximum possible events on this form. So I wrote a case statement of 9 events and one default. I submitting the code and the owner/head software programmer came to the office yelling at me.
- I’ve started reviewing your code and I can not read it. Why you are writing code like this. this is shit code. Case statements!!! No no no no. I want from you to write the same code as I write, so I can read/review it.
- But your example is a nested if-then-else for 11 events and we only have 10 events there. I made a case statement of 9 events and a default. It’s better.
- No, this is not better, it’s shit. I can not review your code. I want you to delete everything and start from the beginning. I want to read your code and think that I was writing this code instead of you.
- I am sorry, but I think your are wrong on this. This is better, trust me. I worked closely with our senior programmer and we believe this is better.
- No, remove everything.
after a couple of hours
- So I need to talk with you.
- Sure, what can I do for you?
- I think this collaboration is not working between you and us.
- okay, I am really sorry about that. Can I please ask what are the problems so that I can improve in the future. This is my first job.
The truth bomb:
- You have all these new ideas to disturb our business model and cash flow. Using the web server to publish and distribute patches? Come on, you are very young to give me advice on how to run my business. you do not know anything.
- You made a lot of comments and suggestions about what we are doing wrong. This should never be the case, especially if you are talking to customers. We never make mistakes and we need to be paid for every customer request. I never make mistakes. I have a master’s degree in computer science and you are still a student. If something is wrong, customers should make a request and we are going to make a patch. That’s it.
- Finally ,you are writing code that I can not read/review. I am the head software engineer and I need from you to write code as I write code. You should never introduce anything new that I can not read.
Two weeks, I felt like really shit. I felt like I didn’t know anything about business but he paid me for the whole month.
After all these years, I now believe that he was afraid of my ideas. Of using the internet to help our business and reduce customer’s costs but the most important was he was afraid that new people came to his business and wrote code that he could not understand.
I made a promise that day to myself, that last Friday from my very first job:
- I will try always to do my best in this industry.
Almost 20 years have past from those two weeks, I never worked as a programmer, I chose to work as a sysadmin, mostly doing operations.
Thankfully I think I am doing well. So here, to the next 20 years ahead.
Thank you for reading my story.
Origin Post on LinkedIn, Published on January 6, 2020
Being abroad in Japan the last couple weeks, I’ve noticed that the high efficiency -from crossing roads to almost everything- they do (cooking/public transportation/etc) is due to the fact of using small queues for every step of the process. Reaching to a maximum throughout with small effort.
The culture of small batches/queues reminds me the core principles of #DevOps as they have identified in the book “The Goal: A Process of Ongoing Improvement” by Eli Goldratt and of course in “Theory of Constraints”.
Imagine this culture to everything you do in your life. From work to your personal life. Reducing any unnecessary extra cost, reducing waste by performing Kata. Kata is about form, from dancing to creating your cloud infrastructure with reproducible daily work or routines that are focusing in the process for reaching your business goals.
This truly impresses me in Japanese culture among with the respect they are showing to each other. You may of course notice the young people riding their bicycles in the middle of the street, watching their smartphone instead of the road 😀but the majority of people bow their head to show respect to other people and other people’s work or service.
We, sometimes forget this simple rule in our work. Sometimes the pressure, the deadlines or the plethora of open tickets in our Jira board (or boards) makes us cranky with our colleagues. We forget to show our respect to other people work. We forget that we need each other for reaching to our business values as a team.
We forget to have fun and joy. To be productive is not about closing tickets is about using your creativity to solve problems or provide a new or improve an old feature that can make your customers happy.
Is about the feedback you will get from your customers and colleagues, is about the respect to your work. Is about being happy.
For the first time in my life, I took almost 30days out of work, to relax, to detox (not having a laptop with me) to spend some time with family and friends. To be happy. So if any colleague from work is reading this article:
- Domo arigato
Happy new year (2020) to everybody. I wish you all good health and happiness.
PS: I am writing this article in a superexpress speed train going to Hiroshima, at 300 km/h