macroblog.rs @ 231f2cb2205988cf87062bc9f595307af1ed827f

feat: Add missing blog post

Add the missing blog post from my hugo blog. Also add a locustfile so I
can do some stress test locally.
  1diff --git a/.gitignore b/.gitignore
  2index 96ef862d54e5aa15d99a496109dfeca5def1163e..634077d90c910d86bd41afa57fe39873037bde26 100644
  3--- a/.gitignore
  4+++ b/.gitignore
  5@@ -1,2 +1,3 @@
  6 target/
  7 .idea/
  8+__pycache__/
  9diff --git a/content/posts/2019-03-03Welcome_to_my_blog.html b/content/posts/2019-03-03Welcome_to_my_blog.html
 10new file mode 100644
 11index 0000000000000000000000000000000000000000..10b1f05fea6422809c15e0f9f3a234f52d461122
 12--- /dev/null
 13+++ b/content/posts/2019-03-03Welcome_to_my_blog.html
 14@@ -0,0 +1,6 @@
 15+<section>
 16+    <p>
 17+      On this blog, I'll be posting some personal projects that I'm working on
 18+      or just logging stuff that I don't want to forget.
 19+    </p>
 20+</section>
 21diff --git a/content/posts/2019-03-07Automating_desktop_setup_with_ansible-pull_part-1.html b/content/posts/2019-03-07Automating_desktop_setup_with_ansible-pull_part-1.html
 22new file mode 100644
 23index 0000000000000000000000000000000000000000..d06a648c3793c6d13fbaae4ac818d84787731e6f
 24--- /dev/null
 25+++ b/content/posts/2019-03-07Automating_desktop_setup_with_ansible-pull_part-1.html
 26@@ -0,0 +1,94 @@
 27+<section>
 28+  <p>
 29+    Every time that I do a clean install on my machine it takes a few hours till I
 30+    get to point where I was before formatting it, install all packages, select
 31+    themes, icons, fonts, install IDEs, extensions and so on. After doing it a few
 32+    times I came to the conclusion that I would save time by spending time
 33+    automating this chore, and as a result, I could tinker a little more with my
 34+    system and not worry about spending a weekend re-installing everything (which
 35+    have happened more time that I'd like to remember).
 36+  </p>
 37+  <p>
 38+    So after a few attempts using python and bash I ended with many files and
 39+    keep everything organized and concise turned out to be more tedious than the
 40+    setup itself. So there comes <a href="https://www.ansible.com/">Ansible</a>.
 41+    It is an enterprise-graded software used to automate tasks. It has A LOT OF
 42+    features and it can be really helpful if you're a sysadmin but for now we're
 43+    going to focuson
 44+    <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html#ansible-pull">
 45+      Ansible Pull
 46+    </a>
 47+    and
 48+    <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks.html">
 49+      Playbooks
 50+    </a>. As better described:
 51+    <blockquote>
 52+      [Ansible-Pull] is used to up a remote copy of ansible on each managed
 53+      node, each set to run via cron and update playbook source via a source
 54+      repository. This inverts the default push architecture of Ansible into a
 55+      pull architecture, which has near-limitless scaling potential.
 56+
 57+      Playbooks are Ansible’s configuration, deployment, and orchestration
 58+      language. They can describe a policy you want your remote systems to
 59+      enforce, or a set of steps in a general IT process.
 60+      (<a href="https://docs.ansible.com/ansible/latest/cli/ansible-pull.html">source</a>)
 61+    </blockquote>
 62+  </p>
 63+  <p>
 64+    The goal is to pull and run a playbook remotely using a git repository. The
 65+    playbook will describe the tasks needed to setup our machine from scratch.
 66+    <br/>
 67+    But first lets tinker a bit a with playbooks locally with ansible-playbook,
 68+    to do so we need to add localhost to ansible's hosts list. Add it to
 69+    /etc/ansible/hosts:
 70+<pre><code>[all]
 71+localhost</code></pre>
 72+  </p>
 73+  <p>
 74+    As an experiment we're going to write a asks to install vim. Currently, I'm
 75+    using Fedora thus we going to use dnf modeule to install packages, but if
 76+    you're using another distribution look for a equivalent module like apt
 77+    module for Ubuntu.
 78+
 79+    The playbook to install is quite simple:
 80+
 81+<pre><code># main.yaml
 82+- hosts: all
 83+  tasks:
 84+     - name: install vim
 85+       dnf:
 86+         name: vim
 87+         state: latest</code></pre>
 88+    <dl>
 89+        <dt>host</dt>
 90+        <dd>it is required and it has to match our hosts otherwise the playbook won't run.</dd>
 91+        <dt>taks</dt>
 92+        <dd>
 93+          it is the list of tasks that the playbook will perform, in this case
 94+          will be dnf install vim.
 95+        </dd>
 96+    </dl>
 97+  </p>
 98+  <p>
 99+    To run a playbook use the command ansible-playbook commando to run main.yml
100+    direct from disk, do to so just run the following command:
101+<pre><code>sudo ansible-playbook --connection=local main.yml</code></pre>
102+  </p>
103+  <p>
104+    After a few seconds, vim will be installed on your machine.
105+<pre><code>PLAY [all] *************************************************************
106+
107+TASK [Gathering Facts] *************************************************
108+ok: [localhost]
109+
110+TASK [install vim] *****************************************************
111+ok: [localhost]
112+
113+PLAY RECAP *************************************************************
114+localhost                  : ok=2    changed=0    unreachable=0    failed=0</code></pre>
115+  </p>
116+  <p>
117+    This is the first step, next part we shall create a more complex playbook and
118+    setup repository to run it remotely using ansible-pull.
119+  </p>
120+</section>
121diff --git a/content/posts/2019-04-22Automating_desktop_setup_with_ansible-pull_part-2.html b/content/posts/2019-04-22Automating_desktop_setup_with_ansible-pull_part-2.html
122new file mode 100644
123index 0000000000000000000000000000000000000000..707ba7d59d5329790642bdbea36cc0b4edcd6102
124--- /dev/null
125+++ b/content/posts/2019-04-22Automating_desktop_setup_with_ansible-pull_part-2.html
126@@ -0,0 +1,70 @@
127+<section>
128+  <a href="/posts/2019-03-07Automating_desktop_setup_with_ansible-pull_part-1.html">See part 1</a>
129+  <p>
130+    Now we're going to setup ansible to work with a git repository. The process is
131+    quite similar to ansible-playbook, the only difference is that the source for
132+    the playbook will be a remote repository and not a local file. Following the
133+    previous example we'll get vim setup automated.
134+  </p>
135+  <p>
136+     Create a git repository wherever you see
137+     fit, <a href="https://about.gitlab.com/">gitlab</a>
138+     and <a href="https://github.com/">github</a> offer free repositories. For
139+     this task we need to add only two file: one for the yml file describing the
140+     tasks and the .vimrc file.
141+  </p>
142+  <p>
143+    In the .vimrc add your own configuration, you can see
144+    mine
145+    <a href="https://gitlab.com/gabrielgio/homestation/-/blob/debcf3458df511aef9f7dca0cb73f6cf6baddd5d/.vimrc">
146+      over here
147+    </a>, it is pretty simple as I don't use it but for simple text editing
148+    (like this post) so you can start with that if you don't have one.
149+  </p>
150+  <p>
151+    The yml file will have two tasks, one is to install vim, just like we did in the part 1.
152+<pre><code># main.yml
153+---
154+- name: install vim
155+  dnf:
156+    name: vim
157+    state: latest</code></pre>
158+  </p>
159+  <p>
160+    To copy .vimrc file to your $HOME we going to
161+    use <a href="https://docs.ansible.com/ansible/latest/modules/copy_module.html">copy
162+    module</a>:
163+  </p>
164+  <p>
165+    After we've added those two files to repository you will have be something
166+    <a href="https://gitlab.com/gabrielgio/homestation/-/tree/debcf3458df511aef9f7dca0cb73f6cf6baddd5d">
167+      like this.
168+    </a>
169+    <br/>
170+    Parms:
171+    <ul>
172+      <li><strong>-i</strong> is a list of hosts</li>
173+      <li><strong>-U</strong> is the get repository url</li>
174+    </ul>
175+  </p>
176+  <p>
177+    Remember man is your best friend, take a look at <code>man ansible-pull</code> to know
178+    more about its parameters.
179+  </p>
180+  <p>
181+    The best part you can quickly test and see the result by running my sample:
182+<pre><code>ansible-pull \
183+    -U https://gitlab.com/gabrielgio/homestation.git \
184+    -C debcf3458df511aef9f7dca0cb73f6cf6baddd5d \
185+    -i all \
186+    main.yml</code></pre>
187+  </p>
188+  <p>
189+    The idea here is to keep your repository as a source of truth when comes to
190+    configuration, you can add ansible-pull to a CRON tab, so you just need to
191+    push something to your repository and after a few minutes not only your
192+    machine but all the machines that have it setup will run the playbooks. You
193+    can use this method as a simple way to install software, update machines or
194+    even distribute tooling company-wise.
195+  </p>
196+</section>
197diff --git a/content/posts/2019-11-16Compiling_emacs_from_source_code_on_fedora.html b/content/posts/2019-11-16Compiling_emacs_from_source_code_on_fedora.html
198new file mode 100644
199index 0000000000000000000000000000000000000000..f47040fac0e8f2ee68dc286124ea78ce81384abe
200--- /dev/null
201+++ b/content/posts/2019-11-16Compiling_emacs_from_source_code_on_fedora.html
202@@ -0,0 +1,31 @@
203+<section>
204+<p>
205+ Compiling emacs from source and installing on fedora.
206+</p>
207+<h3>Installing packages</h3>
208+<p>
209+  Install the following packages:
210+<pre><code>sudo dnf install git autoconf make gcc texinfo \
211+    gnutls-devel giflib-devel ncurses-devel \
212+    libjpeg-turbo-devel giflib-devel gtk3-devel \
213+    libXpm-devel libtiff-devel libxml2-devel -y</code></pre>
214+</p>
215+<h3>Cloning Repository</h3>
216+<p>
217+  Clone repository
218+  <a href="http://savannah.gnu.org/projects/emacs/">savannah.gnu.org</a>
219+<pre><code>git clone -b master git://git.sv.gnu.org/emacs.git</code></pre>
220+</p>
221+<h3>Compiling</h3>
222+<p>
223+  Navigate to the emacs folder <code>cd emacs</code> and execute the following
224+  steps:
225+<pre><code>./autogen.sh
226+./configure
227+make -j$(nproc)
228+sudo make install
229+</code></pre>
230+  After verify version with <code>./emacs --version</code>, it
231+  should be equal or higher than <strong>28.0.50</strong>.
232+</p>
233+</section>
234diff --git a/content/posts/2020-07-12Road_to_local_K8S.html b/content/posts/2020-07-12Road_to_local_K8S.html
235new file mode 100644
236index 0000000000000000000000000000000000000000..5d34b27775f6d3c0c5d80da76ab4d5372aba440d
237--- /dev/null
238+++ b/content/posts/2020-07-12Road_to_local_K8S.html
239@@ -0,0 +1,101 @@
240+<section>
241+  <h3>Goal</h3>
242+  <p>
243+    The goal is to deploy kubernetes on my local networks, and keep everything
244+    as reproducible as possible.
245+  </p>
246+  <h3>Stack</h3>
247+  <p>
248+    I'll use Fedora Core OS, Matchbox and Terraform
249+    <sup><a href="#footnotes">1</a></sup>, a match the requirements for
250+    Tectonic<sup><a href="#footnotes">2</a></sup>.</p>
251+  <h3>Steps</h3>
252+  <ul>
253+    <li>Network Setup DHCP/TFTP/DNS<sup><a href="#footnotes">3</a></sup></li>
254+    <li>Matchbox<sup><a href="#footnotes">4</a></sup></li>
255+    <li>PXE nextwork boot evnrionment</li>
256+    <li>Terraform Tectonic<sup><a href="#footnotes">5</a></sup></li>
257+  </ul>
258+  <h3>Network Setup DHCP/TFTP/DNS</h3>
259+  <p>First learning the basics</p>
260+  <ul>
261+    <li>
262+      <a href="https://linuxhint.com/install_dhcp_server_ubuntu/">
263+        https://linuxhint.com/install_dhcp_server_ubuntu/
264+      </a>
265+    </li>
266+    <li>
267+      <a href="https://www.youtube.com/watch?v=XQ3T14SIlV4">
268+        https://www.youtube.com/watch?v=XQ3T14SIlV4
269+      </a>
270+    </li>
271+  </ul>
272+  <p>
273+    To check open ports
274+<pre><code>lsof -Pni | grep LISTEN</code></pre>
275+  </p>
276+  <p>
277+    Run the provided<sup><a href="#footnotes">6</a></sup> image with dnsmasq and
278+    PXE toolkit
279+<pre><code>docker run --rm --cap-add=NET_ADMIN --net=host quay.io/coreos/dnsmasq \
280+  -d -q \
281+  --dhcp-range=192.168.1.3,192.168.1.254 \
282+  --enable-tftp --tftp-root=/var/lib/tftpboot \
283+  --dhcp-match=set:bios,option:client-arch,0 \
284+  --dhcp-boot=tag:bios,undionly.kpxe \
285+  --dhcp-match=set:efi32,option:client-arch,6 \
286+  --dhcp-boot=tag:efi32,ipxe.efi \
287+  --dhcp-match=set:efibc,option:client-arch,7 \
288+  --dhcp-boot=tag:efibc,ipxe.efi \
289+  --dhcp-match=set:efi64,option:client-arch,9 \
290+  --dhcp-boot=tag:efi64,ipxe.efi \
291+  --dhcp-userclass=set:ipxe,iPXE \
292+  --dhcp-boot=tag:ipxe,http://matchbox.example.com:8080/boot.ipxe \
293+  --address=/matchbox.example/192.168.1.2 \
294+  --log-queries \
295+  --log-dhcp</code></pre>
296+  </p>
297+  <h3>Matchbox</h3>
298+  <p>...</p>
299+  <h3>PXE network boot enviroment</h3>
300+  <p>...</p>
301+  <h3>Terraform Tectonic</h3>
302+  <p>...</p>
303+  <h3 id="footnotes">Links</h3>
304+  <div >
305+    <sup>1</sup>
306+    <a href="https://coreos.com/tectonic/docs/latest/install/bare-metal/metal-terraform.html">
307+      https://coreos.com/tectonic/docs/latest/install/bare-metal/metal-terraform.html
308+    </a>
309+  <div>
310+  <div>
311+    <sup>2</sup>
312+    <a href="https://coreos.com/tectonic/docs/latest/install/bare-metal/requirements.html">
313+      https://coreos.com/tectonic/docs/latest/install/bare-metal/requirements.html
314+    </a>
315+  <div>
316+  <div>
317+    <sup>3</sup>
318+    <a href="https://coreos.com/matchbox/docs/latest/network-setup.html">
319+      https://coreos.com/matchbox/docs/latest/network-setup.html
320+    </a>
321+  <div>
322+  <div>
323+    <sup>4</sup>
324+    <a href="https://coreos.com/matchbox/docs/latest/deployment.html">
325+      https://coreos.com/matchbox/docs/latest/deployment.html
326+    </a>
327+  <div>
328+  <div>
329+    <sup>5</sup>
330+    <a href="https://coreos.com/tectonic/releases/">
331+      https://coreos.com/tectonic/releases/
332+    </a>
333+  <div>
334+  <div>
335+    <sup>6</sup>
336+    <a href="https://github.com/poseidon/matchbox/tree/v0.7.0/contrib/dnsmasq">
337+      https://github.com/poseidon/matchbox/tree/v0.7.0/contrib/dnsmasq
338+    </a>
339+  <div>
340+</section>
341diff --git a/content/posts/2020-07-14Friz_box_turned_off_DHCP.html b/content/posts/2020-07-14Friz_box_turned_off_DHCP.html
342index 7eb69ef92382e479e9cd75d3ea6358ab7dfaaff9..3ee5dafa5ea3e288538cc315eee4e12337379850 100644
343--- a/content/posts/2020-07-14Friz_box_turned_off_DHCP.html
344+++ b/content/posts/2020-07-14Friz_box_turned_off_DHCP.html
345@@ -1,9 +1,11 @@
346 <section>
347     <p>
348-        If you turned off your DHCP server follow these steps to connect to FritzBox settings.
349-        <br/>
350+        If you turned off your DHCP server follow these steps to connect to
351+        FritzBox settings. <br/>
352     <ul>
353-        <li> Set your computer IP to 170.254.1.2 and your mask to 255.255.0.0</li>
354+        <li>
355+            Set your computer IP to 170.254.1.2 and your mask to 255.255.0.0
356+        </li>
357         <li> Then go to 169.254.1.1, login and re-enable the DHCP server:</li>
358     </ul>
359     </p>
360@@ -11,7 +13,7 @@     <p>
361         On gnome turn the wired connection off on again to apply the settings.
362     </p>
363     <p>
364-        <strong>Note</strong>: why in the hell does FritzBox 7490 require a land-line telephone to be physically factory
365-        reset?
366+        <strong>Note</strong>: why in the hell does FritzBox 7490 require a
367+        land-line telephone to be physically factory reset?
368     </p>
369 </section>
370diff --git a/content/posts/2020-08-22Moving_from_Github_to_Gilab_pages.html b/content/posts/2020-08-22Moving_from_Github_to_Gilab_pages.html
371new file mode 100644
372index 0000000000000000000000000000000000000000..5fb1d7897fb4b28d23a4178706c8151bc624ad25
373--- /dev/null
374+++ b/content/posts/2020-08-22Moving_from_Github_to_Gilab_pages.html
375@@ -0,0 +1,38 @@
376+<section>
377+  <p>
378+    This was quite simple, I had just to create a simple Gitlab pipeline job and
379+    publish to pages this is done by:
380+  </p>
381+  <pre><code>image: clojure:lein-2.7.0
382+
383+before_script:
384+  - lein deps
385+
386+test:
387+  script:
388+    - lein test
389+
390+pages:
391+  stage: deploy
392+  script:
393+    - lein package
394+  artifacts:
395+    paths:
396+      - public
397+  only:
398+    - master</code></pre>
399+  <dl>
400+    <dt>before_script</dt>
401+    <dd>will download all the dependencies with <code>lein deps.</code></dd>
402+    <dt>test</dt>
403+    <dd>it is self explanatory</dd>
404+    <dt>pages</dt>
405+    <dd>
406+      it will compile cljs into js with <code>lein package</code> into
407+      <code>public</code> folder to later be published into gitlab pages. Take a
408+      look at the <code>artifacts</code> property, it is used to say wich will
409+      will be collected.
410+    </dd>
411+  </dl>
412+
413+</section>
414diff --git a/content/posts/2021-12-26Enable_NFS_on_K3S.html b/content/posts/2021-12-26Enable_NFS_on_K3S.html
415index 09f91e78e01caa8e58aad4dc1f37ca285a7fc510..22ddf3331353303480fec1892b4f4904135635ba 100644
416--- a/content/posts/2021-12-26Enable_NFS_on_K3S.html
417+++ b/content/posts/2021-12-26Enable_NFS_on_K3S.html
418@@ -1,10 +1,10 @@
419 <section>
420     <p>
421-        By default <a href="https://k3s.io/">K3S</a> comes only with <a
422-            href="https://github.com/rancher/local-path-provisioner">local-path</a> storage class, and if you are
423-        running
424-        with more than one node in your cluster you may want to use a more &ldquo;distributed&rdquo;
425-        solution. For may case I opted for NFS.
426+        By default <a href="https://k3s.io/">K3S</a> comes only
427+        with <a href="https://github.com/rancher/local-path-provisioner">local-path</a>
428+        storage class, and if you are running with more than one node in your
429+        cluster you may want to use a more &ldquo;distributed&rdquo; solution.
430+        For may case I opted for NFS.
431     </p>
432     <p>
433         To check the current storage class you can run:
434@@ -16,21 +16,22 @@     </p>
435     <pre><code>NAME                   PROVISIONER                                     RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
436 local-path (default)   rancher.io/local-path                           Delete          WaitForFirstConsumer   false                  154d</code></pre>
437     <p>
438-        To start adding First you need to install <a href="https://github.com/helm/helm">helm</a> on your server. To do
439-        so you may
440-        run:
441+        To start adding First you need to
442+        install <a href="https://github.com/helm/helm">helm</a> on your server.
443+        To do so you may run:
444     </p>
445 
446     <pre><code>curl -sSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash</code></pre>
447     <p>
448-        Be careful when running scripts directly into bash always check the source
449-        Sometimes is also recommended to do not pipe directly to bash
450+        Be careful when running scripts directly into bash always check the
451+        source Sometimes is also recommended to do not pipe directly to bash
452     </p>
453     <p>
454-        Once it is installed we need to add the <a
455-            href="https://kubernetes.io/docs/concepts/storage/storage-classes/#nfs">NFS storage classes</a>. It has two
456-        providers, I have chose <a href="https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner">NFS Subdir
457-        External Provisioner</a>.
458+        Once it is installed we need to add
459+        the <a href="https://kubernetes.io/docs/concepts/storage/storage-classes/#nfs">NFS
460+        storage classes</a>. It has two providers, I have
461+        chose <a href="https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner">NFS
462+        Subdir External Provisioner</a>.
463     </p>
464     <p>
465         Add the helm repo
466@@ -46,12 +47,12 @@ --set nfs.server=x.x.x.x
467 --set nfs.path=/exported/path</code></pre>
468     </div>
469     <p>
470-        Set the <code>nfs.server</code> and <code>nfs.path</code> accordingly with your setup.
471+        Set the <code>nfs.server</code> and <code>nfs.path</code> accordingly
472+        with your setup.
473     </p>
474-
475     <p>
476-        After that if we run <code>k3s kubectl get storageclasses</code> it will now print another
477-        NFS provider:
478+        After that if we run <code>k3s kubectl get storageclasses</code> it will
479+        now print another NFS provider:
480     </p>
481 
482     <pre><code>NAME                   PROVISIONER                                     RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
483diff --git a/content/posts/2021-12-26K8S_private_gitlab_registry_using_podman.html b/content/posts/2021-12-28K8S_private_gitlab_registry_using_podman.html
484rename from content/posts/2021-12-26K8S_private_gitlab_registry_using_podman.html
485rename to content/posts/2021-12-28K8S_private_gitlab_registry_using_podman.html
486diff --git a/contrib/locust/locustfile.py b/contrib/locust/locustfile.py
487new file mode 100644
488index 0000000000000000000000000000000000000000..ca7f8f3b7e911333bacd1123451bb2ca6c340fe8
489--- /dev/null
490+++ b/contrib/locust/locustfile.py
491@@ -0,0 +1,18 @@
492+from locust import HttpUser, task
493+
494+class HelloWorldUser(HttpUser):
495+    @task
496+    def index(self):
497+        self.client.get("/")
498+
499+    @task
500+    def posts(self):
501+        self.client.get("/posts/2021-12-28K8S_private_gitlab_registry_using_podman.html")
502+        self.client.get("/posts/2021-12-26Enable_NFS_on_K3S.html")
503+        self.client.get("/posts/2020-08-22Moving_from_Github_to_Gilab_pages.html")
504+        self.client.get("/posts/2020-07-14Friz_box_turned_off_DHCP.html")
505+        self.client.get("/posts/2020-07-12Road_to_local_K8S.html")
506+        self.client.get("/posts/2019-11-16Compiling_emacs_from_source_code_on_fedora.html")
507+        self.client.get("/posts/2019-04-22Automating_desktop_setup_with_ansible-pull_part-2.html")
508+        self.client.get("/posts/2019-03-07Automating_desktop_setup_with_ansible-pull_part-1.html")
509+        self.client.get("/posts/2019-03-03Welcome_to_my_blog.html")
510diff --git a/src/blog.rs b/src/blog.rs
511index e549fb2b5a88dd5de475938f001e493a0ab854e8..6bbda4996f521103a23a5b6667ed3db8c9388ae1 100644
512--- a/src/blog.rs
513+++ b/src/blog.rs
514@@ -3,8 +3,9 @@ use sailfish::TemplateOnce;
515 use chrono::NaiveDate;
516 use regex::{Regex};
517 use std::str;
518+use std::cmp::{PartialOrd, Ord, PartialEq, Eq};
519 
520-const BLOG_REGEX: &str = r"(?P<date>[\d]{4}-[\d]{2}-[\d]{2})(?P<title>[a-zA-Z0-9_]*)";
521+const BLOG_REGEX: &str = r"(?P<date>[\d]{4}-[\d]{2}-[\d]{2})(?P<title>[a-zA-Z0-9-_]*)";
522 
523 #[derive(RustEmbed)]
524 #[folder = "content/posts/"]
525@@ -25,6 +26,7 @@     title: String,
526     date: String
527 }
528 
529+#[derive(PartialEq, Eq, PartialOrd, Ord)]
530 pub struct BlogEntry {
531     pub title: String,
532     pub datetime: NaiveDate,
533@@ -46,10 +48,15 @@         }
534     }
535 
536     pub fn read_assets() -> Vec<BlogEntry> {
537-        PostAsset::iter()
538+
539+        let mut entries: Vec<BlogEntry> = PostAsset::iter()
540             .map(|e| format!("{}", e))
541             .map(|e| BlogEntry::new(&e))
542-            .collect()
543+            .collect();
544+
545+        entries.sort_by(|a, b| b.datetime.cmp(&a.datetime));
546+
547+        entries
548     }
549 }
550 
551diff --git a/templates/post.html b/templates/post.html
552index 4e5cf9ad95c1437b78a52453f993571bfff2474d..7e0a909a4d894a4bb21020e25283e8a3fff97dcc 100644
553--- a/templates/post.html
554+++ b/templates/post.html
555@@ -7,7 +7,7 @@ <body>
556 <% include!("header.html"); %>
557 <main class="container">
558     <h2><%- title %></h2>
559-    <h5>created at: <%- date %></h2>
560+    <h5>Created At: <%- date %></h2>
561     <%- content %>
562     </section>
563 </main>