One of the main drawbacks I can think of to a static blog is the lack of easy search function. Because all the files are pre-generated HTML, CSS, and JS, there's no server-side interpreted language that can perform actions and no database of posts which can be filtered. I decided to change this and did a little proof-of-concept on my local machine for how it would work. If you're running a [Hugo](http://gohugo.io/) blog, you can repeat my little experiment yourself! If not, you can follow along and modify parts of it to work with your own system, as this should work with platforms like Jekyll too. ## Elasticsearch And Loading Posts Firstly, set up an Ubuntu virtual machine with it's own private IP and install Oracle's Java 8 JDK (I recommend using the [webupd8team PPA](https://launchpad.net/~webupd8team/+archive/ubuntu/java)), then install a recent version of [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html). Following the linked docs should help you out. Lastly, make sure Python3, PIP and Varnish are installed too. You'll need two Python packages, you can install them with the following command: ``` pip3 install python-frontmatter elasticsearch ``` Now check out your Hugo blog repository. Change into the directory and create a new file, `elasticsearch.py` and fill it with the following: ``` import frontmatter import glob from datetime import datetime from elasticsearch import Elasticsearch es = Elasticsearch() es.indices.delete(index='blog') for file in glob.iglob('content/**/*.md', recursive=True): post = frontmatter.load(file) doc = { 'title': post['title'], 'text': post.content, } res = es.index(index="blog", doc_type='post', body=doc) ``` You can now run this file with `python3 blog.py`. What's it doing? It's going through your blog content file and every Markdown file gets read and has the "frontmatter" (metadata in YAML, TOML, or JSON format) turned into a dictionary. This dictionary is then turned into an Elasticsearch document and indexed for future searching. ## Configuring Varnish Next up, you'll want to edit your `/etc/varnish/default.vcl` file and change the backend port number to `9200` and insert the following inside the `vcl_recv` section: ``` if (req.method != "GET" && req.method != "OPTIONS" && req.method != "HEAD")$ /* We only deal with GET and OPTIONS and HEAD by default */ return (synth(405)); } ``` This limits us to only performing simple GET queries (and preflight checks for CORS) to prevent anyone in the world from indexing or deleting documents from our Elasticsearch node. You'll also want to add some Access-Control headers, so insert the following into the `vcl_deliver` portion: ``` set resp.http.Access-Control-Allow-Origin = "*"; set resp.http.Access-Control-Allow-Methods = "GET, OPTIONS, HEAD"; set resp.http.Access-Control-Allow-Headers = "Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token"; ``` This will allow us to make search queries in JavaScript from our statically hosted blog to our Elasticsearch node without need for any server in the middle (except our reverse proxy, Varnish). Please restart your Varnish install so it picks up the new configuration and continue on to the next section. ## JavaScript-Based Search Next up let's create our search page. If you're running a Hugo blog, you'll probably want to create a file in the `static` top level directory called `search.html` and fill it with something like so: ```