This is my first blog post, mainly about my static website setup.

TL;DR: I use vimwiki, combined with a simple static server I wrote in golang to serve content. Apart from that, I use prism.js for code highlighting. All the css is hand-written by me.

I think it's tradition that every time a developer hosts their own website, the first post has to be about how to host it. I am no exception, and this is my "hello world" for a static website setup.

Strictly speaking, this is not a pure static site. I have written some APIs, and plan to write more, which help in my day-to-day task management. However, all of those APIs require authorization. As I am the only person at present who is going to use those, I am fine with that. Otherwise, I would have to read up on all sorts of web-security techniques, of which I have only a very shallow knowledge.

Currently, I have rented a small server from scaleway, and purchased my domain name from gandi.

If all you want is to write a blog, there's no reason to build your own server. Use wordpress, or hugo, or whatever's popular and provides good support. Not only they will have more tooling, they would also be more secure and, in general, will provide better management.

In my case, since I left my job and started my Master's, I have felt myself getting a little rusty. I thought this would be a good starter project. I would have complete control over the final project, and would also learn some stuff about hosting and how DNS works as well.

I use vimwiki for content generation. It is an excellent plugin, for creating your own knowledge base about stuff.

Here are the contents of my personal wiki:
website-setup_1.png

However, I ran into some trouble with links in wiki files.

In the beginning, there was no server. Just simple html files, viewed by a browser. This approach worked well for me when I was using linux, but since shifting to Windows + WSL, this has some problems. Absolute links to other files stop working, and while I could have gone around that, I thought it would be better if instead of linking files, I simply hosted them in a server, and then provide the url's to those files.

Now, the problem was simply creating a static server. I wrote a simple server in golang. Go is a fantastic language, for such things, and my code for such a server was easily contained in a single file initially:



package main

import (
	"log"
	"net/http"
	"time"

	"github.com/gorilla/mux"
)

const (
	// DomainName is the name of my domain
	DomainName = "orakem.site"
	// BLOG is a placeholder, to be used for "blog.orakem.ste"
	BLOG = "blog"

	// WIKI is a placeholder, to be used for "wiki.orakem.ste"
	WIKI = "wiki"
)

func main() {
	log.Println("Starting the server")

	r := mux.NewRouter()

	createSubRouters(r)

	srv := &http.Server{
		Handler: r,
		// Good practice: enforce timeouts for servers you create!
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
		Addr: ":8080"
	}

	certFile := Config.CertFile
	keyFile := Config.KeyFile
	log.Fatal(srv.ListenAndServe())

}

func mapStaticFiles(r *mux.Router) {
	// mathjax and js folders for js and css
	r.PathPrefix("/mathjax/").Handler(http.StripPrefix("/mathjax/", http.FileServer(http.Dir(Config.MathjaxDir))))
	r.PathPrefix("/js/").Handler(http.StripPrefix("/js/", http.FileServer(http.Dir(Config.JsCSSDir))))
}

// createSubRouters create routers for wiki and blogs
func createSubRouters(r *mux.Router) {

	// map wiki pages
	wikiSubRouter := r.Host(WIKI + "." + DomainName).Subrouter()
	mapStaticFiles(wikiSubRouter)

	wikiSubRouter.PathPrefix("/files/").Handler(http.StripPrefix("/files/", http.FileServer(http.Dir(Config.FilesDir))))
	wikiSubRouter.PathPrefix("/").Handler(http.StripPrefix("/", http.FileServer(http.Dir("../html"))))

	// map blog pages
	blogSubrouter := r.Host(BLOG + "." + DomainName).Subrouter()
	mapStaticFiles(blogSubrouter)

	blogSubrouter.PathPrefix("/files/").Handler(http.StripPrefix("/files/", http.FileServer(http.Dir("../blog/files"))))
	blogSubrouter.PathPrefix("/").Handler(http.StripPrefix("/", http.FileServer(http.Dir("../html/blog"))))

}

Not very good, but gets the job done. Prior to this, I had no idea that you can not make javaScript requests across different domains by default. There are ways to bypass it, but my use-case was not relevant to them, so I simply hosted the required files under the "js" folder.

As mentioned, I am renting a small box from scaleway. It's one of the cheapest ones I could find, "DEV1-S", which only costs me €3/per month. It runs Centos 7.6, which is good enough for me. I did have to manually install new version of vim on it, but it's good enough.

For domain, I went with gandi. Prior to this, I had no idea how domains worked. So after creating my domain, I read up a bit on how to modify my DNS records, and added the following entries:

@ 10800 IN A 51.158.96.58
blog 1800 IN A 51.158.96.58
wiki 1800 IN A 51.158.96.58

where 51.158.96.581 is the public ip of my scaleway box. The first line directs adds entry for "orakem.site". The next following lines add entries for dub-domains "blog.orakem.site" and "wiki.orakem.site". Embarrassingly, this took me a long time to figure out. In the end, I went ahead and read the official RFC-1035 documentation. (Which I should have done in the first place instead of googling "dns record add subdomain", which irritatingly brings up links from every domain provider, each with annoying graphics and buttons and images and stuff).

There are almost no reasons not to use HTTPS in 2020, so I decided to implement that as well.

I used LetsEncrypt to get a certificate. Their process was simple, and I had gotten a new certificate in less than 5 minutes. Looking up how to add a sub-domain was not that simple, but still easy. One thing that is not always mentioned is that you have to keep your server running, so that certbot can authenticate you. Alternatively, you can directly add the files to your webroot directory, but I did not use that option.

The changes in the code were very small. I simply had to add the certificate files, and use the ListenAndServeTLS function.


	srv := &http.Server{
		Handler: r,
		// Good practice: enforce timeouts for servers you create!
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
		TLSConfig: &tls.Config{
			MinVersion: tls.VersionTLS12,
		},
	}

	srv.Addr = ":443"
	certFile := Config.CertFile
	keyFile := Config.KeyFile
	log.Fatal(srv.ListenAndServeTLS(certFile, keyFile))

I also changed the minimum TLS version supported to 1.2, since TLS 1.1 is considered vulnerable. I will probably change this to TLS 1.3 in some time, once I read up on it. I am simply following the advice of people more experienced than me. I do not know the difference between the different versions of TLS, except for the fact that TLS 1.1 uses MD5 and SHA-1, and those are cryptographically weak hashes. (That still doesn't prevent people from using them for hashing passwords).

After adding support for HTTPS, I run into a little snag with vimwiki. My default template for wiki files contained links to static files with protocol prefix as "http", which failed to work, since it violated the same origin policy.

So I wrote a simple deployment script (in bash, shamefully). When I am writing my code on local computer, and need to link against internal files, I always write links as "blog.localhost" (followed by some special characters that I don't use anywhere else). I try not to use internal links or absolute links. Then, when my script runs, it replaces all such occurrences by "blog.orakem.site".


This concludes part 1. In part 2, I will write about how to expand the server, CSS, and how to add authentication to above as well (for private use). I will also the link the github repo where my server code is hosted.