<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>matoski.com on matoski.com</title>
        <link>https://matoski.com/</link>
        <description>Recent content in matoski.com on matoski.com</description>
        
        <language>en-us</language>
        <copyright>(c) 2017 Ilija Matoski</copyright>
        <lastBuildDate>Tue, 27 Nov 2018 13:14:21 +0000</lastBuildDate>
        <atom:link href="/" rel="self" type="application/rss+xml" />
        
        <item>
            <title>Automatic collection of prometheus metrics, cadvisor and grafana in Docker Swarm</title>
            <link>https://matoski.com/article/golang-prometheus-cadvisor-grafana/</link>
            <pubDate>Tue, 27 Nov 2018 13:14:21 +0000</pubDate>
            
            <guid>https://matoski.com/article/golang-prometheus-cadvisor-grafana/</guid>
            <description>&lt;p&gt;Last time in were exposing some metrics for a golang application, but exposing the data is useless without having a way to visualise it or even store it somewhere in a location so we can analyze it when needed.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Some of the tools that we can use to do this are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://prometheus.io/&#34;&gt;Prometheus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/google/cadvisor&#34;&gt;cAdvisor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://grafana.com/&#34;&gt;Grafana&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, I will assume have a docker swarm cluster available and ready to use.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s create a stack file that will allow us to replicate this one on another swarm easily.
All the required resources are on &lt;a href=&#34;https://github.com/ilijamt/gomeetupamsnov2018&#34;&gt;github.com/ilijamt/gomeetupamsnov2018&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need some prerequisites first&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network for the monitoring applications&lt;/li&gt;
&lt;li&gt;Node metrics exporter/prometheus&lt;/li&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;Grafana&lt;/li&gt;
&lt;li&gt;cAdvisor&lt;/li&gt;
&lt;li&gt;Application that will expose metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let&amp;rsquo;s create a very simple application that will build a small service that will expose various metrics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;main.go&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;package main

import (
	&amp;quot;github.com/prometheus/client_golang/prometheus&amp;quot;
	&amp;quot;github.com/prometheus/client_golang/prometheus/promhttp&amp;quot;
	&amp;quot;net/http&amp;quot;
)

func main() {
	prometheus.MustRegister(prometheus.NewGauge(prometheus.GaugeOpts{
		Name: &amp;quot;version&amp;quot;,
		Help: &amp;quot;Version information about this service&amp;quot;,
		ConstLabels: map[string]string{
			&amp;quot;version&amp;quot;: &amp;quot;v1.1.51&amp;quot;,
			&amp;quot;service&amp;quot;: &amp;quot;demo&amp;quot;,
		},
	}))

	http.Handle(&amp;quot;/metrics&amp;quot;, promhttp.Handler())
	if err := http.ListenAndServe(&amp;quot;:2112&amp;quot;, nil); err != nil {
		panic(err)
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need to create 2 services off the code and build create the docker images, running these commands will build and tag the images&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;docker build demo-v1 -t gomeetup-demo-v1:latest
docker build demo-v2 -t gomeetup-demo-v2:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I think everyone should be able to understand the stack file bellow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;stack.yaml&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;version: &amp;quot;3&amp;quot;

networks:
  monitoring:
  api:

services:
  demo_service_v1:
    image: gomeetup-demo-v1:latest
    deploy:
      mode: replicated
      replicas: 6
    networks:
      - monitoring
      - api
  demo_service_v2:
    image: gomeetup-demo-v2:latest
    deploy:
      mode: replicated
      replicas: 4
    networks:
      - monitoring
      - api
  cadvisor:
    image: google/cadvisor:latest
    deploy:
      mode: global
    ports:
      - &amp;quot;8080:8080&amp;quot;
    volumes:
      - /var/lib/docker/:/var/lib/docker
      - /dev/disk/:/dev/disk
      - /sys:/sys
      - /var/run:/var/run
      - /:/rootfs
      - /dev/zfs:/dev/zfs
    networks:
      - monitoring
  grafana:
    image: grafana/grafana
    ports:
      - &amp;quot;3000:3000&amp;quot;
    volumes:
      - ./data/grafana:/var/lib/grafana:rw
    deploy:
      mode: replicated
      replicas: 1
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_USERS_ALLOW_SIGN_UP=false
    networks:
      - monitoring
  prometheus:
    image: prom/prometheus:latest
    ports:
      - &#39;9090:9090&#39;
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./data/prometheus:/prometheus:rw
    deploy:
      mode: replicated
      replicas: 1
    networks:
      - monitoring
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We also need to create the configuration for prometheus so we can get the data automatically off the services.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;global:
  evaluation_interval: 15s
  scrape_interval: 15s

scrape_configs:
  - job_name: services
    metrics_path: &amp;quot;/metrics&amp;quot;
    scrape_interval: 10s
    dns_sd_configs:
      - names:
          - &#39;tasks.demo_service_v1&#39;
          - &#39;tasks.demo_service_v2&#39;
        type: &#39;A&#39;
        port: 2112
  - job_name: cadvisor
    metrics_path: /metrics
    scrape_interval: 30s
    dns_sd_configs:
      - names:
          - &amp;quot;tasks.cadvisor&amp;quot;
        type: &#39;A&#39;
        port: 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What this will do is create 2 jobs that will collect the metrics, at their specified periods, the
&lt;strong&gt;tasks.&lt;servicename&gt;&lt;/strong&gt; is something you can use in docker swarm to get all the IP addresses associated with the service
so the node exporter/prometheus can get all the data without us having to manually configure it.&lt;/p&gt;

&lt;p&gt;Now to deploy this stack we can just issue the command bellow.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;docker stack deploy gomeetupamsnov -c stack.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will spin up all the necessary services required for this to work, after which we will be able to access.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cAdvisor on port 8080&lt;/li&gt;
&lt;li&gt;Prometheus on port 9090&lt;/li&gt;
&lt;li&gt;Grafana on port 3000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Load up some dashboards, there are plenty available on grafana&amp;rsquo;s page.&lt;/p&gt;

&lt;p&gt;And voila we have some dashboards with information relevant to us.&lt;/p&gt;

&lt;h2 id=&#34;golang-process-data-regarding-cadvisor&#34;&gt;Golang process data regarding cAdvisor&lt;/h2&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;go-process-data-01.png&#34; alt=&#34;Golang process data regarding cAdvisor&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;h2 id=&#34;golang-process-data-regarding-the-demo-services&#34;&gt;Golang process data regarding the demo services&lt;/h2&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;go-process-data-02.png&#34; alt=&#34;Golang process data regarding the demo services&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;h2 id=&#34;docker-data-from-cadvisor&#34;&gt;Docker data from cAdvisor&lt;/h2&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;cadvisor-dashboard-data.png&#34; alt=&#34;Docker data from cAdvisor&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;h2 id=&#34;next-steps&#34;&gt;Next steps&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Automatic configuration of jobs, we can use consul for this, so anytime a new service is added we pick it up right away&lt;/li&gt;
&lt;li&gt;Adding node exporter instead of full prometheus inside the swarm (done for simplicity)&lt;/li&gt;
&lt;li&gt;Setting up alerting based on our parameters&lt;/li&gt;
&lt;/ul&gt;</description>
        </item>
        
        <item>
            <title>Golang remote profiling and flamegraphs</title>
            <link>https://matoski.com/article/golang-profiling-flamegraphs/</link>
            <pubDate>Tue, 02 Oct 2018 16:21:31 +0000</pubDate>
            
            <guid>https://matoski.com/article/golang-profiling-flamegraphs/</guid>
            <description>&lt;p&gt;Quite often we are found with a challenge to troubleshoot something in production, or to see why is our application slow, or why isn&amp;rsquo;t it serving requests fast enough.&lt;/p&gt;

&lt;p&gt;We can use golang tool &lt;a href=&#34;https://golang.org/pkg/net/http/pprof/&#34;&gt;pprof&lt;/a&gt; to troubleshoot our system.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Golang has a package called &lt;a href=&#34;https://golang.org/pkg/net/http/pprof/&#34;&gt;pprof&lt;/a&gt; that provides an HTTP server with runtime profiling data in the format expected by the visualisation tool. We need to make sure that this endpoint is never exposed as it can leak sensitive data.&lt;/p&gt;

&lt;p&gt;Profiling most commonly allows us to optimize our application, by providing dynamic analysis of various aspects of the running application.&lt;/p&gt;

&lt;p&gt;In Golang there are several profilers that we can use as of version 1.11, and they are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;allocs&lt;/strong&gt;: A sampling of all past memory allocations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;block&lt;/strong&gt;: Stack traces that led to blocking on synchronization primitives&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cmdline&lt;/strong&gt;: The command line invocation of the current program&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;goroutine&lt;/strong&gt;: Stack traces of all current goroutines&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;heap&lt;/strong&gt;: A sampling of memory allocations of live objects. You can specify the gc GET parameter to run GC before taking the heap sample.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mutex&lt;/strong&gt;: Stack traces of holders of contended mutexes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;profile&lt;/strong&gt;: CPU profile. You can specify the duration in the seconds GET parameter. After you get the profile file, use the go tool pprof command to investigate the profile.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;threadcreate&lt;/strong&gt;: Stack traces that led to the creation of new OS threads&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;trace&lt;/strong&gt;: A trace of execution of the current program. You can specify the duration in the seconds GET parameter. After you get the trace file, use the go tool trace command to investigate the trace.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Profile and optimize only if you know that you have a performance problem. Because premature optimization is not only a waste of your time, but it will also slow you down in the future if you have to refactor your brittle and finely-tuned code.
Attaching the network profiler has negligible performance overhead, so we can run it in production with live traffic without any noticeable performance penalties, and it gives you insight into how your application works with live data.&lt;/p&gt;

&lt;h2 id=&#34;profiling&#34;&gt;Profiling&lt;/h2&gt;

&lt;p&gt;Let&amp;rsquo;s look at some profiles to get us started. Before we begin let&amp;rsquo;s clone the GitHub repository locally so we can check it out and run it.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ mkdir $GOPATH/src/github.com/ilijamt -p
$ cd $GOPATH/src/github.com/ilijamt
$ git clone https://github.com/ilijamt/gomeetupamsoct2018
$ cd gomeetupamsoct2018
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;cpu-profile&#34;&gt;CPU Profile&lt;/h3&gt;

&lt;p&gt;The CPU profiler runs for 30s, and uses sampling to determine which functions spend the most of the CPU time. The go runtime stops the execution every 10ms and records the stack of all running goroutines. If you want to increase the sampling rate you can take a look at &lt;a href=&#34;https://golang.org/pkg/runtime/#SetCPUProfileRate&#34;&gt;SetCPUProfileRate&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cd pprof
$ go build
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Just running the application won&amp;rsquo;t really help us, as we need to generate some load on the application so the profiler can gather the CPU samples while it&amp;rsquo;s running under load.&lt;/p&gt;

&lt;p&gt;First we need to run the compiled application, and then generate some load, while the &lt;strong&gt;ab&lt;/strong&gt; commands are running we need to run &lt;strong&gt;go tool pprof pprof &lt;a href=&#34;http://127.0.0.1:6060/debug/pprof/profile&#34;&gt;http://127.0.0.1:6060/debug/pprof/profile&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ ./pprof &amp;amp;
$ ab -k -c 8 -n 100000 &amp;quot;http://127.0.0.1:6060/concat/?str=test&amp;amp;count=50&amp;quot; &amp;amp;
$ ab -k -c 8 -n 100000 &amp;quot;http://127.0.0.1:6060/fib/?n=50&amp;amp;type=recursive&amp;quot; &amp;amp;
$ ab -k -c 8 -n 100000 &amp;quot;http://127.0.0.1:6060/fib/?n=50&amp;amp;type=iterative&amp;quot; &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So in a different terminal we need to run at the same time&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ go tool pprof pprof http://127.0.0.1:6060/debug/pprof/profile
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After it finishes dumping you can examine it when you need using the command&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ go tool pprof -http=:8080 dumps/pprof.pprof.samples.cpu.001.pb.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let&amp;rsquo;s examine the CPU profile and see what is going on, if you want to play around with it you can run the command above and check the interactive graph and play with it.&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;cpu-profile-graph-001.png&#34; alt=&#34;CPU Profile Graph&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;On the graph we can see that most of the CPU time was spent in &lt;strong&gt;fibRecursive&lt;/strong&gt; function which calculates the fibonacci number recursively. Let&amp;rsquo;s take a look at the function implementation, to see what it&amp;rsquo;s doing.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;func fibRecursive(n int64) int64 {
	if n &amp;lt; 2 {
		return n
	}
	return fibRecursive(n-1) + fibRecursive(n-2)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s take a look at the flame graph&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;flame-graph-001.png&#34; alt=&#34;Flame Graph&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;We can also see from the flame graph that most of the time it&amp;rsquo;s the &lt;strong&gt;fibRecursive&lt;/strong&gt; function that is slowing the application down.&lt;/p&gt;

&lt;p&gt;We can drill even more down to see which part of &lt;strong&gt;fibIterative&lt;/strong&gt; and &lt;strong&gt;fibRecursive&lt;/strong&gt; is taking the most time.&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;list-fib-functions.png&#34; alt=&#34;List fibonacci functions&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;As a comparison I&amp;rsquo;ve put both &lt;strong&gt;fibIterative&lt;/strong&gt; and &lt;strong&gt;fibRecursive&lt;/strong&gt; so we can see the difference in implementation.&lt;/p&gt;

&lt;p&gt;We can see that &lt;strong&gt;fibRecursive&lt;/strong&gt; takes on average 13.91 sec to run, and total 1.2 minutes, versus the &lt;strong&gt;fibIterative&lt;/strong&gt; which is 20ms.&lt;/p&gt;

&lt;p&gt;We can play with the pprof ui tool and investigate more in details about what is going on, but I leave that up to you the reader to do so.&lt;/p&gt;

&lt;h3 id=&#34;heap-profile&#34;&gt;Heap profile&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ ./pprof &amp;amp;
ab -k -c 80 -n 1000000 &amp;quot;http://127.0.0.1:6060/concat/?str=test&amp;amp;count=5000&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So in a different terminal we need to run at the same time, this is usually quite quick to create a heap profile unlike the CPU profile&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ go tool pprof pprof http://127.0.0.1:6060/debug/pprof/heap
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After it finishes dumping you can examine it when you need using the command&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ go tool pprof -http=:8080 dumps/pprof.pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After it finishes dumping we can investigate the data we have collected and check out the issues that we have in our current system&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s take a look at the data, there are four parameters that we can pass to check out the application details and in short the profiler too can show you either allocation counts or in memory use. If you are concerned with the amount of memory being used, you want to take a look at the in memory use metrics, but if you are want to know about the garbage collection you look at the allocations. For more details you can take a look at the &lt;a href=&#34;https://golang.org/src/runtime/mprof.go&#34;&gt;memory profiler&lt;/a&gt;, the code has quite a lot of useful comments about how it works.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s look at some of the data that we&amp;rsquo;ve collected&lt;/p&gt;

&lt;h4 id=&#34;alloc-object-alloc-space&#34;&gt;alloc_object, alloc_space&lt;/h4&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;alloc_objects_concat.png&#34; alt=&#34;Concat allocation objects&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;From the picture we can see that we have allocated quite a lot of object in contact, up to 61.7% of the objects allocated came from that function.&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;alloc_space_concat.png&#34; alt=&#34;Concat allocation space&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;From the picture we can see that we have allocated a whole of objects up to a total of 340GB&lt;/p&gt;

&lt;h3 id=&#34;inuse-object-inuse-space&#34;&gt;inuse_object, inuse_space&lt;/h3&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;inuse_objects_concat.png&#34; alt=&#34;Concat inuse objects&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;But when we look at the inuse objects of the application we can see that &lt;strong&gt;concat&lt;/strong&gt; is not the one that created the most objects, but &lt;strong&gt;bufio.NewReaderSize&lt;/strong&gt;&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;inuse_space_concat.png&#34; alt=&#34;Concat inuse space&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;But if we take a look at the inuse space, we can see that the &lt;strong&gt;concat&lt;/strong&gt; function uses whole 19.23MB of memory which accounts for a total of 82.75% of the whole memory usage.&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;inuse_space_list_concat.png&#34; alt=&#34;Concat inuse objects list&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;And if we drill down we can see where is the memory being allocated, and it&amp;rsquo;s on the line 17 on the picture, we can easily improve this one by creating a buffer and writing to it instead of prepending a new string each time, which creates new objects all the time. Just replacing the function concat with&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;func concatV2(str string, count int) (ret string) {
	data := bytes.NewBuffer([]byte{})
	for i := 0; i &amp;lt; count; i ++ {
        data.WriteString(str)
	}
	return data.String()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can verify that we are doing less allocations now and we are actually using less memory, I leave it up to you to check out the details, there is already a dump in &lt;strong&gt;dumps/pprof.pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.002.pb.gz&lt;/strong&gt; in the GitHub repo that you can use right away.&lt;/p&gt;

&lt;h3 id=&#34;go-routines&#34;&gt;Go routines&lt;/h3&gt;

&lt;p&gt;This is an interesting one, it creates a dump of the goroutine call stack and the number of running goroutines. Let&amp;rsquo;s take a look at the profile of the dump we did, but before we do let&amp;rsquo;s generate the dump.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ ./pprof &amp;amp;
ab -k -c 80 -n 1000000 &amp;quot;http://127.0.0.1:6060/concat/?str=test&amp;amp;count=5000&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So in a different terminal we need to run at the same time, this is usually quite quick to create a goroutine profile unlike the CPU profile.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ go tool pprof pprof http://127.0.0.1:6060/debug/pprof/goroutines
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After it finishes dumping you can examine it when you need using the command&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ go tool pprof -http=:8080 dumps/pprof.pprof.goroutine.001.pb.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;graph&#34;&gt;Graph&lt;/h4&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;goroutines-graph.png&#34; alt=&#34;goroutines graphs&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;h4 id=&#34;flame-graph&#34;&gt;Flame-graph&lt;/h4&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;goroutines-flamegraph.png&#34; alt=&#34;goroutines flamegraph&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;If we take a look at both the graph and flamegraph, we can see that the biggest time we spend is something called &lt;a href=&#34;https://golang.org/src/runtime/proc.go?s=&#34;&gt;runtime.gopark&lt;/a&gt;, if we take a look at the code comments of what this function does, we can see&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Puts the current goroutine into a waiting state and calls unlockf.
// If unlockf returns false, the goroutine is resumed.
// unlockf must not access this G&#39;s stack, as it may be moved between
// the call to gopark and the call to unlockf.
// Reason explains why the goroutine has been parked.
// It is displayed in stack traces and heap dumps.
// Reasons should be unique and descriptive.
// Do not re-use reasons, add new ones.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the goroutine scheduler, which happens because we spawn a lot of goroutines to serve every request, we should maybe think about limiting the amount of requests that we serve.&lt;/p&gt;

&lt;h3 id=&#34;block-profile&#34;&gt;Block profile&lt;/h3&gt;

&lt;p&gt;It show function calls that led to blocking on synchronization primitives like mutexes and channels. One thing to remember is that before dumping the profile we have to &lt;a href=&#34;https://golang.org/pkg/runtime/#SetBlockProfileRate&#34;&gt;SetBlockProfileRate&lt;/a&gt; in the application either in the main or the init function. We need to do this so we can capture the profiling information.&lt;/p&gt;

&lt;h4 id=&#34;contentions&#34;&gt;Contentions&lt;/h4&gt;

&lt;p&gt;In the picture we can see a lot of the time is spend in &lt;a href=&#34;https://golang.org/pkg/sync/#Cond&#34;&gt;sync.Cond&lt;/a&gt; which is a conditional variable, with a an associated locker (often a *Mutex or a *RWMutex), which is held when changing the condition and when calling the &lt;a href=&#34;https://golang.org/pkg/sync/#Cond.Wait&#34;&gt;Wait&lt;/a&gt;&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;block_profile_contentions.png&#34; alt=&#34;block profile with contentions&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;h4 id=&#34;mean-delay&#34;&gt;Mean delay&lt;/h4&gt;

&lt;p&gt;In this picture we can see the mean delay for each block, which for &lt;a href=&#34;https://golang.org/pkg/sync/#Cond.Wait&#34;&gt;sync.(*Cond).Wait&lt;/a&gt; is 2.65ms and &lt;a href=&#34;https://golang.org/pkg/sync/#Mutex.Lock&#34;&gt;sync.(*Mutex).Lock&lt;/a&gt; is 3.91ms.&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;block_profile_mean_delay.png&#34; alt=&#34;block profile with mean delay&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;h4 id=&#34;total-delay&#34;&gt;Total delay&lt;/h4&gt;

&lt;p&gt;In this picture we can see the total time spent in each block, and in our case the &lt;a href=&#34;https://golang.org/pkg/sync/#Cond.Wait&#34;&gt;sync.(*Cond).Wait&lt;/a&gt; is the problem because it&amp;rsquo;s being called 2614 times which brings to total time 6.91s.&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;block_profile_total_delay.png&#34; alt=&#34;block profile with total delay&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;h3 id=&#34;trace&#34;&gt;Trace&lt;/h3&gt;

&lt;p&gt;And last but not least it&amp;rsquo;s the tracing tool, which visualizes the runtime events in fine detail over a run of a your application.&lt;/p&gt;

&lt;p&gt;But I should also note that we shouldn&amp;rsquo;t use trace if you want to track down slow functions, or find where exactly is your program is spending most of its CPU time. For problems like that you should use &lt;strong&gt;pprof&lt;/strong&gt;. &lt;strong&gt;trace&lt;/strong&gt; is useful if you want to find out what is your program doing over time.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s dig in a bit with the tracing now, to be able to trace we have to create a tracing file.&lt;/p&gt;

&lt;p&gt;We can download the trace file just by doing executing the command bellow, and in the 10 seconds we need to generate some load to have some meaningful traces&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;wget http://localhost:6060/debug/pprof/trace?seconds=10 -O dumps/trace
go tool trace dumps/trace
&lt;/code&gt;&lt;/pre&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;go_tool_trace.png&#34; alt=&#34;go trace&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;We can see here what was executed at what point and what exactly was the flow between each piece in the system.&lt;/p&gt;

&lt;p&gt;There are various other tools that trace has that can be of use to us like.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View trace&lt;/li&gt;
&lt;li&gt;Goroutine analysis&lt;/li&gt;
&lt;li&gt;Network blocking profile&lt;/li&gt;
&lt;li&gt;Synchronization blocking profile&lt;/li&gt;
&lt;li&gt;Syscall blocking profile&lt;/li&gt;
&lt;li&gt;Scheduler latency profile&lt;/li&gt;
&lt;li&gt;User-defined tasks&lt;/li&gt;
&lt;li&gt;User-defined regions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;comparison-of-different-profiles&#34;&gt;Comparison of different profiles&lt;/h2&gt;

&lt;p&gt;We can also compare several profiles and visualise the differences between them, this is applicable to any pprof profile (except maybe trace), so we can compare the details between each heap profile capture by using the following commands.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;go tool pprof -http=:8080 --base dumps/heap-profile-cmp-001.pb.gz dumps/heap-profile-cmp-002.pb.gz
go tool pprof -http=:8080 --base dumps/heap-profile-cmp-001.pb.gz dumps/heap-profile-cmp-003.pb.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we can see the differences between both profiles to see how our application is behaving.&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s all folks. This was a lot of information and hopefully it will be of use to someone.&lt;/p&gt;

&lt;p&gt;If you have some comments or remarks, let me know in the comment section.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Exposing metrics in your golang application</title>
            <link>https://matoski.com/article/golang-expvar-metrics/</link>
            <pubDate>Sun, 30 Sep 2018 06:31:31 +0000</pubDate>
            
            <guid>https://matoski.com/article/golang-expvar-metrics/</guid>
            <description>&lt;p&gt;A lot of times it&amp;rsquo;s useful to expose metrics for your application so you can know what is going on with the application, there are two ways you can do this one it&amp;rsquo;s either using a pull or a push mechanism.&lt;/p&gt;

&lt;p&gt;Golang has a package called &lt;a href=&#34;https://golang.org/pkg/expvar/&#34;&gt;expvar&lt;/a&gt; that provides a standardized interface to public variables, such as operation counters in servers, and exports these variables via HTTP in a JSON format.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;We can use this package to export all our metrics, custom variables, counters or anything we would want and then visualize our data so we can analyze it and understand how our application works.
The package has several types that it exports like &lt;strong&gt;float&lt;/strong&gt;, &lt;strong&gt;int&lt;/strong&gt;, &lt;strong&gt;string&lt;/strong&gt;, &lt;strong&gt;map&lt;/strong&gt;, and we can even define custom types to our metrics by implementing the &lt;strong&gt;&lt;a href=&#34;https://golang.org/pkg/expvar/#Var&#34;&gt;Var&lt;/a&gt;&lt;/strong&gt; interface&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s take a look at a simple implementation of how we can use &lt;strong&gt;expvar&lt;/strong&gt; to export various metrics for our application, and even implementing a custom type that we can use in our application.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;package main

import (
	&amp;quot;expvar&amp;quot;
	&amp;quot;fmt&amp;quot;
	&amp;quot;math/rand&amp;quot;
	&amp;quot;net/http&amp;quot;
	&amp;quot;os&amp;quot;
	&amp;quot;runtime&amp;quot;
	&amp;quot;time&amp;quot;
)

type TimeVar struct{ v time.Time }

func (o *TimeVar) Set(date time.Time)         { o.v = date }
func (o *TimeVar) Add(duration time.Duration) { o.v = o.v.Add(duration) }
func (o *TimeVar) String() string             { return fmt.Sprintf(&#39;&amp;quot;%s&amp;quot;&#39;, o.v.Format(time.RFC3339)) }

func NewStats(name string) *expvar.Map {
	stats = expvar.NewMap(name)
	stats.Set(&amp;quot;counter&amp;quot;, new(expvar.Int))
	stats.Set(&amp;quot;success_rate&amp;quot;, new(expvar.Float))
	stats.Set(&amp;quot;pid&amp;quot;, new(expvar.Int))

	go func() {
		t := time.NewTicker(time.Millisecond)
		for {
			select {
			case &amp;lt;-t.C:
				stats.Add(&amp;quot;counter&amp;quot;, rand.Int63n(100))
				stats.Get(&amp;quot;success_rate&amp;quot;).(*expvar.Float).Set(rand.Float64())
			}
		}
	}()

	return stats
}

var stats *expvar.Map
var lastUpdate *TimeVar

func init() {
	stats = NewStats(&amp;quot;stats&amp;quot;)
	lastUpdate = &amp;amp;TimeVar{}
	lastUpdate.Set(time.Now())
	stats.Get(&amp;quot;pid&amp;quot;).(*expvar.Int).Set(int64(os.Getpid()))
	expvar.Publish(&amp;quot;last_update&amp;quot;, lastUpdate)
	expvar.Publish(&amp;quot;goroutines&amp;quot;, expvar.Func(func() interface{} {
		return fmt.Sprintf(&amp;quot;%d&amp;quot;, runtime.NumGoroutine())
	}))
	expvar.Publish(&amp;quot;cgocall&amp;quot;, expvar.Func(func() interface{} {
		return fmt.Sprintf(&amp;quot;%d&amp;quot;, runtime.NumCgoCall())
	}))
	expvar.Publish(&amp;quot;cpu&amp;quot;, expvar.Func(func() interface{} {
		return fmt.Sprintf(&amp;quot;%d&amp;quot;, runtime.NumCPU())
	}))
}

func randomGoRoutineSpawn() {

	for {
		go func() {
			r := rand.Intn(10)
			time.Sleep(time.Duration(r) * time.Microsecond)
		}()
		r := rand.Intn(3)
		time.Sleep(time.Duration(r) * time.Microsecond)
	}
}

func main() {
	go randomGoRoutineSpawn()
	http.ListenAndServe(&amp;quot;:6000&amp;quot;, http.DefaultServeMux)

}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You may have noticed that we are using &lt;strong&gt;expvar.Func&lt;/strong&gt; with &lt;strong&gt;Publish&lt;/strong&gt;, what this one means is that the function will be called anytime we are retrieving the metrics, which makes it perfect for calculating the values only when they are needed and not all the time.&lt;/p&gt;

&lt;p&gt;After running the application and querying the endpoint we have the following data.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ curl localhost:6000/debug/vars
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
 &amp;quot;cgocall&amp;quot;: &amp;quot;1&amp;quot;,
 &amp;quot;cmdline&amp;quot;: [&amp;quot;/tmp/go-build381034895/b001/exe/main&amp;quot;],
 &amp;quot;cpu&amp;quot;: &amp;quot;4&amp;quot;,
 &amp;quot;goroutines&amp;quot;: &amp;quot;8&amp;quot;,
 &amp;quot;last_update&amp;quot;: &amp;quot;2018-09-30T09:59:08+02:00&amp;quot;,
 &amp;quot;memstats&amp;quot;: {&amp;quot;Alloc&amp;quot;:2729112,&amp;quot;TotalAlloc&amp;quot;:67979672,&amp;quot;Sys&amp;quot;:72349944,&amp;quot;Lookups&amp;quot;:0,&amp;quot;Mallocs&amp;quot;:1055537,&amp;quot;Frees&amp;quot;:1016347,&amp;quot;HeapAlloc&amp;quot;:2729112,&amp;quot;HeapSys&amp;quot;:66191360,&amp;quot;HeapIdle&amp;quot;:62775296,&amp;quot;HeapInuse&amp;quot;:3416064,&amp;quot;HeapReleased&amp;quot;:0,&amp;quot;HeapObjects&amp;quot;:39190,&amp;quot;StackInuse&amp;quot;:917504,&amp;quot;StackSys&amp;quot;:917504,&amp;quot;MSpanInuse&amp;quot;:64752,&amp;quot;MSpanSys&amp;quot;:98304,&amp;quot;MCacheInuse&amp;quot;:6912,&amp;quot;MCacheSys&amp;quot;:16384,&amp;quot;BuckHashSys&amp;quot;:1442870,&amp;quot;GCSys&amp;quot;:2445312,&amp;quot;OtherSys&amp;quot;:1238210,&amp;quot;NextGC&amp;quot;:4194304,&amp;quot;LastGC&amp;quot;:1538294385797517989,&amp;quot;PauseTotalNs&amp;quot;:1435570,&amp;quot;PauseNs&amp;quot;:[79199,42451,50945,155414,71632,34360,112997,78210,80689,94101,197658,110553,47645,97254,37034,58762,86666,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],&amp;quot;PauseEnd&amp;quot;:[1538294350363250463,1538294352540250881,1538294354731420295,1538294356927816598,1538294358983245342,1538294361184114356,1538294363384264942,1538294365590777905,1538294367789220774,1538294370179305387,1538294372387563780,1538294374656050641,1538294376896879760,1538294379162055815,1538294381539608947,1538294383722948035,1538294385797517989,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],&amp;quot;NumGC&amp;quot;:17,&amp;quot;NumForcedGC&amp;quot;:0,&amp;quot;GCCPUFraction&amp;quot;:0.00008913387405867569,&amp;quot;EnableGC&amp;quot;:true,&amp;quot;DebugGC&amp;quot;:false,&amp;quot;BySize&amp;quot;:[{&amp;quot;Size&amp;quot;:0,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:8,&amp;quot;Mallocs&amp;quot;:59,&amp;quot;Frees&amp;quot;:24},{&amp;quot;Size&amp;quot;:16,&amp;quot;Mallocs&amp;quot;:579,&amp;quot;Frees&amp;quot;:180},{&amp;quot;Size&amp;quot;:32,&amp;quot;Mallocs&amp;quot;:133,&amp;quot;Frees&amp;quot;:72},{&amp;quot;Size&amp;quot;:48,&amp;quot;Mallocs&amp;quot;:163,&amp;quot;Frees&amp;quot;:48},{&amp;quot;Size&amp;quot;:64,&amp;quot;Mallocs&amp;quot;:1053800,&amp;quot;Frees&amp;quot;:1015659},{&amp;quot;Size&amp;quot;:80,&amp;quot;Mallocs&amp;quot;:25,&amp;quot;Frees&amp;quot;:9},{&amp;quot;Size&amp;quot;:96,&amp;quot;Mallocs&amp;quot;:60,&amp;quot;Frees&amp;quot;:8},{&amp;quot;Size&amp;quot;:112,&amp;quot;Mallocs&amp;quot;:11,&amp;quot;Frees&amp;quot;:8},{&amp;quot;Size&amp;quot;:128,&amp;quot;Mallocs&amp;quot;:22,&amp;quot;Frees&amp;quot;:12},{&amp;quot;Size&amp;quot;:144,&amp;quot;Mallocs&amp;quot;:7,&amp;quot;Frees&amp;quot;:6},{&amp;quot;Size&amp;quot;:160,&amp;quot;Mallocs&amp;quot;:18,&amp;quot;Frees&amp;quot;:5},{&amp;quot;Size&amp;quot;:176,&amp;quot;Mallocs&amp;quot;:8,&amp;quot;Frees&amp;quot;:3},{&amp;quot;Size&amp;quot;:192,&amp;quot;Mallocs&amp;quot;:8,&amp;quot;Frees&amp;quot;:6},{&amp;quot;Size&amp;quot;:208,&amp;quot;Mallocs&amp;quot;:39,&amp;quot;Frees&amp;quot;:16},{&amp;quot;Size&amp;quot;:224,&amp;quot;Mallocs&amp;quot;:5,&amp;quot;Frees&amp;quot;:3},{&amp;quot;Size&amp;quot;:240,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:256,&amp;quot;Mallocs&amp;quot;:25,&amp;quot;Frees&amp;quot;:7},{&amp;quot;Size&amp;quot;:288,&amp;quot;Mallocs&amp;quot;:11,&amp;quot;Frees&amp;quot;:8},{&amp;quot;Size&amp;quot;:320,&amp;quot;Mallocs&amp;quot;:2,&amp;quot;Frees&amp;quot;:1},{&amp;quot;Size&amp;quot;:352,&amp;quot;Mallocs&amp;quot;:21,&amp;quot;Frees&amp;quot;:14},{&amp;quot;Size&amp;quot;:384,&amp;quot;Mallocs&amp;quot;:223,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:416,&amp;quot;Mallocs&amp;quot;:8,&amp;quot;Frees&amp;quot;:4},{&amp;quot;Size&amp;quot;:448,&amp;quot;Mallocs&amp;quot;:1,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:480,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:512,&amp;quot;Mallocs&amp;quot;:28,&amp;quot;Frees&amp;quot;:22},{&amp;quot;Size&amp;quot;:576,&amp;quot;Mallocs&amp;quot;:8,&amp;quot;Frees&amp;quot;:6},{&amp;quot;Size&amp;quot;:640,&amp;quot;Mallocs&amp;quot;:3,&amp;quot;Frees&amp;quot;:1},{&amp;quot;Size&amp;quot;:704,&amp;quot;Mallocs&amp;quot;:2,&amp;quot;Frees&amp;quot;:1},{&amp;quot;Size&amp;quot;:768,&amp;quot;Mallocs&amp;quot;:2,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:896,&amp;quot;Mallocs&amp;quot;:16,&amp;quot;Frees&amp;quot;:4},{&amp;quot;Size&amp;quot;:1024,&amp;quot;Mallocs&amp;quot;:2,&amp;quot;Frees&amp;quot;:1},{&amp;quot;Size&amp;quot;:1152,&amp;quot;Mallocs&amp;quot;:8,&amp;quot;Frees&amp;quot;:7},{&amp;quot;Size&amp;quot;:1280,&amp;quot;Mallocs&amp;quot;:1,&amp;quot;Frees&amp;quot;:1},{&amp;quot;Size&amp;quot;:1408,&amp;quot;Mallocs&amp;quot;:1,&amp;quot;Frees&amp;quot;:1},{&amp;quot;Size&amp;quot;:1536,&amp;quot;Mallocs&amp;quot;:1,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:1792,&amp;quot;Mallocs&amp;quot;:6,&amp;quot;Frees&amp;quot;:2},{&amp;quot;Size&amp;quot;:2048,&amp;quot;Mallocs&amp;quot;:5,&amp;quot;Frees&amp;quot;:3},{&amp;quot;Size&amp;quot;:2304,&amp;quot;Mallocs&amp;quot;:7,&amp;quot;Frees&amp;quot;:3},{&amp;quot;Size&amp;quot;:2688,&amp;quot;Mallocs&amp;quot;:2,&amp;quot;Frees&amp;quot;:1},{&amp;quot;Size&amp;quot;:3072,&amp;quot;Mallocs&amp;quot;:2,&amp;quot;Frees&amp;quot;:1},{&amp;quot;Size&amp;quot;:3200,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:3456,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:4096,&amp;quot;Mallocs&amp;quot;:14,&amp;quot;Frees&amp;quot;:9},{&amp;quot;Size&amp;quot;:4864,&amp;quot;Mallocs&amp;quot;:9,&amp;quot;Frees&amp;quot;:9},{&amp;quot;Size&amp;quot;:5376,&amp;quot;Mallocs&amp;quot;:1,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:6144,&amp;quot;Mallocs&amp;quot;:4,&amp;quot;Frees&amp;quot;:3},{&amp;quot;Size&amp;quot;:6528,&amp;quot;Mallocs&amp;quot;:2,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:6784,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:6912,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:8192,&amp;quot;Mallocs&amp;quot;:1,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:9472,&amp;quot;Mallocs&amp;quot;:4,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:9728,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:10240,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:10880,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:12288,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:13568,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:14336,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:16384,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:18432,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0},{&amp;quot;Size&amp;quot;:19072,&amp;quot;Mallocs&amp;quot;:0,&amp;quot;Frees&amp;quot;:0}]},
 &amp;quot;stats&amp;quot;: {&amp;quot;counter&amp;quot;: 1893889, &amp;quot;pid&amp;quot;: 23657, &amp;quot;success_rate&amp;quot;: 0.45610231133193085}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we need to store this data somewhere, and we can visualize it and use the data in a lot of useful ways for us.&lt;/p&gt;

&lt;p&gt;If you want to try it out you can pull the code from GitHub and run it in a container to see it in action&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ git clone https://github.com/ilijamt/gomeetupamsoct2018
$ cd watch
$ docker-compose up -d
$ export EXPVAR_HOST=http://`docker inspect -f &#39;{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}&#39; expvar_app_1`:6000/debug/vars
$ watch -n 1 curl $EXPVAR_HOST -s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is one of the ways we can do the export of the metrics, another one is to use Prometheus, which I will cover in a future article, with the same example just to see how to implement it in Prometheus way.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Sum Two Values</title>
            <link>https://matoski.com/article/sum-two-values/</link>
            <pubDate>Wed, 12 Sep 2018 09:27:31 +0000</pubDate>
            
            <guid>https://matoski.com/article/sum-two-values/</guid>
            <description>&lt;p&gt;Given an array of integers and a value, determine if there are any two integers in the array which sum equal to the given value.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s see an example array that we can visualise it so we can come up with a proper approach.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[ 5, 6, 7, 1, 4, 2, 3 ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need to see if any 2 numbers create a sum of X. Let&amp;rsquo;s evaluate on a real case.&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sum&lt;/th&gt;
&lt;th&gt;Values&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;6+4&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;5+6, 7+3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;How we can solve this, we can use a hash set to store the values that can when added total to X, and we should also sort the array.&lt;/p&gt;

&lt;h2 id=&#34;algorithm&#34;&gt;Algorithm&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Scan the whole array once and store the visit elements in a hash set.&lt;/li&gt;
&lt;li&gt;While scanning, for every element in the array we check if X - e is already visited

&lt;ul&gt;
&lt;li&gt;If X - e is found in the hash set, it means that there is a pair(e, X - e) in array whose sum is equal to the given value&lt;/li&gt;
&lt;li&gt;If we have scanned all elements in the array and we didn&amp;rsquo;t find anything, return false&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;solution-with-a-hash-set&#34;&gt;Solution with a hash set&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let find_sum_of_two = function(A, X) {
    let values = new Set();
    for (let a in A) {
        if (values.has(X - A[a])) {
            return true;
        }
        values.add(A[a]);
    }
    return false;
}

let arr = [ 5, 6, 7, 1, 4, 2, 3 ];

console.log(arr, &amp;quot;has items with sum of&amp;quot;, 5, find_sum_of_two(arr, 5));
console.log(arr, &amp;quot;has items with sum of&amp;quot;, 10, find_sum_of_two(arr, 10));
console.log(arr, &amp;quot;has items with sum of&amp;quot;, 11, find_sum_of_two(arr, 11));
console.log(arr, &amp;quot;has items with sum of&amp;quot;, 20, find_sum_of_two(arr, 20));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And it should output&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[ 5, 6, 7, 1, 4, 2, 3 ] &#39;has items with sum of&#39; 5 true
[ 5, 6, 7, 1, 4, 2, 3 ] &#39;has items with sum of&#39; 10 true
[ 5, 6, 7, 1, 4, 2, 3 ] &#39;has items with sum of&#39; 11 true
[ 5, 6, 7, 1, 4, 2, 3 ] &#39;has items with sum of&#39; 20 false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Runtime complexity&lt;/strong&gt;: Linear &lt;strong&gt;O(n)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory complexity&lt;/strong&gt;: &lt;strong&gt;O(n)&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;solution&#34;&gt;Solution&lt;/h2&gt;

&lt;p&gt;Let&amp;rsquo;s look at a solution that will allow us to improve a bit on the previous solution.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;let find_sum_of_two = function(A, X) {
    let i = 0;
    let j = A.length - 1;

    while (i &amp;lt; j) {
        let sum = A[i] + A[j];
        if (sum == X) {
            return true;
        }

        if (sum &amp;lt; X) {
            i++;
        } else {
            j--;
        }
    }

    return false;

}

let arr = [1, 2, 3, 4, 5, 6, 7];

console.log(arr, &amp;quot;has items with sum of&amp;quot;, 5, find_sum_of_two(arr, 5));
console.log(arr, &amp;quot;has items with sum of&amp;quot;, 10, find_sum_of_two(arr, 10));
console.log(arr, &amp;quot;has items with sum of&amp;quot;, 11, find_sum_of_two(arr, 11));
console.log(arr, &amp;quot;has items with sum of&amp;quot;, 20, find_sum_of_two(arr, 20));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And it should output&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[1, 2, 3, 4, 5, 6, 7] &#39;has items with sum of&#39; 5 true
[1, 2, 3, 4, 5, 6, 7] &#39;has items with sum of&#39; 10 true
[1, 2, 3, 4, 5, 6, 7] &#39;has items with sum of&#39; 11 true
[1, 2, 3, 4, 5, 6, 7] &#39;has items with sum of&#39; 20 false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Runtime complexity&lt;/strong&gt;: Linear &lt;strong&gt;O(n)&lt;/strong&gt;, if we need to sort the array before we start then the complexity is &lt;strong&gt;O(nlogn)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory complexity&lt;/strong&gt;: &lt;strong&gt;O(1)&lt;/strong&gt;&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Merge Overlapping Intervals</title>
            <link>https://matoski.com/article/merge-overlapping-intervals/</link>
            <pubDate>Wed, 12 Sep 2018 06:27:31 +0000</pubDate>
            
            <guid>https://matoski.com/article/merge-overlapping-intervals/</guid>
            <description>&lt;p&gt;Given an array (list) of intervals as input where each interval has a start and end timestamps. Input array is sorted by starting timestamps. You are required to merge overlapping intervals and return output array (list).&lt;/p&gt;

&lt;p&gt;Consider below input array. Intervals (2, 10), (4, 12), (11, 13), (15, 20) are overlapping so should be merged to one big interval (2, 13). Similarly interval (15, 20) doesn&amp;rsquo;t overlap anywhere so it should be added to the merged overlapping interval list.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The problem can be solved with a simple linear scan. And the intervals are sorted by the starting timestamps.&lt;/p&gt;

&lt;p&gt;We can also expand this solution for an unsorted array of intervals, by just sorting the intervals based on the start time.&lt;/p&gt;

&lt;h2 id=&#34;algorithm&#34;&gt;Algorithm&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;List of input intervals is given, and we we keep the merged inteval list in a separate list&lt;/li&gt;
&lt;li&gt;For each interval in the list

&lt;ul&gt;
&lt;li&gt;If interval is overlapping with the last interval in the output list we merge these two intervals and update the last interval of the output interval with the merged one&lt;/li&gt;
&lt;li&gt;Otherwise we add the input interval to the output interval&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;solution&#34;&gt;Solution&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let merge_intervals = function(v1) {
  if (!v1 || v1.length === 0) {
    return;
  }

  let v2 = [];
  v2.push([ v1[0][0], v1[0][1] ]);

  for (let i = 0; i &amp;lt; v1.length; i++) {
    let x1 = v1[i][0];
    let y1 = v1[i][1];
    let x2 = v2[v2.length - 1][0];
    let y2 = v2[v2.length - 1][1];

    if (y2 &amp;gt;= x1) {
      v2[v2.length - 1][1] = Math.max(y1, y2);
    } else {
      v2.push([ x1, y1 ]);
    }

  }
  return v2;
};

console.log(merge_intervals([[1,5],[3,7],[4,6],[6,8],[10,12],[11,15]]));
console.log(merge_intervals([[4,12],[13,16],[19,20],[20,24]]));
console.log(merge_intervals([[2,10],[4, 12], [11, 13], [15, 20]]));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the output would be&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[ [ 1, 8 ], [ 10, 15 ] ]
[ [ 4, 12 ], [ 13, 16 ], [ 19, 24 ] ]
[ [ 2, 12 ] ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Runtime complexity&lt;/strong&gt;: Linear &lt;strong&gt;O(n)&lt;/strong&gt;, if we need to sort the array before we start then the complexity is &lt;strong&gt;O(nlogn)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory complexity&lt;/strong&gt;: &lt;strong&gt;O(n)&lt;/strong&gt; worst case, when they are no overlapping intervals&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Finding maximum in a sliding window</title>
            <link>https://matoski.com/article/find-maximum-in-sliding-window/</link>
            <pubDate>Mon, 10 Sep 2018 14:55:31 +0000</pubDate>
            
            <guid>https://matoski.com/article/find-maximum-in-sliding-window/</guid>
            <description>&lt;p&gt;So I&amp;rsquo;m trying to stay true to my resolution, write one or more article about algorithms and datastructure everyday to refresh my memory on how everything works.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h1 id=&#34;description&#34;&gt;Description&lt;/h1&gt;

&lt;p&gt;Given a large array of integers and a window of size &amp;lsquo;w&amp;rsquo;, find the current maximum in the window as the window slides through the entire array.&lt;/p&gt;

&lt;h1 id=&#34;example&#34;&gt;Example&lt;/h1&gt;

&lt;p&gt;Consider the array below and let&amp;rsquo;s try to find all maximum with window size = 3, for explanation let&amp;rsquo;s start with a smaller array so we can go over each steps.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[-1 2 -2 5 9]
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;For the first window size (3) elements, the max is 2&lt;/li&gt;
&lt;li&gt;Slide window one position right and then the max element is 5&lt;/li&gt;
&lt;li&gt;Slide window one position right again, and then the max element is 9&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&#34;solutions&#34;&gt;Solutions&lt;/h1&gt;

&lt;h2 id=&#34;algorithm&#34;&gt;Algorithm&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Check if the window size is bigger than the array it self, and if so return&lt;/li&gt;
&lt;li&gt;Find the max for the first window, by storing the max value into a window&lt;/li&gt;
&lt;li&gt;Push the first element of the window into the results array&lt;/li&gt;
&lt;li&gt;Iterate the rest of the elements
** Remove all the elements from the tail of the window that are equal or smaller than the current element
** Remove the element in the head if the index no longer is in the current window
** Push the current element into the window
** Current max is at the head of the array and can be pushed in results&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;iterative-solution&#34;&gt;Iterative solution&lt;/h2&gt;

&lt;h3 id=&#34;runtime-complexity&#34;&gt;Runtime complexity&lt;/h3&gt;

&lt;p&gt;Linear, О(nlogw)&lt;/p&gt;

&lt;h3 id=&#34;memory-complexity&#34;&gt;Memory complexity&lt;/h3&gt;

&lt;p&gt;Logarithmic, О(w)&lt;/p&gt;

&lt;p&gt;The reason why it has O(logn) memory complexity is because it will have to consume memory on the stack.&lt;/p&gt;

&lt;h3 id=&#34;implementation&#34;&gt;Implementation&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;let find_max_sliding_window = function(arr, window_size) {
  let result = [];
  if (window_size &amp;gt; arr.length) {
    return [];
  }

  let wind = [];
  for (let i = 0; i &amp;lt; window_size; i++) {
    while (wind.length &amp;gt; 0 &amp;amp;&amp;amp; arr[i] &amp;gt;= arr[wind[wind.length - 1]]) {
      wind.pop(); // remove the element of the window
    }
    wind.push(i); // put the index of the element that has max in the window
  }

  result.push(arr[wind[0]]);

  // move the window to the right side and go over the window again
  for (let i = window_size; i &amp;lt; arr.length; i++) {
    while (wind.length &amp;gt; 0 &amp;amp;&amp;amp; arr[i] &amp;gt;= arr[wind[wind.length - 1]]) {
      wind.pop(); // remove the element of the window
    }
    // move the element to right and remove the first element in the window
    if (wind.length &amp;gt; 0 &amp;amp;&amp;amp; (wind[0] &amp;lt;= i - window_size)) {
      wind.shift();
    }
    wind.push(i);
    result.push(arr[wind[0]]);
  }

  return result;
};

console.log(find_max_sliding_window([97, 7, 36, 16, 90, 54, 54, 81, 43, 66, 72, 97, 68, 27, 12, 83, 8, 26, 70, 8], 2));
console.log(find_max_sliding_window([97, 7, 36, 16, 90, 54, 54, 81, 43, 66, 72, 97, 68, 27, 12, 83, 8, 26, 70, 8], 3));
console.log(find_max_sliding_window([97, 7, 36, 16, 90, 54, 54, 81, 43, 66, 72, 97, 68, 27, 12, 83, 8, 26, 70, 8], 4));
console.log(find_max_sliding_window([97, 7, 36, 16, 90, 54, 54, 81, 43, 66, 72, 97, 68, 27, 12, 83, 8, 26, 70, 8], 5));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After running the application the output is&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;[97, 36, 36, 90, 90, 54, 81, 81, 66, 72, 97, 97, 68, 27, 83, 83, 26, 70, 70]
[97, 36, 90, 90, 90, 81, 81, 81, 72, 97, 97, 97, 68, 83, 83, 83, 70, 70]
[97, 90, 90, 90, 90, 81, 81, 81, 97, 97, 97, 97, 83, 83, 83, 83, 70]
[97, 90, 90, 90, 90, 81, 81, 97, 97, 97, 97, 97, 83, 83, 83, 83]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This was quite easy but we have to wrap our heads around how we would approach this, if we remember that do we really need to store all the elements in memory, and how can we create an efficient structure that can store the data for us.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Binary search algorithm, find the index of a given key</title>
            <link>https://matoski.com/article/arrays-binary-search/</link>
            <pubDate>Sun, 09 Sep 2018 17:45:35 +0000</pubDate>
            
            <guid>https://matoski.com/article/arrays-binary-search/</guid>
            <description>&lt;p&gt;It&amp;rsquo;s been a while since I&amp;rsquo;ve been writing on the blog, so I&amp;rsquo;ve decided to start being more active and since it&amp;rsquo;s been almost 15 years since I&amp;rsquo;ve studied this in University, it can also be a good refreshment course for me as well as anyone else looking into refreshing their memory or learning.&lt;/p&gt;

&lt;p&gt;Binary search is a very useful algorithm, also known as half-interval search, logarithmic search, or binary chop, is a search algorithm that finds the position of a target value within a sorted array.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Binary search is used to find the index of an element in a sorted array, and if the element doesn&amp;rsquo;t exist, that can be determined efficiently as well. It does it by dividing the input array by half at every step, and after every step, either we have found the index that we are looking for or half of the array can be discarded.&lt;/p&gt;

&lt;h1 id=&#34;description&#34;&gt;Description&lt;/h1&gt;

&lt;p&gt;Given a sorted array of integers, return the index of the given key. Return -1 if not found.&lt;/p&gt;

&lt;h1 id=&#34;example&#34;&gt;Example&lt;/h1&gt;

&lt;p&gt;Given the following array, if search key is 4, binary search will return 2.&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;binary-search-array.svg&#34; alt=&#34;binary search array&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;h1 id=&#34;solutions&#34;&gt;Solutions&lt;/h1&gt;

&lt;p&gt;There are a couple of ways to solve this problem easily, we can either use a recursive or iterative approach, but before we look into both let&amp;rsquo;s evaluate the complexity for both solutions, and the algorithms for both solutions.&lt;/p&gt;

&lt;h2 id=&#34;algorithm&#34;&gt;Algorithm&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;At every step, consider the array between low and high indices&lt;/li&gt;
&lt;li&gt;Calculate the middle index.&lt;/li&gt;
&lt;li&gt;If element at the middle index is the key, return middle.&lt;/li&gt;
&lt;li&gt;If element at middle is greater than the key, then reduce the array size such that high becomes mid - 1. Index at low remains the same.&lt;/li&gt;
&lt;li&gt;If element at middle is less than the key, then reduce the array size such that low becomes mid + 1. Index at high remains the same.&lt;/li&gt;
&lt;li&gt;When low is greater than high, key doesn&amp;rsquo;t exist. Return -1.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;recursive&#34;&gt;Recursive&lt;/h2&gt;

&lt;h3 id=&#34;runtime-complexity&#34;&gt;Runtime complexity&lt;/h3&gt;

&lt;p&gt;Logarithmic, О(logn)&lt;/p&gt;

&lt;h3 id=&#34;memory-complexity&#34;&gt;Memory complexity&lt;/h3&gt;

&lt;p&gt;Logarithmic, О(logn)&lt;/p&gt;

&lt;p&gt;The reason why it has O(logn) memory complexity is because it will have to consume memory on the stack.&lt;/p&gt;

&lt;h3 id=&#34;implementation&#34;&gt;Implementation&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-c&#34;&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

int binary_search_recursive(int A[], int key, int low, int high) {
  if (low &amp;gt; high) {
    return -1;
  }

  int mid = low + ((high - low) / 2);
  if (A[mid] == key) {
    return mid;
  } else if (key &amp;lt; A[mid]) {
    return binary_search_recursive(A, key, low, mid - 1);
  }

  return binary_search_recursive(A, key, mid + 1, high);
}

int main(int argc, char ** argv) {
  int arr[] = { 1, 3, 4, 6, 7, 8, 10, 13, 14 };
  int size = sizeof(arr) / sizeof(arr[0]);
  cout &amp;lt;&amp;lt; &amp;quot;Key(2) found at: &amp;quot; &amp;lt;&amp;lt; binary_search_recursive(arr, 2, 0, size - 1) &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &amp;quot;Key(4) found at: &amp;quot; &amp;lt;&amp;lt; binary_search_recursive(arr, 4, 0, size - 1) &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &amp;quot;Key(9) found at: &amp;quot; &amp;lt;&amp;lt; binary_search_recursive(arr, 9, 0, size - 1) &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &amp;quot;Key(13) found at: &amp;quot; &amp;lt;&amp;lt; binary_search_recursive(arr, 13, 0, size - 1) &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &amp;quot;Key(90) found at: &amp;quot; &amp;lt;&amp;lt; binary_search_recursive(arr, 90, 0, size - 1) &amp;lt;&amp;lt; endl;
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After running the application the output is&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ g++ arr-binary-search-rec.cpp
$ ./a.out
Key(2) found at: -1
Key(4) found at: 2
Key(9) found at: -1
Key(13) found at: 7
Key(90) found at: -1
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;iterative&#34;&gt;Iterative&lt;/h2&gt;

&lt;h3 id=&#34;runtime-complexity-1&#34;&gt;Runtime complexity&lt;/h3&gt;

&lt;p&gt;Logarithmic О(logn)&lt;/p&gt;

&lt;h3 id=&#34;memory-complexity-1&#34;&gt;Memory complexity&lt;/h3&gt;

&lt;p&gt;Constants, O(1)&lt;/p&gt;

&lt;h3 id=&#34;implementation-1&#34;&gt;Implementation&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-c&#34;&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

int binary_search_iterative(int A[], int key, int len) {
  int low = 0;
  int high = len - 1;

  while (low &amp;lt;= high) {
    int mid = low + ((high - low) / 2);
    if (A[mid] == key) {
      return mid;
    } else if (key &amp;lt; A[mid]) {
      high = mid - 1;
    } else {
      low = mid + 1;
    }
  }

  return -1;
}

int main(int argc, char ** argv) {
  int arr[] = { 1, 3, 4, 6, 7, 8, 10, 13, 14 };
  int size = sizeof(arr) / sizeof(arr[0]);
  cout &amp;lt;&amp;lt; &amp;quot;Key(2) found at: &amp;quot; &amp;lt;&amp;lt; binary_search_iterative(arr, 2, size - 1) &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &amp;quot;Key(4) found at: &amp;quot; &amp;lt;&amp;lt; binary_search_iterative(arr, 4, size - 1) &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &amp;quot;Key(9) found at: &amp;quot; &amp;lt;&amp;lt; binary_search_iterative(arr, 9, size - 1) &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &amp;quot;Key(13) found at: &amp;quot; &amp;lt;&amp;lt; binary_search_iterative(arr, 13, size - 1) &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &amp;quot;Key(90) found at: &amp;quot; &amp;lt;&amp;lt; binary_search_iterative(arr, 90, size - 1) &amp;lt;&amp;lt; endl;
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After running the application the output is&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ g++ arr-binary-search-iter.cpp
$ ./a.out
Key(2) found at: -1
Key(4) found at: 2
Key(9) found at: -1
Key(13) found at: 7
Key(90) found at: -1
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&#34;resources&#34;&gt;Resources&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Picture for binary search taken from &lt;a href=&#34;https://en.wikipedia.org/wiki/Binary_search_algorithm&#34;&gt;Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;If you want to know about different variations of binary search take a look at the wikipedia page&lt;/li&gt;
&lt;/ul&gt;</description>
        </item>
        
        <item>
            <title>Site to site with OpenVPN with TLS and FirewallD on Debian</title>
            <link>https://matoski.com/article/site-to-site-openvpn-firewalld-debian/</link>
            <pubDate>Mon, 05 Feb 2018 21:02:58 +0000</pubDate>
            
            <guid>https://matoski.com/article/site-to-site-openvpn-firewalld-debian/</guid>
            <description>&lt;p&gt;So I needed to setup a site to site transport between our two datacenters, so our internal network will be able to communicate between the two datacenters easily.&lt;/p&gt;

&lt;p&gt;There are a lot of ways to setup site to site VPN link between two networks, in our case let&amp;rsquo;s take a look at one way using OpenVPN.&lt;/p&gt;

&lt;p&gt;This is quite long tutorial so get yourself a bit comfortable so we can get started.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Our network looks like this&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;site2site-vpn.png&#34; alt=&#34;Site to site VPN&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;Datacenter at location A has internal network &lt;strong&gt;10.5.200.20&lt;/strong&gt; on the interface &lt;strong&gt;eth1&lt;/strong&gt; and &lt;strong&gt;94.x.x.x.x&lt;/strong&gt; on &lt;strong&gt;eth0&lt;/strong&gt;, we will configure the openvpn server on this location.
Datacenter at location B has internal network &lt;strong&gt;10.0.0.5&lt;/strong&gt; on the interface &lt;strong&gt;eth1&lt;/strong&gt; and &lt;strong&gt;93.x.x.x.x&lt;/strong&gt; on &lt;strong&gt;eth0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Both machine have two network interfaces &lt;strong&gt;eth0&lt;/strong&gt; which is connected to the internet, and &lt;strong&gt;eth1&lt;/strong&gt; which is connected the the LAN&lt;/p&gt;

&lt;p&gt;The IP subnet has to be different for this to work, if they are on the same subnet this won&amp;rsquo;t work.&lt;/p&gt;

&lt;h2 id=&#34;vpn-gateway-at-location-a&#34;&gt;VPN gateway at location A&lt;/h2&gt;

&lt;p&gt;So to begin login to the machine in the location A&lt;/p&gt;

&lt;h3 id=&#34;forwarding&#34;&gt;Forwarding&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/sysctl.d/30-openvpn-forward.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
EOF
$ sysctl -p /etc/sysctl.d/30-openvpn-forward.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;installation&#34;&gt;Installation&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get install openvpn easy-rsa firewalld
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;firewall&#34;&gt;Firewall&lt;/h3&gt;

&lt;p&gt;Let&amp;rsquo;s configure the firewall to allow us to connect to the machine and all the necessary configuration needed for it&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ firewall-cmd --permanent --zone=public --add-source=93.x.x.x/32
$ firewall-cmd --permanent --zone=trusted --add-interface=eth1
$ firewall-cmd --permanent --zone=trusted --add-interface=tun0
$ firewall-cmd --permanent --zone=trusted --add-masquerade
$ DEV=$(ip route get 8.8.8.8 | awk &#39;NR==1 {print $(NF-2)}&#39;)
$ firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s  172.16.1.0/24 -o $DEV -j MASQUERADE
$ firewall-cmd --reload
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;generating-openvpn-keys&#34;&gt;Generating OpenVPN keys&lt;/h3&gt;

&lt;p&gt;After we have installed all this we need to generate some configuration and tls keys for us to use.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ make-cadir ~/ca
$ cd ~/ca
$ ls -lah
drwx------ 2 root root 4.0K Feb  5 21:23 .
drwxr-xr-x 4 root root 4.0K Feb  5 21:23 ..
lrwxrwxrwx 1 root root   28 Feb  5 21:23 build-ca -&amp;gt; /usr/share/easy-rsa/build-ca
lrwxrwxrwx 1 root root   28 Feb  5 21:23 build-dh -&amp;gt; /usr/share/easy-rsa/build-dh
lrwxrwxrwx 1 root root   31 Feb  5 21:23 build-inter -&amp;gt; /usr/share/easy-rsa/build-inter
lrwxrwxrwx 1 root root   29 Feb  5 21:23 build-key -&amp;gt; /usr/share/easy-rsa/build-key
lrwxrwxrwx 1 root root   34 Feb  5 21:23 build-key-pass -&amp;gt; /usr/share/easy-rsa/build-key-pass
lrwxrwxrwx 1 root root   36 Feb  5 21:23 build-key-pkcs12 -&amp;gt; /usr/share/easy-rsa/build-key-pkcs12
lrwxrwxrwx 1 root root   36 Feb  5 21:23 build-key-server -&amp;gt; /usr/share/easy-rsa/build-key-server
lrwxrwxrwx 1 root root   29 Feb  5 21:23 build-req -&amp;gt; /usr/share/easy-rsa/build-req
lrwxrwxrwx 1 root root   34 Feb  5 21:23 build-req-pass -&amp;gt; /usr/share/easy-rsa/build-req-pass
lrwxrwxrwx 1 root root   29 Feb  5 21:23 clean-all -&amp;gt; /usr/share/easy-rsa/clean-all
lrwxrwxrwx 1 root root   33 Feb  5 21:23 inherit-inter -&amp;gt; /usr/share/easy-rsa/inherit-inter
lrwxrwxrwx 1 root root   24 Feb  5 21:23 keys -&amp;gt; /usr/share/easy-rsa/keys
lrwxrwxrwx 1 root root   28 Feb  5 21:23 list-crl -&amp;gt; /usr/share/easy-rsa/list-crl
-rw-r--r-- 1 root root 7.7K Feb  5 21:23 openssl-0.9.6.cnf
-rw-r--r-- 1 root root 8.3K Feb  5 21:23 openssl-0.9.8.cnf
-rw-r--r-- 1 root root 8.2K Feb  5 21:23 openssl-1.0.0.cnf
-rw-r--r-- 1 root root 8.2K Feb  5 21:23 openssl.cnf
lrwxrwxrwx 1 root root   27 Feb  5 21:23 pkitool -&amp;gt; /usr/share/easy-rsa/pkitool
lrwxrwxrwx 1 root root   31 Feb  5 21:23 revoke-full -&amp;gt; /usr/share/easy-rsa/revoke-full
lrwxrwxrwx 1 root root   28 Feb  5 21:23 sign-req -&amp;gt; /usr/share/easy-rsa/sign-req
-rw-r--r-- 1 root root 2.1K Feb  5 21:23 vars
lrwxrwxrwx 1 root root   35 Feb  5 21:23 whichopensslcnf -&amp;gt; /usr/share/easy-rsa/whichopensslcnf
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can replace the openssl.cnf with whichever version you want to use for generation, I decided to go with openssl-1.0.0.cnf&lt;/p&gt;

&lt;p&gt;Open the file ~/ca/vars and update accordingly, you can customize it however you want but you should at least modify the following to suit your organization.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;export KEY_COUNTRY=&amp;quot;US&amp;quot;
export KEY_PROVINCE=&amp;quot;CA&amp;quot;
export KEY_CITY=&amp;quot;SanFrancisco&amp;quot;
export KEY_ORG=&amp;quot;Fort-Funston&amp;quot;
export KEY_EMAIL=&amp;quot;me@myhost.mydomain&amp;quot;
export KEY_OU=&amp;quot;MyOrganizationalUnit&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After you have edited the file you need to source it so we have the environment variables ready, to do so you can just run&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cd ~/ca
$ . ./vars
$ env | grep ^KEY
KEY_OU=MyOrganizationalUnit
KEY_SIZE=2048
KEY_NAME=EasyRSA
KEY_EXPIRE=3650
KEY_EMAIL=me@myhost.mydomain
KEY_ORG=Fort-Funston
KEY_CITY=SanFrancisco
KEY_COUNTRY=US
KEY_PROVINCE=CA
KEY_CONFIG=/root/ca/openssl.cnf
KEY_DIR=/root/ca/keys
$ ./clean-all
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you are ready to build your ca key and tls-crypt key for OpenVPN&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cd ~/ca
$ ./build-ca
$ openvpn --genkey --secret ~/ca/keys/ta.key
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You CA is ready now we have to generate a server key, make sure you sign the certificate when asked&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cd ~/ca
$ ./build-key-server server
$ ./build-dh
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we also need to generate a client key for each client that will connect, make sure you sign the certificates when asked&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cd ~/ca
$ ./build-key locb
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s see what have we generated your &lt;strong&gt;keys&lt;/strong&gt; folder should have the following files&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ ls -lh ~/ca/keys
total 84K
-rw-r--r-- 1 root root 5.4K Feb  5 21:31 01.pem
-rw-r--r-- 1 root root 5.3K Feb  5 21:35 02.pem
-rw-r--r-- 1 root root 1.7K Feb  5 21:30 ca.crt
-rw------- 1 root root 1.7K Feb  5 21:30 ca.key
-rw-r--r-- 1 root root  424 Feb  5 21:33 dh2048.pem
-rw-r--r-- 1 root root  238 Feb  5 21:35 index.txt
-rw-r--r-- 1 root root   21 Feb  5 21:35 index.txt.attr
-rw-r--r-- 1 root root   21 Feb  5 21:31 index.txt.attr.old
-rw-r--r-- 1 root root  120 Feb  5 21:31 index.txt.old
-rw-r--r-- 1 root root 5.3K Feb  5 21:35 locb.crt
-rw-r--r-- 1 root root 1.1K Feb  5 21:35 locb.csr
-rw------- 1 root root 1.7K Feb  5 21:35 locb.key
-rw-r--r-- 1 root root    3 Feb  5 21:35 serial
-rw-r--r-- 1 root root    3 Feb  5 21:31 serial.old
-rw-r--r-- 1 root root 5.4K Feb  5 21:31 server.crt
-rw-r--r-- 1 root root 1.1K Feb  5 21:31 server.csr
-rw------- 1 root root 1.7K Feb  5 21:31 server.key
-rw------- 1 root root  636 Feb  5 21:30 ta.key
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we have everything so we can send finally do the connection between our datacenters.&lt;/p&gt;

&lt;h3 id=&#34;configuration&#34;&gt;Configuration&lt;/h3&gt;

&lt;p&gt;So let&amp;rsquo;s prepare some things before we start&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ mkdir -p /etc/openvpn/ccd
$ cp -v ~/ca/keys/{ca.crt,server.*,dh2048.pem,ta.key} /etc/openvpn/server
&#39;/root/ca/keys/ca.crt&#39; -&amp;gt; &#39;/etc/openvpn/server/ca.crt&#39;
&#39;/root/ca/keys/server.crt&#39; -&amp;gt; &#39;/etc/openvpn/server/server.crt&#39;
&#39;/root/ca/keys/server.csr&#39; -&amp;gt; &#39;/etc/openvpn/server/server.csr&#39;
&#39;/root/ca/keys/server.key&#39; -&amp;gt; &#39;/etc/openvpn/server/server.key&#39;
&#39;/root/ca/keys/dh2048.pem&#39; -&amp;gt; &#39;/etc/openvpn/server/dh2048.pem&#39;
&#39;/root/ca/keys/ta.key&#39; -&amp;gt; &#39;/etc/openvpn/server/ta.key&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now lets make our configuration for the server. We need to create a separate user for our process to run in, so it&amp;rsquo;s isolated from the system.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ addgroup ovpn
$ useradd --shell=/bin/false -g ovpn ovpn
$ cat /etc/openvpn/server.conf
dev tun
persist-key
persist-local-ip
persist-remote-ip
persist-tun
topology subnet
port 1194
proto udp
keepalive 10 60

ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/server.crt
key /etc/openvpn/server/server.key
dh /etc/openvpn/server/dh2048.pem

server 172.16.1.0 255.255.255.0
client-to-client

client-config-dir ccd

explicit-exit-notify 10

user ovpn
group ovpn

tls-crypt /etc/openvpn/server/ta.key
auth SHA512
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256
ncp-ciphers AES-256-GCM:AES-256-CBC

ifconfig-pool-persist ipp.txt
status openvpn-status.log
log /var/log/openvpn.log
verb 4

route 10.0.0.0 255.255.255.0

tun-mtu 1500
tun-mtu-extra 32
mssfix 1450
reneg-sec 0

cipher AES-128-CBC
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All the configuration in here is self explanatory, the only thing worth of not is &lt;strong&gt;route 10.0.0.0 255.255.255.0&lt;/strong&gt;, which needs to be in the main file so the server knows that it needs to route that subnet to the connected client, if you don&amp;rsquo;t add that line then we will be missing the required routes to access the server.&lt;/p&gt;

&lt;p&gt;Now we need to setup the vm in the location b, we still have to install the same packages as for location a, but before we do that we need to create a configuration file for the client&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cd /etc/openvpn/ccd
cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/openvpn/ccd/locb
push &amp;quot;route 10.5.100.0 255.255.252.0&amp;quot;
iroute 10.0.0.0 255.255.255.0
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will tell that the client &lt;strong&gt;locb&lt;/strong&gt; when connected that it needs to add the route for accessing the subnet in &lt;strong&gt;loca&lt;/strong&gt; and for the server to setup an internal route for the &lt;strong&gt;locb&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&#34;service&#34;&gt;Service&lt;/h3&gt;

&lt;p&gt;Let&amp;rsquo;s enable the server&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ systemctl disable openvpn
$ systemctl enable openvpn@server
$ systemctl restart openvpn@server
$ systemctl status openvpn@server.service
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;vpn-gateway-at-location-b&#34;&gt;VPN gateway at location B&lt;/h2&gt;

&lt;p&gt;Now we are ready to connect we need to transfer the files ca.crt,locb.*,dh2048.pem,ta.key in the keys folder from the server to the client in &lt;strong&gt;/etc/openvpn/client&lt;/strong&gt; folder.&lt;/p&gt;

&lt;h3 id=&#34;forwarding-1&#34;&gt;Forwarding&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/sysctl.d/30-openvpn-forward.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
EOF
$ sysctl -p /etc/sysctl.d/30-openvpn-forward.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;installation-1&#34;&gt;Installation&lt;/h3&gt;

&lt;p&gt;Let&amp;rsquo;s install the prerequisites&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ apt-get install openvpn firewalld
$ addgroup ovpn
$ useradd --shell=/bin/false -g ovpn ovpn
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;firewall-1&#34;&gt;Firewall&lt;/h3&gt;

&lt;p&gt;Let&amp;rsquo;s configure the firewall to allow us to connect to the machine and all the necessary configuration needed for it&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ firewall-cmd --permanent --zone=public --add-source=94.x.x.x/32
$ firewall-cmd --permanent --zone=trusted --add-interface=eth1
$ firewall-cmd --permanent --zone=trusted --add-interface=tun0
$ firewall-cmd --permanent --zone=trusted --add-masquerade
$ DEV=$(ip route get 8.8.8.8 | awk &#39;NR==1 {print $(NF-2)}&#39;)
$ firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s  172.16.1.0/24 -o $DEV -j MASQUERADE
$ firewall-cmd --reload
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;configuration-1&#34;&gt;Configuration&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cat /etc/openvpn/client.conf
client
dev tun
persist-key
persist-tun
persist-local-ip
persist-remote-ip
proto udp
nobind
user ovpn
group ovpn
remote-cert-tls server
auth SHA512
verb 4

remote s2s.example.com 1194

ca /etc/openvpn/client/ca.crt
cert /etc/openvpn/client/locb.crt
key /etc/openvpn/client/locb.key
tls-crypt /etc/openvpn/client/ta.key

log /var/log/openvpn.log

keepalive 10 60
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ systemctl disable openvpn
$ systemctl enable openvpn@client
$ systemctl restart openvpn@client
$ systemctl status openvpn@client.service
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;routes&#34;&gt;Routes&lt;/h2&gt;

&lt;p&gt;The only thing missing now is setting up the routes required so we know where we need to go for a given subnet&lt;/p&gt;

&lt;h3 id=&#34;etc-network-interfaces&#34;&gt;/etc/network/interfaces&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cat /etc/network/interfaces
source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto ens18
iface ens18 inet dhcp

auto ens19
iface ens19 inet static
    address 10.0.0.3
    netmask 255.255.255.0
    up route add -net 10.5.100.0 netmask 255.255.252.0 gw 10.0.0.5
    down route add -net 10.5.100.0 netmask 255.255.252.0 gw 10.0.0.5
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now everytime our interface is configured our route will be set up so we can access the servers on the other side of the VPN&lt;/p&gt;

&lt;h3 id=&#34;ip-route&#34;&gt;ip route&lt;/h3&gt;

&lt;p&gt;We need to add a static route on the internal network interface so we can route the subnet.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ ip route
default via 95.x.x.x dev ens18 onlink
10.0.0.0/24 dev ens19 proto kernel scope link src 10.0.0.3
95.x.x.x/25 dev ens18 proto kernel scope link src 95.x.x.x

$ ping 10.5.100.10 -c1
PING 10.5.100.10 (10.5.100.10) 56(84) bytes of data.

--- 10.5.100.10 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

$ ip route add 10.5.100.0/22 via 10.0.0.5 dev ens19

$ ip route
default via 95.x.x.x dev ens18 onlink
10.0.0.0/24 dev ens19 proto kernel scope link src 10.0.0.3
10.5.100.0/22 via 10.0.0.5 dev ens19
95.x.x.x/25 dev ens18 proto kernel scope link src 95.x.x.x

$ ping 10.5.100.10 -c1
PING 10.5.100.10 (10.5.100.10) 56(84) bytes of data.
64 bytes from 10.5.100.10: icmp_seq=1 ttl=62 time=2.17 ms

--- 10.5.100.10 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 2.171/2.171/2.171/0.000 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;dhcp&#34;&gt;DHCP&lt;/h3&gt;

&lt;p&gt;If we use DHCP we can easily put a stateless route so all machines automatically get the correct route.&lt;/p&gt;

&lt;h4 id=&#34;dnsmasq&#34;&gt;dnsmasq&lt;/h4&gt;

&lt;p&gt;We just need to add this to the DHCP server in location A and we are done, the route will be automatically setup when the client requests an IP address.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dhcp-option=121,10.5.100.0/22,10.0.0.5
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;testing&#34;&gt;Testing&lt;/h2&gt;

&lt;p&gt;And now let&amp;rsquo;s see the result of our process finally&lt;/p&gt;

&lt;h3 id=&#34;vpn-gateway-in-location-a&#34;&gt;VPN gateway in location A&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ traceroute 10.0.0.3 -n
traceroute to 10.0.0.3 (10.0.0.3), 30 hops max, 60 byte packets
 1  172.16.1.2  2.050 ms  2.038 ms  2.033 ms
 2  10.0.0.3  2.239 ms  2.242 ms  2.315 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;vpn-gateway-in-location-b&#34;&gt;VPN gateway in location B&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ traceroute 10.5.100.10 -n
traceroute to 10.5.100.10 (10.5.100.10), 30 hops max, 60 byte packets
 1  172.16.1.1  2.023 ms  2.007 ms  2.000 ms
 2  10.5.100.10  1.991 ms  1.986 ms  1.979 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;machine-in-location-b-to-a-machine-in-location-a&#34;&gt;Machine in location B to a machine in location A&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ traceroute 10.5.100.10 -n
traceroute to 10.5.100.10 (10.5.100.10), 30 hops max, 60 byte packets
 1  10.0.0.5  0.514 ms  0.497 ms  0.486 ms
 2  * * *
 3  10.5.100.10  2.238 ms  2.234 ms  2.219 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The 2nd hop is our VPN gateway doing the forwarding&lt;/p&gt;

&lt;h3 id=&#34;speed&#34;&gt;Speed&lt;/h3&gt;

&lt;p&gt;The speed we got it&amp;rsquo;s not that bad, it&amp;rsquo;s &lt;strong&gt;281 Mbits/sec&lt;/strong&gt; which is around &lt;strong&gt;35 MB/s&lt;/strong&gt;. We can make it even faster by using Elliptic curve crypto (ECC) for the keys&lt;/p&gt;

&lt;h4 id=&#34;machine-on-location-a&#34;&gt;Machine on location A&lt;/h4&gt;

&lt;p&gt;We start an iperf server on any machine on location A by logging into it and running&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ apt-get install iperf
$ iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[  4] local 10.5.100.10 port 5001 connected with 10.5.100.10 port 42076
[ ID] Interval       Transfer     Bandwidth
[  4]  0.0-10.0 sec   335 MBytes   280 Mbits/sec
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;machine-on-location-b&#34;&gt;Machine on location B&lt;/h4&gt;

&lt;p&gt;We start an iperf client on any machine on location B by logging into it and running&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ apt-get install iperf
$ iperf -c 10.5.100.10
------------------------------------------------------------
Client connecting to 10.5.100.20, TCP port 5001
TCP window size: 45.0 KByte (default)
------------------------------------------------------------
[  3] local 10.0.0.3 port 42076 connected with 10.5.100.20 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   335 MBytes   281 Mbits/sec
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Confirm before executing shutdown/reboot command on linux</title>
            <link>https://matoski.com/article/confirm-before-executing-shutdown-reboot-linux/</link>
            <pubDate>Mon, 23 Oct 2017 11:54:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/confirm-before-executing-shutdown-reboot-linux/</guid>
            <description>&lt;p&gt;I was rushing to leave and was still logged into a server so I wanted to shutdown my laptop, but what I didn&amp;rsquo;t notice is that I was still connected to the remote server.
Luckily before pressing enter I noticed I&amp;rsquo;m not on my machine but on a remote server.
So I was thinking there should be a very easy way to prevent it from happening again, to me or to anyone else.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;So first thing we need to create a new bash script at &lt;strong&gt;/usr/local/bin/confirm&lt;/strong&gt; with the contents bellow and with execution permissions&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/usr/bin/env bash
echo &amp;quot;About to execute $1 command&amp;quot;
echo -n &amp;quot;Would you like to proceed y/n? &amp;quot;
read reply

if [ &amp;quot;$reply&amp;quot; = y -o &amp;quot;$reply&amp;quot; = Y ]
then
   $1 &amp;quot;${@:2}&amp;quot;
else
   echo &amp;quot;$1 ${@:2} cancelled&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now only thing left to do is to setup the aliases so they go through this command to confirm instead of directly calling the command.&lt;/p&gt;

&lt;p&gt;So I create the following files&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/etc/profile.d/confirm-shutdown.sh&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;alias shutdown=&amp;quot;/usr/local/bin/confirm /sbin/shutdown&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;/etc/profile.d/confirm-reboot.sh&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;alias reboot=&amp;quot;/usr/local/bin/confirm /sbin/reboot&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now when I actually try to do a shutdown/reboot it will prompt me like so.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ilijamt@x1 ~ $ reboot 
Before proceeding to perform /sbin/reboot, please ensure you have approval to perform this task
Would you like to proceed y/n? n
/sbin/reboot  cancelled
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Compiling Redis Desktop Manager on Debian</title>
            <link>https://matoski.com/article/compiling-rdm-debian/</link>
            <pubDate>Sun, 01 Jan 2017 21:20:24 +0000</pubDate>
            
            <guid>https://matoski.com/article/compiling-rdm-debian/</guid>
            <description>&lt;p&gt;So I&amp;rsquo;ve used redis desktop manager in the past, but suddenly I can&amp;rsquo;t use it anymore it&amp;rsquo;s not compiling on debian, and there are no packages for the application.
So I decided to find a way to to compile it on my machine, which uses Debian Stretch.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;So first we need to install some prerequisites so we can compile the application&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;sudo apt-get install build-essential git libssh2-1-dev zlib1g zlib1g-dev cmake libssl-dev qt5-default automake libtool \
    libssl-dev libssh2-1-dev g++ libgl1-mesa-dev qtdeclarative5-dev qml-module-qtgraphicaleffects \
    qml-module-qtquick-controls qml-module-qtquick-dialogs qml-module-qtquick-extras \
    qml-module-qtquick-layouts qml-module-qtquick-privatewidgets \
    qml-module-qtquick-window2 qml-module-qtquick2 qml-module-qttest
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now to compile we need to pull the code from github, currently the stable version is &lt;strong&gt;0.8.8&lt;/strong&gt;, so we can execute the following commands to pull the code from Github.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir ~/builds &amp;amp;&amp;amp; cd ~/builds
export RDM_ROOT=~/builds/rdm
export RDM_VERSION=0.8.8

git clone --recursive https://github.com/uglide/RedisDesktopManager.git --branch $RDM_VERSION --depth 1 $RDM_ROOT
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that we have the code for Redis Desktop Manager, we need to pull some extra repos so we can compile the application. We need to pull and compile breakpad&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;git clone https://chromium.googlesource.com/linux-syscall-support $RDM_ROOT/3rdparty/gbreakpad/src/third_party/lss

cd $RDM_ROOT/3rdparty/gbreakpad/
touch README
./configure
make -j 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we have everything required to compile Redis Desktop Manager, running the following commands will compile Redis Desktop Manager, so it can be used.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cd $RDM_ROOT/src

echo &amp;quot;#define RDM_VERSION \&amp;quot;$RDM_VERSION\&amp;quot;&amp;quot; &amp;gt; version.h

qmake
make -j 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The binary is located in &lt;strong&gt;$RDM_ROOT/bin&lt;/strong&gt;, depending on the compilation, in my case it was in &lt;strong&gt;$RDM_ROOT/bin/linux/release&lt;/strong&gt;, so just copy the binary &lt;strong&gt;rdm&lt;/strong&gt; to where ever you want and you can run it.&lt;/p&gt;

&lt;p&gt;If you don&amp;rsquo;t want to polute your OS, you can always do this in a chroot.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;debootstrap --arch amd64 stretch /srv/chroot/stretch http://ftp.debian.org/debian
chroot /srv/chroot/stretch
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The rest of the steps are the same, just now you don&amp;rsquo;t need to install all the packages from above, but you will need to install all the &lt;strong&gt;qml&lt;/strong&gt; packages on the machine you will run the application.&lt;/p&gt;

&lt;p&gt;And after it finishes compiling, you can remove the folder by issuing.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;rm -rf /srv/chroot/stretch
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you have redis desktop manager. Well that&amp;rsquo;s it.&lt;/p&gt;

&lt;p&gt;Enjoy.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Codility - OddOccurrencesInArray</title>
            <link>https://matoski.com/article/codility-odd-occurrences-array/</link>
            <pubDate>Tue, 13 Dec 2016 17:12:03 +0000</pubDate>
            
            <guid>https://matoski.com/article/codility-odd-occurrences-array/</guid>
            <description>&lt;p&gt;A non-empty zero-indexed array A consisting of N integers is given. The array contains an odd number of elements, and each element of the array can be paired with another element that has the same value, except for one element that is left unpaired.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;For example, in array A such that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  A[0] = 9  A[1] = 3  A[2] = 9
  A[3] = 3  A[4] = 9  A[5] = 7
  A[6] = 9
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;the elements at indexes 0 and 2 have value 9&lt;/li&gt;
&lt;li&gt;the elements at indexes 1 and 3 have value 3&lt;/li&gt;
&lt;li&gt;the elements at indexes 4 and 6 have value 9&lt;/li&gt;
&lt;li&gt;the element at index 5 has value 7 and is unpaired&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Write a function that, given an array A consisting of N integers fulfilling the above conditions, returns the value of the unpaired element.&lt;/p&gt;

&lt;p&gt;For example, given array A such that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  A[0] = 9  A[1] = 3  A[2] = 9
  A[3] = 3  A[4] = 9  A[5] = 7
  A[6] = 9
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;the function should return 7, as explained in the example above.&lt;/p&gt;

&lt;p&gt;Assume that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;N is an odd integer within the range [1..1,000,000]&lt;/li&gt;
&lt;li&gt;each element of array A is an integer within the range [1..1,000,000,000]&lt;/li&gt;
&lt;li&gt;all but one of the values in A occur an even number of times&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Complexity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;expected worst-case time complexity is O(N);&lt;/li&gt;
&lt;li&gt;expected worst-case space complexity is O(1), beyond input storage (not counting the storage required for input arguments).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Elements of input arrays can be modified.&lt;/p&gt;

&lt;h3 id=&#34;solution&#34;&gt;Solution&lt;/h3&gt;

&lt;p&gt;This problem looks very complicated in the begining, but actually it&amp;rsquo;s quite simple.&lt;/p&gt;

&lt;p&gt;We need to find out which number is not paired, and that can easily be accomplished by using bitwise operation, more to the point &lt;strong&gt;XOR&lt;/strong&gt; operator.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0 0 = 0
0 A = A
A 0 = A
A A = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From this table we can see that everytime we use a XOR operator on the number it self it will reset to zero, that&amp;rsquo;s what we need.&lt;/p&gt;

&lt;p&gt;So the solution is iterating the whole array and doing a XOR on a variable that will hold the missing number.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;func Solution(A []int) int {

    var number int = 0;
    
    for _, v := range A {
        number ^= v
    }
    
    return number
}
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Codility - CyclicRotation</title>
            <link>https://matoski.com/article/codility-cyclic-rotation/</link>
            <pubDate>Tue, 13 Dec 2016 16:32:03 +0000</pubDate>
            
            <guid>https://matoski.com/article/codility-cyclic-rotation/</guid>
            <description>&lt;p&gt;A zero-indexed array A consisting of N integers is given. Rotation of the array means that each element is shifted right by one index, and the last element of the array is also moved to the first place.&lt;/p&gt;

&lt;p&gt;For example, the rotation of array A = [3, 8, 9, 7, 6] is [6, 3, 8, 9, 7]. The goal is to rotate array A K times; that is, each element of A will be shifted to the right by K indexes.&lt;/p&gt;

&lt;p&gt;Write a function that, given a zero-indexed array A consisting of N integers and an integer K, returns the array A rotated K times.&lt;/p&gt;

&lt;p&gt;For example, given array A = [3, 8, 9, 7, 6] and K = 3, the function should return [9, 7, 6, 3, 8].&lt;/p&gt;

&lt;p&gt;Assume that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;N and K are integers within the range [0..100];&lt;/li&gt;
&lt;li&gt;each element of array A is an integer within the range [−1,000..1,000].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In your solution, focus on correctness. The performance of your solution will not be the focus of the assessment.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function solution(A, K) {

    var size = A.length;
    var ret = [];

    if (K &amp;lt; 0 || K &amp;gt; 100 || size == 0) {
        return ret;
    }

    if (size == 1) {
        return A;
    }

    for (i = 0; i &amp;lt; size; i++) {
        ret[(i + K) % size] = A[i];
    }

    return ret;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Some of the steps are obvious but let&amp;rsquo;s see the rest of them.&lt;/p&gt;

&lt;p&gt;If we want to shift an element K times we can calculate the new index by using &lt;strong&gt;(index + shift_times) % size_of_element&lt;/strong&gt;, but how does this actually work.&lt;/p&gt;

&lt;p&gt;The modulo operator returns the reminder of the division between two numbers. So if we have an array with 10 elements, and we want to shift the index 3, 5 times if we do it manually we can figure out that the new index should be 8.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;3 + 5 = 8
8 % 10 = 8
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But lets say that the array has 5 elements instead of 10 then, we know that we need to shift the array to position 3, if you do it one step at a time you can verify that it&amp;rsquo;s so.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;3 + 5 = 8
8 % 5 = 3
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But what if the array had 3 elements&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;3 + 5 = 8
8 % 3 = 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And there you go very simple.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Codility - BinaryGap</title>
            <link>https://matoski.com/article/codility-binarygap/</link>
            <pubDate>Tue, 13 Dec 2016 16:01:03 +0000</pubDate>
            
            <guid>https://matoski.com/article/codility-binarygap/</guid>
            <description>&lt;p&gt;A binary gap within a positive integer N is any maximal sequence of consecutive zeros that is surrounded by ones at both ends in the binary representation of N.&lt;/p&gt;

&lt;p&gt;For example, number 9 has binary representation 1001 and contains a binary gap of length 2. The number 529 has binary representation 1000010001 and contains two binary gaps: one of length 4 and one of length 3. The number 20 has binary representation 10100 and contains one binary gap of length 1. The number 15 has binary representation 1111 and has no binary gaps.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Write a function that, given a positive integer N, returns the length of its longest binary gap. The function should return 0 if N doesn&amp;rsquo;t contain a binary gap.&lt;/p&gt;

&lt;p&gt;For example, given N = 1041 the function should return 5, because N has binary representation 10000010001 and so its longest binary gap is of length 5.&lt;/p&gt;

&lt;p&gt;Assume that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;N is an integer within the range [1..2,147,483,647].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Complexity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;expected worst-case time complexity is O(log(N));&lt;/li&gt;
&lt;li&gt;expected worst-case space complexity is O(1).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So lets see how we can solve this. Actually it&amp;rsquo;s quite an easy thing to do. But what would be the fastest way to do it.&lt;/p&gt;

&lt;p&gt;There are several options to solve this case, one way would be to convert it to a binary string and explode the string to a group, and you can just check which group has the most zeroes.
Another way and fastest way would be to do bit checks on the number it self, this is what we gonna try.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func Solution(N int) int {

	var max int = 0
	var current int = 0
	var startFound bool = false

	for i := 31; i &amp;gt;= 0; i-- {
		bit := ((N &amp;amp; (1 &amp;lt;&amp;lt; uint(i))) &amp;gt; 0)
		if startFound {
			// we have found the start
			if !bit {
				current++
			} else {
				if max &amp;lt; current {
					max = current
				}
				current = 0
			}
		} else {
			startFound = bit
		}
	}

	return max

}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can probably optimze the following code a bit more, but it should be sufficient for now, and I leave it up to you guys to see and decide how to do it.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Automatic starting and stopping of AWS EC2 instances with Lambda and CloudWatch</title>
            <link>https://matoski.com/article/aws-automatic-start-stop-instances-lambda/</link>
            <pubDate>Sat, 19 Nov 2016 10:12:35 +0000</pubDate>
            
            <guid>https://matoski.com/article/aws-automatic-start-stop-instances-lambda/</guid>
            <description>&lt;p&gt;I needed to figure out a way to start/stop instances automatically during certain periods. The obvious way is Lambda, but how to do it. We wanted some instances to run from Monday to Friday, and to start at 7am and stop at 5pm.&lt;/p&gt;

&lt;p&gt;Luckily there is a library that abstracts everything you need for starting and stopping your instances. And coupled with Lambda and CloudWatch we can easily accomplish what we want.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;iam-role&#34;&gt;IAM Role&lt;/h2&gt;

&lt;p&gt;First thing let&amp;rsquo;s create a new IAM role. The role is defined bellow, so we need some things so we can create logs and allow our Lambda functions to be able to start/stop an instance, with the following steps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to IAM Management console&lt;/li&gt;
&lt;li&gt;Roles&lt;/li&gt;
&lt;li&gt;Create New Role

&lt;ul&gt;
&lt;li&gt;Role Name: &lt;strong&gt;lambda_start_stop_ec2&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Role Type

&lt;ul&gt;
&lt;li&gt;AWS Service Roles: &lt;strong&gt;AWS Lambda&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Create role&lt;/li&gt;
&lt;li&gt;Edit &lt;strong&gt;lambda_start_stop_ec2&lt;/strong&gt; role, and create a new custom inline policy with the json contents bellow.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;Version&amp;quot;: &amp;quot;2012-10-17&amp;quot;,
  &amp;quot;Statement&amp;quot;: [
    {
      &amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;,
      &amp;quot;Action&amp;quot;: [
        &amp;quot;logs:CreateLogGroup&amp;quot;,
        &amp;quot;logs:CreateLogStream&amp;quot;,
        &amp;quot;logs:PutLogEvents&amp;quot;
      ],
      &amp;quot;Resource&amp;quot;: &amp;quot;arn:aws:logs:*:*:*&amp;quot;
    },
    {
      &amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;,
      &amp;quot;Action&amp;quot;: [
        &amp;quot;ec2:Start*&amp;quot;,
        &amp;quot;ec2:Stop*&amp;quot;
      ],
      &amp;quot;Resource&amp;quot;: &amp;quot;*&amp;quot;
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;lambda&#34;&gt;Lambda&lt;/h2&gt;

&lt;p&gt;We need to create 2 lambda functions this, and if you really want you can rework both functions into one.&lt;/p&gt;

&lt;p&gt;So for both lambda functions you create a new Python Lambda function, with the respective code and existing role &lt;strong&gt;lambda_start_stop_ec2&lt;/strong&gt;, and we have our functions that can start and stop our instances&lt;/p&gt;

&lt;h3 id=&#34;start-instance&#34;&gt;Start Instance&lt;/h3&gt;

&lt;p&gt;This function is responsible for starting the instances.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import boto3

def lambda_handler(event, context):

    if not bool(event):
        raise Exception(&#39;No event defined!&#39;)
        
    instances = event.get(&amp;quot;instances&amp;quot;)
    region = event.get(&amp;quot;region&amp;quot;)
        
    if not bool(instances):
        raise Exception(&#39;Instances are not defined!&#39;)
        
    if not type(instances) is list:
        raise Exception(&#39;Instances is not a list!&#39;)
        
    if not bool(instances):
        raise Exception(&#39;No instances defined&#39;)

    if not bool(region):
        raise Exception(&#39;Region is not defined!&#39;)

    ec2 = boto3.client(&#39;ec2&#39;, region_name=region)
    ec2.start_instances(InstanceIds=instances)
        
    for instance in instances:
         print &amp;quot;Started {} instance in {} region&amp;quot;.format(instance, region)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;stop-instance&#34;&gt;Stop Instance&lt;/h3&gt;

&lt;p&gt;This function is responsible for stopping the instances&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import boto3

def lambda_handler(event, context):

    if not bool(event):
        raise Exception(&#39;No event defined!&#39;)
        
    instances = event.get(&amp;quot;instances&amp;quot;)
    region = event.get(&amp;quot;region&amp;quot;)       
    
    if not bool(instances):
        raise Exception(&#39;Instances are not defined!&#39;)
        
    if not type(instances) is list:
        raise Exception(&#39;Instances is not a list!&#39;)
        
    if not bool(instances):
        raise Exception(&#39;No instances defined&#39;)

    if not bool(region):
        raise Exception(&#39;Region is not defined!&#39;)

    ec2 = boto3.client(&#39;ec2&#39;, region_name=region)
    ec2.stop_instances(InstanceIds=instances)
        
    for instance in instances:
         print &amp;quot;Started {} instance in {} region&amp;quot;.format(instance, region)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;cloudwatch&#34;&gt;CloudWatch&lt;/h2&gt;

&lt;p&gt;Create both rules for starting and stopping the instances you have defined.&lt;/p&gt;

&lt;p&gt;When creating new rule, set &lt;strong&gt;Event selector&lt;/strong&gt; to &lt;strong&gt;Schedule&lt;/strong&gt;, and select how and when to trigger it.
You can add as many targets as you want to a rule, for different regions and so on.&lt;/p&gt;

&lt;h3 id=&#34;startinstances&#34;&gt;StartInstances&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;New target: &lt;strong&gt;Lambda function&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Function name: &lt;strong&gt;StartEC2Instances&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Configure input

&lt;ul&gt;
&lt;li&gt;Constant (JSON)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;region&amp;quot;: &amp;quot;us-east-1&amp;quot;,
  &amp;quot;instances&amp;quot;: [
    &amp;quot;i-1e91dd10&amp;quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;stopinstances&#34;&gt;StopInstances&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;New target: &lt;strong&gt;Lambda function&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Function name: &lt;strong&gt;StopEC2Instances&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Configure input

&lt;ul&gt;
&lt;li&gt;Constant (JSON)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;region&amp;quot;: &amp;quot;us-east-1&amp;quot;,
  &amp;quot;instances&amp;quot;: [
    &amp;quot;i-1e91dd10&amp;quot;,
    &amp;quot;i-1e95235f&amp;quot;,
    &amp;quot;i-1e92235f&amp;quot;    
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;logs&#34;&gt;Logs&lt;/h3&gt;

&lt;p&gt;Now in the logs you can see when the instances have been started/stopped&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/aws/lambda/StartEC2Instances&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;START RequestId: b1b0176b-ae46-11e6-b8f8-c9b72337b2e1 Version: $LATEST
Started i-1e91dd10 instance in us-east-1 region
END RequestId: b1b0176b-ae46-11e6-b8f8-c9b72337b2e1
REPORT RequestId: b1b0176b-ae46-11e6-b8f8-c9b72337b2e1	Duration: 0.27 ms	Billed Duration: 100 ms Memory Size: 128 MB	Max Memory Used: 18 MB	
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;/aws/lambda/StopEC2Instances&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;START RequestId: da073d48-ae46-11e6-a365-eb4b71a100af Version: $LATEST
Stopped i-1e91dd10 instance in us-east-1 region
Stopped i-1e95235f instance in us-east-1 region
Stopped i-1e92235f instance in us-east-1 region
END RequestId: da073d48-ae46-11e6-a365-eb4b71a100af
REPORT RequestId: da073d48-ae46-11e6-a365-eb4b71a100af	Duration: 0.32 ms	Billed Duration: 100 ms Memory Size: 128 MB	Max Memory Used: 14 MB	
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And there we go, we have a working system that can start/instances whenever we want.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Compressing multiple files or directories with XZ and TAR</title>
            <link>https://matoski.com/article/xz-compress-directory/</link>
            <pubDate>Mon, 17 Oct 2016 22:35:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/xz-compress-directory/</guid>
            <description>&lt;p&gt;XZ is one of the best compression tools I&amp;rsquo;ve seen, it&amp;rsquo;s compressed files so big to a fraction of their size.
I&amp;rsquo;ve had an 16 GB SQL dump, and it managed to compress it down to 263 MB.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve needed to compress several files using XZ. And as XZ compresses single files we are gonna have to use TAR to do it
&lt;/p&gt;

&lt;p&gt;And since the newer version of XZ supports multi threading, we can speed up compression quite a bit&lt;/p&gt;

&lt;p&gt;Since the XZ utils in Debian/Ubuntu is an old version I&amp;rsquo;ve created my own backports that I can use.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;quot;deb http://packages.matoski.com/ debian main&amp;quot; | sudo tee /etc/apt/sources.list.d/packages-matoski-com.list
curl -s http://packages.matoski.com/keyring.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install xz-utils
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This should give you a newer version of XZ that supports multi threading.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s have a directory with a lot of files and subdirectories, to compress it all we would do&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;tar -cf - directory/ | xz -9e --threads=8 -c - &amp;gt; tarfile.tar.xz 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On the newer versions of tar you can also do the following too&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;XZ_OPT=&amp;quot;-9e --threads=8&amp;quot; tar cJf tarfile.tar.xz directory
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or if you want you can do it separately with a progress bar like this.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;tar -cf - directory/ | (pv -s $(du -sb directory/ | awk &#39;{print $1}&#39;) -p --timer --rate --bytes &amp;gt; tarfile.tar)
xz -9ev --threads=8 tarfile.tar
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will give you a nice progress bar while it&amp;rsquo;s creating the archive firstly and then compressing it with XZ&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Tracking versions in Go</title>
            <link>https://matoski.com/article/tracking-versions-go/</link>
            <pubDate>Fri, 14 Oct 2016 12:23:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/tracking-versions-go/</guid>
            <description>&lt;p&gt;Some of my services were written in Go, and we wanted a way to track which version was used, so we can track and solve issues.
Or even see when the application was deployed or from which source was built.
The code is on git, so adding a git commit hash to the mix will make our problem easier.
Luckily go provides us with a simple way of doing this.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Lets look at some of the stuff I keep track of so I can easily see which version I&amp;rsquo;m using.
I usually call this file &lt;strong&gt;version.go&lt;/strong&gt; and drop it in the root of the package.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;package main

import (
	&amp;quot;flag&amp;quot;
	&amp;quot;fmt&amp;quot;
	&amp;quot;os&amp;quot;
	&amp;quot;runtime&amp;quot;
)

var version = flag.Bool(&amp;quot;version&amp;quot;, false, &amp;quot;Print the version and exit&amp;quot;)

var BuildVersion string
var BuildHash string
var BuildDate string
var BuildClean string
var Name = &amp;quot;application-name&amp;quot;

func init() {
	flag.Parse()
	if *version {
		fmt.Printf(&amp;quot;Name: %s\n&amp;quot;, Name);
		fmt.Printf(&amp;quot;Version: %s\n&amp;quot;, BuildVersion);
		fmt.Printf(&amp;quot;Git Commit Hash: %s\n&amp;quot;, BuildHash);
		fmt.Printf(&amp;quot;Build Date: %s\n&amp;quot;, BuildDate);
		fmt.Printf(&amp;quot;Built from clean source tree: %s\n&amp;quot;, BuildClean)
		fmt.Printf(&amp;quot;OS: %s\n&amp;quot;, runtime.GOOS)
		fmt.Printf(&amp;quot;Architecture: %s\n&amp;quot;, runtime.GOARCH)
		os.Exit(1)
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lets also create a file called &lt;strong&gt;VERSION&lt;/strong&gt;, and we use that file to keep track of what version is our application.
My version file contains the following information&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cat VERSION
0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To build the application that will show me the version details I would issue the following command, I usually write a Makefile that will generate the command bellow, with all the necessary information.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;go build -ldflags &amp;quot;-X &#39;main.BuildVersion=$(cat VERSION)&#39; -X &#39;main.BuildHash=$(git log --pretty=format:&#39;%H&#39; -n 1)&#39; -X &#39;main.BuildDate=$(date -u)&#39; -X &#39;main.BuildClean=no&#39;&amp;quot; -o app .
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After building the application, we can run it and see the following details&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ ./app -version
Name: application-name
Version: 0.0.1
Git Commit Hash: 5f80f2f91251474da7e92ccddbcabecad0fea35d
Build Date: Thu Oct 13 22:16:08 UTC 2016
Built from clean source tree: no
OS: linux
Architecture: amd64
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Usually all our errors are logged to an elasticsearch cluster, and we can easily track and check if there are any errors and from which services the errors occurred.&lt;/p&gt;

&lt;p&gt;And here is the Makefile that I use to automate this&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-Makefile&#34;&gt;.DEFAULT_GOAL := build

BIN_DIR=bin
BIN_FILE=application-name
VERSION_FILE=VERSION
GO_BIN=$(shell which go)

HAS_GO_BIN := $(shell command -v go 2&amp;gt; /dev/null)

GIT_STATUS=$(shell git status --porcelain)
BUILD_VERSION:=$(shell git log --pretty=format:&#39;%h&#39; -n 1)
BUILD_DATE:=$(shell date -u)

ifneq ($(wildcard $(VERSION_FILE)),)
	VERSION:=$(shell cat $(VERSION_FILE))
else
	VERSION:=
endif

ifeq ($(GIT_STATUS),)
  BUILD_CLEAN=yes
else
  BUILD_CLEAN=no
endif

.PHONY: check-env
check-env:
ifndef GOPATH
	$(error GOPATH is undefined, you need to configure your system ...)
endif
ifndef GOROOT
	$(error GOROOT is undefined, you need to configure your system ...)
endif
ifndef HAS_GO_BIN
	$(error go command couldn&#39;t be found in PATH)
endif

bin:
	mkdir ${BIN_DIR}

.PHONY: build
build: ${BIN_DIR} check-env
	${GO_BIN} build -ldflags &amp;quot;-X &#39;main.BuildVersion=${VERSION}&#39; -X &#39;main.BuildHash=${BUILD_VERSION}&#39; -X &#39;main.BuildDate=${BUILD_DATE}&#39; -X &#39;main.BuildClean=${BUILD_CLEAN}&#39;&amp;quot; -o &amp;quot;${BIN_DIR}/${BIN_FILE}&amp;quot; .

.PHONY: clean
clean:
	rm -fv ${BIN_DIR}/${BIN_FILE}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let me know in the comments if you use some other ways of versioning your go application.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Dropping all databases in a MongoDB</title>
            <link>https://matoski.com/article/mongodb-delete-all-databases/</link>
            <pubDate>Wed, 28 Sep 2016 12:32:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/mongodb-delete-all-databases/</guid>
            <description>&lt;p&gt;I needed to drop all the databases or based on a filter in MongoDB.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The easiest way for would be to run the following javascript command.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;var dbs = db.getMongo().getDBNames();
dbs.forEach(function(dbName) {
    dbd = db.getMongo().getDB( dbName );
        print(&amp;quot;Dropping &amp;quot; + dbName + &amp;quot; database&amp;quot;);
        db.dropDatabase();
})
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you want to actually filter on this you can always add a condition to the drop, like drop all the databases that begin with &lt;strong&gt;stats_&lt;/strong&gt; you can do like this&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;var dbs = db.getMongo().getDBNames();
dbs.forEach(function(dbName) {
    dbd = db.getMongo().getDB( dbName );
    if (dbName.startsWith(&amp;quot;stats_&amp;quot;)) {
        print(&amp;quot;Dropping &amp;quot; + dbName + &amp;quot; database&amp;quot;);
        db.dropDatabase();
    }
})
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Dropping all collections in a MongoDB database</title>
            <link>https://matoski.com/article/mongodb-delete-all-collections/</link>
            <pubDate>Sat, 13 Aug 2016 14:23:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/mongodb-delete-all-collections/</guid>
            <description>&lt;p&gt;I needed to drop all the collections in a database without dropping the database.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The easiest way for would be to run the following javascript command.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;var dbName = &#39;exampleDb&#39;;
db.getSiblingDB(dbName).getCollectionNames().forEach(function(collName) {
    if (!collName.startsWith(&amp;quot;system.&amp;quot;)) {
        print(&amp;quot;Dropping [&amp;quot;+dbName+&amp;quot;.&amp;quot;+collName+&amp;quot;]&amp;quot;);
        db[collName].drop();
    }
})
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Interview Question - Fibonachos User Story</title>
            <link>https://matoski.com/article/interview-problem-fibonacci/</link>
            <pubDate>Fri, 19 Feb 2016 12:00:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/interview-problem-fibonacci/</guid>
            <description>&lt;p&gt;As an avid foodie, I want to eat Fibonachos. I want to see a program that will print the Fibonacci sequence described below so that I can assess how many I can fit on a plate, and assess basic to moderate programming skills in a language of the candidate&amp;rsquo;s choice.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Fibonacci numbers or Fibonacci sequence are the numbers in the following integer sequence
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987&lt;/p&gt;

&lt;p&gt;The program should print the first 30 Fibonacci numbers where the definition of a Fibonacci number is&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;f(0) = 0&lt;/li&gt;
&lt;li&gt;f(1) = 1&lt;/li&gt;
&lt;li&gt;f(n) = f(n-1) + f(n-2)&lt;/li&gt;
&lt;li&gt;n &amp;gt; 0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Calculating Fibonacci is quite easy as the formula is quite simple, there are several ways to implement the calculations, Recursive algorithm (extremely slow), Dynamic programming (slow), Matrix exponentiation, Fast doubling.&lt;/p&gt;

&lt;p&gt;One thing to note is that because JavaScript uses floating points for integers, after &lt;strong&gt;n=78&lt;/strong&gt;, the results are not correct.&lt;/p&gt;

&lt;p&gt;For example &lt;strong&gt;Fibonacci(80) = 23416728348467685&lt;/strong&gt; but we get &lt;strong&gt;23416728348467684&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recursive algorithm (extremely slow)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can directly execute the recurrence as given in the mathematical definition of the Fibonacci sequence. But it&amp;rsquo;s extremely slow: It uses O(n) stack space and O(?n)) arithmetic operations, where ?=5?+12?=5+12 (the golden ratio). In other words, the number of operations to compute F(n) is proportional to the resulting value itself, which grows exponentially.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function fibonacci(n) {
    if (n &amp;lt; 0 || isNaN(parseInt(n))) {
        throw new Error(&amp;quot;Invalid number or less than zero&amp;quot;);
    }
    if (n === 0 || n === 1) {
        return n;
    }
    return fibonacci(n - 1) + fibonacci(n - 2);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;Iterative (slow)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It should be clear that if we&amp;rsquo;ve already computed F(n-2) and F(n-1), then we can add them to get F(n). We repeat until we reach i=n.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function fibonacci(n) {
    if (n &amp;lt; 0 || isNaN(parseInt(n))) {
        throw new Error(&amp;quot;Invalid number or less than zero&amp;quot;);
    }
    if (n === 0 || n === 1) {
        return n;
    }
    var seq = [0, 1];
    for (i = 2; i &amp;lt;= n; i++) {
        seq[i] = seq[i - 1] + seq[i - 2];
    }
    return seq[n];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;With memoization (Dynamic Programming)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is quite simple as you can see, but using it on bigger numbers will be slower on repetitive calculations, one thing we can do is do memoization of the number, so the next calculations are faster.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function Fibonacci() {
    return {
        dictionary: [0, 1],
        recursive: function(n) {
            if ( n &amp;lt; 0 || isNaN(parseInt(n)) ) {
                throw new Error(&amp;quot;Invalid number or less than zero&amp;quot;);
            }
            if (n === 0 || n === 1) {
                return n;
            }
            if (this.dictionary[n]) {
                return this.dictionary[n];
            }
            this.dictionary[n] = this.recursive(n - 1) + this.recursive(n - 2);
            return this.dictionary[n];
        },
        iterative: function(n) {
            if ( n &amp;lt; 0 || isNaN(parseInt(n)) ) {
                throw new Error(&amp;quot;Invalid number or less than zero&amp;quot;);
            }
            if (n === 0 || n === 1) {
                return n;
            }
            if (this.dictionary[n]) {
                return this.dictionary[n];
            }
            for (i = 2; i &amp;lt;= n; i++) {
                this.dictionary[i] = this.dictionary[i - 1] + this.dictionary[i - 2];
            }
            return this.dictionary[n];
        }
    };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;Fast doubling method&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fast doubling method is even better, running in O(log(n)) time.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s defined like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;F(2n)   = F(n) * (2*F(n+1) - F(n))
F(2n+1) = F(n+1)^2 + F(n)^2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And here is a sample implementation of the code&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;function fibonacci(n) {

    if ( n &amp;lt; 0 || isNaN(parseInt(n)) ) {
        throw new Error(&amp;quot;Invalid number or less than zero&amp;quot;);
    }

    if ( n == 0 ){
        return 0;
    }
    
    return fibonacci_tuple(n-1)[1];
}

function fibonacci_tuple(n) {

    if ( n &amp;lt; 0 || isNaN(parseInt(n)) ) {
        throw new Error(&amp;quot;Invalid number or less than zero&amp;quot;);
    }

    if (n == 0)
        return [0, 1];
    
    var result = fibonacci_tuple(Math.floor(n/2));
    var a = result[0], b = result[1];
    
    c = a * ( b * 2 - a );
    d = a * a + b * b;
    if ( n % 2 == 0 ) {
        return [c, d];
    } else {
        return [d, c + d];
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;Matrix exponentiation&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code&gt;[1 1]^n   [F(n+1) F(n)  ]
[1 0]   = [F(n)   F(n-1)]
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Verifying SSH Key Fingerprints with DNS records</title>
            <link>https://matoski.com/article/sshfp-dns-records/</link>
            <pubDate>Sat, 30 Jan 2016 11:48:46 +0100</pubDate>
            
            <guid>https://matoski.com/article/sshfp-dns-records/</guid>
            <description>&lt;p&gt;SSH Fingerprinting is a method to provide DNS records for key fingerprint verification of any client that logs into said machine.&lt;/p&gt;

&lt;p&gt;Doing this will prevent users from blindly typing &amp;lsquo;yes&amp;rsquo; when asked if they want to continue connecting to an SSH host who&amp;rsquo;s authenticity is unknown.&lt;/p&gt;

&lt;p&gt;Most of the people just type &amp;lsquo;yes&amp;rsquo; without even checking if it&amp;rsquo;s correct or not, which defeats the purpose of the prompt.&lt;/p&gt;

&lt;p&gt;The fingerprint records together with &lt;strong&gt;DNSSEC&lt;/strong&gt; will completely bypass the prompt and have SSH verify the fingerprint automatically.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;If the authenticity of the host is unknown, you haven&amp;rsquo;t been logged in before or you have changed the fingerprint of the machine, you will be greeted by a very familiar prompt, and most users here will just type yes without even checking if really we are connecting to the correct machine.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ ssh root@myserverplace.de
The authenticity of host &#39;myserverplace.de (148.251.100.157)&#39; can&#39;t be established.
ECDSA key fingerprint is SHA256:y2STsQ4RA/8durhpic+pb6UjcKwz7+bUaKX3C40yOGk.
Are you sure you want to continue connecting (yes/no)?
Warning: Permanently added &#39;myserverplace.de&#39; (ECDSA) to the list of known hosts.
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;generating-ssh-key-fingerpint-records&#34;&gt;Generating SSH Key Fingerpint records&lt;/h2&gt;

&lt;p&gt;If you want to generate the DNS records you need to login to the said server and run &lt;strong&gt;ssh-keygen&lt;/strong&gt; to generate the records, and then add the relevant records to your DNS server.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ ssh-keygen -r myserverplace.de
myserverplace.de IN SSHFP 1 1 db744817e8d6ac2027e6629aac7f0fc1750f6588
myserverplace.de IN SSHFP 1 2 a61db02b9b26ca48663c3272821b451773c7cd1e9a412f5a09994ec8f8738c79
myserverplace.de IN SSHFP 2 1 493a9e6a4b5078b1d0c5424aecf817ea54e1dfdf
myserverplace.de IN SSHFP 2 2 064b9dd10805069eb508bd087a37db61fda2107138924112ded3ccdbaafd6cb3
myserverplace.de IN SSHFP 3 1 7c4b9b9105d6a0d7aacf44534a7800fc10466683
myserverplace.de IN SSHFP 3 2 cb6493b10e1103ff1dbab86989cfa96fa52370ac33efe6d468a5f70b8d323869
myserverplace.de IN SSHFP 4 1 69ac080ccf6cd52f4788373bd4dca21731e69713
myserverplace.de IN SSHFP 4 2 7cae4ff942899f8e155bfc675e72e4146a1bf4107977fe73c6cffa8f3fda8fc3
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Each line contains the following information&lt;/p&gt;

&lt;table class=&#39;pure-table pure-table-horizontal pure-table-striped&#39;&gt;
&lt;thead&gt;
    &lt;tr&gt;
        &lt;th&gt;#&lt;/th&gt;&lt;th&gt;Hostname&lt;/th&gt;&lt;th&gt;Algorithm&lt;/th&gt;&lt;th&gt;Fingerprint Type&lt;/th&gt;&lt;th&gt;Hash&lt;/th&gt;
    &lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;myserverplace.de&lt;/td&gt;&lt;td&gt;RSA&lt;/td&gt;&lt;td&gt;SHA-1&lt;/td&gt;&lt;td&gt;db744817e8d6ac2027e6629aac7f0fc1750f6588&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;myserverplace.de&lt;/td&gt;&lt;td&gt;RSA&lt;/td&gt;&lt;td&gt;SHA-2&lt;/td&gt;&lt;td&gt;a61db02b9b26ca48663c3272821b451773c7cd1e9a412f5a09994ec8f8738c79&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;myserverplace.de&lt;/td&gt;&lt;td&gt;DSA&lt;/td&gt;&lt;td&gt;SHA-1&lt;/td&gt;&lt;td&gt;493a9e6a4b5078b1d0c5424aecf817ea54e1dfdf&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;myserverplace.de&lt;/td&gt;&lt;td&gt;DSA&lt;/td&gt;&lt;td&gt;SHA-2&lt;/td&gt;&lt;td&gt;064b9dd10805069eb508bd087a37db61fda2107138924112ded3ccdbaafd6cb3&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;myserverplace.de&lt;/td&gt;&lt;td&gt;ECDSA&lt;/td&gt;&lt;td&gt;SHA-1&lt;/td&gt;&lt;td&gt;7c4b9b9105d6a0d7aacf44534a7800fc10466683&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;myserverplace.de&lt;/td&gt;&lt;td&gt;ECDSA&lt;/td&gt;&lt;td&gt;SHA-2&lt;/td&gt;&lt;td&gt;cb6493b10e1103ff1dbab86989cfa96fa52370ac33efe6d468a5f70b8d323869&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;myserverplace.de&lt;/td&gt;&lt;td&gt;ED25519&lt;/td&gt;&lt;td&gt;SHA-1&lt;/td&gt;&lt;td&gt;69ac080ccf6cd52f4788373bd4dca21731e69713&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;myserverplace.de&lt;/td&gt;&lt;td&gt;ED25519&lt;/td&gt;&lt;td&gt;SHA-2&lt;/td&gt;&lt;td&gt;7cae4ff942899f8e155bfc675e72e4146a1bf4107977fe73c6cffa8f3fda8fc3&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&#34;algorithm&#34;&gt;Algorithm&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;RSA&lt;/li&gt;
&lt;li&gt;DSA&lt;/li&gt;
&lt;li&gt;ECDSA&lt;/li&gt;
&lt;li&gt;ED25519&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should never use &lt;strong&gt;DSA&lt;/strong&gt; or &lt;strong&gt;ECDSA&lt;/strong&gt;, &lt;strong&gt;Ed25519&lt;/strong&gt; is probably the strongest mathematically (and also the fastest), but not yet widely supported. As a bonus, it has stronger encryption (password-protection) of the private key by default than other key types. &lt;strong&gt;RSA&lt;/strong&gt; is the best bet if you can&amp;rsquo;t use &lt;strong&gt;Ed25519&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&#34;fingerprint-type&#34;&gt;Fingerprint type&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;SHA-1&lt;/li&gt;
&lt;li&gt;SHA-2&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You shouldn&amp;rsquo;t use &lt;strong&gt;SHA-1&lt;/strong&gt; fingerprints as they are less secure.&lt;/p&gt;

&lt;h2 id=&#34;dns-records&#34;&gt;DNS Records&lt;/h2&gt;

&lt;p&gt;After adding the DNS records you can check if they are present or not very simple&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ dig SSHFP +noadditional +noquestion +nocomments +nocmd +nostats myserverplace.de
myserverplace.de.	10539	IN	SSHFP	4 2 7CAE4FF942899F8E155BFC675E72E4146A1BF4107977FE73C6CFFA8F 3FDA8FC3
myserverplace.de.	10539	IN	SSHFP	3 1 7C4B9B9105D6A0D7AACF44534A7800FC10466683
myserverplace.de.	10539	IN	SSHFP	3 2 CB6493B10E1103FF1DBAB86989CFA96FA52370AC33EFE6D468A5F70B 8D323869
myserverplace.de.	10539	IN	SSHFP	4 1 69AC080CCF6CD52F4788373BD4DCA21731E69713
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;ssh-client&#34;&gt;SSH Client&lt;/h2&gt;

&lt;p&gt;You need to add &lt;strong&gt;VerifyHostKeyDNS&lt;/strong&gt; to your &lt;strong&gt;~/.ssh/config&lt;/strong&gt; or your global &lt;strong&gt;/etc/ssh/ssh_config&lt;/strong&gt;, if you set this property then SSH will try to validate host keys from DNS.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Host *
    VerifyHostKeyDNS yes
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;connecting-to-ssh-with-sshfp&#34;&gt;Connecting to SSH with SSHFP&lt;/h2&gt;

&lt;p&gt;Now if I connect to the server I get the following prompt, without &lt;strong&gt;DNSSEC&lt;/strong&gt; you will still get a prompt, and &lt;strong&gt;Matching host key fingerprint found in DNS&lt;/strong&gt; line in the output now.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ ssh root@myserverplace.de
The authenticity of host &#39;myserverplace.de (148.251.100.157)&#39; can&#39;t be established.
ECDSA key fingerprint is SHA256:y2STsQ4RA/8durhpic+pb6UjcKwz7+bUaKX3C40yOGk.
Matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With &lt;strong&gt;DNSSEC&lt;/strong&gt; in place it will not add a new entry in &lt;strong&gt;~/.ssh/known_hosts&lt;/strong&gt;, and will connect right away.&lt;/p&gt;

&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://tools.ietf.org/html/rfc4255&#34; rel=&#34;nofollow&#34;&gt;Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://tools.ietf.org/html/rfc6594&#34; rel=&#34;nofollow&#34;&gt;ECDSA and SHA-256 Algorithms for SSHFP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://tools.ietf.org/html/rfc7479&#34; rel=&#34;nofollow&#34;&gt;Using ED25519 in SSHFP Resource Records&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
        </item>
        
        <item>
            <title>Automatically switch between WiFi and Ethernet</title>
            <link>https://matoski.com/article/wifi-ethernet-autoswitch/</link>
            <pubDate>Sun, 20 Dec 2015 22:25:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/wifi-ethernet-autoswitch/</guid>
            <description>&lt;p&gt;I wanted a way to automatically switch between wifi and ethernet when I connect the system to the ethernet port, or auto start wifi when I disconnect the ethernet port.&lt;/p&gt;

&lt;p&gt;Simplest way to do so was to use NetworkManager to enable/disable wifi, when we detect an ethernet connection.&lt;/p&gt;

&lt;p&gt;I also wanted a way to track what is happening so we log to syslog our actions, and a way to disable the functionality without removing the file from they system.&lt;/p&gt;

&lt;p&gt;
Open up your favorite editor and create the file bellow with the contents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/etc/NetworkManager/dispatcher.d/70-wifi-wired-exclusive.sh&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/usr/bin/env bash

name_tag=&amp;quot;wifi-wired-exclusive&amp;quot;
syslog_tag=&amp;quot;$name_tag&amp;quot;
skip_filename=&amp;quot;/etc/NetworkManager/.$name_tag&amp;quot;

if [ -f &amp;quot;$skip_filename&amp;quot; ]; then
  exit 0
fi

interface=&amp;quot;$1&amp;quot;
iface_mode=&amp;quot;$2&amp;quot;
iface_type=$(nmcli dev | grep &amp;quot;$interface&amp;quot; | tr -s &#39; &#39; | cut -d&#39; &#39; -f2)
iface_state=$(nmcli dev | grep &amp;quot;$interface&amp;quot; | tr -s &#39; &#39; | cut -d&#39; &#39; -f3)

logger -i -t &amp;quot;$syslog_tag&amp;quot; &amp;quot;Interface: $interface = $iface_state ($iface_type) is $iface_mode&amp;quot;

enable_wifi() {
   logger -i -t &amp;quot;$syslog_tag&amp;quot; &amp;quot;Interface $interface ($iface_type) is down, enabling wifi ...&amp;quot;
   nmcli radio wifi on
}

disable_wifi() {
   logger -i -t &amp;quot;$syslog_tag&amp;quot; &amp;quot;Disabling wifi, ethernet connection detected.&amp;quot;
   nmcli radio wifi off
}

if [ &amp;quot;$iface_type&amp;quot; = &amp;quot;ethernet&amp;quot; ] &amp;amp;&amp;amp; [ &amp;quot;$iface_mode&amp;quot; = &amp;quot;down&amp;quot; ]; then
  enable_wifi
elif [ &amp;quot;$iface_type&amp;quot; = &amp;quot;ethernet&amp;quot; ] &amp;amp;&amp;amp; [ &amp;quot;$iface_mode&amp;quot; = &amp;quot;up&amp;quot;  ] &amp;amp;&amp;amp; [ &amp;quot;$iface_state&amp;quot; = &amp;quot;connected&amp;quot; ]; then
  disable_wifi
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we want to disable this script, instead of deleting it we can just do&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;touch /etc/NetworkManager/.wifi-wired-exclusive
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And this will skip the script everytime it&amp;rsquo;s invoked.&lt;/p&gt;

&lt;p&gt;And here are some details from the syslog, as you can see it turns off the wifi if there is an ethernet connection on the system, and turn on the wifi if the ethernet connection is disabled.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Dec 20 22:47:13 x1 wifi-wired-exclusive[7980]: Interface: enx0050b6c0408e = connected (ethernet) is up
Dec 20 22:47:13 x1 wifi-wired-exclusive[7981]: Disabling wifi, ethernet connection detected.
Dec 20 22:47:13 x1 wifi-wired-exclusive[8051]: Interface: wlp4s0 = unavailable (wifi) is down
Dec 20 22:47:21 x1 wifi-wired-exclusive[8097]: Interface: enx0050b6c0408e = unavailable (ethernet) is down
Dec 20 22:47:21 x1 wifi-wired-exclusive[8098]: Interface enx0050b6c0408e (ethernet) is down, enabling wifi ...
Dec 20 22:47:25 x1 wifi-wired-exclusive[8252]: Interface: wlp4s0 = connected (wifi) is up
Dec 20 22:47:31 x1 wifi-wired-exclusive[8407]: Interface: enx0050b6c0408e = connected (ethernet) is up
Dec 20 22:47:31 x1 wifi-wired-exclusive[8408]: Disabling wifi, ethernet connection detected.
Dec 20 22:47:31 x1 wifi-wired-exclusive[8474]: Interface: wlp4s0 = unavailable (wifi) is down
Dec 20 22:47:42 x1 wifi-wired-exclusive[8525]: Interface: enx0050b6c0408e = unavailable (ethernet) is down
Dec 20 22:47:42 x1 wifi-wired-exclusive[8526]: Interface enx0050b6c0408e (ethernet) is down, enabling wifi ...
Dec 20 22:47:46 x1 wifi-wired-exclusive[8679]: Interface: wlp4s0 = connected (wifi) is up
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Debian daily backup domains with tartarus.</title>
            <link>https://matoski.com/article/debian-backup-tartarus-plesk-vhost/</link>
            <pubDate>Sun, 14 Jun 2015 10:13:58 +0000</pubDate>
            
            <guid>https://matoski.com/article/debian-backup-tartarus-plesk-vhost/</guid>
            <description>&lt;p&gt;In a previous article we saw how to set up a backup process for tartarus, in this article we will see how we can generate backups of the data in each vhost with tartarus, the reason I do this is so we can set up a daily incremental backup of the files for each domain.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Make sure you read the article &lt;a href=&#34;https://matoski.com/articles/debian-backup-tartarus&#34;&gt;Debian Backup with Tartarus&lt;/a&gt;, this will prepare you for the basics of this article.&lt;/p&gt;

&lt;p&gt;Now lets create some files that we can use for this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/etc/tartarus/generic.inc&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;STORAGE_METHOD=&amp;quot;FILE&amp;quot;
STORAGE_SERVER=&amp;quot;example.com&amp;quot;
STORAGE_USER=&amp;quot;user&amp;quot;
STORAGE_DIR=&amp;quot;backup&amp;quot;
STORAGE_FILE_DIR=&amp;quot;/mnt/$STORAGE_SERVER/$STORAGE_DIR/&amp;quot;
WEEK_NUMBER=`date +%V`

LIMIT_DISK_IO=&amp;quot;yes&amp;quot;

FILE_LIST_CREATION=&amp;quot;yes&amp;quot;
FILE_LIST_DIRECTORY=&amp;quot;/mnt/$STORAGE_SERVER/$STORAGE_DIR/&amp;quot;

COMPRESSION_METHOD=&amp;quot;bzip2&amp;quot;

STAY_IN_FILESYSTEM=&amp;quot;yes&amp;quot;

TAR_OPTIONS=&amp;quot;--preserve-permissions&amp;quot;

ENCRYPT_SYMMETRICALLY=&amp;quot;no&amp;quot;
ENCRYPT_PASSPHRASE_FILE=&amp;quot;/etc/tartarus/backup.sec&amp;quot;

TARTARUS_PRE_PROCESS_HOOK() {

  if [ ! -d &amp;quot;/mnt/$STORAGE_SERVER&amp;quot; ]; then
    mkdir -p &amp;quot;/mnt/$STORAGE_SERVER&amp;quot;
  fi
  
  umount &amp;quot;/mnt/$STORAGE_SERVER&amp;quot;
  sshfs $STORAGE_USER@$STORAGE_SERVER:/ /mnt/$STORAGE_SERVER -o reconnect

  if [ ! -d &amp;quot;$STORAGE_FILE_DIR&amp;quot; ]; then
     mkdir -p &amp;quot;$STORAGE_FILE_DIR&amp;quot;
  fi

  if [ ! -d &amp;quot;$FILE_LIST_DIRECTORY&amp;quot; ]; then
     mkdir -p &amp;quot;$FILE_LIST_DIRECTORY&amp;quot;
  fi

}

TARTARUS_PRE_CLEANUP_HOOK() {
  echo &amp;quot;Cleaning ...&amp;quot; | logger -i
}

TARTARUS_POST_CLEANUP_HOOK() {
   umount &amp;quot;/mnt/$STORAGE_SERVER&amp;quot;
}

TARTARUS_DEBUG_HOOK() {
    echo $DEBUGMSG | logger -i
}

TARTARUS_PRE_FREEZE_HOOK() {
  sync
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need to supply the proper information for &lt;strong&gt;STORAGE_USER&lt;/strong&gt; and &lt;strong&gt;STORAGE_SERVER&lt;/strong&gt; in the bash script above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/etc/tartarus/vhost.template&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;source /etc/tartarus/generic.inc
NAME=&amp;quot;%NAME%&amp;quot;
DIRECTORY=&amp;quot;%DIRECTORY%&amp;quot;
EXCLUDE=&amp;quot;&amp;quot;
CREATE_LVM_SNAPSHOT=&amp;quot;no&amp;quot;
INCREMENTAL_STACKING=&amp;quot;yes&amp;quot;
INCREMENTAL_TIMESTAMP_FILE=&amp;quot;/var/spool/tartarus/timestamps/%NAME%&amp;quot;
STORAGE_FILE_DIR=&amp;quot;$STORAGE_FILE_DIR/vhosts/%NAME%/archives/${WEEK_NUMBER}&amp;quot;
FILE_LIST_DIRECTORY=&amp;quot;$FILE_LIST_DIRECTORY/vhosts/%NAME%/lists&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;/etc/tartarus/create.sh&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/bash
items=`find /var/www/vhosts/ -maxdepth 1 -group psaserv`

for itm in $items; do
  basefile=$(basename $itm)
  name=$basefile
  dir=$itm
  ./create_vhost.sh &amp;quot;$name&amp;quot; &amp;quot;$dir&amp;quot;
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;/etc/tartarus/create_vhost.sh&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/bash

if [ &amp;quot;$#&amp;quot; -ne 2 ]
then
  echo &amp;quot;Usage: ./create_vhost.sh &amp;lt;name&amp;gt; &amp;lt;directory&amp;gt;&amp;quot;
  exit 1
fi

NAME=$1
DIRECTORY=$2

sed -e &amp;quot;s:%DIRECTORY%:$DIRECTORY:g&amp;quot; -e &amp;quot;s:%NAME%:$NAME:g&amp;quot; vhost.template &amp;gt; &amp;quot;vhost_${NAME}.conf&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And there you go, now calling the script &lt;strong&gt;/etc/tartarus/create.sh&lt;/strong&gt; will create all the required files for the hosts, you will need to re-run this whenever you add new domains, so you can also run this periodically, once a week, for the first full backup.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Touchpad not working on Debian after suspend/hibernate</title>
            <link>https://matoski.com/article/debian-touchpad-not-working/</link>
            <pubDate>Fri, 12 Jun 2015 01:00:44 +0000</pubDate>
            
            <guid>https://matoski.com/article/debian-touchpad-not-working/</guid>
            <description>&lt;p&gt;Touchpad doesn&amp;rsquo;t work after suspend/hibernate on Debian, I ran into this issue a while ago when I installed Debian on my MSI GT70 DRAGON EDITION laptop, this probably will apply for other laptops too.&lt;/p&gt;

&lt;p&gt;Turns out the solution is simple, you just need to reinitialize the touchpad, can be done by simple commands.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;modprobe -r psmouse
modprobe psmouse
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now it will work, but let&amp;rsquo;s see if we can make it automated.&lt;/p&gt;

&lt;p&gt;So firstly let&amp;rsquo;s install some prerequisites before continuing.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get install pm-utils
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After installing you should create the following file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/etc/pm/sleep.d/00_trackpad&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/sh
case &amp;quot;$1&amp;quot; in
    suspend|hibernate)
         modprobe -r psmouse ;;
    resume|thaw)
        modprobe psmouse ;;
        synclient TouchpadOff=0 ;;
esac
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now suspend and hibernate will work properly when you resume the system.&lt;/p&gt;

&lt;p&gt;Some DMI information about my system&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ grep &#39;.*&#39; /sys/class/dmi/id/*_* 2&amp;gt;/dev/null
/sys/class/dmi/id/bios_date:11/08/2012
/sys/class/dmi/id/bios_vendor:American Megatrends Inc.
/sys/class/dmi/id/bios_version:E1762IMS.70T
/sys/class/dmi/id/board_asset_tag:To be filled by O.E.M.
/sys/class/dmi/id/board_name:MS-1762
/sys/class/dmi/id/board_serial:BSS-0123456789
/sys/class/dmi/id/board_vendor:Micro-Star International Co., Ltd.
/sys/class/dmi/id/board_version:REV:1.0
/sys/class/dmi/id/chassis_asset_tag:No Asset Tag
/sys/class/dmi/id/chassis_serial:None
/sys/class/dmi/id/chassis_type:10
/sys/class/dmi/id/chassis_vendor:Micro-Star International
/sys/class/dmi/id/chassis_version:N/A
/sys/class/dmi/id/product_name:GT70
/sys/class/dmi/id/product_serial:FFFFFFFF
/sys/class/dmi/id/product_uuid:00000000-0000-0000-0000-8C89A50783FA
/sys/class/dmi/id/product_version:REV:1.0
/sys/class/dmi/id/sys_vendor:Micro-Star International Co., Ltd.
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Coding Problem - Prime Path</title>
            <link>https://matoski.com/article/coding-problem-primepath/</link>
            <pubDate>Tue, 02 Jun 2015 23:24:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/coding-problem-primepath/</guid>
            <description>&lt;p&gt;The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit room numbers on their offices.

* It is a matter of security to change such things every now and then, to keep the enemy in the dark.
* But look, I have chosen my number 1033 for good reasons. I am the Prime minister, you know!
* I know, so therefore your new number 8179 is also a prime. You will just have to paste four new digits over the four old ones on your office door.
* No, it’s not that simple. Suppose that I change the first digit to an 8, then the number will read 8033 which is not a prime!
* I see, being the prime minister you cannot stand having a non-prime number on your door even for a few seconds.
* Correct! So I must invent a scheme for going from 1033 to 8179 by a path of prime numbers where only one digit is changed from one prime to the next prime.&lt;/p&gt;

&lt;p&gt;Now, the minister of finance, who had been eavesdropping, intervened.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No unnecessary expenditure, please! I happen to know that the price of a digit is one pound.&lt;/li&gt;
&lt;li&gt;Hmm, in that case I need a computer program to minimize the cost. You don’t know some very cheap software gurus, do you?&lt;/li&gt;
&lt;li&gt;In fact, I do. You see, there is this programming contest going on…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Help the prime minister to find the cheapest prime path between any two given four-digit primes! The first digit must be nonzero, of course. Here is a solution in the case above.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1033
1733     
3733     
3739     
3779
8779
8179     
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The cost of this solution is 6 pounds. Note that the digit 1 which got pasted over in step 2 can not be reused in the last step – a new 1 must be purchased.&lt;/p&gt;

&lt;h4 id=&#34;input&#34;&gt;Input&lt;/h4&gt;

&lt;p&gt;One line with a positive number: the number of test cases (at most 100). Then for each test case, one line with two numbers separated by a blank. Both numbers are four-digit primes (without leading zeros).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;3
1033 8179
1373 8017
1033 1033
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;output&#34;&gt;Output&lt;/h4&gt;

&lt;p&gt;One line for each case, either with a number stating the minimal cost or containing the word “Impossible”.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;6
7
0
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;solution&#34;&gt;Solution&lt;/h4&gt;

&lt;p&gt;Lets see how would we do the algorithm for this, first before we proceed we need a way to check if the number is prime or not, so we will need a list of prime numbers up to 10000.&lt;/p&gt;

&lt;p&gt;To do this we can use &lt;a href=&#34;http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes&#34;&gt;Sieve of Eratosthenes&lt;/a&gt;, &lt;a href=&#34;http://en.wikipedia.org/wiki/Trial_division&#34;&gt;Trial division&lt;/a&gt;, or some other method to generate a list of prime numbers.&lt;/p&gt;

&lt;p&gt;This is a graph problem, so we can use &lt;a href=&#34;http://en.wikipedia.org/wiki/Breadth-first_search&#34;&gt;Breadth-first search&lt;/a&gt; or &lt;a href=&#34;http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm&#34;&gt;Dijkstra&amp;rsquo;s algorithm&lt;/a&gt; algorithms to find the shortest path between the number that we want.&lt;/p&gt;

&lt;p&gt;Now let&amp;rsquo;s see a working implementation of this in Java&lt;/p&gt;

&lt;h5 id=&#34;java&#34;&gt;Java&lt;/h5&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;import java.io.BufferedInputStream;
import java.util.LinkedList;
import java.util.Scanner;

class PrimePath {

    static boolean[] isPrime = getPrimes(10000);

    public static boolean[] getPrimes(int n) {
        int i, j, k, x;
        boolean[] a = new boolean[n];
        n++;
        n /= 2;
        int[] b = new int[(n + 1) * 2];
        a[2] = true;
        a[3] = true;
        for (i = 1; i &amp;lt;= 2 * n; i++) {
            b[i] = 0;
        }
        for (i = 3; i &amp;lt;= n; i += 3) {
            for (j = 0; j &amp;lt; 2; j++) {
                x = 2 * (i + j) - 1;
                while (b[x] == 0) {
                    a[x] = true;
                    for (k = x; k &amp;lt;= 2 * n; k += x) {
                        b[k] = 1;
                    }
                }
            }
        }
        return a;
    }

    public static void main(String[] args) {

        Scanner scan = new Scanner(new BufferedInputStream(System.in));
        int cas = scan.nextInt();
        for (int i = 1; i &amp;lt;= cas; i++) {
            int start = scan.nextInt();
            int end = scan.nextInt();
            boolean[] isVisited = new boolean[10000];
            int[] step = new int[10000];
            LinkedList&amp;lt;Integer&amp;gt; queue = new LinkedList();
            queue.addLast(start);
            isVisited[start] = true;
            while (!queue.isEmpty()) {
                int current = queue.pop();
                if (current == end) {
                    break;
                }
                for (int j = 0; j &amp;lt;= 9; j++) {
                    int next1 = getNext(1, j, current);
                    int next2 = getNext(2, j, current);
                    int next3 = getNext(3, j, current);
                    int next4 = getNext(4, j, current);
                    if (!isVisited[next1]) {
                        queue.addLast(next1);
                        step[next1] = step[current] + 1;
                        isVisited[next1] = true;
                    }
                    if (!isVisited[next2]) {
                        queue.addLast(next2);
                        step[next2] = step[current] + 1;
                        isVisited[next2] = true;
                    }
                    if (!isVisited[next3]) {
                        queue.addLast(next3);
                        step[next3] = step[current] + 1;
                        isVisited[next3] = true;
                    }
                    if (!isVisited[next4]) {
                        queue.addLast(next4);
                        step[next4] = step[current] + 1;
                        isVisited[next4] = true;
                    }
                }
            }
            System.out.println(step[end]);
        }
    }

    public static int getNext(int flag, int i, int current) {
        int next = 0;
        if (flag == 1) {
            if (i == 0) {
                return current;
            }
            next = current % 1000 + i * 1000;
        }
        if (flag == 2) {
            int t = current / 1000;
            next = t * 1000 + current % 1000 % 100 + i * 100;
        }
        if (flag == 3) {
            int t = current / 100;
            int tt = current % 10;
            next = t * 100 + i * 10 + tt;
        }
        if (flag == 4) {
            next = current / 10 * 10 + i;

        }
        if (!isPrime[next]) {
            return current;
        }
        return next;
    }

}
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Coding Problem - Phone List</title>
            <link>https://matoski.com/article/coding-problem-phonelist/</link>
            <pubDate>Tue, 02 Jun 2015 16:03:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/coding-problem-phonelist/</guid>
            <description>&lt;p&gt;Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let’s say the phone catalogue listed these numbers:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Emergency 911
Alice 97 625 999
Bob 91 12 54 26
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case, it’s not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob’s phone number. So this list would not be consistent.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h4 id=&#34;input&#34;&gt;Input&lt;/h4&gt;

&lt;p&gt;The first line of input gives a single integer, &lt;strong&gt;1≤t≤40&lt;/strong&gt;, the number of test cases. Each test case starts with n, the number of phone numbers, on a separate line, &lt;strong&gt;1≤n≤10000&lt;/strong&gt;. Then follows n lines with one unique phone number on each line. A phone number is a sequence of at most ten digits.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;output&#34;&gt;Output&lt;/h4&gt;

&lt;p&gt;For each test case, output “YES” if the list is consistent, or “NO” otherwise.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;NO
YES
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;solution&#34;&gt;Solution&lt;/h4&gt;

&lt;p&gt;Lets see how we would go about solving this.&lt;/p&gt;

&lt;p&gt;Since the maximum length of a number is 10 digits, we would iterate over the list backwards, and check for doubles.&lt;/p&gt;

&lt;p&gt;To be able to detect if the list is consistent or not, the algorithm would be something along these lines.&lt;/p&gt;

&lt;h5 id=&#34;algorithm-1&#34;&gt;Algorithm 1&lt;/h5&gt;

&lt;ol&gt;
&lt;li&gt;Group the numbers by length in an array (Hash tree)&lt;/li&gt;
&lt;li&gt;Check for doubles, if there is a double then it&amp;rsquo;s not consistent, don&amp;rsquo;t proceed with the test, even though it says it&amp;rsquo;s unique, you never know what could happen, so it doesn&amp;rsquo;t hurt to try, and it doesn&amp;rsquo;t hurt the performance too much&lt;/li&gt;
&lt;li&gt;Iterate over the the array backwards from the biggest available number length

&lt;ol&gt;
&lt;li&gt;Check for doubles, and if there are it&amp;rsquo;s not consistent, so break&lt;/li&gt;
&lt;li&gt;If MAX_NUMBER_LENGTH = CURRENT_NUMBER_LENGTH or CURRENT_NUMBER_LENGTH == MAX_NUMBER_LENGTH_IN_LIST, then we continue as it&amp;rsquo;s consistent and there are no duplicates&lt;/li&gt;
&lt;li&gt;Build the array from the previous data set and merge into current so we can keep the results&lt;/li&gt;
&lt;li&gt;Create an array the we gonna use to compare&lt;/li&gt;
&lt;li&gt;Check if the keys are present in the array&lt;/li&gt;
&lt;li&gt;Break if we detected a match&lt;/li&gt;
&lt;li&gt;Add the values to current index, so we can compare with previous one on the next run&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is implemented in PHP&lt;/p&gt;

&lt;h5 id=&#34;algorithm-2&#34;&gt;Algorithm 2&lt;/h5&gt;

&lt;p&gt;Another way to do this is to use a Tree, and each of the Nodes needs to have 10 leafs (one for each digit of a number), and you build the Tree by appending another Tree onto the leaf.
If it&amp;rsquo;s a new leaf (the node is consistent if the digit position of the processing number equals the length of the number).
If it&amp;rsquo;s not a new leaf, but the node is consistent, then the list of number is not consistent, also the same applies if the digit position of the processing number equals the length of the number.&lt;/p&gt;

&lt;p&gt;This is implemented in Java&lt;/p&gt;

&lt;h4 id=&#34;implementations&#34;&gt;Implementations&lt;/h4&gt;

&lt;p&gt;There are a lot of ways to do this, some faster some slower, a slower one would be to use a sort algorithm, but this is not good for really big values.&lt;/p&gt;

&lt;p&gt;The input sample provided by the problem is OK, but we need better one, so here is firstly a script that will generate random test cases, for us to test.
Simplest is here in &lt;strong&gt;PHP&lt;/strong&gt;, but we can use it for testing in the other languages too.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-php&#34;&gt;&amp;lt;?php
$test = rand(1, 40);
$testname = utime();
file_put_contents(&amp;quot;rt-$testname&amp;quot;, &amp;quot;$test\n&amp;quot;);

$line = 1;

for ($i = 0; $i &amp;lt; $test; $i++) {
    $numbers = rand(1, 10000);
    file_put_contents(&amp;quot;rt-$testname&amp;quot;, &amp;quot;$numbers\n&amp;quot;, FILE_APPEND);
    $line++;
    for ($n = 0; $n &amp;lt; $numbers; $n++) {
        $number = rand(100, 9999999999);
        file_put_contents(&amp;quot;rt-$testname&amp;quot;, &amp;quot;$number\n&amp;quot;, FILE_APPEND);
        $line++;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h5 id=&#34;php&#34;&gt;PHP&lt;/h5&gt;

&lt;pre&gt;&lt;code class=&#34;language-php&#34;&gt;&amp;lt;?php

$output = array();

$stdin = fopen(&#39;php://stdin&#39;, &#39;r&#39;);
$totalTests = trim(fgets($stdin));
$maxLengthNumber = 10;

for ($i = 0; $i &amp;lt; $totalTests; $i++) {

    $totalNumbers = trim(fgets($stdin));

    $list = array();
    $numbers = array();

    // 1. Group the numbers by length in an array
    for ($a = 0; $a &amp;lt; $totalNumbers; $a++) {
        $phone = trim(fgets($stdin));
        $numbers[] = $phone;
        $digits = strlen($phone);
        $list[$digits][] = $phone;
    }

    if ($totalNumbers != count(array_flip($numbers))) {
        // 2. Check for doubles, if there is a double then it&#39;s not consistent
        $isConsistent = false;
    } else {
        $isConsistent = true;
        // 3. Iterate over the the array
        $keys = array_keys($list);
        sort($keys);
        $keys = array_reverse($keys, SORT_NUMERIC);
        $max_key = max($keys);
        foreach ($keys as $index =&amp;gt; $key) {

            $totalItems = count($list[$key]);

            // 3.1. Check for doubles, and if there are it&#39;s not consistent, so break
            if ($totalItems != count(array_flip($list[$key]))) {
                $isConsistent = false;
                break;
            }

            // 3.2. If MAX_NUMBER_LENGTH = CURRENT_NUMBER_LENGTH || $key == $max_key, then we continue as it&#39;s consistent and there are no duplicates
            if ($maxLengthNumber == $key || $key == $max_key) {
                $isConsistent = true;
                continue;
            }

            // 3.3. Build the array from the previous data set and merge into current so we can keep the results
            $prevCut = array();
            $prev = array();
            $currentListIndex = $keys[$index];
            $prevListIndex = $keys[$index + 1];

            // 3.4. Create an array the we gonna use to compare
            foreach ($list[$prevListIndex] as $idx =&amp;gt; &amp;amp;$val) {
                $prevCut[$idx] = substr($val, 0, $key);
                $prev[$idx] = $val; // point it as a reference for faster memory access
            }

            // 3.5. Check if the keys are present in the array
            $prevCutKeys = array_flip($prevCut);
            foreach ($list[$currentListIndex] as $idx =&amp;gt; $val) {

                if (isset($prevCutKeys[$val])) {
                    $isConsistent = false;
                    break;
                } else {
                    $isConsistent = true;
                }

            }

            // 3.6. Break if we detected a match
            if (!$isConsistent) {
                break;
            }

            // 3.7. Add the values to current index, so we can compare with previous one on the next run
            foreach ($prev as $val) {
                $list[$currentListIndex][] = $val;
            }

        }
    }
    array_push($output, $isConsistent ? &amp;quot;YES&amp;quot; : &amp;quot;NO&amp;quot;);

}

$out = fopen(&#39;php://output&#39;, &#39;w&#39;); //output handler
fputs($out, join(&amp;quot;\n&amp;quot;, $output) . &amp;quot;\n&amp;quot;); //writing output operation
fclose($out);
&lt;/code&gt;&lt;/pre&gt;

&lt;h5 id=&#34;java&#34;&gt;Java&lt;/h5&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class PhoneList {

    public static final String YES = &amp;quot;YES&amp;quot;;
    public static final String NO = &amp;quot;NO&amp;quot;;
    private static Tree tree = new Tree();
    private static boolean isConsistent = true;

    private static class Tree {
        int node = 0;
        boolean isCons = false;
        Tree[] next = new Tree[10];

        public void setNext(int index, Tree t) {
            next[index] = t;
        }

        public Tree getTree(int index) {
            return next[index];
        }
    }

    // Should be on a separate class
    public static void main(String[] args) {
        PhoneList phoneList = new PhoneList();
        try {
            phoneList.build();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void build() throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        int t = Integer.parseInt(reader.readLine());
        for (int i = 0; i &amp;lt; t; ++i) {
            int n = Integer.parseInt(reader.readLine());
            tree = new Tree();
            isConsistent = true;
            for (int j = 0; j &amp;lt; n; ++j) {
                String phone = reader.readLine();
                if (isConsistent)
                    buildTree(phone);
            }
            if (isConsistent)
                System.out.println(YES);
            else
                System.out.println(NO);
        }
    }

    private void buildTree(String s) {
        int len = s.length();
        Tree auxTree = tree;
        for (int i = 0; i &amp;lt; len; ++i) {
            int ch = Integer.parseInt(s.substring(i, i + 1));
            Tree aux = auxTree.next[ch];
            if (aux == null) {
                aux = new Tree();
                aux.node = 1;
                if (i == len - 1)
                    aux.isCons = true;
                auxTree.setNext(ch, aux);
                auxTree = aux;
            } else {
                if (aux.isCons) {
                    isConsistent = false;
                    break;
                }
                if (i == len - 1) {
                    isConsistent = false;
                    break;
                }
                auxTree = aux;
            }
        }
    }

}
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Amazon Glacier Interface</title>
            <link>https://matoski.com/article/glacier-interface/</link>
            <pubDate>Wed, 14 Jan 2015 14:55:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/glacier-interface/</guid>
            <description>&lt;p&gt;Amazon Glacier is an archive/backup service with very low storage price. However with some caveats in usage and archive retrieval prices. Read more about Amazon Glacier&lt;/p&gt;

&lt;p&gt;I used a couple of utilities on linux and windows in the past for uploading data to Amazon Glacier servers, though I haven&amp;rsquo;t tested this on Windows, I don&amp;rsquo;t see any reason for this not to work on Windows.&lt;/p&gt;

&lt;p&gt;I needed a tool that will make this easier to do so from the command line, that should work on Linux/Windows, and support some of the metadata from other tools. Also the tools I was using were good but none of them meet all my needs so I decided to write my own.&lt;/p&gt;

&lt;p&gt;So I want to introduce a glacier interface for Linux a command line tool to interface with glacier.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s a multithreaded application, that supports multipart uploads to Amazon Glacier servers, you can specify concurrency, to speed up the upload.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Anyone is welcome to help in development of this tool, see a bug, or a want a new feature, send me a pull request, or create an issue and I will see what I can do.&lt;/p&gt;

&lt;p&gt;Any contributors will be added to the list of contributors.&lt;/p&gt;

&lt;p&gt;This tool is still in &lt;strong&gt;Beta&lt;/strong&gt;, though I&amp;rsquo;ve used it for a lot of stuff and have uploaded close to 1 TB of data so far and haven&amp;rsquo;t run into an issue so far with the uploads.&lt;/p&gt;

&lt;p&gt;Take a look at the &lt;a href=&#34;https://github.com/ilijamt/glacier-interface/blob/master/README.md&#34;&gt;README.md&lt;/a&gt; at the projects GitHub page.&lt;/p&gt;

&lt;p&gt;There are a lot of examples, and how to use.&lt;/p&gt;

&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Debian based systems&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;quot;deb http://packages.matoski.com debian-gi main&amp;quot; | sudo tee /etc/apt/sources.list.d/debian-gi.list
sudo wget -O /etc/apt/trusted.gpg.d/pm.gpg http://packages.matoski.com/keyring.gpg
sudo apt-get update
sudo apt-get -y install glacier-interface
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;Source&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can checkout the code from the repository, and build it with gradle.&lt;/p&gt;

&lt;h2 id=&#34;source-code&#34;&gt;Source Code&lt;/h2&gt;

&lt;p&gt;&lt;a href=&#34;https://github.com/ilijamt/glacier-interface&#34;&gt;Github Glacier Interface&lt;/a&gt;&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Git delete a remote/local branch or tag</title>
            <link>https://matoski.com/article/git-delete-remote-branch-tag/</link>
            <pubDate>Thu, 08 Jan 2015 14:18:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/git-delete-remote-branch-tag/</guid>
            <description>&lt;p&gt;A lot of people keep asking me on Skype or chat how to delete a remote branch/tag in git, so I decided to put it in a nice little article, so I can refer it to them.&lt;/p&gt;

&lt;p&gt;If you want to delete a local tag then you would do&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;git tag -d &amp;lt;tag name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But if you want to delete remote tag,  then the syntax is a little different&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;git push origin :refs/tags/&amp;lt;tag name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will delete the tag on the remote &lt;strong&gt;origin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now let&amp;rsquo;s see how to delete a local branch,&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;git branch -d &amp;lt;branch name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now for a remote branch,&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;git push origin :&amp;lt;branch name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or since version 1.7.0 now you can delete the branch like so.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;git push origin --delete &amp;lt;branch name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
</description>
        </item>
        
        <item>
            <title>fail2ban for Wordpress and Plesk</title>
            <link>https://matoski.com/article/fail2ban-wordpress/</link>
            <pubDate>Mon, 22 Dec 2014 22:54:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/fail2ban-wordpress/</guid>
            <description>&lt;p&gt;I&amp;rsquo;m hosting quite a bit of pages that run WordPress, and one of the biggest problem that I ran into is that people don&amp;rsquo;t keep their WordPress or plugin installations updated.&lt;/p&gt;

&lt;p&gt;I gave up on having everyone upgrade, because they all use different plugins, customized plugins, and a lot of other stuff that will break if they upgrade.&lt;/p&gt;

&lt;p&gt;So here comes fail2ban to the rescue, we can use it to go through the logs, to configure the system to ban the users when they fail to log in, or do some bad stuff, or try to brute force their way into the wordpress installation, either through the login form or through xmlrpc.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;You should install &lt;strong&gt;fail2ban&lt;/strong&gt; if you haven&amp;rsquo;t already, on debian based you would just issue.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get install fail2ban
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you use &lt;strong&gt;Plesk&lt;/strong&gt; you can skip creation of the files, and just use the frontend to create the necessary jails and filters, also replace &lt;strong&gt;common.conf&lt;/strong&gt; with &lt;strong&gt;apache-common.conf&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The configuration is located in &lt;strong&gt;/etc/fail2ban&lt;/strong&gt; on most systems.&lt;/p&gt;

&lt;p&gt;So firstly let&amp;rsquo;s create a filter.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;/etc/fail2ban/filter.d&lt;/strong&gt;, create a file called &lt;strong&gt;wordpress-login.conf&lt;/strong&gt;, and put the following text inside.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# Fail2Ban filter for WordPress Login
#

[INCLUDES]
before = common.conf

[Definition]
_daemon = wordpress
failregex = ^&amp;lt;HOST&amp;gt;.*].*POST.*/wp-login\.php HTTP.*
ignoreregex =

# DEV Notes:
#
# Rule Author: Ilija Matoski
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What this does it creates a filter to be used in the next step. Also let&amp;rsquo;s create one filter for XMLRPC for WordPress in the same directory named &lt;strong&gt;wordpress-xmlrpc.conf&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# Fail2Ban filter for WordPress XMLRPC
#

[INCLUDES]
before = common.conf

[Definition]
_daemon = wordpress
failregex = ^&amp;lt;HOST&amp;gt;.*].*/xmlrpc\.php.*
ignoreregex =

# DEV Notes:
#
# Rule Author: Ilija Matoski
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s create two new jails, that we gonna use to ban the people who are gonna abuse this.&lt;/p&gt;

&lt;p&gt;In the folder &lt;strong&gt;/etc/fail2ban/jail.d&lt;/strong&gt;, &lt;strong&gt;wordpress.conf&lt;/strong&gt;,&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;[wordpress-xmlrpc]

enabled  = true
filter   = wordpress-xmlrpc
action   = iptables-multiport[name=WordPressXMLRPC, port=&amp;quot;http,https&amp;quot;]
logpath  = /var/log/apache2/access_log
maxretry = 10

[wordpress-login]

enabled  = true
filter   = wordpress-login
action   = iptables-multiport[name=WordPressLogin, port=&amp;quot;http,https&amp;quot;]
logpath  = /var/log/apache2/access_log
maxretry = 10

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you are running &lt;strong&gt;Plesk&lt;/strong&gt;, then replace the &lt;strong&gt;logpath&lt;/strong&gt; with&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;logpath  = /var/www/vhosts/system/*/logs/*access*log
           /var/log/apache2/*access.log
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So in &lt;strong&gt;Plesk&lt;/strong&gt;, the action will look like.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;iptables-multiport[name=&amp;quot;&amp;lt;NAME_OF_FILTER&amp;gt;&amp;quot;, port=&amp;quot;http,https&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will read the data from all the hosts in &lt;strong&gt;Plesk&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So what happens if someone tries to POST to &lt;strong&gt;wp-login.php&lt;/strong&gt;, or hit &lt;strong&gt;xmlrpc.php&lt;/strong&gt;, 10 times in a 10 minute period he will be banned for a day, also there is a jail called &lt;strong&gt;recidive&lt;/strong&gt; in &lt;strong&gt;fail2ban&lt;/strong&gt;, which if you get jailed 5 times with the previous filters, the IP will get ban for a week.&lt;/p&gt;

&lt;p&gt;You can adjust the times in the configuration file, if you want to lower or increase them.&lt;/p&gt;

&lt;p&gt;Well this should work, now let it run for a while, and you can see what does your, after 15 minutes of running this is what was present in my logs.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ iptables -L fail2ban-WordPressLogin
Chain fail2ban-WordPressLogin (1 references)
target     prot opt source               destination
REJECT     all  --  189.1.169.141         anywhere            reject-with icmp-port-unreachable
REJECT     all  --  181.140.198.180       anywhere            reject-with icmp-port-unreachable
REJECT     all  --  117.21.191.227        anywhere            reject-with icmp-port-unreachable
RETURN     all  --  anywhere              anywhere

$ iptables -L fail2ban-WordPressXMLRPC
Chain fail2ban-WordPressXMLRPC (1 references)
target     prot opt source               destination
REJECT     all  --  117.21.191.227        anywhere            reject-with icmp-port-unreachable
RETURN     all  --  anywhere              anywhere
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Interview question - About arrays</title>
            <link>https://matoski.com/article/interview-arrays/</link>
            <pubDate>Thu, 16 Oct 2014 04:03:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/interview-arrays/</guid>
            <description>&lt;p&gt;I had an interview for a job, and one question they asked was how to do something in a language I&amp;rsquo;m comfortable with.&lt;/p&gt;

&lt;p&gt;So I told them what language would they like for me to give them a solution, I said I can do it in Java, PHP, C/C++, &amp;hellip;, and they said that it&amp;rsquo;s not a problem, they understand everything, doesn&amp;rsquo;t mater which language it is written in,  if you want to know the difference read bellow in the PHP section.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The job I was applying was for a scripting language Perl (the developers that interviewed me had experience with Perl), so in this case they said I can do it in PHP because its a scripting language too.&lt;/p&gt;

&lt;p&gt;They wanted me to remove an item from an array, and to tell them how would I do it in the said language.&lt;/p&gt;

&lt;p&gt;The problem is that they don&amp;rsquo;t understand the representation of array in PHP is completely different than any other language, but we will get into that in a little while.&lt;/p&gt;

&lt;p&gt;Before we proceed lets see a little about the array data structure, and the internal workings of the array.&lt;/p&gt;

&lt;h2 id=&#34;array-data-structure&#34;&gt;Array Data Structure&lt;/h2&gt;

&lt;p&gt;Arrays is a basic data structure representing a group of similar elements, accessed by an index, it can be stored effectively and accessed quite fast to the all of the elements.&lt;/p&gt;

&lt;p&gt;An array doesn&amp;rsquo;t have an overhead per element. and any element of the array can be accessed at O(1) time by it&amp;rsquo;s index.&lt;/p&gt;

&lt;p&gt;On the other hand, the array structure is not dynamic. Most programming languages provide a way to allocate arrays with arbitrary size (dynamically allocated arrays), the problem with that is when the space is used up, a new array will have to be generated and the old data copied into it.&lt;/p&gt;

&lt;p&gt;The insertion and deletion of an element in an array requires to shift O(n) elements on average.&lt;/p&gt;

&lt;h5 id=&#34;static-and-dynamically-allocated-arrays&#34;&gt;Static and dynamically allocated arrays&lt;/h5&gt;

&lt;p&gt;There are two types of arrays, and both of them are implemented differently.&lt;/p&gt;

&lt;p&gt;Static array has a constant size and they are defined and present any time during runtime of the application.&lt;/p&gt;

&lt;p&gt;But the dynamic array is created during runtime and may be deleted, when it&amp;rsquo;s not needed any more, and they can be quite big, even bigger than the amount of physical memory, even though they are dynamic they can&amp;rsquo;t be resized. But you can expand it by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a new array of bigger size&lt;/li&gt;
&lt;li&gt;Copying data from old one to new one&lt;/li&gt;
&lt;li&gt;Free the memory of the old one&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&#34;dynamic-arrays&#34;&gt;Dynamic arrays&lt;/h5&gt;

&lt;p&gt;The problem when working with an array data structure is that its size cannot be changed during program run.&lt;/p&gt;

&lt;h6 id=&#34;internal-representation&#34;&gt;Internal representation&lt;/h6&gt;

&lt;p&gt;So how can we do this then ?&lt;/p&gt;

&lt;p&gt;The application allocates memory and divides it into two parts, one part contains the data and the other one contains the free space.&lt;/p&gt;

&lt;p&gt;In the beginning all space is free space. As you add items to the array, it will fill up, and when it has no space it will expand by creating a new larger array and copying the old contents to the new location.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;storage&lt;/strong&gt;: dynamically allocated space to store data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;capacity&lt;/strong&gt;: size of the storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;size&lt;/strong&gt;: real size of the data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are worried about speed don&amp;rsquo;t be because copying the arrays is done on the hardware level and can be done very efficiently.&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;dynamic-array.png&#34; alt=&#34;Dynamic Array&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;h2 id=&#34;php&#34;&gt;PHP&lt;/h2&gt;

&lt;p&gt;First of all, the arrays in PHP are not like traditional arrays, and everyone who comes to PHP or goes from PHP to other languages, are confused because arrays in PHP don&amp;rsquo;t work as expected, especially for people coming from Javascript, Java, Perl, C/C++, C#.&lt;/p&gt;

&lt;p&gt;If you look at the syntax it is similar to other languages, so let&amp;rsquo;s take a look at a simple implementation of an array in PHP.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-php&#34;&gt;&amp;lt;?php
$element = array();
for ($i = 7; $i &amp;gt;= 0; --$i) {
  $element[$i] = $i;
}

print implode(&#39; &#39;, $element);

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You would expect the following to be outputted:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0 1 2 3 4 5 6 7
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But in reality, it will output&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;7 6 5 4 3 2 1 0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Why? Because it&amp;rsquo;s not an array, it&amp;rsquo;s an ordered map, which is something I pointed out to the interviewers, so I proceeded to explain to them how this works, as I was asked to do so in this language, so I should explain properly how this is handled in the language in question, and was met with skepticism, and doubt.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-php&#34;&gt;&amp;lt;?php
$element = array();
for ($i = 7; $i &amp;gt;= 0; --$i) {
  $element[$i] = $i;
}

unset($element[4]);

$element[4] = 4;

print implode(&#39; &#39;, $element);

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case the result would be:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;7 6 5 3 2 1 0 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So what actually happened, because this is not an array and it&amp;rsquo;s an ordered map the result is not what you would expect.&lt;/p&gt;

&lt;p&gt;If you actually want the keys to be sorted you will need to use &lt;a href=&#34;http://php.net/manual/en/function.ksort.php&#34;&gt;ksort&lt;/a&gt; function.&lt;/p&gt;

&lt;p&gt;The real index ordering is inaccessible to us, if you actually write this in &lt;strong&gt;JavaScript, Python, Ruby, Perl, Java, or C#&lt;/strong&gt; you will get:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0 1 2 3 4 5 6 7
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So the reason why is this happening is because this is an ordered map, but lets actually see what goes under the hood in PHP.&lt;/p&gt;

&lt;p&gt;Basically everything in PHP is a HASH TABLE, not only the implementation of PHP arrays, but also they are used to store object properties, methods, functions, variables, &amp;hellip; (everything)&lt;/p&gt;

&lt;p&gt;And because the hash table is so fundamental to PHP, you should know what it actually is, before proceeding with PHP, at least that is what I think.&lt;/p&gt;

&lt;p&gt;Any variable in PHP is defined by &lt;strong&gt;zval&lt;/strong&gt;, and it&amp;rsquo;s value by &lt;strong&gt;zval_value&lt;/strong&gt;, lets see the data structures.&lt;/p&gt;

&lt;p&gt;These are taken from the PHP source code.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;http://lxr.php.net/xref/PHP_5_5/Zend/zend_hash.h#53&#34;&gt;PHP_5_5/Zend/zend_hash.h#53&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;typedef struct _hashtable {
	uint nTableSize;
	uint nTableMask;
	uint nNumOfElements;
	ulong nNextFreeElement;
	Bucket *pInternalPointer;	/* Used for element traversal */
	Bucket *pListHead;
	Bucket *pListTail;
	Bucket **arBuckets;
	dtor_func_t pDestructor;
	zend_bool persistent;
	unsigned char nApplyCount;
	zend_bool bApplyProtection;
#if ZEND_DEBUG
	int inconsistent;
#endif
} HashTable;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&#34;http://lxr.php.net/xref/PHP_5_5/Zend/zend.h#_zval_struct&#34;&gt;PHP_5_5/Zend/zend.h#_zval_struct&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-c&#34;&gt;struct _zval_struct {
    /* Variable information */
    zvalue_value value;     /* value */
    zend_uint refcount__gc;
    zend_uchar type;    /* active type */
    zend_uchar is_ref__gc;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&#34;http://lxr.php.net/xref/PHP_5_5/Zend/zend.h#_zvalue_value&#34;&gt;PHP_5_5/Zend/zend.h#_zvalue_value&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-c&#34;&gt;typedef union _zvalue_value {
    long lval;                  /* long value */
    double dval;                /* double value */
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;              /* hash table value */
    zend_object_value obj;
} zvalue_value;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Just a simple explanation, for those of you that don&amp;rsquo;t know C, you see the union there, that basically means that this is not actually a structure, but a single type.&lt;/p&gt;

&lt;p&gt;In C, variables are just labels for raw memory address.&lt;/p&gt;

&lt;p&gt;As you can see in the data structures above, we keep track of what primitive type is the value.&lt;/p&gt;

&lt;p&gt;I won&amp;rsquo;t delve deep into explaining this, it will take quite a while to do so, and maybe I will do so in a future article.&lt;/p&gt;

&lt;p&gt;If we actually have this code&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-php&#34;&gt;&amp;lt;?php
$a = 1;
$b =&amp;amp; $a;
unset($a); 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case &lt;strong&gt;$a&lt;/strong&gt; will be unset, but &lt;strong&gt;$b&lt;/strong&gt; will still remain the same with the value &lt;strong&gt;1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now let&amp;rsquo;s see this too&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-php&#34;&gt;&amp;lt;?php
$a = 1;
$b = &amp;amp;$a;
$a = 2;
echo &amp;quot;$a = $b&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the previous case when you unset, the value actually remains in &lt;strong&gt;$b&lt;/strong&gt;, but in this case, if we change &lt;strong&gt;$a&lt;/strong&gt;, &lt;strong&gt;$b&lt;/strong&gt; will also change.&lt;/p&gt;

&lt;p&gt;Well we strayed quite a bit from arrays, so let&amp;rsquo;s finish it here for PHP.&lt;/p&gt;

&lt;h2 id=&#34;java&#34;&gt;Java&lt;/h2&gt;

&lt;p&gt;In the heap (not on the stack), the array is a block of memory made of all the elements together, each element in the arrays is identified by a zero based index [0,1,2,3,&amp;hellip;.].&lt;/p&gt;

&lt;p&gt;There are ways of putting objects and arrays onto the stack instead, it&amp;rsquo;s called &lt;strong&gt;Escape analysis&lt;/strong&gt;, you can read some info on this &lt;a href=&#34;http://www.ibm.com/developerworks/library/j-jtp09275/&#34;&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Java language does not offer any way to explicitly allocate an object on the stack, but this fact doesn&amp;rsquo;t prevent JVMs from still using stack allocation where appropriate. JVMs can use a technique called escape analysis, by which they can tell that certain objects remain confined to a single thread for their entire lifetime, and that lifetime is bounded by the lifetime of a given stack frame. Such objects can be safely allocated on the stack instead of the heap. Even better, for small objects, the JVM can optimize away the allocation entirely and simply hoist the object&amp;rsquo;s fields into registers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The length of an array in Java cannot be changed if created with new, let&amp;rsquo;s take a look at this example.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;type arr[]; // declare the array
arr = new type[10]; // will initialize the array to 10 elements, and store the pointer
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;type&lt;/strong&gt; can be a primitive or an object.&lt;/p&gt;

&lt;p&gt;Lets see the previous example in PHP, with primitives without using Collections, or Lists.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;public class Test {

    public static void main(String args[]) {
        
		int[] arr = new int[8];
		
		for(int index = arr.length - 1; index &amp;gt;= 0; index--) {
			arr[index] = index;
		}
		
		for(int index = 0; index &amp;lt; arr.length; index++) {
			System.out.print(arr[index]);
		}    
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The output will be&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0 1 2 3 4 5 6 7
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Even though we inserted them in reverse the order is still correct.&lt;/p&gt;

&lt;p&gt;If you want to remove an array, you need to follow create a new array and copy it into the old one, while removing the element you don&amp;rsquo;t want.&lt;/p&gt;

&lt;p&gt;You can use &lt;strong&gt;System.copyarray&lt;/strong&gt; to do so&lt;/p&gt;

&lt;h2 id=&#34;c&#34;&gt;C&lt;/h2&gt;

&lt;p&gt;Arrays are allocated as a fixed number of contiguous elements, and there is no way to actually remove the memory used by an individual element in the array, but the elements can be shifted to fill in the hole made by the removal of the element.&lt;/p&gt;

&lt;p&gt;As you know from above that statical arrays can not be resized, but dynamically allocated ones can be resized with &lt;strong&gt;realloc()&lt;/strong&gt;, and what this will do is move the array to a new memory location, that can accomodate the whole array.&lt;/p&gt;

&lt;h2 id=&#34;javascript&#34;&gt;Javascript&lt;/h2&gt;

&lt;p&gt;In javascript the arrays can be sparse arrays and dense array.
Javascript arrays are dynamic. So any implementation has to account for variable length of the array.&lt;/p&gt;

&lt;p&gt;The Javascript Array wraps a simple C array allocated with a fixed number of elements. (a flat array)
The elements in the C array are resized everytime access to a location beyond the current maximum length is required. Hence insertion could be expensive.&lt;/p&gt;

&lt;p&gt;When the runtime detects that the array is Sparse, it is implemented in a similar way to an object. So instead of maintaining a contiguous array, a key/value map is built. In case of an array since the indexes are integers, this map can be efficiently implemented using a balanced Binary Search Tree or a similar structure. The performance of a sparse array is likely similar to the performance of an object.&lt;/p&gt;

&lt;p&gt;The arrays are initialized with Flat arrays and are then later replaced with Sparse array map if necessary.&lt;/p&gt;

&lt;p&gt;Even with the above general ideas, there is still so much leeway for browsers to tweak their implementations &amp;ndash; the heuristic for deciding if the array is sparse/dense, internal data structures used etc.&lt;/p&gt;

&lt;p&gt;The key lessons though, from understanding these differences are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Never use an object, when you need an array&lt;/li&gt;
&lt;li&gt;Never initialize arrays backwards (this will force create sparse array which is less efficient than dense arrays)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lets look at some examples&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sparse arrays&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you define the length of the array, you are not actually allocating the entries up front, but you are just allocates a slot for all the entries.&lt;/p&gt;

&lt;p&gt;So if we do this&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;var arr = new Array(10);
arr.forEach(function(v, k) {
 console.log(v, k);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The array is actually&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;[undefined × 10]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The keys are allocated but with no value, and the for cycle will actually not output anything.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dense arrays&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;var arr = Array.apply(null, Array(10));
arr.forEach(function(v, k) {
 console.log(v, k);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The array now is&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;[undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And as you can see now the array is now defined.&lt;/p&gt;

&lt;p&gt;One thing that we can use with this is&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Array.apply(null, Array(10)).map(function (x,i) { return i })
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And this will create for you an array of items&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lets see the example from up, and compare it with PHP.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;arr = [];
for(i=7; i &amp;gt;= 0; i--) {
   arr[i]=i;
} 
console.log(arr);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the output will be&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0 1 2 3 4 5 6 7
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;ending&#34;&gt;Ending&lt;/h2&gt;

&lt;p&gt;Well I think it&amp;rsquo;s enough to describe some of the intricacies of arrays between programing languages, we can probably go into more detail, but it should be sufficient.&lt;/p&gt;

&lt;p&gt;Well this turned out to be quite long.&lt;/p&gt;

&lt;p&gt;If you made it to the end, leave a comment, or your thoughts on this.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Getting started with gradle and java</title>
            <link>https://matoski.com/article/started-gradle-java/</link>
            <pubDate>Thu, 02 Oct 2014 23:26:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/started-gradle-java/</guid>
            <description>&lt;p&gt;I always used &lt;strong&gt;ant&lt;/strong&gt; with &lt;strong&gt;Apache Ivy&lt;/strong&gt; or &lt;strong&gt;maven&lt;/strong&gt; to build java applications, so I thought there has to be something better and easier to build the application instead of using them. So I decided to give &lt;strong&gt;gradle&lt;/strong&gt; a go.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;To build a project with &lt;strong&gt;gradle&lt;/strong&gt; is quite simple, and unlike &lt;strong&gt;ant&lt;/strong&gt; and &lt;strong&gt;maven&lt;/strong&gt;, managing dependencies is really easy.&lt;/p&gt;

&lt;h4 id=&#34;build-gradle&#34;&gt;build.gradle&lt;/h4&gt;

&lt;pre&gt;&lt;code&gt;apply plugin: &#39;java&#39;
apply plugin: &#39;eclipse&#39;

version = &#39;1.0&#39;

eclipse {
    classpath {
       downloadSources=true
       downloadJavadoc=true
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile &#39;log4j:log4j:1.2.17&#39;
    compile &#39;com.google.guava:guava:18.0&#39;
    compile &#39;io.netty:netty-all:4.0.23.Final&#39;
    testCompile &#39;junit:junit:4.11&#39;
}

jar {
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    manifest { 
        attributes &#39;Implementation-Title&#39;: &#39;&#39;, &#39;Implementation-Version&#39;: version
        attributes &#39;Main-Class&#39;: &#39;com.matoski.blog.demo.Hello&#39;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;src-main-java-com-matoski-blog-demo-hello-java&#34;&gt;src/main/java/com/matoski/blog/demo/Hello.java&lt;/h4&gt;

&lt;pre&gt;&lt;code&gt;package com.matoski.blog.demo;

public class Hello {

	public static void main(String[] args) {
		System.out.println(&amp;quot;Hello&amp;quot;);
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you run the build command &lt;strong&gt;gradle build&lt;/strong&gt; it will build the project and create a &lt;strong&gt;jar&lt;/strong&gt; file so we can run it.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# gradle build
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources
:testClasses
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 12.48 secs
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now we can run the application easily by running&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# java -jar build/libs/hello.jar
Hello
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It was really simple to build everything with gradle.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Express4 &#43; Mongoose &#43; JSON Web Token Authentication</title>
            <link>https://matoski.com/article/jwt-express-node-mongoose/</link>
            <pubDate>Sat, 20 Sep 2014 09:47:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/jwt-express-node-mongoose/</guid>
            <description>&lt;p&gt;Authentication is part of almost every system, even if it is in node.js, Express, Angular.JS, PHP, Perl, Ruby, or any other languages you are using. Dealing with authentication is a must for most of the systems.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;This article is quite long, so be prepared.&lt;/p&gt;

&lt;h2 id=&#34;table-of-contents&#34;&gt;Table of contents&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#how-we-used-auth&#34;&gt;How we used to do authentication&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#how-we-solved&#34;&gt;How did we solve this&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#jwt&#34;&gt;JSON Web Token&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#implementation&#34;&gt;Implementation&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#preparation&#34;&gt;Preparation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#errors&#34;&gt;Errors&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#nfe&#34;&gt;errors/NotFoundError.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#uae&#34;&gt;errors/UnauthorizedAccessError.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#main&#34;&gt;Main App&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#app&#34;&gt;app.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#models&#34;&gt;Models&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#user&#34;&gt;models/user.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#routes&#34;&gt;Routes&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#utils&#34;&gt;utils.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#default&#34;&gt;routes/default.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#login&#34;&gt;/api/login&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#verify&#34;&gt;/api/verify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#logout&#34;&gt;/api/logout&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#create-user&#34;&gt;Creating a user&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;tutorial-resources&#34;&gt;Tutorial Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/ilijamt/express-jwt-auth-mongoose&#34;&gt;Source Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://matoski.com/articles/node-express-generate-ssl/&#34;&gt;How to generate self-signed certificate for usage in Express4 or Node.js HTTP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;a-name-how-we-used-auth-a-how-we-used-to-do-authentication&#34;&gt;&lt;a name=&#34;how-we-used-auth&#34;&gt;&lt;/a&gt; How we used to do authentication&lt;/h2&gt;

&lt;p&gt;As we know HTTP protocol is stateless, so it cannot remember anything between requests, as it forgets everything on the next request.&lt;/p&gt;

&lt;p&gt;Imagine if you need to login in on every request you make to the page, which is a real pain.&lt;/p&gt;

&lt;h4 id=&#34;a-name-how-we-solved-a-how-did-we-solve-this&#34;&gt;&lt;a name=&#34;how-we-solved&#34;&gt;&lt;/a&gt; How did we solve this&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sessions:&lt;/strong&gt; We have to store our sessions on the server, and if we have multiple server then we need to synchronize the sessions between the servers, we can use redis to make it easier to share the sessions. But with no sessions we don&amp;rsquo;t have a problem.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile:&lt;/strong&gt; From my experience native mobile apps have problems working with cookies. If we need to query an API maybe session is not the best way to do it.&lt;/li&gt;
&lt;li&gt;&lt;abbr title=&#34;Cross-site request forgery&#34;&gt;&lt;strong&gt;CSRF&lt;/strong&gt;&lt;/abbr&gt;: If we use cookies for authentications, we will have to implement &lt;abbr title=&#34;Cross-site request forgery&#34;&gt;CSRF&lt;/abbr&gt;, for more details visit this &lt;a href=&#34;http://en.wikipedia.org/wiki/Cross-site_request_forgery&#34;&gt;link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;abbr title=&#34;Cross-origin resource sharing&#34;&gt;&lt;strong&gt;CORS&lt;/strong&gt;&lt;/abbr&gt;: Have you tried using cookies with CORS? For more details visit this &lt;a href=&#34;http://en.wikipedia.org/wiki/Cross-origin_resource_sharing&#34;&gt;link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;a-name-jwt-a-json-web-token&#34;&gt;&lt;a name=&#34;jwt&#34;&gt;&lt;/a&gt;JSON Web Token&lt;/h2&gt;

&lt;p&gt;Good thing about &lt;abbr title=&#34;JSON Web Token&#34;&gt;JWT&lt;/abbr&gt; is that it doesn&amp;rsquo;t use sessions, meaning has no problems with &lt;abbr title=&#34;Cross-site request forgery&#34;&gt;&lt;strong&gt;CSRF&lt;/strong&gt;&lt;/abbr&gt;, works excellent with &lt;abbr title=&#34;Cross-origin resource sharing&#34;&gt;&lt;strong&gt;CORS&lt;/strong&gt;&lt;/abbr&gt;, Mobile&lt;/p&gt;

&lt;p&gt;So the flow is:
1. Client Login
2. Client receives a token
3. Client does request with the token
4. Token gets decoded on the server, and you get the information stored in the token
   - In here you can verify if the user has access for this resource, this will simplify ACL
   - If the token is invalid return 401
5. With the data the server has it will decide if it will let the user get data or return a 401
   - I can query database and return the data that the user requested if he has privileges
   - I can update if the user has privileges&lt;/p&gt;

&lt;p&gt;So one important thing is how and where do we store the token?
* localStorage
* sessionStorage
* in the application that does the requests&lt;/p&gt;

&lt;p&gt;Another thing you can also do is share your token with a different client and he can login with that token too.&lt;/p&gt;

&lt;p&gt;To create a token we will need a secret key, as long as we don&amp;rsquo;t share that key, no one can&lt;/p&gt;

&lt;p&gt;If you are interested in more details you can read the &lt;a href=&#34;https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25&#34;&gt;IETF JSON Web Token draft&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;a-name-implementation-a-implementation&#34;&gt;&lt;a name=&#34;implementation&#34;&gt;&lt;/a&gt; Implementation&lt;/h2&gt;

&lt;p&gt;Lets see how we would go about implementing this.&lt;/p&gt;

&lt;p&gt;We can use &lt;strong&gt;express-generator&lt;/strong&gt;, to generate a skeleton for the application, but in our case we wouldn&amp;rsquo;t need one as we are only gonna focus on creating an authentication mechanism, without a front-end&lt;/p&gt;

&lt;h4 id=&#34;a-name-preparation-a-preparation&#34;&gt;&lt;a name=&#34;preparation&#34;&gt;&lt;/a&gt; Preparation&lt;/h4&gt;

&lt;p&gt;So let&amp;rsquo;s run the following commands to create the necessary structure for the project&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir express-jwt-auth
mkdir express-jwt-auth/keys
mkdir express-jwt-auth/routes
mkdir express-jwt-auth/models
mkdir express-jwt-auth/errors

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need to prepare the &lt;strong&gt;package.json&lt;/strong&gt; so we can install all the dependencies&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
    &amp;quot;name&amp;quot;: &amp;quot;express-jwt-auth&amp;quot;,
    &amp;quot;version&amp;quot;: &amp;quot;0.0.1&amp;quot;,
    &amp;quot;private&amp;quot;: true,
    &amp;quot;main&amp;quot;: &amp;quot;app.js&amp;quot;,
    &amp;quot;dependencies&amp;quot;: {
        &amp;quot;bcryptjs&amp;quot;: &amp;quot;~2.0.2&amp;quot;,
        &amp;quot;body-parser&amp;quot;: &amp;quot;~1.0.0&amp;quot;,
        &amp;quot;compression&amp;quot;: &amp;quot;^1.0.11&amp;quot;,
        &amp;quot;cors&amp;quot;: &amp;quot;^2.4.1&amp;quot;,
        &amp;quot;debug&amp;quot;: &amp;quot;~0.7.4&amp;quot;,
        &amp;quot;express&amp;quot;: &amp;quot;^4.2.0&amp;quot;,
        &amp;quot;express-jwt&amp;quot;: &amp;quot;^0.3.1&amp;quot;,
        &amp;quot;express-unless&amp;quot;: &amp;quot;*&amp;quot;,
        &amp;quot;hiredis&amp;quot;: &amp;quot;^0.1.17&amp;quot;,
        &amp;quot;jsonwebtoken&amp;quot;: &amp;quot;^0.4.1&amp;quot;,
        &amp;quot;lodash&amp;quot;: &amp;quot;~2.4.1&amp;quot;,
        &amp;quot;mongoose&amp;quot;: &amp;quot;~3.8.14&amp;quot;,
        &amp;quot;morgan&amp;quot;: &amp;quot;~1.2.2&amp;quot;,
        &amp;quot;on-finished&amp;quot;: &amp;quot;^2.1.0&amp;quot;,
        &amp;quot;redis&amp;quot;: &amp;quot;^0.12.1&amp;quot;,
        &amp;quot;response-time&amp;quot;: &amp;quot;~2.0.1&amp;quot;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can look up these packages to see what all of them do.&lt;/p&gt;

&lt;p&gt;You need to install all the package, so issue the following command&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;a-name-errors-a-errors&#34;&gt;&lt;a name=&#34;errors&#34;&gt;&lt;/a&gt; Errors&lt;/h4&gt;

&lt;p&gt;First lets create the error files in &lt;strong&gt;errors&lt;/strong&gt; directory, if you are asking why we would use this, it&amp;rsquo;s simple, we can pass the errors onto the &lt;strong&gt;next&lt;/strong&gt; handler, and we can process all the errors and handle them in one places instead of handling them in each route separately.&lt;/p&gt;

&lt;h5 id=&#34;a-name-nfe-a-errors-notfounderror-js&#34;&gt;&lt;a name=&#34;nfe&#34;&gt;&lt;/a&gt; errors/NotFoundError.js&lt;/h5&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;&amp;quot;use strict&amp;quot;;
function NotFoundError(code, error) {
    Error.call(this, typeof error === &amp;quot;undefined&amp;quot; ? undefined : error.message);
    Error.captureStackTrace(this, this.constructor);
    this.name = &amp;quot;NotFoundError&amp;quot;;
    this.message = typeof error === &amp;quot;undefined&amp;quot; ? undefined : error.message;
    this.code = typeof code === &amp;quot;undefined&amp;quot; ? &amp;quot;404&amp;quot; : code;
    this.status = 404;
    this.inner = error;
}

NotFoundError.prototype = Object.create(Error.prototype);
NotFoundError.prototype.constructor = NotFoundError;

module.exports = NotFoundError;
&lt;/code&gt;&lt;/pre&gt;

&lt;h5 id=&#34;a-name-uae-a-errors-unauthorizedaccesserror-js&#34;&gt;&lt;a name=&#34;uae&#34;&gt;&lt;/a&gt; errors/UnauthorizedAccessError.js&lt;/h5&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;&amp;quot;use strict&amp;quot;;
function UnauthorizedAccessError(code, error) {
    Error.call(this, error.message);
    Error.captureStackTrace(this, this.constructor);
    this.name = &amp;quot;UnauthorizedAccessError&amp;quot;;
    this.message = error.message;
    this.code = code;
    this.status = 401;
    this.inner = error;
}

UnauthorizedAccessError.prototype = Object.create(Error.prototype);
UnauthorizedAccessError.prototype.constructor = UnauthorizedAccessError;

module.exports = UnauthorizedAccessError;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We have created the errors, that we are gonna use in the application.&lt;/p&gt;

&lt;h4 id=&#34;a-name-main-a-main-app&#34;&gt;&lt;a name=&#34;main&#34;&gt;&lt;/a&gt; Main App&lt;/h4&gt;

&lt;p&gt;Now we need to create the main file &lt;strong&gt;app.js&lt;/strong&gt; in the root of the directory with the following contents&lt;/p&gt;

&lt;h5 id=&#34;a-name-app-a-app-js&#34;&gt;&lt;a name=&#34;app&#34;&gt;&lt;/a&gt; app.js&lt;/h5&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;&amp;quot;use strict&amp;quot;;

var debug = require(&#39;debug&#39;)(&#39;app:&#39; + process.pid),
    path = require(&amp;quot;path&amp;quot;),
    fs = require(&amp;quot;fs&amp;quot;),
    http_port = process.env.HTTP_PORT || 3000,
    https_port = process.env.HTTPS_PORT || 3443,
    jwt = require(&amp;quot;express-jwt&amp;quot;),
    config = require(&amp;quot;./config.json&amp;quot;),
    mongoose_uri = process.env.MONGOOSE_URI || &amp;quot;localhost/express-jwt-auth&amp;quot;,
    onFinished = require(&#39;on-finished&#39;),
    NotFoundError = require(path.join(__dirname, &amp;quot;errors&amp;quot;, &amp;quot;NotFoundError.js&amp;quot;)),
    utils = require(path.join(__dirname, &amp;quot;utils.js&amp;quot;)),
    unless = require(&#39;express-unless&#39;);

debug(&amp;quot;Starting application&amp;quot;);

debug(&amp;quot;Loading Mongoose functionality&amp;quot;);
var mongoose = require(&#39;mongoose&#39;);
mongoose.set(&#39;debug&#39;, true);
mongoose.connect(mongoose_uri);
mongoose.connection.on(&#39;error&#39;, function () {
    debug(&#39;Mongoose connection error&#39;);
});
mongoose.connection.once(&#39;open&#39;, function callback() {
    debug(&amp;quot;Mongoose connected to the database&amp;quot;);
});

debug(&amp;quot;Initializing express&amp;quot;);
var express = require(&#39;express&#39;), app = express();

debug(&amp;quot;Attaching plugins&amp;quot;);
app.use(require(&#39;morgan&#39;)(&amp;quot;dev&amp;quot;));
var bodyParser = require(&amp;quot;body-parser&amp;quot;);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(require(&#39;compression&#39;)());
app.use(require(&#39;response-time&#39;)());

app.use(function (req, res, next) {

    onFinished(res, function (err) {
        debug(&amp;quot;[%s] finished request&amp;quot;, req.connection.remoteAddress);
    });

    next();

});

var jwtCheck = jwt({
    secret: config.secret
});
jwtCheck.unless = unless;

app.use(jwtCheck.unless({path: &#39;/api/login&#39; }));
app.use(utils.middleware().unless({path: &#39;/api/login&#39; }));

app.use(&amp;quot;/api&amp;quot;, require(path.join(__dirname, &amp;quot;routes&amp;quot;, &amp;quot;default.js&amp;quot;))());

// all other requests redirect to 404
app.all(&amp;quot;*&amp;quot;, function (req, res, next) {
    next(new NotFoundError(&amp;quot;404&amp;quot;));
});

// error handler for all the applications
app.use(function (err, req, res, next) {

    var errorType = typeof err,
        code = 500,
        msg = { message: &amp;quot;Internal Server Error&amp;quot; };

    switch (err.name) {
        case &amp;quot;UnauthorizedError&amp;quot;:
            code = err.status;
            msg = undefined;
            break;
        case &amp;quot;BadRequestError&amp;quot;:
        case &amp;quot;UnauthorizedAccessError&amp;quot;:
        case &amp;quot;NotFoundError&amp;quot;:
            code = err.status;
            msg = err.inner;
            break;
        default:
            break;
    }

    return res.status(code).json(msg);

});

debug(&amp;quot;Creating HTTP server on port: %s&amp;quot;, http_port);
require(&#39;http&#39;).createServer(app).listen(http_port, function () {
    debug(&amp;quot;HTTP Server listening on port: %s, in %s mode&amp;quot;, http_port, app.get(&#39;env&#39;));
});

debug(&amp;quot;Creating HTTPS server on port: %s&amp;quot;, https_port);
require(&#39;https&#39;).createServer({
    key: fs.readFileSync(path.join(__dirname, &amp;quot;keys&amp;quot;, &amp;quot;server.key&amp;quot;)),
    cert: fs.readFileSync(path.join(__dirname, &amp;quot;keys&amp;quot;, &amp;quot;server.crt&amp;quot;)),
    ca: fs.readFileSync(path.join(__dirname, &amp;quot;keys&amp;quot;, &amp;quot;ca.crt&amp;quot;)),
    requestCert: true,
    rejectUnauthorized: false
}, app).listen(https_port, function () {
    debug(&amp;quot;HTTPS Server listening on port: %s, in %s mode&amp;quot;, https_port, app.get(&#39;env&#39;));
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So let&amp;rsquo;s see what happens here:
* We connect to Mongo database via Mongoose
* We add various plugins to extend Express
* We initialize JSON Web Token library and give it a secret key
    * We exclude JSON Web Token verification for &lt;strong&gt;/api/login&lt;/strong&gt;
* We hook the &lt;strong&gt;default&lt;/strong&gt; route, for login, logout, verify routes
* We create handler for &lt;strong&gt;404&lt;/strong&gt; messages
* We create handler for &lt;strong&gt;Error&lt;/strong&gt; messages
* We start &lt;strong&gt;HTTP&lt;/strong&gt; and &lt;strong&gt;HTTPS&lt;/strong&gt; version on the defined ports&lt;/p&gt;

&lt;h4 id=&#34;a-name-models-a-models&#34;&gt;&lt;a name=&#34;models&#34;&gt;&lt;/a&gt; Models&lt;/h4&gt;

&lt;p&gt;Now let&amp;rsquo;s create the &lt;strong&gt;models/user.js&lt;/strong&gt; file, this will serve us as a way to store the users and the password, and then authenticate against it later on&lt;/p&gt;

&lt;h5 id=&#34;a-name-user-a-models-user-js&#34;&gt;&lt;a name=&#34;user&#34;&gt;&lt;/a&gt; models/user.js&lt;/h5&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;&amp;quot;use strict&amp;quot;;

var mongoose = require(&#39;mongoose&#39;),
    bcrypt = require(&amp;quot;bcryptjs&amp;quot;),
    Schema = mongoose.Schema;

var UserSchema = new Schema({

    username: {
        type: String,
        unique: true,
        required: true
    },

    password: {
        type: String,
        required: true
    }

}, {
    toObject: {
        virtuals: true
    }, toJSON: {
        virtuals: true
    }
});

UserSchema.pre(&#39;save&#39;, function (next) {
    var user = this;
    if (this.isModified(&#39;password&#39;) || this.isNew) {
        bcrypt.genSalt(10, function (err, salt) {
            if (err) {
                return next(err);
            }
            bcrypt.hash(user.password, salt, function (err, hash) {
                if (err) {
                    return next(err);
                }
                user.password = hash;
                next();
            });
        });
    } else {
        return next();
    }
});

UserSchema.methods.comparePassword = function (passw, cb) {
    bcrypt.compare(passw, this.password, function (err, isMatch) {
        if (err) {
            return cb(err);
        }
        cb(null, isMatch);
    });
};

module.exports = mongoose.model(&#39;User&#39;, UserSchema);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see, before saving the model into database, the password is hashed and we cannot retrieve it.&lt;/p&gt;

&lt;h4 id=&#34;a-name-routes-a-routes&#34;&gt;&lt;a name=&#34;routes&#34;&gt;&lt;/a&gt; Routes&lt;/h4&gt;

&lt;p&gt;Now lets define the routes, we will use this for logging in or logging out of the system, also to verify if we are logged in or not&lt;/p&gt;

&lt;p&gt;First lets create the necessary utilities to be able to log in and log out&lt;/p&gt;

&lt;h5 id=&#34;a-name-utils-a-utils-js&#34;&gt;&lt;a name=&#34;utils&#34;&gt;&lt;/a&gt; utils.js&lt;/h5&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;&amp;quot;use strict&amp;quot;;

var debug = require(&#39;debug&#39;)(&#39;app:utils:&#39; + process.pid),
    path = require(&#39;path&#39;),
    util = require(&#39;util&#39;),
    redis = require(&amp;quot;redis&amp;quot;),
    client = redis.createClient(),
    _ = require(&amp;quot;lodash&amp;quot;),
    config = require(&amp;quot;./config.json&amp;quot;),
    jsonwebtoken = require(&amp;quot;jsonwebtoken&amp;quot;),
    TOKEN_EXPIRATION = 60,
    TOKEN_EXPIRATION_SEC = TOKEN_EXPIRATION * 60,
    UnauthorizedAccessError = require(path.join(__dirname, &#39;errors&#39;, &#39;UnauthorizedAccessError.js&#39;));

client.on(&#39;error&#39;, function (err) {
    debug(err);
});

client.on(&#39;connect&#39;, function () {
    debug(&amp;quot;Redis successfully connected&amp;quot;);
});

module.exports.fetch = function (headers) {
    if (headers &amp;amp;&amp;amp; headers.authorization) {
        var authorization = headers.authorization;
        var part = authorization.split(&#39; &#39;);
        if (part.length === 2) {
            var token = part[1];
            return part[1];
        } else {
            return null;
        }
    } else {
        return null;
    }
};

module.exports.create = function (user, req, res, next) {

    debug(&amp;quot;Create token&amp;quot;);

    if (_.isEmpty(user)) {
        return next(new Error(&#39;User data cannot be empty.&#39;));
    }

    var data = {
        _id: user._id,
        username: user.username,
        access: user.access,
        name: user.name,
        email: user.email,
        token: jsonwebtoken.sign({ _id: user._id }, config.secret, {
            expiresInMinutes: TOKEN_EXPIRATION
        })
    };

    var decoded = jsonwebtoken.decode(data.token);

    data.token_exp = decoded.exp;
    data.token_iat = decoded.iat;

    debug(&amp;quot;Token generated for user: %s, token: %s&amp;quot;, data.username, data.token);

    client.set(data.token, JSON.stringify(data), function (err, reply) {
        if (err) {
            return next(new Error(err));
        }

        if (reply) {
            client.expire(data.token, TOKEN_EXPIRATION_SEC, function (err, reply) {
                if (err) {
                    return next(new Error(&amp;quot;Can not set the expire value for the token key&amp;quot;));
                }
                if (reply) {
                    req.user = data;
                    next(); // we have succeeded
                } else {
                    return next(new Error(&#39;Expiration not set on redis&#39;));
                }
            });
        }
        else {
            return next(new Error(&#39;Token not set in redis&#39;));
        }
    });

    return data;

};

module.exports.retrieve = function (id, done) {

    debug(&amp;quot;Calling retrieve for token: %s&amp;quot;, id);

    if (_.isNull(id)) {
        return done(new Error(&amp;quot;token_invalid&amp;quot;), {
            &amp;quot;message&amp;quot;: &amp;quot;Invalid token&amp;quot;
        });
    }

    client.get(id, function (err, reply) {
        if (err) {
            return done(err, {
                &amp;quot;message&amp;quot;: err
            });
        }

        if (_.isNull(reply)) {
            return done(new Error(&amp;quot;token_invalid&amp;quot;), {
                &amp;quot;message&amp;quot;: &amp;quot;Token doesn&#39;t exists, are you sure it hasn&#39;t expired or been revoked?&amp;quot;
            });
        } else {
            var data = JSON.parse(reply);
            debug(&amp;quot;User data fetched from redis store for user: %s&amp;quot;, data.username);

            if (_.isEqual(data.token, id)) {
                return done(null, data);
            } else {
                return done(new Error(&amp;quot;token_doesnt_exist&amp;quot;), {
                    &amp;quot;message&amp;quot;: &amp;quot;Token doesn&#39;t exists, login into the system so it can generate new token.&amp;quot;
                });
            }

        }

    });

};

module.exports.verify = function (req, res, next) {

    debug(&amp;quot;Verifying token&amp;quot;);

    var token = exports.fetch(req.headers);

    jsonwebtoken.verify(token, config.secret, function (err, decode) {

        if (err) {
            req.user = undefined;
            return next(new UnauthorizedAccessError(&amp;quot;invalid_token&amp;quot;));
        }

        exports.retrieve(token, function (err, data) {

            if (err) {
                req.user = undefined;
                return next(new UnauthorizedAccessError(&amp;quot;invalid_token&amp;quot;, data));
            }

            req.user = data;
            next();

        });

    });
};

module.exports.expire = function (headers) {

    var token = exports.fetch(headers);

    debug(&amp;quot;Expiring token: %s&amp;quot;, token);

    if (token !== null) {
        client.expire(token, 0);
    }

    return token !== null;

};

module.exports.middleware = function () {

    var func = function (req, res, next) {

        var token = exports.fetch(req.headers);

        exports.retrieve(token, function (err, data) {

            if (err) {
                req.user = undefined;
                return next(new UnauthorizedAccessError(&amp;quot;invalid_token&amp;quot;, data));
            } else {
                req.user = _.merge(req.user, data);
                next();
            }

        });
    };

    func.unless = require(&amp;quot;express-unless&amp;quot;);

    return func;

};

module.exports.TOKEN_EXPIRATION = TOKEN_EXPIRATION;
module.exports.TOKEN_EXPIRATION_SEC = TOKEN_EXPIRATION_SEC;

debug(&amp;quot;Loaded&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What does this file do, it is responsible for loading, saving the token into redis, and when verifying the token to make sure it is present in redis too.
By storing the token in redis, we get and extra option, like invalidating tokens, if we just remove it from redis, even if the token is valid but not present, the API will return a 401 error.&lt;/p&gt;

&lt;h5 id=&#34;a-name-default-a-routes-default-js&#34;&gt;&lt;a name=&#34;default&#34;&gt;&lt;/a&gt; routes/default.js&lt;/h5&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;&amp;quot;use strict&amp;quot;;

var debug = require(&#39;debug&#39;)(&#39;app:routes:default&#39; + process.pid),
    _ = require(&amp;quot;lodash&amp;quot;),
    util = require(&#39;util&#39;),
    path = require(&#39;path&#39;),
    bcrypt = require(&#39;bcryptjs&#39;),
    utils = require(&amp;quot;../utils.js&amp;quot;),
    Router = require(&amp;quot;express&amp;quot;).Router,
    UnauthorizedAccessError = require(path.join(__dirname, &amp;quot;..&amp;quot;, &amp;quot;errors&amp;quot;, &amp;quot;UnauthorizedAccessError.js&amp;quot;)),
    User = require(path.join(__dirname, &amp;quot;..&amp;quot;, &amp;quot;models&amp;quot;, &amp;quot;user.js&amp;quot;)),
    jwt = require(&amp;quot;express-jwt&amp;quot;);

var authenticate = function (req, res, next) {

    debug(&amp;quot;Processing authenticate middleware&amp;quot;);

    var username = req.body.username,
        password = req.body.password;

    if (_.isEmpty(username) || _.isEmpty(password)) {
        return next(new UnauthorizedAccessError(&amp;quot;401&amp;quot;, {
            message: &#39;Invalid username or password&#39;
        }));
    }

    process.nextTick(function () {

        User.findOne({
            username: username
        }, function (err, user) {

            if (err || !user) {
                return next(new UnauthorizedAccessError(&amp;quot;401&amp;quot;, {
                    message: &#39;Invalid username or password&#39;
                }));
            }

            user.comparePassword(password, function (err, isMatch) {
                if (isMatch &amp;amp;&amp;amp; !err) {
                    debug(&amp;quot;User authenticated, generating token&amp;quot;);
                    utils.create(user, req, res, next);
                } else {
                    return next(new UnauthorizedAccessError(&amp;quot;401&amp;quot;, {
                        message: &#39;Invalid username or password&#39;
                    }));
                }
            });
        });

    });


};

module.exports = function () {

    var router = new Router();

    router.route(&amp;quot;/verify&amp;quot;).get(function (req, res, next) {
        return res.status(200).json(undefined);
    });

    router.route(&amp;quot;/logout&amp;quot;).get(function (req, res, next) {
        if (utils.expire(req.headers)) {
            delete req.user;
            return res.status(200).json({
                &amp;quot;message&amp;quot;: &amp;quot;User has been successfully logged out&amp;quot;
            });
        } else {
            return next(new UnauthorizedAccessError(&amp;quot;401&amp;quot;));
        }
    });

    router.route(&amp;quot;/login&amp;quot;).post(authenticate, function (req, res, next) {
        return res.status(200).json(req.user);
    });

    router.unless = require(&amp;quot;express-unless&amp;quot;);

    return router;
};

debug(&amp;quot;Loaded&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;h5 id=&#34;a-name-login-a-api-login&#34;&gt;&lt;a name=&#34;login&#34;&gt;&lt;/a&gt; /api/login&lt;/h5&gt;

&lt;p&gt;Now let&amp;rsquo;s try to login to the system, we can use &lt;strong&gt;curl&lt;/strong&gt; to do this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# curl -v -d &amp;quot;username=demo&amp;amp;password=demo&amp;quot;  http://127.0.0.1:3000/api/login

* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
&amp;gt; POST /api/login HTTP/1.1
&amp;gt; User-Agent: curl/7.37.1
&amp;gt; Host: 127.0.0.1:3000
&amp;gt; Accept: */*
&amp;gt; Content-Length: 27
&amp;gt; Content-Type: application/x-www-form-urlencoded
&amp;gt; 
* upload completely sent off: 27 out of 27 bytes
&amp;lt; HTTP/1.1 200 OK
&amp;lt; X-Powered-By: Express
&amp;lt; Content-Type: application/json; charset=utf-8
&amp;lt; Content-Length: 281
&amp;lt; X-Response-Time: 362.181ms
&amp;lt; Vary: Accept-Encoding
&amp;lt; Date: Fri, 05 Sep 2014 06:07:50 GMT
&amp;lt; Connection: keep-alive
&amp;lt; 
* Connection #0 to host 127.0.0.1 left intact
{
  &amp;quot;_id&amp;quot;: &amp;quot;540951d773d8bf915726de69&amp;quot;,
  &amp;quot;username&amp;quot;: &amp;quot;demo&amp;quot;,
  &amp;quot;token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJfaWQiOiI1NDA5NTFkNzczZDhiZjkxNTcyNmRlNjkiLCJpYXQiOjE0MDk4OTcyNzAsImV4cCI6MTQwOTkwMDg3MH0.NmzXaVUWpAaZLnq4lpsy_HlV6GqW2leOkOqyrvYku-U&amp;quot;,
  &amp;quot;token_exp&amp;quot;: 1409900870,
  &amp;quot;token_iat&amp;quot;: 1409897270
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see we got a token back now, and we can use this to query the API.
What we are doing is we are storing the user id in the token so when we decode it we can use the id to query the database for details, as we are storing the token and the user data in redis, we can use this id to get all the information about the user from Redis instead of querying the data all the time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;token&lt;/strong&gt; is the actual token&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;token_exp&lt;/strong&gt; until when is the token valid (unix timestamp)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;token_iat&lt;/strong&gt; is when the token was created (unix timestamp)&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&#34;a-name-verify-a-api-verify&#34;&gt;&lt;a name=&#34;verify&#34;&gt;&lt;/a&gt; /api/verify&lt;/h5&gt;

&lt;p&gt;Now let&amp;rsquo;s see about verifying if we are logged in or not&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# curl -v  http://127.0.0.1:3000/api/verify
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
&amp;gt; GET /api/verify HTTP/1.1
&amp;gt; User-Agent: curl/7.37.1
&amp;gt; Host: 127.0.0.1:3000
&amp;gt; Accept: */*
&amp;gt; 
&amp;lt; HTTP/1.1 401 Unauthorized
&amp;lt; X-Powered-By: Express
&amp;lt; Content-Type: application/json
&amp;lt; X-Response-Time: 2.777ms
&amp;lt; Vary: Accept-Encoding
&amp;lt; Date: Fri, 05 Sep 2014 06:10:37 GMT
&amp;lt; Connection: keep-alive
&amp;lt; Transfer-Encoding: chunked
&amp;lt; 
* Connection #0 to host 127.0.0.1 left intact
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see we got &lt;strong&gt;401&lt;/strong&gt; response, we didn&amp;rsquo;t supply the token, let&amp;rsquo;s add the token&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# curl -H &amp;quot;Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJfaWQiOiI1NDA5NTFkNzczZDhiZjkxNTcyNmRlNjkiLCJpYXQiOjE0MDk4OTcyNzAsImV4cCI6MTQwOTkwMDg3MH0.NmzXaVUWpAaZLnq4lpsy_HlV6GqW2leOkOqyrvYku-U&amp;quot; -v  http://127.0.0.1:3000/api/verify
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
&amp;gt; GET /api/verify HTTP/1.1
&amp;gt; User-Agent: curl/7.37.1
&amp;gt; Host: 127.0.0.1:3000
&amp;gt; Accept: */*
&amp;gt; Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJfaWQiOiI1NDA5NTFkNzczZDhiZjkxNTcyNmRlNjkiLCJpYXQiOjE0MDk4OTcyNzAsImV4cCI6MTQwOTkwMDg3MH0.NmzXaVUWpAaZLnq4lpsy_HlV6GqW2leOkOqyrvYku-U
&amp;gt; 
&amp;lt; HTTP/1.1 200 OK
&amp;lt; X-Powered-By: Express
&amp;lt; Content-Type: application/json
&amp;lt; X-Response-Time: 3.722ms
&amp;lt; Vary: Accept-Encoding
&amp;lt; Date: Fri, 05 Sep 2014 06:12:03 GMT
&amp;lt; Connection: keep-alive
&amp;lt; Transfer-Encoding: chunked
&amp;lt; 
* Connection #0 to host 127.0.0.1 left intact
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we got &lt;strong&gt;200&lt;/strong&gt;, which means the token is valid&lt;/p&gt;

&lt;h5 id=&#34;a-name-logout-a-api-logout&#34;&gt;&lt;a name=&#34;logout&#34;&gt;&lt;/a&gt; /api/logout&lt;/h5&gt;

&lt;p&gt;Same applies for logout, you cannot logout unless you are logged in, if you try to do it without the token you will get &lt;strong&gt;401&lt;/strong&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;curl -H &amp;quot;Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJfaWQiOiI1NDA5NTFkNzczZDhiZjkxNTcyNmRlNjkiLCJpYXQiOjE0MDk4OTcyNzAsImV4cCI6MTQwOTkwMDg3MH0.NmzXaVUWpAaZLnq4lpsy_HlV6GqW2leOkOqyrvYku-U&amp;quot; -v  http://127.0.0.1:3000/api/logout
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
&amp;gt; GET /api/logout HTTP/1.1
&amp;gt; User-Agent: curl/7.37.1
&amp;gt; Host: 127.0.0.1:3000
&amp;gt; Accept: */*
&amp;gt; Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJfaWQiOiI1NDA5NTFkNzczZDhiZjkxNTcyNmRlNjkiLCJpYXQiOjE0MDk4OTcyNzAsImV4cCI6MTQwOTkwMDg3MH0.NmzXaVUWpAaZLnq4lpsy_HlV6GqW2leOkOqyrvYku-U
&amp;gt; 
&amp;lt; HTTP/1.1 200 OK
&amp;lt; X-Powered-By: Express
&amp;lt; Content-Type: application/json; charset=utf-8
&amp;lt; Content-Length: 51
&amp;lt; ETag: W/&amp;quot;33-3789284850&amp;quot;
&amp;lt; X-Response-Time: 4.644ms
&amp;lt; Vary: Accept-Encoding
&amp;lt; Date: Fri, 05 Sep 2014 06:14:20 GMT
&amp;lt; Connection: keep-alive
&amp;lt; 
* Connection #0 to host 127.0.0.1 left intact
{&amp;quot;message&amp;quot;:&amp;quot;User has been successfully logged out&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;a-name-create-user-a-creating-a-user-create-user-js&#34;&gt;&lt;a name=&#34;create-user&#34;&gt;&lt;/a&gt; Creating a user (&lt;strong&gt;create_user.js&lt;/strong&gt;)&lt;/h4&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;var path = require(&amp;quot;path&amp;quot;),
    config = require(&amp;quot;./config.json&amp;quot;),
    User = require(path.join(__dirname, &amp;quot;models&amp;quot;, &amp;quot;user.js&amp;quot;)),
    mongoose_uri = process.env.MONGOOSE_URI || &amp;quot;localhost/express-jwt-auth&amp;quot;;

var args = process.argv.slice(2);

var username = args[0];
var password = args[1];

if (args.length &amp;lt; 2) {
    console.log(&amp;quot;usage: node %s %s %s&amp;quot;, path.basename(process.argv[1]), &amp;quot;user&amp;quot;, &amp;quot;password&amp;quot;);
    process.exit();
}

console.log(&amp;quot;Username: %s&amp;quot;, username);
console.log(&amp;quot;Password: %s&amp;quot;, password);

console.log(&amp;quot;Creating a new user in Mongo&amp;quot;);


var mongoose = require(&#39;mongoose&#39;);
mongoose.set(&#39;debug&#39;, true);
mongoose.connect(mongoose_uri);
mongoose.connection.on(&#39;error&#39;, function () {
    console.log(&#39;Mongoose connection error&#39;, arguments);
});
mongoose.connection.once(&#39;open&#39;, function callback() {
    console.log(&amp;quot;Mongoose connected to the database&amp;quot;);

    var user = new User();

    user.username = username;
    user.password = password;

    user.save(function (err) {
        if (err) {
            console.log(err);
        } else {
            console.log(user);
        }
        process.exit();
    });

});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So to create a user just execute the following command&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# node create_user.js demo demo

Username: demo
Password: demo
Creating a new user in Mongo
Mongoose: users.ensureIndex({ username: 1 }) { safe: undefined, background: true, unique: true }  
Mongoose connected to the database
Mongoose: users.insert({ __v: 0, _id: ObjectId(&amp;quot;540951d773d8bf915726de69&amp;quot;), username: &#39;demo&#39;, password: &#39;$2a$10$7t4Uz6WUapkmvr.uN1PVkuHfc6JcuMuWiElfv6CFMi/GESe1qSAt2&#39; }) {}  
{ __v: 0,
  password: &#39;$2a$10$7t4Uz6WUapkmvr.uN1PVkuHfc6JcuMuWiElfv6CFMi/GESe1qSAt2&#39;,
  username: &#39;demo&#39;,
  _id: 540951d773d8bf915726de69,
  id: &#39;540951d773d8bf915726de69&#39; }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will create a user demo that you can use to log in&lt;/p&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This approach will enable you a lot of flexibility with login/logout, and API architecture.&lt;/p&gt;

&lt;p&gt;Any modification to the token will invalidate it, also the only way to do modifications to the token is with a secret key, but this is not something we share with other people.&lt;/p&gt;

&lt;p&gt;Also this approach sets a expiry date, in our case 60 min, also that information is saved into the payload, so on the frontend, we can know when the token expires, and reissue a new token before expiry, or user has to re-login into the system to continue using it.&lt;/p&gt;

&lt;p&gt;Using JSON Web Token should be done over SSL preferably as you are sending the token on every request.&lt;/p&gt;

&lt;p&gt;If you want even more security you can change the secret key on every user login, or use a different secret key for every user.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>How to generate self-signed certificate for usage in Express4 or Node.js HTTP</title>
            <link>https://matoski.com/article/node-express-generate-ssl/</link>
            <pubDate>Tue, 09 Sep 2014 11:05:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/node-express-generate-ssl/</guid>
            <description>&lt;p&gt;I needed to generate a self-signed certificate for usage with node.js and express, since I don&amp;rsquo;t want to buy a certificate for just trying out and playing with it.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s figure out how to do it.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;You can also take a look at the following &lt;a href=&#34;http://youtu.be/4kvNFRmL3zg&#34;&gt;YouTube Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure you have install &lt;strong&gt;openssl&lt;/strong&gt;, if you haven&amp;rsquo;t install it&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RHEL/CentOS systems&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;yum install openssl
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Debian&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;apt-get install openssl
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To be able to use SSL you need to generate&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Certificate Authority&lt;/li&gt;
&lt;li&gt;Server Certificate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before we generate anything we need to generate a secure pass phrase&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# pwgen 50 1 -s &amp;gt; passphrase
# cat passphrase
TNOojiJgDeqP1WwUYflXzBpbfZyl1vkAiuoXoikXRPQ9d1VBkC
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So that is our secure pass phrase, and whenever it asks you for a pass phrase you can just copy paste the one we generated above.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s generate &lt;strong&gt;Certificate Authority&lt;/strong&gt; first&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Private Key&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# openssl genrsa -des3 -out ca.key 1024
Generating RSA private key, 1024 bit long modulus
...++++++
...++++++
e is 65537 (0x10001)
Enter pass phrase for ca.key:
Verifying - Enter pass phrase for ca.key:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Certificate Signing Request&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;openssl req -new -key ca.key -out ca.csr
Enter pass phrase for ca.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &#39;.&#39;, the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

Please enter the following &#39;extra&#39; attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Signing the certificate&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# openssl x509 -req -days 365 -in ca.csr -out ca.crt -signkey ca.key
Signature ok
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd
Getting Private key
Enter pass phrase for ca.key:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s generate the &lt;strong&gt;Server Certificate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Private Key with pass phrase&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# openssl genrsa -des3 -out server.key 1024
Generating RSA private key, 1024 bit long modulus
................................++++++
.....++++++
e is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Certificate Signing Request&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# openssl req -new -key server.key -out server.csr
Enter pass phrase for server.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &#39;.&#39;, the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

Please enter the following &#39;extra&#39; attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Private Key without pass phrase&lt;/strong&gt;
This will remove the pass phrase from the key, this step is crucial without this it will not work&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# cp server.key server.key.passphrase
# openssl rsa -in server.key.passphrase -out server.key
openssl rsa -in server.key.passphrase -out server.key
Enter pass phrase for server.key.passphrase:
writing RSA key
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Signing the certificate&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Signature ok
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd
Getting Private key
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These are the files we have now&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ls -la
total 36
drwxr-xr-x  2 user user 4096 Sep  5 16:19 .
drwxr-xr-x 12 user user 4096 Sep  5 16:09 ..
-rw-r--r--  1 user user  757 Sep  5 16:12 ca.crt
-rw-r--r--  1 user user  603 Sep  5 16:10 ca.csr
-rw-r--r--  1 user user  963 Sep  5 16:09 ca.key
-rw-r--r--  1 user user  757 Sep  5 16:19 server.crt
-rw-r--r--  1 user user  603 Sep  5 16:16 server.csr
-rw-r--r--  1 user user  887 Sep  5 16:18 server.key
-rw-r--r--  1 user user  951 Sep  5 16:17 server.key.passphrase
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There you go now we have everything needed, lets see how we can create a HTTPS server with node.js&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;var https = require(&#39;https&#39;),
    fs = require(&#39;fs&#39;), 
    express = require(&#39;express&#39;), 
    app = express();
    
var secureServer = https.createServer({
    key: fs.readFileSync(&#39;./ssl/server.key&#39;),
    cert: fs.readFileSync(&#39;./ssl/server.crt&#39;),
    ca: fs.readFileSync(&#39;./ssl/ca.crt&#39;),
    requestCert: true,
    rejectUnauthorized: false
}, app).listen(&#39;8443&#39;, function() {
    console.log(&amp;quot;Secure Express server listening on port 8443&amp;quot;);
});
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Emergency reboot/shutdown using SysRq</title>
            <link>https://matoski.com/article/emergency-reboot-shutdown-linux-sysrq/</link>
            <pubDate>Mon, 08 Sep 2014 08:07:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/emergency-reboot-shutdown-linux-sysrq/</guid>
            <description>&lt;p&gt;As you know linux implements some type of mechanism to gracefully shutdown and reboot, this means the daemons are stopping, usually linux stops them one by one, the file cache is synced to disk.&lt;/p&gt;

&lt;p&gt;But what sometimes happens is that the system will not reboot or shutdown no mater how many times you issue the &lt;strong&gt;shutdown&lt;/strong&gt; or &lt;strong&gt;reboot&lt;/strong&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;If the server is close to you, you can always just do a physical reset, but what if it&amp;rsquo;s far away from you, where you can&amp;rsquo;t reach it, sometimes it&amp;rsquo;s not feasible, why if the OpenSSH server crashes and you cannot log in again in the system.&lt;/p&gt;

&lt;p&gt;If you ever find yourself in a situation like that, there is another option to force the system to reboot or shutdown.&lt;/p&gt;

&lt;p&gt;The magic SysRq key is a key combination understood by the Linux kernel, which allows the user to perform various low-level commands regardless of the system&amp;rsquo;s state. It is often used to recover from freezes, or to reboot a computer without corrupting the filesystem.&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;QWERTY&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Immediately reboot the system, without unmounting or syncing filesystems&lt;/td&gt;
&lt;td&gt;b&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Sync all mounted filesystems&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Shut off the system&lt;/td&gt;
&lt;td&gt;o&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;Send the SIGKILL signal to all processes except init&lt;/td&gt;
&lt;td&gt;i&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;p&gt;So if you are in a situation where you cannot reboot or shutdown the server, you can force an immediate reboot by issuing&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo 1 &amp;gt; /proc/sys/kernel/sysrq 
echo b &amp;gt; /proc/sysrq-trigger
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you want you can also force a sync before rebooting by issuing these commands&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo 1 &amp;gt; /proc/sys/kernel/sysrq 
echo s &amp;gt; /proc/sysrq-trigger
echo b &amp;gt; /proc/sysrq-trigger
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These are called &lt;a href=&#34;http://en.wikipedia.org/wiki/Magic_SysRq_key&#34;&gt;magic commands&lt;/a&gt;, and they’re pretty much synonymous with holding down &lt;strong&gt;Alt-SysRq&lt;/strong&gt; and another key on older keyboards. Dropping 1 into &lt;strong&gt;/proc/sys/kernel/sysrq&lt;/strong&gt; tells the kernel that you want to enable SysRq access (it’s usually disabled). The second command is equivalent to pressing *&lt;em&gt;Alt-SysRq-b&lt;/em&gt; on a &lt;strong&gt;QWERTY&lt;/strong&gt; keyboard.&lt;/p&gt;

&lt;p&gt;If you want to keep &lt;strong&gt;SysRq&lt;/strong&gt; enabled all the time, you can do that with an entry in your server’s sysctl.conf:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;quot;kernel.sysrq = 1&amp;quot; &amp;gt;&amp;gt; /etc/sysctl.conf
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>rsyslog centralized logging</title>
            <link>https://matoski.com/article/rsyslog-centralized-logging/</link>
            <pubDate>Thu, 04 Sep 2014 18:56:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/rsyslog-centralized-logging/</guid>
            <description>&lt;p&gt;First of all logging is really important, and are a critical part of any system, they will give you insight into what a system is doing as well what happened.&lt;/p&gt;

&lt;p&gt;Virtually every process running on a system generates logs in some form or another. When your system grows to multiple hosts, managing the logs and accessing them can get complicated.&lt;/p&gt;

&lt;p&gt;Searching for a particular error across hundreds of log files on hundreds of servers is difficult without good tools.&lt;/p&gt;

&lt;p&gt;A common approach to this problem is to setup a centralized logging solution so that multiple logs can be aggregated in a central location.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;centralized-logging-system.png&#34; alt=&#34;Centralized Logging System&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;Most people use rsyslog or syslog-ng which are two syslog implementations. These daemons allow processes to send log messages to them and the syslog configuration determines how the are stored. In a centralized logging setup, a central syslog daemon is setup on your network and the client logging dameons are setup to forward messages to the central daemon&lt;/p&gt;

&lt;h1 id=&#34;step-1-installation&#34;&gt;Step 1 - Installation&lt;/h1&gt;

&lt;p&gt;If you don&amp;rsquo;t have &lt;strong&gt;rsyslog&lt;/strong&gt; on the server for any reason you can install them easily.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RHEL/CentOS systems&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;yum install rsyslog
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Debian&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get install rsyslog
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&#34;step-2-configuration&#34;&gt;Step 2 - Configuration&lt;/h1&gt;

&lt;p&gt;So what we need is for us to configure a server that will receive all the logs from remote servers, and configure the clients to send the logs to the server.&lt;/p&gt;

&lt;p&gt;Lets configure the server first.&lt;/p&gt;

&lt;p&gt;The configuration file is found in &lt;strong&gt;/etc/rsyslog.conf&lt;/strong&gt;, open it with your favorite editor, and lets edit the file, and we need to decide if we gonna use &lt;strong&gt;TCP&lt;/strong&gt; or &lt;strong&gt;UDP&lt;/strong&gt;, if you are not sure, just stick with TCP.&lt;/p&gt;

&lt;p&gt;If you want to use &lt;strong&gt;TCP&lt;/strong&gt;, add the following lines in &lt;strong&gt;/etc/rsyslog.conf&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ModLoad imtcp
$InputTCPServerRun 514
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As for &lt;strong&gt;UDP&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ModLoad imudp
$UDPServerRun 514
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yes one can have both UDP and TCP requests on same port as each connection is identified by ( source IP ,Destination IP, Source Port, Destination Port, PROTOCOL) as protocol can be TCP or UDP both connections can be differentiated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RHEL/CentOS systems, Debian&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;service rsyslog restart
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s check if the server is listening on the ports we have specified.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TCP&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ lsof -i :514
rsyslogd 7004 root    5u  IPv4 118878      0t0  TCP *:shell (LISTEN)
rsyslogd 7004 root    6u  IPv6 118879      0t0  TCP *:shell (LISTEN) 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;UDP&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ lsof -i :514
rsyslogd 7004 root    5u  IPv4 118878      0t0  UDP *:514
rsyslogd 7004 root    6u  IPv6 118879      0t0  UDP *:514 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So as you can see now we have &lt;strong&gt;rsyslog&lt;/strong&gt; listening on both &lt;strong&gt;TCP&lt;/strong&gt; and &lt;strong&gt;UDP&lt;/strong&gt; on the port we have specified.&lt;/p&gt;

&lt;p&gt;Lets configure the client now.&lt;/p&gt;

&lt;p&gt;All you need to do, is just add the server to where you want to forward the logs.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;*.*   @@Primary rsyslog server:514
*.*   @@Other Primary rsyslog server:514
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What this does is, it sends the all the logs to both servers specified in the config file (&lt;strong&gt;/etc/rsyslog.conf&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;You can use a selector for defining what logs you want to be sent.A selector processes all messages it receives (*.info;mail.none;authpriv.none;cron.none), and tries to forward every message to Primary rsyslog server&lt;/p&gt;

&lt;p&gt;Another thing you can do is, add failover capability to your logging, but this will only work if the server is configured in &lt;strong&gt;TCP&lt;/strong&gt; mode&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/etc/rsyslog.conf&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;*.info;mail.none;authpriv.none;cron.none  @@&amp;lt;Primary rsyslog server&amp;gt;
$ActionExecOnlyWhenPreviousIsSuspended on
&amp;amp;@@&amp;lt;Address of secondary rsyslog server &amp;gt;
&amp;amp;@@&amp;lt;Address of third rsyslog server &amp;gt;
&amp;amp; /var/log/localbuffer
$ActionExecOnlyWhenPreviousIsSuspended off
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So what happens is, if the primary rsyslog server cannot be reached, it will try on the secondary, and if the secondary can&amp;rsquo;t be reached it will try the third, and if the third is not reachable, it will write the data to &lt;strong&gt;/var/log/localbuffer&lt;/strong&gt;, ideally we would never ever have to write to this file.&lt;/p&gt;

&lt;h1 id=&#34;step-3-firewall-and-se-linux-on-the-server&#34;&gt;Step 3 - Firewall and SE Linux on the Server&lt;/h1&gt;

&lt;p&gt;If you are using SELinux you will have to allow traffic, just replace protocol with the correct one &lt;strong&gt;tcp&lt;/strong&gt;, &lt;strong&gt;udp&lt;/strong&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;semanage -a -t syslogd_port_t -p &amp;lt;protocol&amp;gt; 514
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you are using iptables for firewall you will have to allow, correct one &lt;strong&gt;tcp&lt;/strong&gt;, &lt;strong&gt;udp&lt;/strong&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;iptables -A INPUT -m state --state NEW -m &amp;lt;protocol&amp;gt; -p &amp;lt;protocol&amp;gt; --dport 514 -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So there you have it, now you have your logs in a singular place.&lt;/p&gt;

&lt;p&gt;Having everything in one place will allow you to run a really nice tool like &lt;a href=&#34;http://www.ossec.net/&#34;&gt;ossec&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In a future article I will take a look at other mechanisms for transferring logs.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Upgrade Plesk 11.5 to Plesk 12 on Debian Wheezy 7.6, fixing OpenDKIM and DK</title>
            <link>https://matoski.com/article/upgrade-plesk-11-5-to-12-fixing-dkim-dk/</link>
            <pubDate>Sat, 02 Aug 2014 10:38:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/upgrade-plesk-11-5-to-12-fixing-dkim-dk/</guid>
            <description>&lt;p&gt;I wanted to upgrade to the newer edition of Plesk as it has some interesting features for controlling outgoing mail that make my life easier.
So I wanted to upgrade and ran into some weird issues during the upgrade.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;After downloading the newest Parallels autoinstall script from their webpage, and running it produced the following error.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Components validation detected at least one important issue:
Parallels Panel pre-upgrade check...
dpkg-query: no packages found matching psa-atmail
dpkg-query: no packages found matching psa-horde
dpkg-query: no packages found matching libapache2-modsecurity
WARNING: IP address registered in Plesk is invalid or broken: xxx.xxx.xxx.xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The OS version details are as follow&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# lbs_release -a
No LSB modules are available.
Distributor ID:	Debian
Description:	Debian GNU/Linux 7.6 (wheezy)
Release:	7.6
Codename:	wheezy
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The panel version is 11.5.30 Update #47&lt;/p&gt;

&lt;p&gt;It was a little weird why is stuff missing, so I decided to check if the packages are in the repo.&lt;/p&gt;

&lt;p&gt;So running this command will give you the list of all the packages in the repository.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get install grep-dctrl
grep-dctrl -sPackage . /var/lib/apt/lists/autoinstall.plesk.com_debian_*_Packages | sort | uniq
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So it looks like the 3 packages &lt;strong&gt;psa-atmail, psa-horde, libapache2-modsecurity&lt;/strong&gt; are not present in the repository.&lt;/p&gt;

&lt;p&gt;Turns out that atmail is deprecated, and it doesn&amp;rsquo;t mater, but the other 2 packages I want them.&lt;/p&gt;

&lt;p&gt;And the autoinstaller adds the following lines into &lt;strong&gt;/etc/apt/sources.list&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;## This is temporary appended by Autoinstaller for 
## specify source of product&#39;s packages for APT.
deb http://autoinstall.plesk.com/debian/PSA_12.0.18 wheezy all
deb http://autoinstall.plesk.com/debian/SITEBUILDER_12.0.5 all all
deb http://autoinstall.plesk.com/debian/BILLING_12.0.18 all all
deb http://autoinstall.plesk.com/debian/NGINX_1.6.0 wheezy all
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can safely ignore these, for some reason after the upgrade, they appear in the repository, but not during the upgrade, but you won&amp;rsquo;t have any issues with this, at least I didn&amp;rsquo;t.&lt;/p&gt;

&lt;p&gt;Lets see about the next error:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;WARNING: IP address registered in Plesk is invalid or broken: xxx.xxx.xxx.xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Turns out that according the Plesk, this is an IP registered in the panel but it&amp;rsquo;s not present in the system, to see which ones are present and which ones are not we can just run the following commands.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# brctl show
bridge name	bridge id		STP enabled	interfaces
br0		8000.d43d7edb0649	no		eth0
							vnet0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the info about the IP addresses.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# ip a

1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast master br0 state UP qlen 1000
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
3: br0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP 
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet xx.xx.xx.xx/27 brd xx.xx.xx.xx scope global br0
    inet xx.xx.xx.xx/32 scope global br0
    inet xx.xx.xx.xx/32 scope global br0
    inet6 xxxx::xxxx:xxxx:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
4: vnet0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN qlen 500
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet6 xxxx::xxxx:xxxx:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the biggest problem is that the IP is there but plesk for some reason doesn&amp;rsquo;t detect it, as you can see I have 3 IP&amp;rsquo;s assigned to the network card, and it&amp;rsquo;s not detected one of them, and also I&amp;rsquo;m running a KVM machine with a dedicated IP address.
And I&amp;rsquo;m using a bridge for all of them to be present in the system.&lt;/p&gt;

&lt;p&gt;If this can happen with one IP, I don&amp;rsquo;t know, but it shouldn&amp;rsquo;t happen, as to why it showed an error with the bridge I have no idea.&lt;/p&gt;

&lt;p&gt;So you can just remove the IP temporarily from the system and the run the installer again, then after the upgrade you can just rerun the &lt;strong&gt;Reread IP&lt;/strong&gt; from &lt;strong&gt;Tools &amp;amp; Settings &amp;gt; IP Addresses&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Also one more thing if you have followed my guide about &lt;strong&gt;&lt;a href=&#34;https://matoski.com/articles/spf-dk-dkim-plesk-debian&#34;&gt;Setting up SPF + DK + DKIM with Postfix in Plesk 11.5 on Debian Wheezy&lt;/a&gt;&lt;/strong&gt;, you will notice that &lt;strong&gt;DKIM&lt;/strong&gt; signing is not working for some reason. But turns out to be really easy fix.&lt;/p&gt;

&lt;p&gt;Open /etc/postfix/main.cf with your favorite editor, and edit the following line.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# OpenDKIM
smtpd_milters = , inet:127.0.0.1:8891, inet:127.0.0.1:12768
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# OpenDKIM
smtpd_milters = , inet:127.0.0.1:12768, inet:127.0.0.1:8891
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;rsquo;s it for &lt;strong&gt;DKIM&lt;/strong&gt;, now let&amp;rsquo;s see about &lt;strong&gt;DK (Domain Keys)&lt;/strong&gt; you will notice that it&amp;rsquo;s not signing them anymore, well that is also a simple matter to fix, by doing the following.&lt;/p&gt;

&lt;p&gt;If you have one or two domains it&amp;rsquo;s simple then, just run this for the domain.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;/usr/local/psa/bin/domain_pref -u www.example.com -sign_outgoing_mail false
/usr/local/psa/bin/domain_pref -u www.example.com -sign_outgoing_mail true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will re-enable the signing for the domain in question, it will take a little while until it&amp;rsquo;s actually working, but for some reason in Plesk you need to disable it then enable it again for it to work.&lt;/p&gt;

&lt;p&gt;But in my case I had a lot of domains and I have to go through a big list of domains, so I wrote this script that will do this for all the domains.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/bash
pass=`cat /etc/psa/.psa.shadow`
domains=`mysql --skip-column-names -u admin -p$pass -e &#39;select name from domains where parentDomainId = 0;&#39; psa | tr &#39;\t&#39; &#39;,&#39;`
for domain in $domains; do
echo &amp;quot;Processing: $domain&amp;quot;
/usr/local/psa/bin/domain_pref -u &amp;quot;$domain&amp;quot; -sign_outgoing_mail false
/usr/local/psa/bin/domain_pref -u &amp;quot;$domain&amp;quot; -sign_outgoing_mail true
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;rsquo;s it, now we have everything in place, and you can start using your panel with the new version.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;**UPDATE: ** The packages are now present in the repository, so looks like they added them afterwards, don&amp;rsquo;t know why they weren&amp;rsquo;t present when I was upgrading but now they are so it&amp;rsquo;s OK, either way you can continue ignoring that info about the packages, but the IP has to be resolved before continuing.&lt;/p&gt;

&lt;!--more--&gt;</description>
        </item>
        
        <item>
            <title>tmux logging complete output to a file</title>
            <link>https://matoski.com/article/tmux-auto-logging-output/</link>
            <pubDate>Tue, 22 Jul 2014 22:48:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/tmux-auto-logging-output/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve needed to log the complete output of a node.js process I&amp;rsquo;ve been running, even though I&amp;rsquo;ve been logging everything, there are some situations where the process completely crashes and nothing was logged.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;To log the output of tmux you can use pipes, but in my case I wanted something simpler and more easier and flexible.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve been using the command &lt;strong&gt;script&lt;/strong&gt; to log the output to a file, so we can adjust our approach a little so we can log everything automatically.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;~/.bash_profile&lt;/strong&gt; we need to append the following lines&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;if [[ $TERM = &amp;quot;screen&amp;quot; ]] &amp;amp;&amp;amp; [[ $(ps -p $PPID -o comm=) = &amp;quot;tmux&amp;quot; ]]; then
mkdir $HOME/logs 2&amp;gt; /dev/null
logname=&amp;quot;$(date &#39;+%d%m%Y%H%M%S&#39;).tmux.log&amp;quot;
script -f $HOME/logs/${logname}
exit
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What this does is, when you start &lt;strong&gt;tmux&lt;/strong&gt; manually it will output all the screen output to a log file, but this is always not sufficient.&lt;/p&gt;

&lt;p&gt;In my case I was using tmux to start some commands from the shell with &lt;strong&gt;new-session&lt;/strong&gt;, and this approach for some reason it doesn&amp;rsquo;t work.&lt;/p&gt;

&lt;p&gt;So what I did is, I created a script that I will run to start everything I need&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/bash
tmux new-session -s session -d -n &amp;quot;session&amp;quot; &amp;quot;bash&amp;quot;
tmux send -t session.0 &amp;quot;. $HOME/.bash_profile&amp;quot; ENTER
tmux send -t session.0 &amp;quot;&amp;lt;COMMAND 1 I NEED TO RUN&amp;gt;&amp;quot; ENTER
tmux send -t session.0 &amp;quot;&amp;lt;COMMAND 2 I NEED TO RUN&amp;gt;&amp;quot; ENTER
tmux send -t session.0 &amp;quot;&amp;lt;COMMAND 3 I NEED TO RUN&amp;gt;&amp;quot; ENTER
tmux send -t session.0 &amp;quot;&amp;lt;COMMAND n I NEED TO RUN&amp;gt;&amp;quot; ENTER
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So what this does, it manually loads the .bash_profile script and we are good to go, we can log automatically again.
This can also be used to load all the environments in &lt;strong&gt;tmux&lt;/strong&gt;&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>RVM &#43; GitLab on Debian</title>
            <link>https://matoski.com/article/rvm-gitlab-ssh-shell-ruby/</link>
            <pubDate>Fri, 27 Jun 2014 12:53:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/rvm-gitlab-ssh-shell-ruby/</guid>
            <description>&lt;p&gt;I needed to install my own GitLab on my server for my personal projects, so I don&amp;rsquo;t have to use GitHub and pay for it.
This will require some work, but in the end you will save some money.&lt;/p&gt;

&lt;p&gt;Before proceeding lets install some prerequisites.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get install nginx pwgen openssh-server openssh-client sudo git-core build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server redis-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils libcurl4-openssl-dev libexpat1-dev gettext libz-dev libssl-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lets install RVM first before proceeding with installation of GitLab.
I always install RVM as a global installation as I can use it with other users in the systems if necessary.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;curl -sSL https://get.rvm.io | sudo bash -s stable
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At the time of writing this article the latest version of GitLab is version 7. And the required version of ruby is 2.1.2 according to the requirements, so let&amp;rsquo;s install ruby&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;rvm install ruby-2.1.2
gem install bundler
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Before continuing we need to set up SSH to allow for user environments, because if we don&amp;rsquo;t we will get the following message whenever we try to do something with git.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/usr/bin/env: ruby: no such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is because there is no user environment when doing operations with git.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s edit &lt;strong&gt;/etc/ssh/sshd_config&lt;/strong&gt; and add the following to the end of the file.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;PermitUserEnvironment yes
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Execute the following commands with &lt;strong&gt;root&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;adduser --disabled-login --gecos &#39;GitLab&#39; git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I prefer MySQL over PostgreSQL for GitLab so lets install MySQL for use with GitLab&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get install mysql-server mysql-client libmysqlclient-dev
mysql_secure_installation
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lets generate a password to use with the system.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;pwgen 10 1
iePhee2lae
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then execute the following SQL&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;CREATE USER &#39;git&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;iePhee2lae&#39;; 
SET storage_engine=INNODB;
CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
GRANT SELECT, LOCK TABLES, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `gitlabhq_production`.* TO &#39;git&#39;@&#39;localhost&#39;;
FLUSH PRIVILEGES;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Before we proceed lets add Git user temporarily to sudoers (&lt;strong&gt;/etc/sudoers&lt;/strong&gt;)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git     ALL=(ALL) NOPASSWD: ALL
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we need to checkout GitLab, for more up to date &lt;a href=&#34;https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md&#34;&gt;installation instructions&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;su - git
git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-0-stable gitlab
cd /home/git/gitlab
cp config/gitlab.yml.example config/gitlab.yml
cp config/unicorn.rb.example config/unicorn.rb
cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
cp config/database.yml.mysql config/database.yml
sudo chown -R git log/
sudo chown -R git tmp/
sudo chmod -R u+rwX log/
sudo chmod -R u+rwX tmp/
sudo mkdir /home/git/gitlab-satellites
sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites
sudo chmod -R u+rwX tmp/pids/
sudo chmod -R u+rwX tmp/sockets/
sudo chmod -R u+rwX  public/uploads
git config --global user.name &amp;quot;GitLab&amp;quot;
git config --global user.email &amp;quot;example@example.com&amp;quot;
git config --global core.autocrlf input
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
sudo cp lib/support/init.d/gitlab.default.example /etc/default/gitlab
sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
sudo cp lib/support/nginx/gitlab /etc/nginx/sites-available/gitlab
sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
sudo update-rc.d gitlab defaults 21
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now lets edit the configuration files and modify them according to our needs.&lt;/p&gt;

&lt;p&gt;Make sure to change &amp;ldquo;localhost&amp;rdquo; to the fully-qualified domain name of your host serving GitLab where necessary&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;editor config/gitlab.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Change YOUR_SERVER_FQDN to the fully-qualified domain name of your host serving GitLab.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;sudo editor /etc/nginx/sites-available/gitlab
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Update username/password in config/database.yml.
You only need to adapt the production settings (first part).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;editor config/database.yml
chmod o-rwx config/database.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enable cluster mode if you expect to have a high load instance. Ex. change amount of workers to 3 for 2GB RAM server.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;editor config/unicorn.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now lets install gitlab shell&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cd /home/git/gitlab
bundle install --deployment --without development test postgres aws
bundle exec rake gitlab:shell:install[v1.9.6] REDIS_URL=redis://localhost:6379 RAILS_ENV=production
bundle exec rake gitlab:setup RAILS_ENV=production
bundle exec rake assets:precompile RAILS_ENV=production
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s check if everything was installed correctly&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;bundle exec rake gitlab:env:info RAILS_ENV=production
bundle exec rake gitlab:check RAILS_ENV=production
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now lets start everything up&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;sudo service gitlab restart
sudo service nginx restart
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>KVM port forwarding with NAT network and libvirt on Debian</title>
            <link>https://matoski.com/article/kvm-port-forwarding-nat/</link>
            <pubDate>Tue, 17 Dec 2013 11:09:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/kvm-port-forwarding-nat/</guid>
            <description>&lt;p&gt;I needed to forward some ports from multiple KVM machines, I tried with iptables, but the problem is libvirt adds some rules of it&amp;rsquo;s own, and the rules were never in the correct place so it didn&amp;rsquo;t work.&lt;/p&gt;

&lt;p&gt;Fortunately KVM supports hooks, and we can use them to do what we need.&lt;/p&gt;

&lt;p&gt;You should be able to easily adapt this to any linux distro.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/etc/libvirt/hooks/daemon
&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Executed when the libvirt daemon is started, stopped, or reloads its configuration&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/etc/libvirt/hooks/qemu&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Executed when a QEMU guest is started, stopped, or migrated&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/etc/libvirt/hooks/lxc
&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Executed when an LXC guest is started or stopped&lt;/p&gt;

&lt;p&gt;For a more detailed list we you can check &lt;a href=&#34;http://libvirt.org/hooks.html&#34;&gt;libvirt hooks&lt;/a&gt; on the libvirt home page.&lt;/p&gt;

&lt;p&gt;For us we will need to use &lt;strong&gt;/etc/libvirt/hooks/qemu&lt;/strong&gt; script, because that is the script which triggers whenever we have VM going through the following states&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prepare (libvirt 0.9.0)&lt;/li&gt;
&lt;li&gt;start (libvirt 0.8.0)&lt;/li&gt;
&lt;li&gt;started (libvirt 0.9.13)&lt;/li&gt;
&lt;li&gt;stopped (libvirt 0.8.0)&lt;/li&gt;
&lt;li&gt;release (libvirt 0.9.0)&lt;/li&gt;
&lt;li&gt;migrate (libvirt 0.9.11)&lt;/li&gt;
&lt;li&gt;reconnect (libvirt 0.9.13)&lt;/li&gt;
&lt;li&gt;attach (libvirt 0.9.13)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our case we are interested in three events, and we will split them in two groups&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;stopped&lt;/strong&gt; or &lt;strong&gt;reconnect&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;start&lt;/strong&gt; or &lt;strong&gt;reconnect&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We want to automatically add/remove rules to iptables on starting/stopping the VM, let&amp;rsquo;s see a structure we are gonna use to hold the mappings.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &#39;&amp;lt;guest name (as defined in xml)&amp;gt;&#39;: {
     &#39;ip&#39;: &#39;&amp;lt;private ip&amp;gt;&#39;,
     &#39;publicip&#39;: &#39;&amp;lt;public ip&amp;gt;&#39;,
     &#39;portmap&#39;: &#39;all&#39; |
            {
               &#39;&amp;lt;proto&amp;gt;&#39;: [(&amp;lt;host port&amp;gt;, &amp;lt;guest port&amp;gt;), ...], ...
            }
     }, ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From the definition it is obvious what should go where&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;proto&lt;/strong&gt; is the protocol&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;portmap&lt;/strong&gt; can be either &lt;em&gt;all&lt;/em&gt; or the &lt;em&gt;map&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also we should log all the actions taken by this script to syslog if we want to do checking or debuging, to see if everything is properly working.&lt;/p&gt;

&lt;p&gt;I would gladly accept any improvements to this scripts, so feel free to improve this script, and I will update it, on the page.
This script has been tested on &lt;strong&gt;Python 2.7.3&lt;/strong&gt; and should work on &lt;strong&gt;Python 3&lt;/strong&gt;, as for older versions I don&amp;rsquo;t know.&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s take a look at the python script located under &lt;strong&gt;/etc/libvirt/hooks/qemu&lt;/strong&gt;, make sure you execute &lt;strong&gt;chmod +x /etc/libvirt/hooks/qemu&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import os
import syslog

domain = sys.argv[1]
action = sys.argv[2]

iptables = &#39;/sbin/iptables&#39;

mapping = {
  &amp;quot;vm1&amp;quot;: {
    &amp;quot;ip&amp;quot;: &amp;quot;192.168.22.1&amp;quot;,
    &amp;quot;publicip&amp;quot;: &amp;quot;x.x.x.x&amp;quot;,
    &amp;quot;portmap&amp;quot;: {
      &amp;quot;tcp&amp;quot;: [
        (3901, 80),
        (3701, 22),
        (31621, 31621)
      ]
    }
  }
}

syslog.syslog(&#39;Processing QEMU Signal, domain: &#39; + domain + &#39;, action:&#39;
              + action)

def rules(act, map_dict):
    if map_dict[&#39;portmap&#39;] == &#39;all&#39;:
        cmd = \
            &#39;{} -t nat {} PREROUTING -d {} -j DNAT --to {}&#39;.format(iptables,
                act, map_dict[&#39;publicip&#39;], map_dict[&#39;ip&#39;])
        os.system(cmd)
        syslog.syslog(cmd)
        cmd = \
            &#39;{} -t nat {} POSTROUTING -s {} -j SNAT --to {}&#39;.format(iptables,
                act, map_dict[&#39;ip&#39;], map_dict[&#39;publicip&#39;])
        os.system(cmd)
        syslog.syslog(cmd)
        cmd = \
            &#39;{} -t filter {} FORWARD -d {} -j ACCEPT&#39;.format(iptables,
                act, map_dict[&#39;ip&#39;])
        os.system(cmd)
        syslog.syslog(cmd)
        cmd = \
            &#39;{} -t filter {} FORWARD -s {} -j ACCEPT&#39;.format(iptables,
                act, map_dict[&#39;ip&#39;])
        os.system(cmd)
        syslog.syslog(cmd)
    else:
        for proto in map_dict[&#39;portmap&#39;]:
            for portmap in map_dict[&#39;portmap&#39;].get(proto):
                cmd = \
                    &#39;{} -t nat {} PREROUTING -d {} -p {} --dport {} -j DNAT --to {}:{}&#39;.format(
                    iptables,
                    act,
                    map_dict[&#39;publicip&#39;],
                    proto,
                    str(portmap[0]),
                    map_dict[&#39;ip&#39;],
                    str(portmap[1]),
                    )
                os.system(cmd)
                syslog.syslog(cmd)
                cmd = \
                    &#39;{} -t filter {} FORWARD -d {} -p {} --dport {} -j ACCEPT&#39;.format(iptables,
                        act, map_dict[&#39;ip&#39;], proto, str(portmap[1]))
                os.system(cmd)
                syslog.syslog(cmd)
                cmd = \
                    &#39;{} -t filter {} FORWARD -s {} -p {} --sport {} -j ACCEPT&#39;.format(iptables,
                        act, map_dict[&#39;ip&#39;], proto, str(portmap[1]))
                os.system(cmd)
                syslog.syslog(cmd)


host = mapping.get(domain)

if host is None:
    sys.exit(0)

if action == &#39;stopped&#39; or action == &#39;reconnect&#39;:
    rules(&#39;-D&#39;, host)
    syslog.syslog(&#39;Removed all the iptables rules for &#39; + domain)

if action == &#39;start&#39; or action == &#39;reconnect&#39;:
    rules(&#39;-I&#39;, host)
    syslog.syslog(&#39;Created all the iptables rules for &#39; + domain)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I also added this to my &lt;strong&gt;/etc/sysctl.conf&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
net.ipv6.conf.default.autoconf=0
net.ipv6.conf.default.accept_dad=0
net.ipv6.conf.default.accept_ra=0
net.ipv6.conf.default.accept_ra_defrtr=0
net.ipv6.conf.default.accept_ra_rtr_pref=0
net.ipv6.conf.default.accept_ra_pinfo=0
net.ipv6.conf.default.accept_source_route=0
net.ipv6.conf.default.accept_redirects=0
net.ipv6.conf.default.forwarding=0
net.ipv6.conf.all.autoconf=0
net.ipv6.conf.all.accept_dad=0
net.ipv6.conf.all.accept_ra=0
net.ipv6.conf.all.accept_ra_defrtr=0
net.ipv6.conf.all.accept_ra_rtr_pref=0
net.ipv6.conf.all.accept_ra_pinfo=0
net.ipv6.conf.all.accept_source_route=0
net.ipv6.conf.all.accept_redirects=0
net.ipv6.conf.all.forwarding=0
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_redirects = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.all.log_martians = 0
net.ipv4.ip_local_port_range = 32768 61000
net.ipv4.icmp_echo_ignore_all = 0
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 2400
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you want you can add this too, but if you don&amp;rsquo;t want to you really need to add &lt;strong&gt;net.ipv4.ip_forward&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;After editing &lt;strong&gt;/etc/sysctl.conf&lt;/strong&gt; you need to issue&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;sysctl -p
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To initialize and read the settings from &lt;strong&gt;/etc/sysctl.conf&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now you need to restart the &lt;strong&gt;libvirt&lt;/strong&gt; service so it will initialize the hook, otherwise it will not call it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;libvirt&lt;/strong&gt; Adds it&amp;rsquo;s own rules to ip tables, so if you want to do this manually you will have to make sure you add the correct rules for this to work.&lt;/p&gt;

&lt;p&gt;For my setup the iptables was as follows, the rules will be automatically added/removed depending on the state of the machine whether it is running or not&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-iptables&#34;&gt;# Generated by iptables-save v1.4.14 on Sat Dec 14 18:31:26 2013
*nat
:PREROUTING ACCEPT [126:7694]
:INPUT ACCEPT [126:7694]
:OUTPUT ACCEPT [223:17030]
:POSTROUTING ACCEPT [223:17030]
-A POSTROUTING -s 192.168.22.0/24 ! -d 192.168.22.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 192.168.22.0/24 ! -d 192.168.22.0/24 -p udp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s 192.168.22.0/24 ! -d 192.168.22.0/24 -j MASQUERADE
COMMIT
# Completed on Sat Dec 14 18:31:26 2013
# Generated by iptables-save v1.4.14 on Sat Dec 14 18:31:26 2013
*mangle
:PREROUTING ACCEPT [12485:1642751]
:INPUT ACCEPT [12485:1642751]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [12074:3717410]
:POSTROUTING ACCEPT [12074:3717410]
-A POSTROUTING -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
COMMIT
# Completed on Sat Dec 14 18:31:26 2013
# Generated by iptables-save v1.4.14 on Sat Dec 14 18:31:26 2013
*filter
:INPUT ACCEPT [12466:1639919]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [12074:3717410]
-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
-A FORWARD -d 192.168.22.0/24 -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.22.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
COMMIT
# Completed on Sat Dec 14 18:31:26 2013
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>How to reset var folder permissions and ownership to their default in Debian</title>
            <link>https://matoski.com/article/debian-restore-var-ownership-permissions/</link>
            <pubDate>Thu, 28 Nov 2013 15:40:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/debian-restore-var-ownership-permissions/</guid>
            <description>&lt;p&gt;If by accident you execute a command that changes the permission or ownership of a bunch of folders or file in Debian, you are in a lot of trouble, usually the sollution is to reinstall the system, but as I was unwilling to reinstall thet system, I decided to find another way to do it, as I have finally set up my system as I want it to run, so we will look into a couple of methods of how to do it without reinstallation of the system.&lt;/p&gt;

&lt;p&gt;Using virtual machine, reinstalling packages, or even generating a script from debian packages.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I accidently ran a &lt;strong&gt;chown&lt;/strong&gt; command on the whole &lt;strong&gt;/var&lt;/strong&gt; folder, and ended up with every file and folder in ownership of &lt;strong&gt;www-data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;According to the manual the &lt;strong&gt;var&lt;/strong&gt; directory is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The /var directory is mostly mounted as a separate filesystem under the root where in all the variable content like logs, spool files for printers, crontab,at jobs, mail, running process, lock files etc. Care has to be taken in planning this file system and maintenance as this can fill up pretty quickly and when the FileSystem is full can cause system and application operational issues.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wanted to &lt;strong&gt;chown&lt;/strong&gt; all the hidden files in the directory &lt;strong&gt;/var/www&lt;/strong&gt; to &lt;strong&gt;www-data&lt;/strong&gt;, I was in the directory &lt;strong&gt;/var/www&lt;/strong&gt; when I ran the following command&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;chown -R www-data:www-data .*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And after running this, I noticed that my whole &lt;strong&gt;var&lt;/strong&gt; folder was in ownership of &lt;strong&gt;www-data&lt;/strong&gt;, so my quest to restore it to the original ownership and permissions started.&lt;/p&gt;

&lt;p&gt;Imagine if it was &lt;strong&gt;rm&lt;/strong&gt; instead of &lt;strong&gt;chown&lt;/strong&gt;, I would have ended up deleting all the files in the &lt;strong&gt;var&lt;/strong&gt; folder.&lt;/p&gt;

&lt;p&gt;If you ever what to do something with the hidden files you should use the following approach, what I should have written should have been:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;chown -R /var/www/.[^.]*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This command properly sets the hidden folders to the correct owners&lt;/p&gt;

&lt;p&gt;So now I ended up with a &lt;strong&gt;var&lt;/strong&gt; folder with a lot of messed up ownerships, so how to restore them.&lt;/p&gt;

&lt;p&gt;There are multiple ways to do it, although the only way to completly restore them as they were would require you to deploy on a virtual machine, and copy the properties, that is the surest way so they are restored correctly&lt;/p&gt;

&lt;h2 id=&#34;method-1-virtual-machine&#34;&gt;&lt;strong&gt;Method 1: Virtual Machine&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;Start installing you distribution on the virtual machine, and while you are waiting for the instalation to finish you need to prepeare some data needed for restoration of your machine.&lt;/p&gt;

&lt;p&gt;This doesn&amp;rsquo;t have to happen on your machine, you can easily create a virtual machine on any computer and use the data to restore your own.&lt;/p&gt;

&lt;p&gt;All the commands here are run as &lt;strong&gt;root&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We need a list of all your installed packages so they can be restored on the virtual machine, to get them, execute the following command&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;dpkg --get_selections &amp;gt; selections.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By now the machine should have finished installing, so let&amp;rsquo;s prepare some of the necessities, I use a pinning and a lot of repositores, including testing, unstable, stable, plus 3rd party repositories, so to do so we need to transfer the contents of &lt;strong&gt;/etc/apt&lt;/strong&gt; to the virtual machine, you should know how to transfer the files to the virtual machine.&lt;/p&gt;

&lt;p&gt;We also need to transfer the keys, because you can&amp;rsquo;t copy the keys we need to export them.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-key exportall &amp;gt; keys.gpg
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then transfer them to the virtual machine, and run the import for keys&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-key add keys.gpg
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you are using multiarch you will have to add the appropriate architecture into the system, in my case I&amp;rsquo;m using also &lt;strong&gt;i386&lt;/strong&gt; libraries for skype, so I executed this on my virtual machine&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;dpkg --add-architecture i386
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we need to install all the packages that are on our system, so let&amp;rsquo;s run the following commands on the virtual machine&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get update
dselect update
dpkg --set-selections &amp;lt; selections.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you can leave your virtual machine for a while, while it downloads all the packages and installs them.&lt;/p&gt;

&lt;p&gt;After the installation has finished you can reboot your system, and after it boots, we need to extract all the information so we can restore it successfully.&lt;/p&gt;

&lt;p&gt;On the virtual machine run the following command:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;find /var -printf &amp;quot;%m:%u:%g:%p\n&amp;quot; &amp;gt; /tmp/var.permissions.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you transfer the generated file &lt;strong&gt;/tmp/var.permissions.txt&lt;/strong&gt; to your machine, and you run the following script to restore everything as it was&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin.bash
while IFS=&amp;quot;:&amp;quot; read perms user group file; do 
chmod -R $perms $file &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
chown -R $user:$group $file &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
done &amp;lt; /tmp/var.permissions.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is one way to restore them and it&amp;rsquo;s probably the best way to restore them&lt;/p&gt;

&lt;h4 id=&#34;freebsd&#34;&gt;FreeBSD&lt;/h4&gt;

&lt;p&gt;If you have FreeBSD you can use &lt;strong&gt;mtree&lt;/strong&gt; to copy over the permissions and restore them, the first line creates a list of the permissions and owners the second one restores them&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mtree -c -k uname,gname,mode,time &amp;gt; /tmp/var.permissions.txt
mtree -U -f /tmp/var.permissions.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;method-2-from-the-debian-packages&#34;&gt;&lt;strong&gt;Method 2: From the debian packages&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;You can also restore permissions from the debian packages, but not the owners, as it doesn&amp;rsquo;t contain that information, it will restore them to how they are suppose to be when installing them the first time, but the permissions will be restored correctly.&amp;rsquo;&lt;/p&gt;

&lt;p&gt;There are two ways to do this, you can restore them from the debian cache which is located in &lt;strong&gt;/var/cache/apt/archives/&lt;/strong&gt;, but if you ever issued &lt;strong&gt;apt-get clean&lt;/strong&gt; you will not have all the packages there, or you can just download all the packages and restore them like that, the script will be the same for both approaches.&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s create a new folder in &lt;strong&gt;opt&lt;/strong&gt;, called &lt;strong&gt;restore&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir -p /opt/restore
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I called my script &lt;strong&gt;create_permissions_script.sh&lt;/strong&gt;, and I put it in &lt;strong&gt;/opt/restore&lt;/strong&gt;, it is designed to work from the local directory the script is in.&lt;/p&gt;

&lt;p&gt;This script reads all the packages, extracts the file list including permissions and owners, parses it and then stores it in a file so you can restore it.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/bash
# /opt/restore/create_permissions_script.sh
ARCHIVE_DIR=`pwd`
PACKAGES=`ls $ARCHIVE_DIR/*.deb`
cd $ARCHIVE_DIR

cd /

function changePerms()
{
  CHOWN=&amp;quot;/bin/chown&amp;quot;
  CHMOD=&amp;quot;/bin/chmod&amp;quot;
  PERMS=`echo $1 | sed -e &#39;s/--x/1/g&#39; -e &#39;s/-w-/2/g&#39; -e &#39;s/-wx/3/g&#39; -e &#39;s/r--/4/g&#39; -e &#39;s/r-x/5/g&#39; -e &#39;s/rw-/6/g&#39; -e &#39;s/rwx/7/g&#39; -e &#39;s/---/0/g&#39;` 
  FTYPE=`echo ${PERMS:0:1}`
  PERMS=`echo ${PERMS:1}`
  OWN=`echo $2 | /usr/bin/tr &#39;/&#39; &#39;.&#39;`
  PATHNAME=$3
  PATHNAME=`echo ${PATHNAME:1}`
 
  if [[ &amp;quot;d&amp;quot; = &amp;quot;$FTYPE&amp;quot; ]]; then
    echo &amp;quot;$CHOWN -R $OWN $PATHNAME&amp;quot; &amp;gt;&amp;gt; &amp;quot;${ARCHIVE_DIR}/dir_perms.sh&amp;quot;
    echo &amp;quot;$CHMOD $PERMS $PATHNAME&amp;quot; &amp;gt;&amp;gt; &amp;quot;${ARCHIVE_DIR}/dir_perms.sh&amp;quot;
  else
    echo &amp;quot;$CHOWN $OWN $PATHNAME&amp;quot; &amp;gt;&amp;gt; &amp;quot;${ARCHIVE_DIR}/file_perms.sh&amp;quot;
    echo &amp;quot;$CHMOD $PERMS $PATHNAME&amp;quot; &amp;gt;&amp;gt; &amp;quot;${ARCHIVE_DIR}/file_perms.sh&amp;quot;
  fi;

  #fi;
}

for PACKAGE in $PACKAGES;
do
  if [ -d $PACKAGE ]; then
    continue;
  fi
  echo &amp;quot;Getting information for $PACKAGE&amp;quot;
  FILES=`/usr/bin/dpkg -c &amp;quot;${PACKAGE}&amp;quot;`
  for FILE in &amp;quot;$FILES&amp;quot;;
  do
    echo &amp;quot;$FILE&amp;quot; | awk &#39;{print $1&amp;quot;\t&amp;quot;$2&amp;quot;\t&amp;quot;$6}&#39; | while read line;
    do
      changePerms $line
    done
  done
done

sort &amp;quot;${ARCHIVE_DIR}/dir_perms.sh&amp;quot; | uniq &amp;gt; &amp;quot;${ARCHIVE_DIR}/clean_dir_perms.sh&amp;quot;
sort &amp;quot;${ARCHIVE_DIR}/file_perms.sh&amp;quot; | uniq &amp;gt; &amp;quot;${ARCHIVE_DIR}/clean_file_perms.sh&amp;quot;

cat &amp;quot;${ARCHIVE_DIR}/clean_dir_perms.sh&amp;quot; &amp;quot;${ARCHIVE_DIR}/clean_file_perms.sh&amp;quot; &amp;gt; &amp;quot;${ARCHIVE_DIR}/restore_permissions.sh&amp;quot;
rm &amp;quot;${ARCHIVE_DIR}/clean_dir_perms.sh&amp;quot; &amp;quot;${ARCHIVE_DIR}/clean_file_perms.sh&amp;quot; &amp;quot;${ARCHIVE_DIR}/dir_perms.sh&amp;quot; &amp;quot;${ARCHIVE_DIR}/file_perms.sh&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This script will generate a new script called &lt;strong&gt;restore_permissions.sh&lt;/strong&gt;, which contains all the neccesseary commands like &lt;strong&gt;chown&lt;/strong&gt; and &lt;strong&gt;chmod&lt;/strong&gt; for all the directories and files, executing this script will correct all the ownerships and permissions as they need to be after installation of the package in question&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s download the packages, or if you choose to restore them from the cache folder you can skip this step, just copy over this script to the cache folder and you are done, if you are like me and you ocasionally clean up the folder, you will have to download all the packages first&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;dpkg --get-selections \* | awk &#39;{print $1}&#39; | xargs -l1 apt-get download 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Executing that line will download all the packages into the directory, as this will take a while, you can take a break.&lt;/p&gt;

&lt;p&gt;After all the packages finish downloading, you need to run the script for generating the permissions and owners, this will also take a while to read and process all debian packages&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;./create_permissions_script.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After this is finished you will see that you have a script called &lt;strong&gt;restore_permissions.sh&lt;/strong&gt;, and running it will restore the permissions&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;./restore_permissions.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;method-3-reinstalling-with-aptitude&#34;&gt;&lt;strong&gt;Method 3: Reinstalling with aptitude&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;You can reinstall all the packages using &lt;strong&gt;aptitude&lt;/strong&gt;, but this is a really slow process, but if you want to you can do like so&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;dpkg --get-selections \* | awk &#39;{print $1}&#39; | xargs -l1 aptitude reinstall
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Automatic zone replication with BIND9 in Plesk 11.5 &#43; Debian Wheezy &#43; PHP</title>
            <link>https://matoski.com/article/bind-slave-dns-automatic-additions-of-zones/</link>
            <pubDate>Sat, 19 Oct 2013 15:16:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/bind-slave-dns-automatic-additions-of-zones/</guid>
            <description>&lt;p&gt;This tutorial is aimed at showing how to set up zone replication from a master to a slave server, without the help of the user input on Debian Wheezy with Plesk 11.5 and PHP&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s decide how to call the servers we are gonna use in the setup.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;master&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Main server, that hosts Plesk and BIND9 DNS server in Master mode&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;slave&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Slave DNS server that hosts BIND9 DNS server in Slave mode&lt;/p&gt;

&lt;p&gt;To be able to get a list of available domains on the main server we need &lt;strong&gt;mysql-client&lt;/strong&gt;, on the DNS server, the reason for it is so we can get a list of domains from the primary server, so we can check if they exist or not so we can create them if necesseary.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s install the client and some other requirements on the &lt;strong&gt;slave&lt;/strong&gt; server, we can do so really easy by issuing the following command:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get install mysql-client php5-cli php-pear php5-mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once this is complete let&amp;rsquo;s go to the masters server and configure mysql to allow access from the &lt;strong&gt;slave&lt;/strong&gt; server.&lt;/p&gt;

&lt;p&gt;First thing first, let&amp;rsquo;s connect to the &lt;strong&gt;MySQL&lt;/strong&gt; server on the &lt;strong&gt;master&lt;/strong&gt; and create a user that will be only for viewing the domains records on the server.&lt;/p&gt;

&lt;p&gt;If you need passwords you can use &lt;strong&gt;pwgen&lt;/strong&gt; to generate random passwords, let&amp;rsquo;s generate 4 passwords with length 50.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ pwgen 50 4
aed6Chu5AiphieJaeteirawei7yohrahZ2zaig8Eey9gePh4jo
ohw0sheiPhae1yae0eeghiesh8aevee5aineiyequae8ookaev
noh4icaigh2weiGaiph3sahDoeThaequ5HeGha2oeMeezee6re
Xaeb3uN6nib5cae2yotooz5quai5zohx8OhSah7caeshu3xeQu
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s execute this SQL command to create a user for our case&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-sql&#34;&gt;CREATE USER &#39;dns&#39;@&#39;%&#39; identified by &#39;noh4icaigh2weiGaiph3sahDoeThaequ5HeGha2oeMeezee6re&#39;;
GRANT USAGE ON *.* TO &#39;dns&#39;@&#39;%&#39; with MAX_QUERIES_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_USER_CONNECTIONS 0;
GRANT SELECT ON psa.domains TO &#39;dns&#39;@&#39;%&#39;;
FLUSH PRIVILEGES;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These commands will enable you to query only the domains tables and nothing else, in case someone manages to find out the password they will only be able to query the domains we have.
In our case this will allow a connection from anywhere if identified by the password, if you want to be more restrictive you can always specify the &lt;strong&gt;IP&lt;/strong&gt; instead of &lt;strong&gt;%&lt;/strong&gt; in the SQL.&lt;/p&gt;

&lt;p&gt;Before we start we need to make sure we can add new zones in the system without restarting the server, to do so, we need to add to the options part of &lt;strong&gt;named.conf&lt;/strong&gt;, the option to allow new zones, so we edit the file and add the following option in the config file.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;allow-new-zones yes;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can use rndc to create, update, read, delete the zones&lt;/p&gt;

&lt;p&gt;Now, on to the next problem, we have the data, now we need to generate the zones when there is something new to add, we can do this by creating a script that is gonna run every 15 mins and query the dataset to check if there is new data that we need to input.
We can do this simply in PHP, at the moment this is simplest took me 4 mins to write the whole code, so let&amp;rsquo;s take a look at the finished script:&lt;/p&gt;

&lt;p&gt;The property &lt;strong&gt;parentDomainId&lt;/strong&gt;, which I use to check which domains are TLD, at the moment, this script has been running for ~30 days and so far no issues at all.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-php&#34;&gt;#!/usr/bin/env php
&amp;lt;?php
define(&amp;quot;PSA_USER&amp;quot;, &#39;dns&#39;);
define(&amp;quot;PSA_PASSWORD&amp;quot;, &#39;noh4icaigh2weiGaiph3sahDoeThaequ5HeGha2oeMeezee6re&#39;);
define(&amp;quot;PSA_DB&amp;quot;, &amp;quot;psa&amp;quot;);
define(&amp;quot;PSA_HOST&amp;quot;, &amp;quot;master&amp;quot;);
define(&amp;quot;BIND_VIEW&amp;quot;, &amp;quot;slave&amp;quot;);
define(&amp;quot;PSA_SQL&amp;quot;, &amp;quot;select name from domains where parentDomainId = 0&amp;quot;);
define(&amp;quot;LOCAL_DOMAIN_CACHE&amp;quot;, &amp;quot;/opt/zones.cache&amp;quot;);
define(&amp;quot;NS_IPS&amp;quot;, &amp;quot;10.0.0.1;&amp;quot;);
define(&amp;quot;TEMPLATE&amp;quot;, &amp;quot;%%domain%% &#39;{type slave; file \&amp;quot;slave/%%domain%%\&amp;quot;; masters { &amp;quot; . NS_IPS . &amp;quot; }; };&#39;&amp;quot;);

openlog(&amp;quot;slave.configurator.php&amp;quot;, LOG_PID | LOG_PERROR, LOG_LOCAL0);

$cache = array();

if (file_exists(LOCAL_DOMAIN_CACHE)) {
    $cache = json_decode(file_get_contents(LOCAL_DOMAIN_CACHE), true);
    if (is_null($cache)) {
        $cache = array();
    }
}

$link = mysqli_connect(PSA_HOST, PSA_USER, PSA_PASSWORD, PSA_DB) or die(&amp;quot;Error &amp;quot; . mysqli_error($link));

if (!$link) {
    $err = mysqli_error($link);
    syslog(LOG_ERR, $err);
    die(&amp;quot;Error: $err&amp;quot;);
}

$result = $link-&amp;gt;query(PSA_SQL);

$database_domains = array();

while ($domain = mysqli_fetch_assoc($result)) {
    array_push($database_domains, $domain[&#39;name&#39;]);
}

$process = array_diff($database_domains, $cache);
$full = array_unique(array_merge($database_domains, $process));

file_put_contents(LOCAL_DOMAIN_CACHE, json_encode($full));

$format = &amp;quot;Y-m-d H:i:s - &amp;quot;;

syslog(LOG_INFO,
        date($format, microtime(true)) . &amp;quot;Total available domains in cache: &amp;quot; . count($cache));
syslog(LOG_INFO,
        date($format, microtime(true)) . &amp;quot;Total available domains in database: &amp;quot; . count($database_domains));
syslog(LOG_INFO,
        date($format, microtime(true)) . &amp;quot;Difference elements between cache and database: &amp;quot; . count($process) . &amp;quot;, domains: &amp;quot; . (count($process) &amp;gt; 0 ? join(&amp;quot;,&amp;quot;,
                        $process) : &amp;quot;None available&amp;quot;));
syslog(LOG_INFO,
        date($format, microtime(true)) . &amp;quot;Total domains in system: &amp;quot; . count($full));

if (count($process) &amp;gt; 0) {
    foreach ($process as $domain) {
        echo date($format, microtime(true)) . &amp;quot;Processing domain: $domain\n&amp;quot;;
        $template = str_replace(&amp;quot;%%domain%%&amp;quot;, $domain, TEMPLATE);
        syslog(LOG_INFO, &amp;quot;/usr/sbin/rndc addzone $template&amp;quot;);
        exec(&amp;quot;/usr/sbin/rndc addzone $template&amp;quot;);
    }
    exec(&amp;quot;/usr/sbin/rndc reload&amp;quot;);
} else {
    syslog(LOG_INFO, date($format, microtime(true)) . &amp;quot;Nothing to process.&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;NS_IPS&lt;/strong&gt;, is a &lt;strong&gt;;&lt;/strong&gt; separated list of all your nameservers, you should put your IP of your master nameserver here, in the demo script I put &lt;strong&gt;10.0.0.1&lt;/strong&gt;, but you should replace it with your own master nameserver, the IP should always have a &lt;strong&gt;;&lt;/strong&gt; at the end of the IP in the script it was  &lt;strong&gt;10.0.0.1;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If &lt;strong&gt;/usr/sbin/rndc&lt;/strong&gt; is not the correct path for &lt;strong&gt;rndc&lt;/strong&gt;, you should change the script accordingly;&lt;/p&gt;

&lt;p&gt;Now you can add it to crontab this script I saved mine under &lt;strong&gt;/opt/slave.configurator.php&lt;/strong&gt;, and my crontab entry is like so, I run this script under root.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-crontab&#34;&gt;*/15 * * * * /opt/slave.configurator.php
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Just don&amp;rsquo;t forget to run:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;chmod +x /opt/slave.configurator.php
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Generating DomainKeys for Mail</title>
            <link>https://matoski.com/article/generate-domainkeys/</link>
            <pubDate>Thu, 10 Oct 2013 23:47:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/generate-domainkeys/</guid>
            <description>&lt;p&gt;We need to generate DK (DomainKeys) to validate that we are the original senders and not someone impersonating us, this tutorial is meant to explain how generate the keys&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;To generate a DomainKeys record we can do simply from the command line.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;openssl genrsa -out default 1024
openssl  rsa -in default -out txt -pubout -outform PEM
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will create two files that will contain the private and the public key that we can put in the DNS zone record, let&amp;rsquo;s check the files what they contain.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cat default

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCvcvkiUaVlHZNDo7grpSh+SLc8L5yZMg34uysFdc8HNWB/bbx9
lEMUj2/n/1qlj+AYcisMIpCGGK+LrrGig65x7OH31mpxWjj8zfKNtGzSjdBzgbL+
kMZi21VpoJ8BP/R9oGrJf4woZ/arZUmlzKpTsNqw7RCvNJ55OCAi2jcJWQIDAQAB
AoGBAJfzw8HtZInGq5yRVxi12fRFli0SL1ae+2rI7+GyvrNHj2PN7sn0doSAFjOf
/SoXCcciWhYQeYsqJh+cFUzjL1kc7NqqI8rX36L49G+ur87AJFDYsz851OCly9JN
9rAe36Dv7BToE+hC0cqT7u5bNjKEimNNHsdprQlRm6RiFbABAkEA1Oalhe5GGjsy
ICO7X5JCyF7QI0yjLPY4cP9hHvgS+WPT5/IciQIUKmV2T6+TS48nFgAU5euFjepZ
Bzq4KzhHmQJBANL3bTMoVB0yh8fckN12KFx34DdOCclBqu0vNXTNcEoHspAJhaa5
DlQuZCUursPDwibBv/exWx4BgfFMOQJe58ECQCP/T5Nio1XCFoqaoA7bwxDv/w9I
4Po0M3zfoUNEPKkQOP8pz6tWv6Qffa6hiC0pajltEBuEBBPnwN/ZDNS58lkCQHMc
HFJQi+zOeHXd7JFZ+lXR9t5WT1Kn6Qq3upQ70CwknRKoj2tUB/R4x53eJe+dLZ+W
EhelhxENQ4iUzXp0rEECQEJIsNDQIeDcOyMKy1TOKFwG2TFvvIqDlM7+2NKucmcy
Re2q6DPYpksiJVY/2EAtYqsBAEztVb38bakbY5EUmp0=
-----END RSA PRIVATE KEY-----
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And let&amp;rsquo;s check the txt file&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cat txt

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvcvkiUaVlHZNDo7grpSh+SLc8
L5yZMg34uysFdc8HNWB/bbx9lEMUj2/n/1qlj+AYcisMIpCGGK+LrrGig65x7OH3
1mpxWjj8zfKNtGzSjdBzgbL+kMZi21VpoJ8BP/R9oGrJf4woZ/arZUmlzKpTsNqw
7RCvNJ55OCAi2jcJWQIDAQAB
-----END PUBLIC KEY-----
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From this you can see that we have a public and a private key, the private one we keep for us, if someone has the private key, they can sign as us.&lt;/p&gt;

&lt;p&gt;To convert the &lt;strong&gt;txt&lt;/strong&gt; file to a format suitable for DNS record we need to copy the key, and delete all the new lines&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvcvkiUaVlHZNDo7grpSh+SLc8L5yZMg34uysFdc8HNWB/bbx9lEMUj2/n/1qlj+AYcisMIpCGGK+LrrGig65x7OH31mpxWjj8zfKNtGzSjdBzgbL+kMZi21VpoJ8BP/R9oGrJf4woZ/arZUmlzKpTsNqw7RCvNJ55OCAi2jcJWQIDAQAB
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we just prepend the value &lt;strong&gt;p=&lt;/strong&gt; and append &lt;strong&gt;;&lt;/strong&gt; and we have our key that we can put in a DNS zone&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s see the complete record now:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;_domainkey.example.com.	         IN TXT	 &amp;quot;o=-&amp;quot;
default._domainkey.example.com.  IN TXT	 &amp;quot;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvcvkiUaVlHZNDo7grpSh+SLc8L5yZMg34uysFdc8HNWB/bbx9lEMUj2/n/1qlj+AYcisMIpCGGK+LrrGig65x7OH31mpxWjj8zfKNtGzSjdBzgbL+kMZi21VpoJ8BP/R9oGrJf4woZ/arZUmlzKpTsNqw7RCvNJ55OCAi2jcJWQIDAQAB;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Setting up SPF &#43; DK &#43; DKIM with Postfix in Plesk 11.5 on Debian Wheezy</title>
            <link>https://matoski.com/article/spf-dk-dkim-plesk-debian/</link>
            <pubDate>Thu, 10 Oct 2013 12:55:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/spf-dk-dkim-plesk-debian/</guid>
            <description>&lt;p&gt;Shows up a detailed process on how to set up SPF + DK + DKIM with Postfix in Plesk 11.5 on Debian Wheezy, step by step, and how to test to make sure everything is working correctly&lt;/p&gt;

&lt;p&gt;I leased a dedicated server from &lt;a href=&#34;http://hetzner.de&#34;&gt;Hetzner&lt;/a&gt;, and I got the Plesk option, for administration, so I don&amp;rsquo;t have to bother with administration, but turns out I&amp;rsquo;m not so lucky, I&amp;rsquo;ve ran into a lot of issues with using Plesk, so I had to do my own fixes.&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s take a look at how we can integrate SPF + DK + DKIM with Postfix in Plesk 11.5 on Debian Wheezy.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;First things, first, if you are using QMail switch to Postfix, to install Postfix you can either use the GUI, or you can do it from a console.&lt;/p&gt;

&lt;p&gt;Here is how to do it from the console.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;/usr/local/psa/admin/sbin/autoinstaller --select-release-current --install-component postfix
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&#34;spf&#34;&gt;SPF&lt;/h1&gt;

&lt;p&gt;Let&amp;rsquo;s open the DNS Template, you will see there that, there is an entry for SPF&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;v=spf1 +a +mx -all
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This means the SPF is enabled on our domain.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s modify it a little bit to be better, if you are gonna host multiple domains from your server, then you should probably modify it too.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;v=spf1 +a +mx +ip4:&amp;lt;ip.mail&amp;gt; ?all
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;ip.mail&amp;gt;&lt;/code&gt; - Is the IP of the mail server that is responsible for sending the mails, it is automatically filled in when you apply the zones&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After you do this modification you should apply it&lt;/p&gt;

&lt;p&gt;So now my configuration looks like this:

&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;spf-dns-template.png&#34; alt=&#34;SPF DNS Template&#34; /&gt;
    
    
&lt;/figure&gt;
&lt;/p&gt;

&lt;p&gt;Now let&amp;rsquo;s check with dig if the SPF is OK.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;dig myserverplace.de TXT @ns1.myserverplace.de
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You will see in the Answer section I have the following entry&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;myserverplace.de.	600	IN	TXT	&amp;quot;v=spf1 +a +mx +ip4:144.76.163.46 ?all&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So everything is ok, next onto DomainKeys&lt;/p&gt;

&lt;h1 id=&#34;domainkeys&#34;&gt;DomainKeys&lt;/h1&gt;

&lt;p&gt;First let&amp;rsquo;s activate DomainKeys, take a look at the screenshot, and compare my options with yours.&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;plesk-panel-dk-enabled.png&#34; alt=&#34;Plesk Panel DK Enabled&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;Ok, now that this has been enabled, let&amp;rsquo;s go and enable for the domain in question, if it was already checked, uncheck it press OK, and then check it again and press OK, this is so it will regenerate the DomainKeys data in the DNS zone, as I&amp;rsquo;ve had some problems with the data not present in the DNS zone file&lt;/p&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;enable-dk-domain.png&#34; alt=&#34;Enable DK Domain&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;OK, now let&amp;rsquo;s see if the correct data is there, usually it takes a long time for DNS to propagate between 24-48h, there is a simple way to test if the data is there, by querying the Nameserver that hosts your DNS zone, in my case I host my own Nameserver&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;dig _domainkey.myserverplace.de TXT @ns1.myserverplace.de
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You will see in the Answer section I have the following entry&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;_domainkey.myserverplace.de. 600 IN	TXT	&amp;quot;o=-&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s see if the DomainKey is there too&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;dig default._domainkey.myserverplace.de TXT @ns1.myserverplace.de
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the Answer section you should see something like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;default._domainkey.myserverplace.de. 600 IN TXT	&amp;quot;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAruBNqdsSCKBLwMrFNNKH8z0e7zmlAic7iRoJsDDJK3IlnW8j6G/T6a93m+jqYc6R38MBAZbeSv2LQJ0SepJEsr4Iqk41WFXPBKnyXReO1RXPW5/YnRe6dpJMEqsmPpl2TjInY7ve/6VCiVDOHn9RRrdB+x7CGeK2crgqSZVlFwIDAQAB\;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see everything is in place now for DomainKeys to work, now let&amp;rsquo;s continue on to DKIM&lt;/p&gt;

&lt;h1 id=&#34;dkim-domainkeys-identified-mail&#34;&gt;DKIM (DomainKeys Identified Mail)&lt;/h1&gt;

&lt;p&gt;As always lets update the system first&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;aptitude update
aptitude safe-upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we need to install the DKIM filter, or as it&amp;rsquo;s called now &lt;a href=&#34;http://opendkim.org&#34;&gt;OpenDKIM&lt;/a&gt;, for full specification take a look at their site.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;aptitude install opendkim opendkim-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we need to create the necessary folders so OpenDKIM can work proplery&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir -pv /etc/opendkim/keys
chown -Rv opendkim:opendkim /etc/opendkim
chmod go-rwx /etc/opendkim/*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will create the directory where we will hold the keys for OpenDKIM, after this step let&amp;rsquo;s take a look at how the process will look like, so we can create a script to automate this.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir -p /etc/opendkim/keys/myserverplace.de
cd /etc/opendkim/keys/myserverplace.de
opendkim-genkey -d myserverplace.de -s mail
chown -Rv opendkim:opendkim /etc/opendkim/keys/myserverplace.de
chmod -v u=rw,go-rwx *
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This easily understandble, what happens here.&lt;/p&gt;

&lt;p&gt;Now you have two files &lt;strong&gt;/etc/opendkim/keys/myserverplace.de&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ls -lah /etc/opendkim/keys/myserverplace.de
total 16K
drwxr-xr-x 2 opendkim opendkim 4.0K Oct  9 18:43 .
drwxr-xr-x 5 opendkim opendkim 4.0K Oct  9 19:39 ..
-rw------- 1 opendkim opendkim  887 Oct  9 18:43 mail.private
-rw------- 1 opendkim opendkim  303 Oct  9 18:43 mail.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;/etc/opendkim/keys/myserverplace.de/mail.private&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;contains the RSA PRIVATE KEY&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;/etc/opendkim/keys/myserverplace.de/mail.txt&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contains the record you need to add to your DNS zone&lt;/p&gt;

&lt;p&gt;Next set is to setup the key tables, signing tables, and trusted hosts&lt;/p&gt;

&lt;p&gt;First let&amp;rsquo;s prepare the files&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;touch /etc/opendkim/KeyTable
touch /etc/opendkim/SigningTable
touch /etc/opendkim/TrustedHosts
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;/etc/opendkim/TrustedHosts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;needs to contain some data before we continue, so add the following information to this file, and adjust accordingly&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;127.0.0.1
localhost
144.76.163.46
144.76.163.57
ns1.myserverplace.de
ns2.myserverplace.de
myserverplace.de
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let&amp;rsquo;s see what does what:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;/etc/opendkim/KeyTable&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;KeyID Domain:Selector:PathToPrivateKey&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;/etc/opendkim/SigningTable&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The filter used is programmed to read the table by looking for matched domain&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;/etc/opendkim/TrustedHosts&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It will list the top trusted hosts as you desire&lt;/p&gt;

&lt;p&gt;Those three files contain all the necessary information for the signing to work.&lt;/p&gt;

&lt;p&gt;So in my case for my domain I do.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;quot;myserverplace.de myserverplace.de:mail:/etc/opendkim/keys/myserverplace.de/mail.private&amp;quot; &amp;gt;&amp;gt; /etc/opendkim/KeyTable
echo &amp;quot;*@myserverplace.de myserverplace.de&amp;quot; &amp;gt;&amp;gt; /etc/opendkim/SigningTable
echo &amp;quot;myserverplace.de&amp;quot; &amp;gt;&amp;gt; /etc/opendkim/TrustedHosts
echo &amp;quot;mail.myserverplace.de&amp;quot; &amp;gt;&amp;gt; /etc/opendkim/TrustedHosts
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So let&amp;rsquo;s put all this together in a script so we don&amp;rsquo;t have to do it all the time&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/bash
# /opt/generatedkim.sh
die () {
    echo &amp;gt;&amp;amp;2 &amp;quot;$@&amp;quot;
    exit 1
}

[ &amp;quot;$#&amp;quot; -eq 1 ] || die &amp;quot;1 argument required, $# provided, domain required, ex: ./script example.com&amp;quot;

cwd=`pwd`
opendkim=&amp;quot;/etc/opendkim&amp;quot;
location=&amp;quot;$opendkim/keys/$1&amp;quot;
[ -d &amp;quot;$location&amp;quot; ] &amp;amp;&amp;amp; die &amp;quot;There is already a directory in the folder, delete the folder if you want to create a new one&amp;quot;

mkdir -p &amp;quot;$location&amp;quot;
cd &amp;quot;$location&amp;quot;
opendkim-genkey -d $1 -s mail
chown opendkim:opendkim *
chown opendkim:opendkim &amp;quot;$location&amp;quot;
chmod u=rw,go-rwx *
echo &amp;quot;$1 $1:mail:$location/mail.private&amp;quot; &amp;gt;&amp;gt; &amp;quot;$opendkim/KeyTable&amp;quot;
echo &amp;quot;*@$1 $1&amp;quot; &amp;gt;&amp;gt; &amp;quot;$opendkim/SigningTable&amp;quot;
echo &amp;quot;$1&amp;quot; &amp;gt;&amp;gt; &amp;quot;$opendkim/TrustedHosts&amp;quot;
echo &amp;quot;mail.$1&amp;quot; &amp;gt;&amp;gt; &amp;quot;$opendkim/TrustedHosts&amp;quot;
echo
echo &amp;quot;Put this in the DNS ZONE for domain: $1&amp;quot;
echo
cat &amp;quot;$location/mail.txt&amp;quot;
echo
cd &amp;quot;$cwd&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So if we run the script, we should get output like this, and this is the data we need to put in the DNS zone.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;/opt/generatedkim.sh test.de

Put this in the DNS ZONE for domain: test.de

mail._domainkey IN TXT &amp;quot;v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPzE0GmvFwAQsgcFzopy4zMNWUbL6JM5XIyjBy3bUnANI5axeb/Lw/GBjUoSFLEiO80Tt8m3A5YrBKcodRQQURYiW6/YtElhLupHyfcxQhfNLU4z9JUOJKPjcpMZCj0Xv873QgVOl+7U605JdBHSPOx4ybBZwDq68cw9YFYRPmEwIDAQAB&amp;quot; ; ----- DKIM key mail for test.de
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Unfortunatly I don&amp;rsquo;t have time to create a script to do this automatically, you can always insert a record in MySQL database so it&amp;rsquo;s in the ZONE and you can regenerate the DNS Zone from the command line, and I won&amp;rsquo;t be having a lot of domains, so I can add this entry manually to a domain I want DKIM enabled&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s open the domain and go to DNS Settings, and you can click ** &lt;em&gt;Add Resource&lt;/em&gt; **&lt;/p&gt;

&lt;p&gt;You popuplate the following data in the inputboxes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Record type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TXT&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Domain name&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;mail._domainkey&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TXT Record&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the text record you copy a part of the contents from the file &lt;strong&gt;/etc/opendkim/keys/myserverplace.de/mail.txt&lt;/strong&gt;, it data should start from &lt;strong&gt;v=DKIM1; k=rsa;&lt;/strong&gt; to the end, without the quotes as you can see it&amp;rsquo;s in quotes.&lt;/p&gt;

&lt;p&gt;In the example above for domain test.de you add only the following contents in the input box&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPzE0GmvFwAQsgcFzopy4zMNWUbL6JM5XIyjBy3bUnANI5axeb/Lw/GBjUoSFLEiO80Tt8m3A5YrBKcodRQQURYiW6/YtElhLupHyfcxQhfNLU4z9JUOJKPjcpMZCj0Xv873QgVOl+7U605JdBHSPOx4ybBZwDq68cw9YFYRPmEwIDAQAB
&lt;/code&gt;&lt;/pre&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;dkim-add-dns-zone.png&#34; alt=&#34;DKIM Add DNS Zone&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;p&gt;Well that&amp;rsquo;s it for this, now let&amp;rsquo;s check with dig if the record is there&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;dig mail._domainkey.myserverplace.de TXT @ns1.myserverplace.de
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You will see in the Answer section I have the following entry&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mail._domainkey.myserverplace.de. 600 IN TXT	&amp;quot;v=DKIM1\; k=rsa\; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMziMcgPTWK0kSUKxrgHHzEiWxNkZ2/M0Ugyr/8H9WtoCsJUM+Bc1C9VwqJ6yjTidecDrX7aL0lFZ9Mylku/wtSiPw6KLxMg2LG2vrMzlPTB2lmJNmg/EOu3KPC8BtAuOhXfwVH/ttQbzdKJKWqiCJn7jhF5oqEKnOCORxOQXKIwIDAQAB&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well everything is setup up at least from the DNS side, now we need to configure Postfix to use this data and sign the emails.&lt;/p&gt;

&lt;p&gt;You can also use the following URLs to check the validity of your key&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.protodave.com/tools/dkim-key-checker&#34;&gt;dkim-key-checker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://dkimcore.org/tools/&#34;&gt;DKIM Core Tool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the selector fields try with both &lt;strong&gt;mail&lt;/strong&gt;, and &lt;strong&gt;default&lt;/strong&gt;, you shold be getting valid results&lt;/p&gt;

&lt;h1 id=&#34;opendkim&#34;&gt;OpenDKIM&lt;/h1&gt;

&lt;p&gt;We need to edit the configuration file to configure DKIM, open &lt;strong&gt;/etc/opendkim.conf&lt;/strong&gt; with your favorite editor and add the following lines to the end of the file&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Enable Logging
Syslog yes
SyslogSuccess yes
LogWhy yes

# User mask
UMask 002

# Always oversign From (sign using actual From and a null From to prevent malicious signatures header fields (From and/or others) between the signer and the verifier)
OversignHeaders From

# Our KeyTable and SigningTable
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable

# Trusted Hosts
ExternalIgnoreList /etc/opendkim/TrustedHosts
InternalHosts /etc/opendkim/TrustedHosts

# Hashing Algorithm
SignatureAlgorithm rsa-sha256

# Auto restart when the failure occurs. CAUTION: This may cause a tight fork loops
AutoRestart Yes

# Set the user and group to opendkim user
UserID opendkim:opendkim

# Specify the working socket
Socket inet:8891@localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;rsquo;s it for OpenDKIM, now we should restart the service&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;service opendkim restart
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&#34;postfix&#34;&gt;Postfix&lt;/h1&gt;

&lt;p&gt;Now let&amp;rsquo;s see what we need to do to configure Postfix to use OpenDKIM.&lt;/p&gt;

&lt;p&gt;Execute the following command to see the milters configured&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cat /etc/postfix/main.cf | grep &amp;quot;milters&amp;quot;
smtpd_milters = , inet:127.0.0.1:12768
non_smtpd_milters = , inet:127.0.0.1:12768
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see that we have additional milters we need to put, this one is from the process &lt;strong&gt;psa-pc-remote&lt;/strong&gt;, and it&amp;rsquo;s part of Plesk&lt;/p&gt;

&lt;p&gt;Open &lt;strong&gt;/etc/postfix/main.cf&lt;/strong&gt; with your favorite editor, and add the following to the end of the file&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# OpenDKIM
milter_default_action = accept
milter_protocol = 6
smtpd_milters = , inet:127.0.0.1:8891, inet:127.0.0.1:12768
non_smtpd_milters = $smtpd_milters
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see we added the OpenDKIM milter too, and &lt;strong&gt;milter_protocol&lt;/strong&gt; is set to &lt;strong&gt;6&lt;/strong&gt;, this is important, if it&amp;rsquo;s not set to &lt;strong&gt;6&lt;/strong&gt;, the &lt;strong&gt;psa-pc-remote&lt;/strong&gt; process will segfault like so,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;psa-pc-remote[18523]: segfault at 0 ip 00007fa5be18c034 sp 00007fa5bccffd30 error 4 in libc-2.13.so[7fa5be123000+180000]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And your messages won&amp;rsquo;t be signed with &lt;strong&gt;DomainKey&lt;/strong&gt;, only with &lt;strong&gt;DKIM&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;service postfix restart
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&#34;testing&#34;&gt;Testing&lt;/h1&gt;

&lt;p&gt;There is an easy way to test if everything is correct, create an email account if you haven&amp;rsquo;t already and send a test mail to the following recepients, and the results are cut down because the text is too big&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;check-auth@verifier.port25.com&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code&gt;==========================================================
Summary of Results
==========================================================
SPF check:          pass
DomainKeys check:   pass
DKIM check:         pass
Sender-ID check:    pass
SpamAssassin check: ham
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;AAAA3QcKCQwA@appmaildev.com&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code&gt;============================================================
SPF result: Pass
============================================================
Domain: myserverplace.de
IP: 144.76.163.46

SPF Record: myserverplace.de
        IN TXT = &amp;quot;v=spf1 +a +mx 144.76.163.46 ?all&amp;quot;

============================================================
DomainKey result: pass
============================================================
Signed by: admin@myserverplace.de

PublicKey: default._domainkey.myserverplace.de
        IN TXT = &amp;quot;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAruBNqdsSCKBLwMrFNNKH8z0e7zmlAic7iRoJsDDJK3IlnW8j6G/T6a93m+jqYc6R38MBAZbeSv2LQJ0SepJEsr4Iqk41WFXPBKnyXReO1RXPW5/YnRe6dpJMEqsmPpl2TjInY7ve/6VCiVDOHn9RRrdB+x7CGeK2crgqSZVlFwIDAQAB;&amp;quot;

============================================================
DKIM result: pass
============================================================
Signed by: admin@myserverplace.de
Expected Body Hash: frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN/XKdLCPjaYaY=

PublicKey: mail._domainkey.myserverplace.de
        IN TXT = &amp;quot;v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMziMcgPTWK0kSUKxrgHHzEiWxNkZ2/M0Ugyr/8H9WtoCsJUM+Bc1C9VwqJ6yjTidecDrX7aL0lFZ9Mylku/wtSiPw6KLxMg2LG2vrMzlPTB2lmJNmg/EOu3KPC8BtAuOhXfwVH/ttQbzdKJKWqiCJn7jhF5oqEKnOCORxOQXKIwIDAQAB;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&#34;logs&#34;&gt;Logs&lt;/h1&gt;

&lt;p&gt;You can check the following locations to see if there are errors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/var/log/mail.err&lt;/li&gt;
&lt;li&gt;/var/log/mail.warn&lt;/li&gt;
&lt;li&gt;/var/log/mail.info&lt;/li&gt;
&lt;li&gt;/var/log/syslog&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&#34;note&#34;&gt;Note&lt;/h1&gt;

&lt;p&gt;Make sure you enable testing mode for DKIM if you plan to test, you can also cut down the EXPIRY time so the results propagate faster, so to enable testing mode set the key &lt;strong&gt;&lt;code&gt;_domainkey&lt;/code&gt;&lt;/strong&gt; to &lt;strong&gt;&lt;code&gt;t=y; o=-&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h1 id=&#34;references&#34;&gt;References&lt;/h1&gt;

&lt;p&gt;&lt;a href=&#34;http://kb.parallels.com/en/5801&#34;&gt;How to define what MTA is used in Parallels Plesk Panel and how to switch from Qmail to Postfix and back?&lt;/a&gt;&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Debian Backup with Tartarus</title>
            <link>https://matoski.com/article/debian-backup-tartarus/</link>
            <pubDate>Thu, 03 Oct 2013 19:04:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/debian-backup-tartarus/</guid>
            <description>&lt;p&gt;How to backup a Debian/Ubuntu server with Tartarus, and why is this usefull for us&lt;/p&gt;

&lt;p&gt;Why do you need this, if you are like me and like to experiment a lot, you will end up breaking your server a lot of times, so this will enable you to restore your server fast and easy.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;To be able to use Tartarus first we need to install it, so let&amp;rsquo;s issue the following commands.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;wget -O /etc/apt/sources.list.d/wertarbyte.list http://wertarbyte.de/apt/wertarbyte-apt.list
wget -O - http://wertarbyte.de/apt/software-key.gpg | apt-key add -
apt-get update
apt-get install tartarus tar bzip2 lvm2 gnupg curl
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will add and install the application on your server and some extra applications needed.
Now we need to create the required directories for tartarus.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir /etc/tartarus
mkdir -p /var/spool/tartarus/timestamps
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let&amp;rsquo;s create a passphrase file, we can do this by executing the command&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;pwgen -s 50 1 &amp;gt; /etc/tartarus/backup.sec
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That command will create a file that contains a random generated password, you can just do&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cat /etc/tartarus/backup.sec
JvXqwrouhnV1xaGS563N1ivvmgevUaCVLX13kHkYUmJH6gCiql
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So you can see that we have gotten a random secure password.
Next thing, we need to setup a general configuration, that all the other configurations are gonna extend from.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;touch /etc/tartarus/generic.inc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now open it up in your favorite editor, and adjust your settings to match.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;STORAGE_FTP_SSL_INSECURE=&amp;quot;yes&amp;quot;
STORAGE_METHOD=&amp;quot;FTP&amp;quot;
STORAGE_FTP_SERVER=&amp;quot;&amp;lt;FTP SERVER&amp;gt;&amp;quot;
STORAGE_FTP_USER=&amp;quot;&amp;lt;FTP USER&amp;gt;&amp;quot;
STORAGE_FTP_PASSWORD=&amp;quot;&amp;lt;PUT YOUR FTP PASSWORD HERE&amp;gt;&amp;quot;
STORAGE_FTP_USE_SFTP=&amp;quot;yes&amp;quot;

COMPRESSION_METHOD=&amp;quot;bzip2&amp;quot;
STAY_IN_FILESYSTEM=&amp;quot;yes&amp;quot;

ENCRYPT_SYMMETRICALLY=&amp;quot;yes&amp;quot;
ENCRYPT_PASSPHRASE_FILE=&amp;quot;/etc/tartarus/backup.sec&amp;quot;

TARTARUS_POST_PROCESS_HOOK() {
    echo -n &amp;quot;$STORAGE_FTP_PASSWORD&amp;quot; | /usr/sbin/charon.ftp \
    --host &amp;quot;$STORAGE_FTP_SERVER&amp;quot; \
    --user &amp;quot;$STORAGE_FTP_USER&amp;quot; --readpassword \
    --maxage 7 \
    --dir &amp;quot;$STORAGE_FTP_DIR&amp;quot; --profile &amp;quot;$NAME&amp;quot;
}

TARTARUS_DEBUG_HOOK() {
    echo $DEBUGMSG | logger
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So this is the generic file from which everyone will extend.
Now we have everything, all the variables are set, and we an create our first backup script.
Let&amp;rsquo;s create a complete root backup.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;touch /etc/tartarus/root.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After opening in your favorite editor add the following lines&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;source /etc/tartarus/generic.inc
NAME=&amp;quot;root&amp;quot;
DIRECTORY=&amp;quot;/&amp;quot;
EXCLUDE=&amp;quot;/tmp/ /proc/ /sys/ /var/tmp/ /var/run/ /var/lib/mysql/&amp;quot;
CREATE_LVM_SNAPSHOT=&amp;quot;no&amp;quot;
INCREMENTAL_STACKING=&amp;quot;yes&amp;quot;
INCREMENTAL_TIMESTAMP_FILE=&amp;quot;/var/spool/tartarus/timestamps/root&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see we excluded some of the directories for backup.
Let&amp;rsquo;s explain some of the options, for a full list of options you can check them at &lt;a href=&#34;http://wertarbyte.de/tartarus/doc/tartarus.txt&#34;&gt;Tartarus&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;INCREMENTAL_TIMESTAMP_FILE&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everytime a full backup is successfully completed, Tartarus willtouch the file specified here as a reference point for future incremental backups.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;INCREMENTAL_STACKING&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this option enabled, Tartarus will also update the flagfile after completing a successfull partial (differential/incremental) backup run. By that, incremental backups are &amp;ldquo;stacked&amp;rdquo; on each other instead of being based on the most recent full backup.&lt;/p&gt;

&lt;p&gt;Now let&amp;rsquo;s create a backup script that we gonna put into cron to run everyday.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;touch /usr/local/sbin/tartarus-backup.sh
chmod u+x /usr/local/sbin/tartarus-backup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And with your editor add the following contents&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/sh
# /usr/local/sbin/tartarus-backup.sh
# Run all backup profile found in /etc/tartarus/ and pass
# command line arguments on to tartarus (e.g. -i)
for profile in /etc/tartarus/*.conf; do
 /usr/sbin/tartarus $* &amp;quot;$profile&amp;quot;
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So in crontab we add the following, so it will do a full backup every sunday, and from monday to saturday incremental backup&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;crontab -e
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And copy paste the following entries&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-cron&#34;&gt;0 1 * * mon-sat /usr/local/sbin/tartarus-backup.sh -i
0 1 * * sun /usr/local/sbin/tartarus-backup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When you do a&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;crontab -l
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should be able to see them in the output
OK, so beacuse this is the first time, let&amp;rsquo;s run the backup script so it creates full backups&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;/usr/local/sbin/tartarus-backup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&#34;restoring-a-backup&#34;&gt;Restoring a backup&lt;/h1&gt;

&lt;p&gt;Since tartarus is based on linux utilities, restoring a backup from a rescue system is extremely easy, in case of incremental stacking you will need to extract all the files in the order they were created, you still use the same command to extract them.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir /mnt/restore
curl ftp://USER:PASS@YOURSERVER/DIR/FILE | gpg --decrypt | tar xpvj -C /mnt/restore
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Your backup is restored in the directory &lt;strong&gt;/mnt/restore&lt;/strong&gt;&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Activate maintenance mode manually in WordPress</title>
            <link>https://matoski.com/article/activate-maintenance-mode-manually-wordpress/</link>
            <pubDate>Mon, 30 Sep 2013 12:23:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/activate-maintenance-mode-manually-wordpress/</guid>
            <description>&lt;p&gt;In the previous post I wrote about how to transfer my own WordPress blog, to a static generated site using Wintersmith, but now, I need to take down the blog, so first thing, first, we need to create backup of the database and content I have uploaded on the system. So lets see how we can do it.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I needed to put my WordPress into maintenance mode, so I can create a backup of my database, as I don&amp;rsquo;t want to lose all the information it has, like users, posts, comments, content, and so on.&lt;/p&gt;

&lt;p&gt;The first step was to put the blog into maintenance mode, to do so, we can do fairly easily, the only thing we need to do is create a file called &lt;strong&gt;.maintenance&lt;/strong&gt; in the root of the blog folder.&lt;/p&gt;

&lt;p&gt;To do so we can execute the following command:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;quot;&amp;lt;?php \$upgrading = time(); ?&amp;gt;&amp;quot; &amp;gt; .maintenance
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will create the file with the necesseary contents for the blog to be in maintenance mode. So now your site should be in maintenance mode for a while or until you remove the file.&lt;/p&gt;

&lt;p&gt;The function uses the following sum to work out how long to stay in maintenance mode for&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;The time now = The time specified – 10 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So in the above example when we are using the time() function the sum will always be within 10 minutes.&lt;/p&gt;

&lt;p&gt;If you want you can also just supply the time in unix timestamp for when you want the in the future, let&amp;rsquo;s say in &lt;strong&gt;Sun, 20 Oct 2030 10:30:00 GMT&lt;/strong&gt; so in that case you can create the file like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;quot;&amp;lt;?php \$upgrading = 1918723200; ?&amp;gt;&amp;quot; &amp;gt; .maintenance
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you want to stop maintenance mode, it&amp;rsquo;s really simple, just delete the file and the maintenance mode is over, and the blog will continue functioning‎ as normal&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Migration from Wordpress to Wintersmith static site generator</title>
            <link>https://matoski.com/article/migration-wordpress-to-wintersmith/</link>
            <pubDate>Sun, 29 Sep 2013 19:30:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/migration-wordpress-to-wintersmith/</guid>
            <description>&lt;p&gt;Well my blog was on &lt;a href=&#34;http://wordpress.org/&#34; title=&#34;Wordpress&#34;&gt;Wordpress&lt;/a&gt;, and I was happy, so why did I move away?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Constant maintenance, requires a lot of time, as it&amp;rsquo;s constantly being targeted by hackers&lt;/li&gt;
&lt;li&gt;Slow, even with caching plugins, I didn&amp;rsquo;t want to put a really powerfull machine just to run a blog page&lt;/li&gt;
&lt;li&gt;Server maintenance&lt;/li&gt;
&lt;li&gt;Didn&amp;rsquo;t use all the functionality in the system, don&amp;rsquo;t really need all that functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I got tired of managing all this stuff, so I decide it is time to find something that won&amp;rsquo;t waste so much of my time and let me use it when I need, and not worry about if I&amp;rsquo;m gonna get hacked, or if my server is slow.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s see some of the pros and cons of running a static generated site.&lt;/p&gt;

&lt;h2 id=&#34;pros&#34;&gt;Pros:&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Extremely fast&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t need to worry, if someone is gonna find an exploit for my site, even if I mess up, it&amp;rsquo;s still html and javascript code, there is nothing they can do on the server, to change content and stuff like that&lt;/li&gt;
&lt;li&gt;You can write your posts in Markdown format&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;cons&#34;&gt;Cons:&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You need your computer to publish a new post, you can&amp;rsquo;t do it from the beach or the phone if you want to do it. (Though there is way of how to do this automatically, to accomplish simillar thing, like creating a markdown document, and pushing it to git, while the server periodically regenerates the site if there are new changes)&lt;/li&gt;
&lt;li&gt;You need to regenerate the build and deploy it&lt;/li&gt;
&lt;li&gt;Needed to learn &lt;a href=&#34;http://jade-lang.com&#34;&gt;Jade&lt;/a&gt;, there are other templating plugins available, but in the end I settled with the default one, as it wasn&amp;rsquo;t really difficult to learn, took about one hour to be able to use it&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&#34;choosing-static-site-generator&#34;&gt;Choosing Static Site Generator&lt;/h1&gt;

&lt;p&gt;These are some of the generators that I checked to see if I can use them, after looking through the web to see what other people are using I narrowed the selection down to these items:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://jekyllrb.com&#34;&gt;Jekyll&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://http://blacksmith.jit.su&#34;&gt;Blacksmith&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://wintersmith.io&#34;&gt;Wintersmith&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I played a bit with all of them and in the end I settled with &lt;a href=&#34;http://wintersmith.io&#34;&gt;Wintersmith&lt;/a&gt;, the reason is, that is really easy to use, and extendable.&lt;/p&gt;

&lt;h1 id=&#34;preparation&#34;&gt;Preparation&lt;/h1&gt;

&lt;p&gt;So firstly I needed to prepare the environment for &lt;a href=&#34;http://wintersmith.io&#34;&gt;Wintersmith&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A lot of people install node from repositories, but I prefer to use &lt;a href=&#34;https://github.com/creationix/nvm&#34;&gt;Node Version Manager&lt;/a&gt;, it gives me more control over which version I use, for details about how to install visit this &lt;a href=&#34;https://github.com/creationix/nvm&#34;&gt;page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To get started, you will need to install Wintersmith. Getting Wintersmith installed is fairly easy when using npm. You simply need to type the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;npm install -g wintersmith
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;One of the features that was greatly improved with some of the newer versions of Wintersmith is the ability to generate a new site from the command line utility. This saves a great deal of time in the early creation process. The command can be utlized as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;wintersmith new &amp;lt;project_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the following example, I ran the following command with project name of blog. This generated a basic skeleton for me to use in building this blog.&lt;/p&gt;

&lt;p&gt;Looking at the skeleton of the blog, it is fairly simple to use, and configure.&lt;/p&gt;

&lt;h1 id=&#34;modding&#34;&gt;Modding&lt;/h1&gt;

&lt;p&gt;I needed some data added to the site, so I can safely migrate from my old &lt;a href=&#34;http://wordpress.org/&#34; title=&#34;Wordpress&#34;&gt;Wordpress&lt;/a&gt; blog to my new static generated one.&lt;/p&gt;

&lt;h2 id=&#34;helper&#34;&gt;Helper&lt;/h2&gt;

&lt;p&gt;I needed a function that will return all articles so I can manipulate the generation process, and use it to generate the redirects, sitemap and feeds&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;var _ = require(&#39;underscore&#39;), util = require(&#39;util&#39;);

module.exports = function(env, callback) {

    var defaults = {
        articles: &#39;articles&#39;
    };

    var options = _.extend(env.config.helpers || {
    }, defaults);

    /**
     * Get all available articles
     * @param {Object} contents
     *
     * @returns {Array} A list of available articles sorted by descending date
     */
    var getArticles = function(contents) {
        return contents[options.articles]._.directories.map(function(item) {
            return item.index;
        }).sort(function(a, b) {
            return b.date - a.date;
        });
    };

    // add the article helper to the environment so we can use it later
    env.helpers.getArticles = getArticles;

    return callback();

};
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;robots&#34;&gt;Robots&lt;/h2&gt;

&lt;p&gt;The Robot Exclusion Standard, also known as the Robots Exclusion Protocol or robots.txt protocol, is a convention to prevent cooperating web crawlers and other web robots from accessing all or part of a website which is otherwise publicly viewable. Robots are often used by search engines to categorize and archive web sites, or by webmasters to proofread source code. The standard is different from, but can be used in conjunction with, Sitemaps, a robot inclusion standard for websites.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jade&#34;&gt;- // robots.txt
| User-agent: *
| Disallow: #{locals.robotsDisallowed}
| Sitemap: #{locals.url}/sitemap.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the main config file under locals we create &lt;strong&gt;robotsDisallowed&lt;/strong&gt; property which holds what is not allowed, in my case it&amp;rsquo;s empty.&lt;/p&gt;

&lt;p&gt;So the generated file looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;User-agent: *
Disallow:
Sitemap: http://blog.matoski.com/sitemap.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;sitemap&#34;&gt;Sitemap&lt;/h2&gt;

&lt;p&gt;A site map (or sitemap) is a list of pages of a web site accessible to crawlers or users. It can be either a document in any form used as a planning tool for Web design, or a Web page that lists the pages on a Web site, typically organized in hierarchical fashion. There are two popular versions of a site map. An XML Sitemap is a structured format that a user doesn&amp;rsquo;t need to see, but it tells the search engine about the pages in your site, their relative importance to each other, and how often they are updated. HTML sitemaps are designed for the user to help them find content on the page, and don&amp;rsquo;t need to include each and every subpage. This helps visitors and search engine bots find pages on the site.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jade&#34;&gt;doctype xml
urlset(
  xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;,
  xsi:schemaLocation=&amp;quot;http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd&amp;quot;,
  xmlns=&amp;quot;http://www.sitemaps.org/schemas/sitemap/0.9&amp;quot;)
  - var buildDate = new Date().toISOString()
  url
    loc =locals.url
    lastmod= buildDate
    changefreq daily
    priority 1.0
  url
    loc= locals.url + &amp;quot;/archive.html&amp;quot;
    lastmod= buildDate
    changefreq daily
    priority 1.0
  - var articles = _.chain(contents.articles._.directories).map(function(item) {
  -   return item.index
  - }).compact().filter(function(article) {
  -   return article.metadata.ignored !== true
  - }).sortBy(function(item) {
  -   return -item.date
  - }).value()
  for article in articles
    - var permalink = locals.url + article.url
    url
      loc= permalink
      lastmod= article.date.toISOString()
      changefreq daily
      priority 0.8
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;htaccess&#34;&gt;.htaccess&lt;/h2&gt;

&lt;p&gt;A .htaccess (hypertext access) file is a directory-level configuration file supported by several web servers, that allows for decentralized management of web server configuration. They are placed inside the web tree, and are able to override a subset of the server&amp;rsquo;s global configuration for the directory that they are in, and all sub-directories.&lt;/p&gt;

&lt;p&gt;The reason for this file is so we can provide redirects to the new articles in the old system, this will work on Apache only, for a nginx configuration you can see it bellow&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jade&#34;&gt;- var articles = env.helpers.getArticles(contents);
| RewriteEngine On
| RewriteBase /　#{&amp;quot;\n&amp;quot;}
for article in articles
    if article.metadata.oldurl
        | Redirect 301 #{article.metadata.oldurl} #{article.url} #{&amp;quot;\n&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;nginx-conf&#34;&gt;nginx.conf&lt;/h2&gt;

&lt;p&gt;This file generates the redirects for the old articles in the system to the new system, but you will have to put them manually inside in the configuration file for the host&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jade&#34;&gt;- var articles = env.helpers.getArticles(contents);
for article in articles
    if article.metadata.oldurl
        | location #{article.metadata.oldurl}
        |   rewrite ^(.*)$ #{article.url} redirect;
        | } #{&amp;quot;\n&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;google-analytics-tracking&#34;&gt;Google Analytics Tracking&lt;/h2&gt;

&lt;p&gt;At the end of &lt;strong&gt;&lt;em&gt;layout.jade&lt;/em&gt;&lt;/strong&gt;, I added this bellow the footer, this adds google tracking to my web page&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-jade&#34;&gt;     script(type=&#39;text/javascript&#39;).
        var _gaq = _gaq || [];
        _gaq.push([&#39;_setAccount&#39;, &#39;#{locals.googleTrackingCode}&#39;]);
        _gaq.push([&#39;_trackPageview&#39;]);
        (function() {
          var ga = document.createElement(&#39;script&#39;); ga.type = &#39;text/javascript&#39;; ga.async = true;
          ga.src = (&#39;https:&#39; == document.location.protocol ? &#39;https://ssl&#39; : &#39;http://www&#39;) + &#39;.google-analytics.com/ga.js&#39;;
          var s = document.getElementsByTagName(&#39;script&#39;)[0]; s.parentNode.insertBefore(ga, s);
        })();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;strong&gt;locals.googleTrackingCode&lt;/strong&gt; contains my tracking code, and it&amp;rsquo;s set in the &lt;strong&gt;config.json&lt;/strong&gt; in the root of the directory.&lt;/p&gt;

&lt;p&gt;So that&amp;rsquo;s it the blog is ready to go.&lt;/p&gt;

&lt;p&gt;Next thing to do is to style this up, I&amp;rsquo;m thinking what CSS framework to use, I&amp;rsquo;m thinking about using &lt;a href=&#34;http://foundation.zurb.com&#34;&gt;Foundation&lt;/a&gt;, so should be fun.&lt;/p&gt;

&lt;p&gt;So total in all it took about 2.5 hours to transfer my old blog, to the new static system, not much if you compare the speed you get and stability with the static site builder.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Building lftp on Windows</title>
            <link>https://matoski.com/article/building-lftp-on-windows/</link>
            <pubDate>Wed, 25 Sep 2013 20:50:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/building-lftp-on-windows/</guid>
            <description>&lt;p&gt;One of the best FTP clients I have ever seen is &lt;a href=&#34;http://lftp.yar.ru/&#34; title=&#34;lftp&#34;&gt;lftp&lt;/a&gt;, and what is even best it&amp;rsquo;s open source on Linux, if you want to use it on Windows you will have to compile it with &lt;a href=&#34;http://www.cygwin.com/&#34; title=&#34;Cygwin&#34;&gt;Cygwin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Why would someone use &lt;a href=&#34;http://lftp.yar.ru/&#34; title=&#34;lftp&#34;&gt;lftp&lt;/a&gt;, when there are alternatives like &lt;a href=&#34;https://filezilla-project.org/&#34; title=&#34;FileZilla&#34;&gt;FileZilla&lt;/a&gt;, and a lot of other ones. Yes &lt;a href=&#34;https://filezilla-project.org/&#34; title=&#34;FileZilla&#34;&gt;FileZilla &lt;/a&gt;is good and it&amp;rsquo;s free, but some of the options that are available with &lt;a href=&#34;http://lftp.yar.ru/&#34; title=&#34;lftp&#34;&gt;lftp &lt;/a&gt;are really good and helpful. And I know of a lot of people that use &lt;a href=&#34;http://lftp.yar.ru/&#34; title=&#34;lftp&#34;&gt;lftp &lt;/a&gt;for server backups on Windows Server and Linux machines to do recursive backups and mirroring.&lt;/p&gt;

&lt;p&gt;For a complete feature list you can see this &lt;a href=&#34;http://lftp.yar.ru/features.html&#34; title=&#34;lftp Features&#34;&gt;page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some interesting information about this application can be found on this &lt;a href=&#34;http://linux.overshoot.tv/wiki/networking/lftp&#34; title=&#34;lftp&#34;&gt;page&lt;/a&gt;, there are various examples of how to use it on their page.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;If you want to learn how to compile it on Windows, read bellow, or if you are just interested in the compiled version you can download it bellow, the following builds are built on Cygwin x86x64, also bundled in the package is SSH and BASH. If you have &lt;a href=&#34;http://www.cygwin.com/&#34; title=&#34;Cygwin&#34;&gt;Cygwin&lt;/a&gt; installation you can just unpack this file in the root, and you are set.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://files.matoski.com/blog/lftp-win64-gnutls.tar.gz&#34; title=&#34;lftp + GnuTLS&#34;&gt;lftp + GnuTLS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://files.matoski.com/blog/lftp-win64-openssl.tar.gz&#34; title=&#34;lftp + OpenSSL&#34;&gt;lftp + OpenSSL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the bottom of the post you will find a script that was used to build these packages for anyone who want&lt;/p&gt;

&lt;p&gt;So first things first, download the latest version of &lt;a href=&#34;http://lftp.yar.ru/get.html&#34; title=&#34;Download lftp&#34;&gt;lftp&lt;/a&gt;, and unpack it somewhere where you can access it, in my case I uncompressed it in my home directory, so at the time of writing the latest version is &lt;a href=&#34;http://lftp.yar.ru/ftp/lftp-4.4.9.tar.gz&#34; title=&#34;lftp 4.4.9&#34;&gt;4.4.9&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are some of the perquisites for compiling the application successfully on &lt;a href=&#34;http://www.cygwin.com/&#34; title=&#34;Cygwin&#34;&gt;Cygwin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In short you need the following packages for you to be able to compile &lt;a href=&#34;http://lftp.yar.ru/get.html&#34; title=&#34;Download lftp&#34;&gt;lftp&lt;/a&gt;, for a more complete list of packages that I use to compile you can find them at the end of the post.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;bison, autoconf, gcc, gcc-c++, make, pkg-config, gnutls, gnutls-devel
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the main directory we run:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;./configure
make
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So after compilation let&amp;rsquo;s check what support do we have in lftp:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;lftp.exe --version
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It shows us that we are using: Readline 6.2, Expat 2.1.0, GnuTLS 3.2.0, libiconv 1.14, zlib 1.2.8&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ldd.exe lftp.exe | grep --invert-match Windows
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This shows you all the dependencies for the particular executable, in our case it shows the following.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ldd.exe lftp.exe | grep --invert-match Windows
        cygwin1.dll =&amp;gt; /usr/bin/cygwin1.dll (0x180040000)
        cygexpat-1.dll =&amp;gt; /usr/bin/cygexpat-1.dll (0x3ff980000)
        cyggnutls-28.dll =&amp;gt; /usr/bin/cyggnutls-28.dll (0x3ff590000)
        cyggmp-10.dll =&amp;gt; /usr/bin/cyggmp-10.dll (0x3ff690000)
        cyghogweed-2.dll =&amp;gt; /usr/bin/cyghogweed-2.dll (0x3ff4d0000)
        cygnettle-4.dll =&amp;gt; /usr/bin/cygnettle-4.dll (0x3ff0e0000)
        cygiconv-2.dll =&amp;gt; /usr/bin/cygiconv-2.dll (0x3ff3c0000)
        cygintl-8.dll =&amp;gt; /usr/bin/cygintl-8.dll (0x3ff360000)
        cygp11-kit-0.dll =&amp;gt; /usr/bin/cygp11-kit-0.dll (0x3ff0a0000)
        cygffi-6.dll =&amp;gt; /usr/bin/cygffi-6.dll (0x3ff970000)
        cygtasn1-6.dll =&amp;gt; /usr/bin/cygtasn1-6.dll (0x3feba0000)
        cygz.dll =&amp;gt; /usr/bin/cygz.dll (0x3feb40000)
        cygreadline7.dll =&amp;gt; /usr/bin/cygreadline7.dll (0x3fede0000)
        cygncursesw-10.dll =&amp;gt; /usr/bin/cygncursesw-10.dll (0x3ff120000)
        cyggcc_s-seh-1.dll =&amp;gt; /usr/bin/cyggcc_s-seh-1.dll (0x3ff850000)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you want to compile with OpenSSL support do the following, because by default it doesn&amp;rsquo;t compile with OpenSSL support, instead it uses GnuTLS.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;./configure --without-gnutls --with-openssl
make
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So after compilation let&amp;rsquo;s check what support do we have in lftp:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;lftp.exe --version
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It shows us that we are using: Readline 6.2, Expat 2.1.0, OpenSSL 1.0.1e 11 Feb 2013, libiconv 1.14, zlib 1.2.8&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ldd.exe lftp.exe | grep --invert-match Windows
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This shows you all the dependencies for the particular executable, in our case it shows the following.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ldd.exe lftp.exe | grep --invert-match Windows
        cygcrypto-1.0.0.dll =&amp;gt; /usr/bin/cygcrypto-1.0.0.dll (0x3ffbf0000)
        cygwin1.dll =&amp;gt; /usr/bin/cygwin1.dll (0x180040000)
        cygz.dll =&amp;gt; /usr/bin/cygz.dll (0x3feb40000)
        cygexpat-1.dll =&amp;gt; /usr/bin/cygexpat-1.dll (0x3ff980000)
        cygiconv-2.dll =&amp;gt; /usr/bin/cygiconv-2.dll (0x3ff3c0000)
        cygintl-8.dll =&amp;gt; /usr/bin/cygintl-8.dll (0x3ff360000)
        cygreadline7.dll =&amp;gt; /usr/bin/cygreadline7.dll (0x3fede0000)
        cygncursesw-10.dll =&amp;gt; /usr/bin/cygncursesw-10.dll (0x3ff120000)
        cygssl-1.0.0.dll =&amp;gt; /usr/bin/cygssl-1.0.0.dll (0x3fecc0000)
        cyggcc_s-seh-1.dll =&amp;gt; /usr/bin/cyggcc_s-seh-1.dll (0x3ff850000)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;long-package-list&#34;&gt;Long package list&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;autoconf, automake, bison, bzip2, cygwin-debuginfo, cygwin32, cygwin32-expat, cygwin32-libiconv, expat, expat-debuginfo, gcc-core, gcc-fortran, gcc-g++, gnutls, gnutls-devel, libexpat-devel, libexpat1, libiconv, libiconv-debuginfo, libiconv-devel, libiconv2, libmhash-devel, libmhash2, libreadline-devel, libreadline7, make, mhash-debuginfo, mingw-binutils, mingw-gcc-core, mingw-pthreads, mingw-runtime, mingw-w32api, mingw-zlib, mingw-zlib-devel, mingw-zlib1, mingw64-x86_64-binutils, mingw64-x86_64-gcc-core, mingw64-x86_64-gcc-fortran, mingw64-x86_64-gcc-g++, mingw64-x86_64-headers, mingw64-x86_64-runtime, mingw64-x86_64-winpthreads, mingw64-x86_64-zlib, openssl, openssl-devel, perl, perl-ExtUtils-PkgConfig, pkg-config, pkg-config-debuginfo, python, python-crypto, python-crypto-debuginfo, python-openssl, python-openssl-debuginfo, python-tkinter, zlib-devel, zlib0
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;build-and-packaging-script&#34;&gt;Build and packaging script&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/bash
if [ $# -eq 0 ]
  then
    echo &amp;quot;&amp;amp;lt;script&amp;gt; name&amp;quot;
	exit
fi

if [ ! -f lftp.exe ];
then
 echo &amp;quot;lftp.exe doesn&#39;t exist run this file from where it exists&amp;quot;
 exit
fi
cwd=`pwd`
items=`ldd.exe lftp.exe | grep --invert-match Windows | cut -d &amp;quot; &amp;quot; -f3`
tmpdir=`mktemp.exe --directory`
echo &amp;quot;Creating temporary directory $tmpdir&amp;quot;
mkdir $tmpdir/bin
mkdir $tmpdir/etc
for item in $items
do
 echo &amp;quot;Copying LFTP dependency file: $item to $tmpdir/bin&amp;quot;
 cp $item $tmpdir/bin
done
items=`ldd.exe /bin/ssh.exe | grep --invert-match Windows | cut -d &amp;quot; &amp;quot; -f3`
for item in $items
do
 echo &amp;quot;Copying SSH dependency file: $item&amp;quot;
 cp $item $tmpdir/bin
done
items=`ldd.exe /bin/bash.exe | grep --invert-match Windows | cut -d &amp;quot; &amp;quot; -f3`
for item in $items
do
 echo &amp;quot;Copying BASH dependency file: $item&amp;quot;
 cp $item $tmpdir/bin
done
echo &amp;quot;Copying required files&amp;quot;
cp lftp.exe $tmpdir/bin
cp ../lftp.conf $tmpdir/etc
cp /bin/ssh.exe $tmpdir/bin
cp /bin/bash.exe $tmpdir/bin
cd $tmpdir
tar -cvzf ../$1.tar.gz .
mv ../$1.tar.gz $cwd
cd $cwd
echo &amp;quot;File generated in $cwd/$1.tar.gz&amp;quot;
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>OpenLayers draggable popups</title>
            <link>https://matoski.com/article/openlayers-drag-popups/</link>
            <pubDate>Mon, 23 Sep 2013 09:45:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/openlayers-drag-popups/</guid>
            <description>&lt;p&gt;How to implement a draggable popup in OpenLayers, to have the ability to decide which class will be draggable and which one will not be?&lt;/p&gt;

&lt;p&gt;For a project I needed to be able to drag the OpenLayer popups, the problem was there were some implementations online, but I needed for the popup to be only draggable on the title, and for input elements not to interfere with the dragging process. Becase when I clicked on an input, textarea it suddenly stared dragging and it was a mess.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;So the solution was to implement a control that will do all that for me.&lt;/p&gt;

&lt;p&gt;The solution I came up was this, you can see the file on &lt;a href=&#34;http://github.com&#34; title=&#34;GitHub&#34;&gt;GitHub&lt;/a&gt; on &lt;a href=&#34;https://gist.github.com/ilijamt/6667845#file-openlayers-dragpopup-js&#34; title=&#34;OpenLayers-DragPopup.js&#34;&gt;OpenLayers.Control.DragPopup.js&lt;/a&gt;, the plugin requires &lt;a href=&#34;http://underscorejs.org/&#34; title=&#34;Underscore&#34;&gt;Underscore&lt;/a&gt; and &lt;a href=&#34;http://jquery.com/&#34; title=&#34;jQuery&#34;&gt;jQuery&lt;/a&gt; to work, when I have time I will rewrite them to be pure JavaScript only, but for now it works without any problems.&lt;/p&gt;

&lt;script src=&#34;https://gist.github.com/ilijamt/6667845.js&#34;&gt;&lt;/script&gt;

&lt;p&gt;Let&amp;rsquo;s see some of the available options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;elementsIgnore&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Which html elements should we ignore for dragging, this is useful so we don&amp;rsquo;t accidentally drag the popup on some of the elements inside the popup, like input elements.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;selectorsIgnore&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Which selectors do we ignore, this is an array that is used to check if we should move the element or not.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;moveOnSelector&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On which selector do we move, this can be a title or an icon, and we use this to determine if we should move or not.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To view a demo implementation, you can open this &lt;a href=&#34;http://jsfiddle.net/ilijamt/3fwtD/&#34; title=&#34;jsfiddle&#34;&gt;jsfiddle&lt;/a&gt;&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Generating filename based on the android project name and version name when running ant</title>
            <link>https://matoski.com/article/generating-filename-based-on-the-android-project-name-and-version-name-when-running-ant/</link>
            <pubDate>Sun, 16 Jun 2013 03:34:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/generating-filename-based-on-the-android-project-name-and-version-name-when-running-ant/</guid>
            <description>&lt;p&gt;How to generate a filename based on the android project name and version when running ant, we will look at how the ant scripts should look like after the modifications&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;ve ever wanted to generate the android project filename according to some data from your android manifest, you can use the ant build scripts to add the functionality needed.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;If you don&amp;rsquo;t have your ant build script in your project directory you can run the following to command to create it along with some of the necessary files required.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;android update project -p &amp;lt;android_project_path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The original ant build script is like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;project name=&amp;quot;android_project_name&amp;quot; default=&amp;quot;help&amp;quot;&amp;gt;

    &amp;lt;property file=&amp;quot;local.properties&amp;quot; /&amp;gt;
    &amp;lt;property file=&amp;quot;ant.properties&amp;quot; /&amp;gt;

    &amp;lt;property environment=&amp;quot;env&amp;quot; /&amp;gt;
    &amp;lt;condition property=&amp;quot;sdk.dir&amp;quot; value=&amp;quot;${env.ANDROID_HOME}&amp;quot;&amp;gt;
        &amp;lt;isset property=&amp;quot;env.ANDROID_HOME&amp;quot; /&amp;gt;
    &amp;lt;/condition&amp;gt;

    &amp;lt;loadproperties srcFile=&amp;quot;project.properties&amp;quot; /&amp;gt;

    &amp;lt;fail
            message=&amp;quot;sdk.dir is missing. Make sure to generate local.properties using &#39;android update project&#39; or to inject it through the ANDROID_HOME environment variable.&amp;quot;
            unless=&amp;quot;sdk.dir&amp;quot;
    /&amp;gt;

    &amp;lt;import file=&amp;quot;custom_rules.xml&amp;quot; optional=&amp;quot;true&amp;quot; /&amp;gt;
    &amp;lt;import file=&amp;quot;${sdk.dir}/tools/ant/build.xml&amp;quot; /&amp;gt;

&amp;lt;/project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we need to add the following to the ant build script, you can add all this above the line&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;import file=&amp;quot;${sdk.dir}/tools/ant/build.xml&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the new configuration that you need to add to the ant script&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;    &amp;lt;xmlproperty
        collapseAttributes=&amp;quot;true&amp;quot;
        file=&amp;quot;AndroidManifest.xml&amp;quot;
        prefix=&amp;quot;mymm&amp;quot; /&amp;gt;

    &amp;lt;target name=&amp;quot;custom-set-release-mode&amp;quot; &amp;gt;

        &amp;lt;property
            name=&amp;quot;out.packaged.file&amp;quot;
            location=&amp;quot;${out.absolute.dir}/${ant.project.name}-${mymm.manifest.android:versionName}-release-unsigned.apk&amp;quot; /&amp;gt;

        &amp;lt;property
            name=&amp;quot;out.final.file&amp;quot;
            location=&amp;quot;${out.absolute.dir}/${ant.project.name}-${mymm.manifest.android:versionName}-release.apk&amp;quot; /&amp;gt;
    &amp;lt;/target&amp;gt;

    &amp;lt;target name=&amp;quot;custom-set-debug-files&amp;quot; &amp;gt;

        &amp;lt;property
            name=&amp;quot;out.packaged.file&amp;quot;
            location=&amp;quot;${out.absolute.dir}/${ant.project.name}-${mymm.manifest.android:versionName}-debug-unaligned.apk&amp;quot; /&amp;gt;

        &amp;lt;property
            name=&amp;quot;out.final.file&amp;quot;
            location=&amp;quot;${out.absolute.dir}/${ant.project.name}-${mymm.manifest.android:versionName}-debug.apk&amp;quot; /&amp;gt;
    &amp;lt;/target&amp;gt;

    &amp;lt;target
        name=&amp;quot;debug&amp;quot;
        depends=&amp;quot;custom-set-debug-files, android_rules.debug&amp;quot; /&amp;gt;

    &amp;lt;target
        name=&amp;quot;release&amp;quot;
        depends=&amp;quot;custom-set-release-mode, android_rules.release&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can customize the files to provide any combination you want that you can access from either the &lt;strong&gt;AndroidManifest.xml&lt;/strong&gt; or the properties files.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Using ant to generate javadoc for your android project</title>
            <link>https://matoski.com/article/using-ant-to-generate-javadoc-for-your-android-project/</link>
            <pubDate>Sat, 15 Jun 2013 11:04:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/using-ant-to-generate-javadoc-for-your-android-project/</guid>
            <description>&lt;p&gt;This process describes the generation of an android project using ANT, which will generate the project and also generate the javadoc documentation&lt;/p&gt;

&lt;p&gt;If you want to generate JavaDoc for your project directly from the command line, you can easily do it by adding some extra configuration to the ant &lt;strong&gt;build.xml&lt;/strong&gt; script.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;If you don&amp;rsquo;t have your ant build script in your project directory you can run the following to command to create it along with some of the necessary files required.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;android update project -p &amp;lt;android_project_path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The original ant build script is like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;project name=&amp;quot;android_project_name&amp;quot; default=&amp;quot;help&amp;quot;&amp;gt;

    &amp;lt;property file=&amp;quot;local.properties&amp;quot; /&amp;gt;
    &amp;lt;property file=&amp;quot;ant.properties&amp;quot; /&amp;gt;

    &amp;lt;property environment=&amp;quot;env&amp;quot; /&amp;gt;
    &amp;lt;condition property=&amp;quot;sdk.dir&amp;quot; value=&amp;quot;${env.ANDROID_HOME}&amp;quot;&amp;gt;
        &amp;lt;isset property=&amp;quot;env.ANDROID_HOME&amp;quot; /&amp;gt;
    &amp;lt;/condition&amp;gt;

    &amp;lt;loadproperties srcFile=&amp;quot;project.properties&amp;quot; /&amp;gt;

    &amp;lt;fail
            message=&amp;quot;sdk.dir is missing. Make sure to generate local.properties using &#39;android update project&#39; or to inject it through the ANDROID_HOME environment variable.&amp;quot;
            unless=&amp;quot;sdk.dir&amp;quot;
    /&amp;gt;

    &amp;lt;import file=&amp;quot;custom_rules.xml&amp;quot; optional=&amp;quot;true&amp;quot; /&amp;gt;
    &amp;lt;import file=&amp;quot;${sdk.dir}/tools/ant/build.xml&amp;quot; /&amp;gt;

&amp;lt;/project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we need to add the following to the ant build script, you can add all this above the line&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;import file=&amp;quot;${sdk.dir}/tools/ant/build.xml&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the new configuration that you need to add to the ant script&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;property name=&amp;quot;docs.dir&amp;quot; location=&amp;quot;javadoc&amp;quot; /&amp;gt;
&amp;lt;property name=&amp;quot;bin.dir&amp;quot; location=&amp;quot;bin&amp;quot; /&amp;gt;
&amp;lt;property name=&amp;quot;source.dir&amp;quot; location=&amp;quot;src&amp;quot; /&amp;gt;
&amp;lt;property name=&amp;quot;gen.dir&amp;quot; location=&amp;quot;gen&amp;quot; /&amp;gt;

&amp;lt;target
    name=&amp;quot;javadoc&amp;quot;
    description=&amp;quot;Generate JavaDoc documentation&amp;quot; &amp;gt;

    &amp;lt;xmlproperty
        collapseAttributes=&amp;quot;true&amp;quot;
        file=&amp;quot;AndroidManifest.xml&amp;quot;
        prefix=&amp;quot;tm&amp;quot; /&amp;gt;

    &amp;lt;mkdir dir=&amp;quot;${docs.dir}&amp;quot; /&amp;gt;

    &amp;lt;javadoc
        access=&amp;quot;private&amp;quot;
        author=&amp;quot;true&amp;quot;
        classpath=&amp;quot;${sdk.dir}/platforms/${target}/android.jar&amp;quot;
        destdir=&amp;quot;${docs.dir}&amp;quot;
        linkoffline=&amp;quot;http://d.android.com/reference ${sdk.dir}/docs/reference&amp;quot;
        linksource=&amp;quot;true&amp;quot;
        sourcepath=&amp;quot;${source.dir};${gen.dir}&amp;quot;
        use=&amp;quot;true&amp;quot;
        version=&amp;quot;true&amp;quot; /&amp;gt;

    &amp;lt;jar
        basedir=&amp;quot;${docs.dir}&amp;quot;
        compress=&amp;quot;${jar.compress}&amp;quot;
        jarfile=&amp;quot;${bin.dir}/${tm.manifest.package}_${tm.manifest.android:versionName}_javadoc.jar&amp;quot; /&amp;gt;
&amp;lt;/target&amp;gt;

&amp;lt;target
   name=&amp;quot;clean&amp;quot;
   depends=&amp;quot;android_rules.clean&amp;quot; &amp;gt;

   &amp;lt;delete dir=&amp;quot;${docs.dir}&amp;quot; /&amp;gt;
&amp;lt;/target&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can run the following commands&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ant clean&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Will clean the directories for the android project and also the javadoc directory as it&amp;rsquo;s overridden in the target&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;ant javadoc&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Will generate the JavaDoc in the &lt;strong&gt;${docs.dir}&lt;/strong&gt; It will also generate a jar file with the javadoc&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
        </item>
        
        <item>
            <title>Git alias, color and pretty printing</title>
            <link>https://matoski.com/article/git-alias-color-and-pretty-printing/</link>
            <pubDate>Fri, 14 Jun 2013 06:47:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/git-alias-color-and-pretty-printing/</guid>
            <description>&lt;p&gt;I&amp;rsquo;m tired of looking at the plain old log in git, so let&amp;rsquo;s see how we can spice it up a bit?&lt;/p&gt;

&lt;p&gt;If you ever needed to have a prettier format of printing the git log, for easier changes, you can add this to the alias section of the &lt;strong&gt;.gitconfig&lt;/strong&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;log-color = log --graph --full-history --all --color --pretty=format:&#39;%x1b[31m%h%x09%x1b[32m %C(white)- %d%x1b[0m%x20%s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset&#39; --date=relative
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So after you add this line to the alias section executing &lt;strong&gt;git log-color&lt;/strong&gt; on a git repo directory will give you the following output.&lt;/p&gt;

&lt;p&gt;In our case for the node git repo: &lt;strong&gt;&lt;a href=&#34;https://github.com/joyent/node&#34;&gt;https://github.com/joyent/node&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;git-log-color.png&#34; alt=&#34;git log color screenshot 1&#34; /&gt;
    
    
&lt;/figure&gt;


&lt;figure class=&#34;pure-img&#34;&gt;
    
        &lt;img src=&#34;git-log-color-2.png&#34; alt=&#34;git log color screenshot 2&#34; /&gt;
    
    
&lt;/figure&gt;
&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Websocket traffic forwarding using iptables</title>
            <link>https://matoski.com/article/websocket-traffic-forwarding-using-iptables/</link>
            <pubDate>Tue, 30 Apr 2013 03:53:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/websocket-traffic-forwarding-using-iptables/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve had a problem, I needed to route websocket trafic from internal server for external access, but I ran into a lot of problems, like not connecting, or the connections dropped, so let&amp;rsquo;s see how we can route the traffic successfully&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The machines are all behind a &lt;strong&gt;iptables&lt;/strong&gt; firewall.&lt;/p&gt;

&lt;p&gt;I was using socket.io server in the background on multiple machines and I needed them all to be accessible from the outside through different ports.&lt;/p&gt;

&lt;p&gt;The server is setup like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;eth0      Link encap:Ethernet  HWaddr ##:##:##:##
          inet ##:##:##:##  Bcast:##:##:##:##  Mask:255.255.255.224
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:15151497 errors:0 dropped:0 overruns:0 frame:0
          TX packets:11137070 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:7810856929 (7.8 GB)  TX bytes:4719777638 (4.7 GB)
          Interrupt:20 Memory:ec300000-ec320000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:50967 errors:0 dropped:0 overruns:0 frame:0
          TX packets:50967 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:9190223 (9.1 MB)  TX bytes:9190223 (9.1 MB)

vboxnet1  Link encap:Ethernet  HWaddr 0a:00:27:00:00:01
          inet addr:192.168.22.251  Bcast:192.168.22.255  Mask:255.255.255.0
          inet6 addr: fe80::800:27ff:fe00:1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:102350 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:20302629 (20.3 MB)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So to create the correct iptables rules, we do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;iptables -t nat -A PREROUTING -p tcp --dport &amp;lt;OUTSIDE_PORT&amp;gt; -j DNAT --to-destination &amp;lt;INTERNAL_IP_ADDRESS&amp;gt;:&amp;lt;INTERNAL_PORT&amp;gt;
iptables -t nat -A POSTROUTING -p tcp --dport &amp;lt;INTERNAL_PORT&amp;gt; -j MASQUERADE
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So in my case I had:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;iptables -t nat -A PREROUTING -p tcp --dport 31261 -j DNAT --to-destination 192.168.22.1:31261
iptables -t nat -A POSTROUTING -p tcp --dport 31261 -j MASQUERADE
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let explain what happens with these commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;-j DNAT&lt;/strong&gt; Destination-NAT (DNAT) - Changing the recipient&lt;/p&gt;

&lt;p&gt;If you want to change the receipient of a packet, Destination NAT (DNAT) is your choice! DNAT can be used for servers running behind a firewall. Obviously the receipient has to be changed before any routing decisions are made, therefore DNAT is meaningful within the PREROUTING chain and the OUTPUT chain (for locally generated packets) only&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;-j MASQUERADE&lt;/strong&gt; - Change sender to router&amp;rsquo;s IP-Adress&lt;/p&gt;

&lt;p&gt;Using the MASQUERADE target every packet receives the IP of the router&amp;rsquo;s outgoing interface. The advantage over SNAT is that dynamically assigned IP addresses from the provider do not affect the rule, there is no need to adopt the rule. For ordinary SNAT you would have to change the rule every time the IP of the outgoing interface changes. As for SNAT, MASQUERADE is meaningful within the POSTROUTING-chain only. Unlike SNAT, MASQUERADE does not offer further options.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;-p tcp&lt;/strong&gt; The protocol type&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the connection should be established&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Hard links to a file</title>
            <link>https://matoski.com/article/hard-links-to-a-file/</link>
            <pubDate>Sun, 21 Apr 2013 05:09:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/hard-links-to-a-file/</guid>
            <description>&lt;p&gt;Describes the process of creating a hard link to file, and searching for hard links for any given file.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;To create a hard link it&amp;rsquo;s easy just write&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ln &amp;lt;target&amp;gt; &amp;lt;destination&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Because they are not symbolic links they won&amp;rsquo;t show up as links when you do&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ls -l
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So to find which files have links, you can do the following&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;find -type f -links +1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will give you which files are hard linked, but will not tell you to which files they are hard linked too.&lt;/p&gt;

&lt;p&gt;To find the which files are linked to which files you can use inodes, to find the inode of a file you simply can use the command stat.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;stat &amp;lt;filename/directory&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will give you an output similar to this one.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;  File: `/tmp/tmp.file&#39;
  Size: 122880    Blocks: 240       IO Block: 4096   file
Device: 815h/2069d	Inode: 1441793     Links: 20
Access: (1777/drwxrwxrwt)  Uid: (0/root)   Gid: (0/root)
Access: 2013-03-18 01:04:18.182327478 +0900
Modify: 2013-04-21 13:48:14.227089591 +0900
Change: 2013-04-21 13:48:14.227089591 +0900
 Birth: -
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The inode number is there so now you can just search for that inode&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ls -iR / | grep &amp;lt;inode_number&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another way to find the files linked is to use this command but only if you know the file you want search for.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;find / -samefile &amp;lt;full_path_to_filename&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>SNS/SQS for node.js</title>
            <link>https://matoski.com/article/snssqs-for-node-js/</link>
            <pubDate>Tue, 16 Apr 2013 03:24:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/snssqs-for-node-js/</guid>
            <description>&lt;p&gt;How to interface SNS, SQS for node.js to AWS?&lt;/p&gt;

&lt;p&gt;If you want to be able to create a SNS/SQS bindings from code and not to do it from the AWS Console with node.js you can do it like this.
&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;var AWS = require(&#39;aws-sdk&#39;), util = require(&#39;util&#39;);

// configure AWS
AWS.config.update({
    &#39;region&#39;: &#39;us-east-1&#39;,
    &#39;accessKeyId&#39;: &#39;akId&#39;,
    &#39;secretAccessKey&#39;: &#39;secretKey&#39;
});

var sns = new AWS.SNS().client;
var sqs = new AWS.SQS().client;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will be enough to initialize the required data to be able to connect to the system.&lt;/p&gt;

&lt;p&gt;First let&amp;rsquo;s create a topic:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;sns.createTopic({
    &#39;Name&#39;: &#39;demo&#39;
}, function (err, result) {

    if (err !== null) {
        console.log(util.inspect(err));
        return;
    }

    console.log(util.inspect(result));

});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The following is the output:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;{
    ResponseMetadata: {
        RequestId: &#39;bdceeca8-bbb6-511f-b186-a54e7c61fb0e&#39;
    },
    TopicArn: &#39;arn:aws:sns:us-east-1:&amp;lt;AWSID&amp;gt;:demo&#39;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that we have the &lt;strong&gt;TopicArn&lt;/strong&gt; we can proceed to create the &lt;strong&gt;SQS Queue&lt;/strong&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;sqs.createQueue({
    &#39;QueueName&#39;: &#39;demo&#39;
}, function (err, result) {

    if (err !== null) {
        console.log(util.inspect(err));
        return;
    }

    console.log(util.inspect(result));

});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The output is:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;{
    ResponseMetadata: {
        RequestId: &#39;07d264eb-e8c5-5821-9720-2d0d215a8652&#39;
    },
    QueueUrl: &#39;https://sqs.us-east-1.amazonaws.com/&amp;lt;AWSID&amp;gt;/demo&#39;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we have the &lt;strong&gt;QueueUrl&lt;/strong&gt; which we can use to get the ARN for the Queue&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;sqs.getQueueAttributes({
    QueueUrl: &#39;https://sqs.us-east-1.amazonaws.com/&amp;lt;AWSID&amp;gt;/demo&#39;,
    AttributeNames: [&amp;quot;QueueArn&amp;quot;]
}, function (err, result) {

    if (err !== null) {
        console.log(util.inspect(err));
        return;
    }

    console.log(util.inspect(result));

});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will give us the &lt;strong&gt;QueueArn&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;{
    ResponseMetadata: {
        RequestId: &#39;05be9746-9f9c-5c5a-94e6-dea0550f02f7&#39;
    },
    Attribute: {
        Name: &#39;QueueArn&#39;,
        Value: &#39;arn:aws:sqs:us-east-1:&amp;lt;AWSID&amp;gt;:demo&#39;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we have everything we need to create a subscription and policy.&lt;/p&gt;

&lt;p&gt;First let&amp;rsquo;s create the subscription&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;sns.subscribe({
    &#39;TopicArn&#39;: &#39;arn:aws:sns:us-east-1:&amp;lt;AWSID&amp;gt;:demo&#39;,
    &#39;Protocol&#39;: &#39;sqs&#39;,
    &#39;Endpoint&#39;: &#39;arn:aws:sqs:us-east-1:&amp;lt;AWSID&amp;gt;:demo&#39;
}, function (err, result) {

    if (err !== null) {
        console.log(util.inspect(err));
        return;
    }

    console.log(util.inspect(result));

});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The output from this query is:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;{
    ResponseMetadata: {
        RequestId: &#39;136057ff-0423-5f63-b42c-1e19c80948ad&#39;
    },
    SubscriptionArn: &#39;arn:aws:sns:us-east-1:&amp;lt;AWSID&amp;gt;:demo:7825661f-130e-4e0c-bc29-9ad397660aaa&#39;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will enable us to publish to the &lt;strong&gt;SQS Queue&lt;/strong&gt;, the only thing left now is to add the permissions that will enable the &lt;strong&gt;Topic&lt;/strong&gt; to write to the &lt;strong&gt;SQS Queue&lt;/strong&gt;.**
**&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;var queueUrl = &amp;quot;https://sqs.us-east-1.amazonaws.com/&amp;lt;AWSID&amp;gt;/demo&amp;quot;;
var topicArn = &amp;quot;arn:aws:sns:us-east-1:&amp;lt;AWSID&amp;gt;:demo&amp;quot;;
var sqsArn = &amp;quot;arn:aws:sqs:us-east-1:&amp;lt;AWSID&amp;gt;:demo&amp;quot;;

var attributes = {
    &amp;quot;Version&amp;quot;: &amp;quot;2008-10-17&amp;quot;,
    &amp;quot;Id&amp;quot;: sqsArn + &amp;quot;/SQSDefaultPolicy&amp;quot;,
    &amp;quot;Statement&amp;quot;: [{
            &amp;quot;Sid&amp;quot;: &amp;quot;Sid&amp;quot; + new Date().getTime(),
            &amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;,
            &amp;quot;Principal&amp;quot;: {
                &amp;quot;AWS&amp;quot;: &amp;quot;*&amp;quot;
            },
            &amp;quot;Action&amp;quot;: &amp;quot;SQS:SendMessage&amp;quot;,
            &amp;quot;Resource&amp;quot;: sqsArn,
            &amp;quot;Condition&amp;quot;: {
                &amp;quot;ArnEquals&amp;quot;: {
                    &amp;quot;aws:SourceArn&amp;quot;: topicArn
                }
            }
        }
    ]
};

sqs.setQueueAttributes({
    QueueUrl: queueUrl,
    Attributes: {
        &#39;Policy&#39;: JSON.stringify(attributes)
    }
}, function (err, result) {

    if (err !== null) {
        console.log(util.inspect(err));
        return;
    }

    console.log(util.inspect(result));
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the response is:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;{
    ResponseMetadata: {
        RequestId: &#39;1487064f-38fa-55dd-a772-4fa9f5530f48&#39;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we have everything setup so when we publish something in a topic the queue will also be populated.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Maintaining multiple version of a software</title>
            <link>https://matoski.com/article/maintaining-multiple-version-of-a-software/</link>
            <pubDate>Mon, 18 Mar 2013 13:15:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/maintaining-multiple-version-of-a-software/</guid>
            <description>&lt;p&gt;Describes the process of maintaining multiple version of Eclipse on your linux machine&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve needed on a couple occasions to use a software with different version numbers.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;On Ubuntu, the solution is pretty easy: &lt;a href=&#34;http://linux.die.net/man/8/update-alternatives&#34; title=&#34;update-alternatives&#34;&gt;update-alternatives&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s look at how we can keep multiple versions of eclipse on the system.&lt;/p&gt;

&lt;p&gt;Download, and unpack eclipse in the opt folder, we have version 4.2.2&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;update-alternatives --install /usr/bin/eclipse eclipse /opt/eclipse/eclipse-SDK-4.2.2/eclipse 50
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After this we can see that this command creates a symlink to the eclipse program, this way we can add multiple version of the program and switch really easy. This is applicable to all the application that run on Ubuntu.&lt;/p&gt;

&lt;p&gt;Or you can even link the entire directory&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;update-alternatives --install /opt/eclipse eclipse /opt/.versions/eclipse/eclipse-SDK-4.2.2 500
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Wireshark No Interfaces</title>
            <link>https://matoski.com/article/wireshark-no-interfaces/</link>
            <pubDate>Tue, 29 Jan 2013 09:28:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/wireshark-no-interfaces/</guid>
            <description>&lt;p&gt;How to fix the issue with Wireshark not showing any interface in linux?&lt;/p&gt;

&lt;p&gt;If when you start &lt;strong&gt;Wireshark&lt;/strong&gt; complains that you don&amp;rsquo;t have any interfaces just execute the following commands
&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;sudo addgroup -quiet -system wireshark
sudo chown root:wireshark /usr/bin/dumpcap
sudo setcap cap_net_raw,cap_net_admin=eip /usr/bin/dumpcap
sudo usermod -a -G wireshark $USER
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After this just start &lt;strong&gt;Wireshark&lt;/strong&gt; and it you will have your interfaces back.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Automatic SVN incremental backup</title>
            <link>https://matoski.com/article/automatic-svn-incremental-backup/</link>
            <pubDate>Fri, 25 Jan 2013 04:03:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/automatic-svn-incremental-backup/</guid>
            <description>&lt;p&gt;How to create a simple incremental backup system, that you can restore at any time at a later time?&lt;/p&gt;

&lt;p&gt;There are a lot of ways to create automatic incremental backups.&lt;/p&gt;

&lt;p&gt;The simplest way is to use a post-commit hook that will automatically generate a backup every time we commit something to the repository.&lt;/p&gt;

&lt;p&gt;And then we can always backup those files anywhere we want and we can recreate the SVN repository from those files.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Here is the script that will do that:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/sh

PROJECT=&amp;quot;project_name&amp;quot;
REPOS=&amp;quot;$1&amp;quot;
REV=&amp;quot;$2&amp;quot;
REVPAD=$(printf &amp;quot;%05d&amp;quot; &amp;quot;$REV&amp;quot;)
FILE=&amp;quot;${REVPAD}.svndump&amp;quot;

if [ ! -d &amp;quot;/backup/svn/$PROJECT/incremental/&amp;quot; ]; then
  mkdir -p /backup/svn/$PROJECT/incremental/
fi

svnadmin dump &amp;quot;$REPOS&amp;quot; --revision &amp;quot;$REV&amp;quot; --incremental &amp;gt; &amp;quot;/backup/svn/$PROJECT/incremental/${FILE}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So every time we commit it&amp;rsquo;s gonna create a dump in the backup directory.
And after that we can use any number of tools to sync that directory to any remote server we want to.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Buliding lftp from source with OpenSSL libraries</title>
            <link>https://matoski.com/article/buliding-lftp-from-source-with-openssl-libraries/</link>
            <pubDate>Fri, 25 Jan 2013 03:26:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/buliding-lftp-from-source-with-openssl-libraries/</guid>
            <description>&lt;p&gt;How to build the best ftp client for linux?&lt;/p&gt;

&lt;p&gt;This is one of the best FTP client available, but it will take a little using to it as it&amp;rsquo;s command line and there is no GUI for it.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve needed to connect to SSL sites but the &lt;strong&gt;lftp&lt;/strong&gt; that comes with Ubuntu 10.04 doesn&amp;rsquo;t have SSL support compiled into it.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;To check if your version has SSL support compiled into it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ldd /usr/bin/lftp

linux-vdso.so.1 =&amp;gt;  (0x00007fffcc983000)
libgnutls.so.26 =&amp;gt; /usr/lib/libgnutls.so.26 (0x00007f99eacc5000)
librt.so.1 =&amp;gt; /lib/librt.so.1 (0x00007f99eaabd000)
libreadline.so.6 =&amp;gt; /lib/libreadline.so.6 (0x00007f99ea87b000)
libutil.so.1 =&amp;gt; /lib/libutil.so.1 (0x00007f99ea678000)
libncurses.so.5 =&amp;gt; /lib/libncurses.so.5 (0x00007f99ea435000)
libdl.so.2 =&amp;gt; /lib/libdl.so.2 (0x00007f99ea230000)
libgcc_s.so.1 =&amp;gt; /lib/libgcc_s.so.1 (0x00007f99ea019000)
libc.so.6 =&amp;gt; /lib/libc.so.6 (0x00007f99e9c93000)
/lib64/ld-linux-x86-64.so.2 (0x00007f99eaf93000)
libpthread.so.0 =&amp;gt; /lib/libpthread.so.0 (0x00007f99e9a75000)
libtasn1.so.3 =&amp;gt; /usr/lib/libtasn1.so.3 (0x00007f99e9864000)
libz.so.1 =&amp;gt; /lib/libz.so.1 (0x00007f99e964d000)
libgcrypt.so.11 =&amp;gt; /lib/libgcrypt.so.11 (0x00007f99e93d4000)
libgpg-error.so.0 =&amp;gt; /lib/libgpg-error.so.0 (0x00007f99e91d0000)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will give you a list of the dependencies libraries, see &lt;a href=&#34;http://manpages.ubuntu.com/manpages/precise/man1/ldd.1.html&#34; title=&#34;LDD&#34;&gt;ldd&lt;/a&gt; for a more complete description.&lt;/p&gt;

&lt;p&gt;So if there is no libssl library in the list that means you need to compile it from source.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-src install lftp
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we need to modify the building rules.
We need to edit the &lt;strong&gt;debian/rules&lt;/strong&gt; file and add the following details to the configuration section.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;--with-openssl=/usr/lib \
--with-socks=/usr/lib
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We also need to install some libraries needed to compile.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get build-dep lftp
apt-get install libsocks4 libsocksd0-dev libssl-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So the new configuration should look like this.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;./configure \
--prefix=/usr \
--mandir=\$${prefix}/share/man \
--infodir=\$${prefix}/share/info \
--sysconfdir=/etc \
--with-pager=/etc/alternatives/pager \
--with-openssl=/usr/lib \
--with-socks=/usr/lib
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So after this we need to compile the packages.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-src build lftp
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And after a while you should have a package ready to compile.
And we can install it with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;dpkg -i lftp*.deb
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Getting the IP address of a running VirtualBox VM</title>
            <link>https://matoski.com/article/getting-the-ip-address-of-a-running-virtualbox-vm/</link>
            <pubDate>Wed, 16 Jan 2013 14:15:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/getting-the-ip-address-of-a-running-virtualbox-vm/</guid>
            <description>&lt;p&gt;To get the IP address of a running virtual machine we just need to do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;VBoxManage guestproperty get &amp;lt;UUID|Machine Name&amp;gt; &amp;quot;/VirtualBox/GuestInfo/Net/0/V4/IP&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will give you the IP4 address of the Virtual Machine if it&amp;rsquo;s set.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>Upgrade libssl on Ubuntu Lucid 10.04</title>
            <link>https://matoski.com/article/upgrade-libssl-on-ubuntu-lucid-10-04/</link>
            <pubDate>Mon, 14 Jan 2013 10:25:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/upgrade-libssl-on-ubuntu-lucid-10-04/</guid>
            <description>&lt;p&gt;If you ever needed to upgrade the libssl library on your system this is how you can do it.&lt;/p&gt;

&lt;p&gt;First add the &lt;strong&gt;Precise&lt;/strong&gt; source repository to your apt sources.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Now we just run:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-src install libssl1.0.0
apt-src build libssl1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Compiling will take a little time, but after compilation you will have the following files available:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;libssl1.0.0_1.0.1-4ubuntu3_amd64.deb
libssl1.0.0-dbg_1.0.1-4ubuntu3_amd64.deb
libssl1.0.0-udeb_1.0.1-4ubuntu3_amd64.udeb
libssl-dev_1.0.1-4ubuntu3_amd64.deb
libssl-doc_1.0.1-4ubuntu3_all.deb
openssl_1.0.1-4ubuntu3_amd64.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we can either install all the packages with &lt;strong&gt;dpkg&lt;/strong&gt; or, we can, if you have read &lt;a href=&#34;https://matoski.com/articles/creating-your-own-local-compiled-packages-repository/&#34; title=&#34;Creating your own local compiled packages repository&#34;&gt;Creating your own local compiled packages repository&lt;/a&gt; you can just move those files to the folder described there and after that run the update script the new libssl will be available for installation in the system&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Creating your own local compiled packages repository</title>
            <link>https://matoski.com/article/creating-your-own-local-compiled-packages-repository/</link>
            <pubDate>Mon, 14 Jan 2013 09:50:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/creating-your-own-local-compiled-packages-repository/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve had the problem, I needed to create a local repository that will contain all my packages pre compiled so I can just use the &lt;strong&gt;apt&lt;/strong&gt; utility that comes with Debian based systems.&lt;/p&gt;

&lt;p&gt;
Execute the following commands to prepare your system for this.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir -p /usr/local/deb```

Now let&#39;s create a new file called **update** in that directory
```bash
#!/bin/sh
echo &amp;quot;Updating the local repository in&amp;quot; `pwd`
find . -mindepth 1 -maxdepth 1 -type d \
   | cut -c3- \
   | xargs -n 1 -I DIRNAME dpkg-scanpackages DIRNAME /dev/null \
   | gzip -c9 &amp;gt;Packages.gz
[ $? -ne 0 ] \
   &amp;amp;&amp;amp; echo &amp;quot;Update failed&amp;quot; 1&amp;gt;&amp;amp;2 \
   &amp;amp;&amp;amp; [ `id -u` -ne 0 ] &amp;amp;&amp;amp; echo &amp;quot;Maybe you&#39;ve forgotten to sudo?&amp;quot; 1&amp;gt;&amp;amp;2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This file is to help us create a packaging list that should be used as a repository.&lt;/p&gt;

&lt;p&gt;So in our example for &lt;strong&gt;Lucid&lt;/strong&gt; we execute the following commands from&lt;strong&gt; /usr/local/deb&lt;/strong&gt; directory:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir -p lucid/packages
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now all the debian packages that we have we need to put in &lt;strong&gt;lucid/packages&lt;/strong&gt; directory, and after that we need to run the &lt;strong&gt;update&lt;/strong&gt; script from &lt;strong&gt;/usr/local/deb&lt;/strong&gt; directory.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;sudo ./update lucid
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will create the necessary structure and files so it can be recognized by &lt;strong&gt;apt&lt;/strong&gt; .&lt;/p&gt;

&lt;p&gt;Now we just need to add this repository to the &lt;strong&gt;apt sources list&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo /etc/apt/sources.list.d/local.list &amp;gt; deb file:/usr/local/deb/lucid/ ./
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After this we run the update command and then we can just use apt to install or upgrade from the command line.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get update
apt-get upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Some resources of where you can implement this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://matoski.com/articles/compilebackport-packages-from-source-ubuntudebian/&#34; title=&#34;Compile/Backport packages from source Ubuntu/Debian&#34;&gt;&lt;span style=&#34;line-height: 15px;&#34;&gt;Compile/Backport packages from source Ubuntu/Debian&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://matoski.com/articles/upgrade-libssl-on-ubuntu-lucid-10-04/&#34; title=&#34;Upgrade libssl on Ubuntu Lucid 10.04&#34;&gt;Upgrade libssl on Ubuntu Lucid 10.04&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
        </item>
        
        <item>
            <title>Compile qt 4.8.4 on Ubuntu 10.04 Lucid</title>
            <link>https://matoski.com/article/compile-qt-4-8-4-on-ubuntu-10-04-lucid/</link>
            <pubDate>Mon, 14 Jan 2013 07:18:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/compile-qt-4-8-4-on-ubuntu-10-04-lucid/</guid>
            <description>&lt;p&gt;Download the full installation from &lt;a href=&#34;http://releases.qt-project.org/qt4/source/qt-everywhere-opensource-src-4.8.4.tar.gz&#34; title=&#34;qt 4.8.4&#34;&gt;qt 4.8.4&lt;/a&gt;, and un-compress the file onto a separate directory.&lt;/p&gt;

&lt;p&gt;Before running the installation run the following command to get all the dependencies&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get build-dep libqt4-core libqt4-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
This will download and install the necessary libraries for qt4.&lt;/p&gt;

&lt;p&gt;You can also review which libraries are required &lt;a href=&#34;http://qt-project.org/doc/qt-4.8/requirements-x11.html&#34; title=&#34;qt4 Requirements&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to build everything then just run&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;./configure
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will build everything but it will take a lot of time, if you are like me and you don&amp;rsquo;t need the examples, tutorials, demos run the following command&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;./configure \
       -debug-and-release \
       -opensource \
       -developer-build \
       -no-webkit \
       -nomake examples \
       -nomake demos \
       -nomake docs \
       -fast
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After this one is finished and if there are no errors, you can proceed to running&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;make
sudo make install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Make sure you build the source code without root privileges and after that if you want to install it globally run the &lt;strong&gt;make install &lt;/strong&gt;command with &lt;strong&gt;sudo&lt;/strong&gt;&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Intel Wireless N Cards</title>
            <link>https://matoski.com/article/intel-wireless-n-cards/</link>
            <pubDate>Thu, 03 Jan 2013 03:59:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/intel-wireless-n-cards/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve had a lot of problems with the Intel wireless cards, when connecting to Wireless N Routers.&lt;/p&gt;

&lt;p&gt;The speed cuts off, or drops to 1MB/s, you can set the rate manually by issuing the following command, replace &lt;strong&gt;wlan0&lt;/strong&gt; with the equivalent for your system, but usually it&amp;rsquo;s &lt;strong&gt;wlan0&lt;/strong&gt; unless you have multiple wireless cards.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;iwconfig wlan0 rate 54M
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
This is a temporary solution and it won&amp;rsquo;t solve the problem permanently.&lt;/p&gt;

&lt;p&gt;To solve this permanently issue the following command, to create a new file:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;quot;options iwlagn 11n_disable=1&amp;quot; &amp;gt; /etc/modprobe.d/intel_11n_disable.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After this we need issue the following commands:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;update-initramfs -u
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then we need to either restart the system, or we can just issue the following commands to reinitialize the wifi driver.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;modprobe -r iwlagn
modprobe iwlagn
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Tracing jQuery trigger events</title>
            <link>https://matoski.com/article/tracing-jquery-trigger-events/</link>
            <pubDate>Wed, 02 Jan 2013 10:13:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/tracing-jquery-trigger-events/</guid>
            <description>&lt;p&gt;We will see how to modify the trigger event of jQuery so we can see everytime there is an event triggered, this is really usefull if you need debuging&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve had to see what trigger events have been fired when I was using jQuery, or to see if the trigger events I&amp;rsquo;ve done were working for a project.&lt;/p&gt;

&lt;p&gt;So I had to modify the trigger event, but to also keep the functionality of jQuery the same so the following command gave me the stuff I needed to modify the trigger event.&lt;/p&gt;

&lt;p&gt;Just write the following in developer tools of Chrome&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;$.fn.trigger
function ( type, data ) {
		return this.each(function() {
			jQuery.event.trigger( type, data, this );
		});
	}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So you modify this to the following, and now every-time there is a trigger event from jQuery you will be notified in the console.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;$.fn.trigger = function ( type, data ) {
        return this.each(function() {
            console.log(&amp;quot;trigger&amp;quot;, type, data, this);
            jQuery.event.trigger( type, data, this );
        });
    };
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Setting JAVA_HOME to proper value</title>
            <link>https://matoski.com/article/setting-java_home-to-proper-value/</link>
            <pubDate>Sun, 07 Oct 2012 21:51:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/setting-java_home-to-proper-value/</guid>
            <description>&lt;p&gt;There were a lot of times, when I needed to set up more than one java version.

We should add the following line at the beginning of the file &lt;strong&gt;/etc/environment&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;JAVA_HOME=$(readlink -f /usr/bin/java | sed &amp;quot;s:bin/java::&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This way every-time you start the system it will read which java has been selected by &lt;strong&gt;update-alternatives&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Also if you change your java version often you can add it to your &lt;strong&gt;.bashrc&lt;/strong&gt; file so everytime you login in a shell it will read and set JAVA_HOME to the proper directory.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Compile/Backport packages from source Ubuntu/Debian</title>
            <link>https://matoski.com/article/compilebackport-packages-from-source-ubuntudebian/</link>
            <pubDate>Thu, 12 Apr 2012 09:52:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/compilebackport-packages-from-source-ubuntudebian/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve run into several situations where the packages I want are not available on the distribution version I&amp;rsquo;m running.&lt;/p&gt;

&lt;p&gt;One way to solve this is to upgrade to a newer distribution that contains the packages you want.&lt;/p&gt;

&lt;p&gt;Or you can just compile them your self and install them after that.

This is done in two steps, one is we need to fetch the sources and then we need to compile them.&lt;/p&gt;

&lt;p&gt;As I&amp;rsquo;m on on Lucid 10.04 and I need a newer &lt;strong&gt;libnotify&lt;/strong&gt; library, I will get it from &lt;strong&gt;Maveric &lt;/strong&gt;sources repository and then compile it.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-src install libnotify
apt-src build libnotify
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or just run the following, it will have the same effect as the previous two lines:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-src install -b -i libnotify
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After this you will have the following packages:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;libnotify1_0.5.0-2ubuntu1_amd64.deb
libnotify-bin_0.5.0-2ubuntu1_amd64.deb
libnotify-dev_0.5.0-2ubuntu1_amd64.deb
libnotify-doc_0.5.0-2ubuntu1_all.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have read &lt;a href=&#34;https://matoski.com/articles/creating-your-own-local-compiled-packages-repository/&#34; title=&#34;Creating your own local compiled packages repository&#34;&gt;Creating your own local compiled packages repository&lt;/a&gt; you can just move those files to the folder described there and after that run the update script and then run:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;apt-get upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It will upgrade the version of &lt;strong&gt;libnotify &lt;/strong&gt;to the one you just compiled.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Daily SVN Incremental Backup</title>
            <link>https://matoski.com/article/daily-svn-incremental-backup/</link>
            <pubDate>Thu, 20 Oct 2011 08:14:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/daily-svn-incremental-backup/</guid>
            <description>&lt;p&gt;Lately I&amp;rsquo;ve had a lot of repositories to deal with, so I wanted to back it up, beside doing the usual, creating a hotcopy I decided to create incremental backups of all the repositories, so we can restore them even if for some reason the hotcopy fails or the repository get&amp;rsquo;s corrupted, both of them the master and the hotcopy.&lt;/p&gt;

&lt;p&gt;So I need to do this on windows, and on linux (ubuntu), but this should work on all the distributions of linux, provided you have the required programs installed, this is mostly for Cygwin, because usually the tools required come pre-installed on the distributions, and you also have to have installed Subversion and have it in your path.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/bash

SCRIPT_NAME=`basename $0`

function help() {

    echo
    echo &amp;quot;Incremental dumping for SVN by Ilija Matoski (ilijamt@gmail.com)&amp;quot;
    echo &amp;quot;No command arguments detected, there need to be as following.&amp;quot;
    echo &amp;quot;Usage: ${SCRIPT_NAME} &amp;lt;path_to_repo&amp;gt; &amp;lt;path_to_dump&amp;gt; &amp;lt;identifier&amp;gt;&amp;quot;
    echo
    echo &amp;quot;Parameters:&amp;quot;
    echo &amp;quot;  &amp;lt;path_to_repo&amp;gt; - Where is the repository located&amp;quot;
    echo &amp;quot;  &amp;lt;path_to_dump&amp;gt; - Where should we dump the repository&amp;quot;
    echo &amp;quot;  &amp;lt;identifier&amp;gt;   - Used to record the last recorded dump, always stored in the file with the&amp;quot;
    echo &amp;quot;                   dumps from the repo, so we can keep a track of where we at with dumping,&amp;quot;
    echo &amp;quot;                   also identifier is used to generate the dumps names.&amp;quot;
    echo &amp;quot;  &amp;lt;compress&amp;gt;     - compress the output dump (default: false)&amp;quot;
    echo
    echo &amp;quot;Examples:&amp;quot;
    echo &amp;quot;  ${SCRIPT_NAME} test /backup/SVN/test test&amp;quot;
    echo &amp;quot;  ${SCRIPT_NAME} test /backup/SVN/test test true&amp;quot;
    echo

    exit -1

}

if [ ! $# -ge 3 ]; then
    help
fi

PATH_TO_REPO=$1
PATH_TO_DUMP=$2
IDENTIFIER=$3
COMPRESS=$4

# Check if they are empty and if they are quit
if [[ -z &amp;quot;$PATH_TO_REPO&amp;quot; || -z &amp;quot;$PATH_TO_DUMP&amp;quot; || -z &amp;quot;$IDENTIFIER&amp;quot; ]]; then
    help
fi

if [ &amp;quot;$COMPRESS&amp;quot; == &amp;quot;true&amp;quot; ]; then
    COMPRESS=&amp;quot;true&amp;quot;
else
    COMPRESS=&amp;quot;false&amp;quot;
fi

# Check if the repo path exists, and if it&#39;s a valid SVN repository
if [ ! -d &amp;quot;$PATH_TO_REPO&amp;quot; ]; then
    echo &amp;quot;Directory ${PATH_TO_REPO} doesn&#39;t exist.&amp;quot;
    echo &amp;quot;Exiting.&amp;quot;
    exit -1
fi

# Check if SVN folder is valid, check for format file in the directory
if [ ! -f &amp;quot;${PATH_TO_REPO}/format&amp;quot; ]; then
    echo &amp;quot;Probably not a valid SVN repository.&amp;quot;
    echo &amp;quot;Exiting.&amp;quot;
    exit -1
else
    echo &amp;quot;Probably a valid SVN repository detected. Continuing.&amp;quot;
fi

# Check if destination exist and if we have writing permissions
# and if it doesn&#39;t then create it
if [ ! -d &amp;quot;$PATH_TO_DUMP&amp;quot; ]; then
    echo &amp;quot;Dump directory doesn&#39;t exist, creating a new directory: $PATH_TO_DUMP&amp;quot;
    mkdir -p &amp;quot;$PATH_TO_DUMP&amp;quot;
fi

# Check if the directory has writing permissions
if [ ! -w &amp;quot;$PATH_TO_DUMP&amp;quot; ]; then
    echo &amp;quot;No writing permissions.&amp;quot;
    echo &amp;quot;Exiting.&amp;quot;
    exit -1
fi

# Get the full paths if we have relative paths in the command line
PATH_TO_REPO=`cd $PATH_TO_REPO; pwd`
PATH_TO_DUMP=`cd $PATH_TO_DUMP; pwd`
IDENTIFIER_PATH=&amp;quot;$PATH_TO_DUMP/$IDENTIFIER&amp;quot;
DUMP_FILE_MASK=&amp;quot;$IDENTIFIER_PATH&amp;quot;
# Check if the identifier exists
if [ ! -f &amp;quot;$IDENTIFIER_PATH&amp;quot; ]; then
    # Doesn&#39;t exist, so we create it and set it to revision 0
    echo &amp;quot;-1&amp;quot; &amp;gt; &amp;quot;$IDENTIFIER_PATH&amp;quot;
fi

CYGWIN=`uname -o`

# Check if we are running cygwin, for windows
if [ &amp;quot;$CYGWIN&amp;quot; == &amp;quot;Cygwin&amp;quot; ]; then
    CYGWIN=&amp;quot;true&amp;quot;
else
    CYGWIN=&amp;quot;false&amp;quot;
fi

# Set up some stuff for cygwin
if [ &amp;quot;$CYGWIN&amp;quot; == &amp;quot;true&amp;quot; ]; then
    repoDrive=&amp;quot;${PATH_TO_REPO:10:1}&amp;quot;
    REPO_URL=`echo $PATH_TO_REPO | sed &amp;quot;s/\/cygdrive\/${repoDrive}/${repoDrive}:/g&amp;quot;`
    REPO_DIR=&amp;quot;$REPO_URL&amp;quot;
    REPO_URL=&amp;quot;file:///${REPO_URL}&amp;quot;
else
    REPO_URL=&amp;quot;file:///$PATH_TO_REPO&amp;quot;
    REPO_DIR=&amp;quot;$PATH_TO_REPO&amp;quot;
fi

# Get the last revision from the directory repository
REPO_LAST_REVISION=`svn info $REPO_URL | grep &amp;quot;^Revision: &amp;quot; | sed &amp;quot;s/Revision: //g&amp;quot;`
REPO_DUMPED_REVISION=`cat &amp;quot;$PATH_TO_DUMP/$IDENTIFIER&amp;quot;`

# check if the call succeded
if [[ $REPO_LAST_REVISION  != [0-9]* ]]; then
    echo &amp;quot;Cannot fetch information from SVN repository&amp;quot;
    exit -1
fi

# Increment it by one number from the last revision
# so we don&#39;t re dump the last one again
REPO_DUMPED_REVISION=$(($REPO_DUMPED_REVISION+1))

echo &amp;quot;Settings&amp;quot;
echo &amp;quot;  Compress: ${COMPRESS}&amp;quot;
echo &amp;quot;  Directory: ${REPO_URL}&amp;quot;
echo &amp;quot;  Dump: ${PATH_TO_DUMP}&amp;quot;
echo &amp;quot;  Identifier: ${IDENTIFIER}&amp;quot;
echo &amp;quot;  Cygwin: ${CYGWIN}&amp;quot;
echo
echo &amp;quot;Repository&amp;quot;
echo &amp;quot;  Revisions: ${REPO_LAST_REVISION}&amp;quot;
echo &amp;quot;  Dumping from: ${REPO_DUMPED_REVISION}&amp;quot;
echo

if [ $REPO_DUMPED_REVISION -gt $REPO_LAST_REVISION ]; then
    echo &amp;quot;ERROR: Dumped revision bigger than the revision in the repository&amp;quot;
    echo &amp;quot;Exiting.&amp;quot;
    exit -1
fi

echo &amp;quot;Starting to dump&amp;quot;

list=$(seq &amp;quot;$REPO_DUMPED_REVISION&amp;quot; 1 &amp;quot;$REPO_LAST_REVISION&amp;quot; )

for rev in $list
do

    padding_rev=`printf &amp;quot;%08d&amp;quot; $rev`
    dump_file=&amp;quot;$DUMP_FILE_MASK.rev.$padding_rev.svndump&amp;quot;

    if [ &amp;quot;$COMPRESS&amp;quot; == &amp;quot;true&amp;quot; ]; then
        dump_file=&amp;quot;${dump_file}.gz&amp;quot;
    fi

    echo &amp;quot;  Dumping revision $rev of $REPO_LAST_REVISION&amp;quot;

    if [ &amp;quot;$COMPRESS&amp;quot; == &amp;quot;true&amp;quot; ]; then
        svnadmin dump &amp;quot;$REPO_DIR&amp;quot; --revision &amp;quot;$rev:$rev&amp;quot; --incremental --deltas -q | gzip &amp;gt; $dump_file
    else
        svnadmin dump &amp;quot;$REPO_DIR&amp;quot; --revision &amp;quot;$rev:$rev&amp;quot; --incremental --deltas -q &amp;gt; $dump_file
    fi

    # put the new dumped revision in the file
    echo $rev &amp;gt; &amp;quot;$IDENTIFIER_PATH&amp;quot;

done

echo &amp;quot;Done.&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;rsquo;s really easy to use this to create a incremental backup of your SVN repository.
If you need help just write, without any arguments:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;./incremental_backup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And it will show you the help/usage screen.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Domain and Web hosting on different servers</title>
            <link>https://matoski.com/article/domain-and-web-hosting-on-different-servers/</link>
            <pubDate>Thu, 08 Sep 2011 09:08:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/domain-and-web-hosting-on-different-servers/</guid>
            <description>&lt;p&gt;If you want a website you need two things, the domain name and the web hosting. I ran into a small problem a while ago, the usual method of integrating them together is simple, just point the domain nameservers to the web hosting nameservers and it&amp;rsquo;s finished, after the DNS fully propagates you can assign it to your account.&lt;/p&gt;

&lt;p&gt;
My problem was this I had a web hosting account on &lt;a href=&#34;http://www.hostmonster.com/&#34; title=&#34;http://www.hostmonster.com/&#34;&gt;Hostmonster&lt;/a&gt; and a I had a &amp;ldquo;.dk&amp;rdquo; domain registered on &lt;a href=&#34;http://www.bb-online.com/&#34; title=&#34;http://www.bb-online.com/&#34;&gt;BB-Online&lt;/a&gt;, and it turns out I can&amp;rsquo;t point the nameservers to the hostmonster ones, because for some reason they can&amp;rsquo;t communicate between them.&lt;/p&gt;

&lt;p&gt;And, I was wondering what to do, but the solution turned out to be pretty simple, you just edit your DNS Zone File for the domain and point it to the server that you use in  &lt;a href=&#34;http://www.hostmonster.com/&#34; title=&#34;http://www.hostmonster.com/&#34;&gt;Hostmonster&lt;/a&gt;, it&amp;rsquo;s in cPanel on the side where it says IP Address, in my case it says &amp;ldquo;Shared IP Address&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;After that you just sit back and wait for the DNS to update, between 24-48 hours.&lt;/p&gt;

&lt;p&gt;This method should be applicable almost on any web hosting.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Move the steam apps installation folder</title>
            <link>https://matoski.com/article/steamapps-folder-move/</link>
            <pubDate>Thu, 28 Jul 2011 20:17:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/steamapps-folder-move/</guid>
            <description>&lt;p&gt;Well like a lot of people, I had a problem that I have no space on my install partition, at best around 2GB-3GB, so I wanted to move the SteamApp folder to a different partition which had a lot more space, but I couldn&amp;rsquo;t find anywhere in setting where to set install directory or where to change the install directory.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;You have only two choices if you have installed Windows Vista or Windows 7, there is an utility called:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/NTFS_symbolic_link&#34; title=&#34;NTFS symbolic link&#34;&gt;mklink&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This creates a link between folders on different partitions, so you can have installed some stuff on your main partition and some on a different partition, so what I did is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Shutdown Steam if it&amp;rsquo;s ruining&lt;/li&gt;
&lt;li&gt;Create a new folder on the partition where you have space, in my case I have on partition &lt;strong&gt;D&lt;/strong&gt; so I decided to create a folder there called &lt;strong&gt;SteamApps&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Copy everything from the folder called **steamapps **in the installation directory of steam, to the new directory called **SteamApps, **on your new partition, in my case partition &lt;strong&gt;D&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Delete the directory called &lt;strong&gt;steamapps&lt;/strong&gt; in the installation directory as you wont need it anymore&lt;/li&gt;
&lt;li&gt;Go to the steam installation directory and execute the command to create a junction between folders
&lt;code&gt;
mklink /J steamapps D:\SteamApps
&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And that&amp;rsquo;s it, but what about all the other people who don&amp;rsquo;t use Windows Vista or Windows 7, well there is a solution for them too, and it can be used on Windows XP too, but the prerequisite is that the partitions need to be NTFS, or it wont work.&lt;/p&gt;

&lt;p&gt;There is an application that was released with Windows 2000, that can do the same thing mklink can&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&#34;http://support.microsoft.com/kb/205524/en-us&#34; title=&#34;How to create and manipulate NTFS junction points&#34;&gt;linkd&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And don&amp;rsquo;t ask me where to find it, you can easily find it with a search on your favorite search provider.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Unix timestamp in Intersystems Caché</title>
            <link>https://matoski.com/article/unix-timestamp-in-intersystems-cache/</link>
            <pubDate>Fri, 22 Jul 2011 08:07:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/unix-timestamp-in-intersystems-cache/</guid>
            <description>&lt;p&gt;I wanted to have Unix Timestamp in Intersystems Caché, but their timestamp is a little different than the one you are used  to in other programming languages, their timestamp is &amp;ldquo;&lt;strong&gt;ddddd,sssss.fff&lt;/strong&gt;&amp;rdquo;, while Unix Timestamp is defined as the number of seconds elapsed since midnight Coordinated Universal Time (UTC) of January 1, 1970, not counting leap seconds.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;So to convert Intersystems version to Unix Timestamp we use this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;({CACHETIMESTAMP} - 47117 * 86400 + $PIECE({CACHETIMESTAMP},&amp;quot;,&amp;quot;,2))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So to convert Unix Timestamp to Intersystems version we use this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(({UNIXTIMESTAMP}\86400 + 47117)_&amp;quot;,&amp;quot;_({UNIXTIMESTAMP} # 86400))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can combine these and create our own macros that will do the conversion on the fly when compiling.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#define toUnixTimestamp(%ct) (%ct - 47117 * 86400 + $PIECE(%ct,&amp;quot;,&amp;quot;,2))
#define toCacheTimestamp(%ut) ((%ut\86400 + 47117)_&amp;quot;,&amp;quot;_(%ut # 86400))
#define addToUnixTimestamp(%ct, %a) ($$$toUnixTimestamp(%ct) + %a)
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Remove old kernels from debian based systems</title>
            <link>https://matoski.com/article/remove-old-kernels-from-debian-based-systems/</link>
            <pubDate>Wed, 20 Jul 2011 22:29:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/remove-old-kernels-from-debian-based-systems/</guid>
            <description>&lt;p&gt;I&amp;rsquo;ve always hated that there is no simple way to remove all the kernels you don&amp;rsquo;t use from the Debian/Ubuntu system.&lt;/p&gt;

&lt;p&gt;But fortunately it&amp;rsquo;s really easy to do so, from the command line.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;First thing reboot your system and start the kernel you want to keep, in this instance I want to keep the newest only, because I&amp;rsquo;m dual-booting between Windows and Ubuntu, I just keep only the latest kernel.&lt;/p&gt;

&lt;p&gt;So to do that we just write in the console, you can also use purge instead of remove.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;dpkg -l linux-* | awk &#39;/^ii/{ print $2}&#39; | grep -v -e `uname -r | cut -f1,2 -d&amp;quot;-&amp;quot;` | grep -e [0-9] | xargs sudo apt-get -y remove
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;dpkg -l linux-* | awk &#39;/^ii/{ print $2}&#39; | grep -v -e `uname -r | cut -f1,2 -d&amp;quot;-&amp;quot;` | grep -e [0-9] | xargs sudo apt-get -y purge
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So maybe I should explain what is happening here, though if you have used linux you know most if not all of these commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;awk&lt;/strong&gt; - used for textual data manipulation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;grep&lt;/strong&gt; - filters out the data from the input&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cut&lt;/strong&gt; - remove sections from each line of files&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;uname&lt;/strong&gt; - shows system information&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dpkg&lt;/strong&gt; - package manager in debian distributions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;xargs&lt;/strong&gt; - build and execute command lines from standard input&lt;/p&gt;

&lt;p&gt;So basically I use &lt;strong&gt;dpkg&lt;/strong&gt; to get  the linux kernel files, and we pipe it to &lt;strong&gt;awk&lt;/strong&gt; to filter out everything but the package name, and we use &lt;strong&gt;uname&lt;/strong&gt; and &lt;strong&gt;cut&lt;/strong&gt; to get the kernel version only, and when we put it together we select all linux kernel files except the one provided by &lt;strong&gt;uname&lt;/strong&gt; .&lt;/p&gt;

&lt;p&gt;And that is it, the best way to learn it is to try and experiment by yourself.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Show empty categories in WordPress</title>
            <link>https://matoski.com/article/show-empty-categories-in-wordpress/</link>
            <pubDate>Sat, 16 Jul 2011 10:22:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/show-empty-categories-in-wordpress/</guid>
            <description>&lt;p&gt;I wanted to show all my categories on the screen on the sidebar widget, because if the category doesn&amp;rsquo;t have any posts inside the categories doesn&amp;rsquo;t show.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;So, one way of fixing it is to assign an dummy post to all categories, and they will show then, but instead of doing that we can add a filter that will always show our categories, without assigning a post to all the categories in WordPress.&lt;/p&gt;

&lt;p&gt;Open the file called &amp;ldquo;/wp-includes/default-filters.php&amp;rdquo; in the WordPress root directory, and add this snipped to the end of the file.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-php&#34;&gt;function force_widget_cat_args($cat_args) {
    $cat_args[&#39;hide_empty&#39;] = 0;
    return $cat_args;
}

add_filter( &#39;widget_categories_args&#39;, &#39;force_widget_cat_args&#39; );
&lt;/code&gt;&lt;/pre&gt;</description>
        </item>
        
        <item>
            <title>Hello</title>
            <link>https://matoski.com/article/hello/</link>
            <pubDate>Tue, 12 Jul 2011 20:13:00 +0000</pubDate>
            
            <guid>https://matoski.com/article/hello/</guid>
            <description>&lt;p&gt;Hi, I&amp;rsquo;ve finally decided to set up my blog.&lt;/p&gt;

&lt;p&gt;So here it is and hope you guys have fun here.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m thinking of starting this blog off, with some kind of android app, like show you how to build it from scratch, or something else, but we will see, the night is still young.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
