Browse Source

Switch to Hugo

keycloak-part-2
Hannes Körber 3 years ago
parent
commit
0a157159a2
Signed by: hannes GPG Key ID: CD28A7CC31318017
  1. 62
      .drone.yml
  2. 5
      .gitignore
  3. 2
      Dockerfile
  4. 27
      Gemfile
  5. 104
      Gemfile.lock
  6. 21
      README.md
  7. 1
      _config.development.yml
  8. 1
      _config.production.yml
  9. 1
      _config.staging.yml
  10. 56
      _config.yml
  11. 5
      _data/authors.yml
  12. 37
      _data/social.yml
  13. 1
      _data/ui-text.yml
  14. 44
      _includes/author-profile.html
  15. 53
      _includes/page__hero.html
  16. 5
      _pages/about.md
  17. 5
      _pages/contact.md
  18. 6
      _pages/software.md
  19. 6
      archetypes/default.md
  20. 85
      config.yaml
  21. 10
      content/_index.md
  22. 21
      content/about.md
  23. 12
      content/blog/2015-09-27-about-this-blog.md
  24. 19
      content/blog/2015-09-27-elk-stack-with-rsyslog.md
  25. 14
      content/blog/2015-12-29-homelab-centos-package-management.md
  26. 14
      content/blog/2016-09-08-ceph-single-node-deployment.md
  27. 12
      content/blog/2017-08-19-ansible-puppet-why-not-both.md
  28. 7
      content/blog/2017-08-22-clone-disk-over-network.md
  29. 8
      content/blog/2018-04-22-drone-kubernetes-docker-in-docker-mtu-issues.md
  30. 12
      content/blog/2018-06-03-ansible-is-not-yet-perfect.md
  31. 47
      content/blog/2018-07-01-rabbithole-proc-self-mountstats.md
  32. 3
      content/blog/_index.md
  33. 88
      content/blog/test-pls-ignore.md
  34. 5
      content/events/2018-global-game-jam.md
  35. 11
      content/events/_index.md
  36. 7
      content/events/dev-night-22.md
  37. 7
      content/events/devops-meetup-paessler.md
  38. 5
      content/events/itsa-2017.md
  39. 7
      content/events/osdc-2018.md
  40. 13
      content/projects/something.md
  41. 9
      content/talks/_index.md
  42. 17
      content/talks/prometheus-unifying-infrastructure-application-monitoring.md
  43. 4
      index.html
  44. 9
      layouts/404.html
  45. 29
      layouts/_default/baseof.html
  46. 5
      layouts/_default/list.html
  47. 34
      layouts/_default/single.html
  48. 17
      layouts/index.html
  49. 9
      layouts/partials/header.html
  50. 27
      layouts/partials/pagelist-default.html
  51. 15
      layouts/partials/related.html
  52. 2
      layouts/partials/site-favicon.html
  53. 8
      layouts/partials/site-footer.html
  54. 11
      layouts/partials/site-navigation.html
  55. 9
      layouts/partials/social-follow.html
  56. 3
      layouts/partials/taglist.html
  57. 0
      layouts/partials/tags.html
  58. 7
      layouts/robots.txt
  59. 5
      layouts/shortcodes/staticRef.html
  60. 17
      layouts/static/single.html
  61. 5
      layouts/taxonomy/list.html
  62. 10
      layouts/taxonomy/terms.html
  63. 0
      static/assets/images/kibana.png
  64. 0
      static/assets/images/me.jpg
  65. 1
      static/assets/presentations/prometheus/slides.html
  66. 1
      static/assets/presentations/prometheus/slides.pdf
  67. 250
      static/css/cache.css
  68. 252
      static/css/main.css
  69. 0
      static/favicon.ico
  70. 5
      static/fonts/fontawesome/css/all.css
  71. BIN
      static/fonts/fontawesome/webfonts/fa-brands-400.eot
  72. 1127
      static/fonts/fontawesome/webfonts/fa-brands-400.svg
  73. BIN
      static/fonts/fontawesome/webfonts/fa-brands-400.ttf
  74. BIN
      static/fonts/fontawesome/webfonts/fa-brands-400.woff
  75. BIN
      static/fonts/fontawesome/webfonts/fa-brands-400.woff2
  76. BIN
      static/fonts/fontawesome/webfonts/fa-regular-400.eot
  77. 467
      static/fonts/fontawesome/webfonts/fa-regular-400.svg
  78. BIN
      static/fonts/fontawesome/webfonts/fa-regular-400.ttf
  79. BIN
      static/fonts/fontawesome/webfonts/fa-regular-400.woff
  80. BIN
      static/fonts/fontawesome/webfonts/fa-regular-400.woff2
  81. BIN
      static/fonts/fontawesome/webfonts/fa-solid-900.eot
  82. 2231
      static/fonts/fontawesome/webfonts/fa-solid-900.svg
  83. BIN
      static/fonts/fontawesome/webfonts/fa-solid-900.ttf
  84. BIN
      static/fonts/fontawesome/webfonts/fa-solid-900.woff
  85. BIN
      static/fonts/fontawesome/webfonts/fa-solid-900.woff2
  86. 0
      static/keybase.txt

62
.drone.yml

@ -1,27 +1,25 @@
pipeline:
build:
image: registry.haktec.de/jekyll:86e0546618060dc5c7d00ff66ce218022768d4a0
environment:
TARGET: production
commands:
- make build
when:
branch:
include: "*"
exclude: staging
# build:
# image: registry.haktec.de/jekyll:86e0546618060dc5c7d00ff66ce218022768d4a0
# environment:
# TARGET: production
# commands:
# - make build
# when:
# branch:
# include: "*"
# exclude: staging
build_staging:
image: registry.haktec.de/jekyll:86e0546618060dc5c7d00ff66ce218022768d4a0
environment:
TARGET: staging
image: registry.haktec.de/hugo:04d0d7f0967508c9efe5678f96b90dc21a7d958b
commands:
- make build
- /app/bin/hugo --baseURL https://staging.blog.haktec.de/ --buildDrafts --ignoreCache
when:
branch:
- staging
package:
image: registry.haktec.de/docker:2bf92189803126ca18eb9dc75ae689ffc6319ffa
image: registry.haktec.de/docker:636402f9f2ddd0e29f31fd1369ad69a38cb72fef
environment:
TARGET: production
commands:
@ -48,20 +46,20 @@ pipeline:
# - KUBERNETES_CERT
- KUBERNETES_TOKEN
deploy:
image: quay.io/honestbee/drone-kubernetes:master
deployment: de-haktec-blog
kubernetes_server: ${KUBERNETES_SERVER}
# kubernetes_cert: ${KUBERNETES_CERT}
kubernetes_token: ${KUBERNETES_TOKEN}
repo: registry.haktec.de/blog
container: blog
tag: ${DRONE_COMMIT_SHA}
namespace: default
when:
branch:
- master
secrets:
- KUBERNETES_SERVER
# - KUBERNETES_CERT
- KUBERNETES_TOKEN
# deploy:
# image: quay.io/honestbee/drone-kubernetes:master
# deployment: de-haktec-blog
# kubernetes_server: ${KUBERNETES_SERVER}
# # kubernetes_cert: ${KUBERNETES_CERT}
# kubernetes_token: ${KUBERNETES_TOKEN}
# repo: registry.haktec.de/blog
# container: blog
# tag: ${DRONE_COMMIT_SHA}
# namespace: default
# when:
# branch:
# - master
# secrets:
# - KUBERNETES_SERVER
# # - KUBERNETES_CERT
# - KUBERNETES_TOKEN

5
.gitignore

@ -1,3 +1,2 @@
_site
.sass-cache
.jekyll-metadata
/public
/themes

2
Dockerfile

@ -1,3 +1,3 @@
FROM nginx:1.12.2-alpine
ADD _site/ /usr/share/nginx/html/
ADD public/ /usr/share/nginx/html/

27
Gemfile

@ -1,27 +0,0 @@
source "https://rubygems.org"
ruby RUBY_VERSION
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "jekyll", "3.3.1"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
gem "minimal-mistakes-jekyll"
gem "classifier-reborn"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.6"
gem 'jekyll-graphviz'
end

104
Gemfile.lock

@ -1,104 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (4.2.7.1)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.5.0)
public_suffix (~> 2.0, >= 2.0.2)
classifier-reborn (2.1.0)
fast-stemmer (~> 1.0)
colorator (1.1.0)
faraday (0.11.0)
multipart-post (>= 1.2, < 3)
fast-stemmer (1.0.2)
ffi (1.9.17)
forwardable-extended (2.6.0)
gemoji (2.1.0)
html-pipeline (2.5.0)
activesupport (>= 2)
nokogiri (>= 1.4)
i18n (0.7.0)
jekyll (3.3.1)
addressable (~> 2.4)
colorator (~> 1.0)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 1.1)
kramdown (~> 1.3)
liquid (~> 3.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (~> 1.7)
safe_yaml (~> 1.0)
jekyll-feed (0.8.0)
jekyll (~> 3.3)
jekyll-gist (1.4.0)
octokit (~> 4.2)
jekyll-graphviz (0.1.0)
jekyll-paginate (1.1.0)
jekyll-sass-converter (1.5.0)
sass (~> 3.4)
jekyll-sitemap (0.13.0)
jekyll (~> 3.3)
jekyll-watch (1.5.0)
listen (~> 3.0, < 3.1)
jemoji (0.7.0)
activesupport (~> 4.0)
gemoji (~> 2.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0)
json (1.8.6)
kramdown (1.13.2)
liquid (3.0.6)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
mercenary (0.3.6)
mini_portile2 (2.1.0)
minimal-mistakes-jekyll (4.1.1)
jekyll (~> 3.3)
jekyll-feed (~> 0.8)
jekyll-gist (~> 1.4)
jekyll-paginate (~> 1.1)
jekyll-sitemap (~> 0.12)
jemoji (~> 0.7)
minitest (5.10.1)
multipart-post (2.0.0)
nokogiri (1.7.0.1)
mini_portile2 (~> 2.1.0)
octokit (4.6.2)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.14.0)
forwardable-extended (~> 2.6)
public_suffix (2.0.5)
rb-fsevent (0.9.8)
rb-inotify (0.9.7)
ffi (>= 0.5.0)
rouge (1.11.1)
safe_yaml (1.0.4)
sass (3.4.23)
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
thread_safe (0.3.5)
tzinfo (1.2.2)
thread_safe (~> 0.1)
PLATFORMS
ruby
DEPENDENCIES
classifier-reborn
jekyll (= 3.3.1)
jekyll-feed (~> 0.6)
jekyll-graphviz
minimal-mistakes-jekyll
RUBY VERSION
ruby 2.5.0p0
BUNDLED WITH
1.16.1

21
README.md

@ -1,21 +0,0 @@
## Building
Build requirements (Fedora 25):
```
# dnf install rubygem-bundler ruby-devel libxml2-devel redhat-rpm-config
```
```
$ git clone https://github.com/hakoerber/blog.haktec.de.git blog
$ cd blog
$ bundle install
$ bundle exec jekyll serve .
```
Now open [http://localhost:4000](http://localhost:4000) in your browser.
## Used Software
This site uses [jekyll](https://jekyllrb.com/) with the [minimal mistakes](https://github.com/mmistakes/minimal-mistakes)
theme.

1
_config.development.yml

@ -1 +0,0 @@
url: "http://localhost:8000"

1
_config.production.yml

@ -1 +0,0 @@
url: "https://blog.haktec.de"

1
_config.staging.yml

@ -1 +0,0 @@
url: "https://staging.blog.haktec.de"

56
_config.yml

@ -1,56 +0,0 @@
title: My Blog
author: hannes
name: hannes
locale: en-US
timezone: Europe/Berlin
encoding: utf-8
# setting this to true breaks pagination
safe: false
show_drafts: false
future: false
unpublished: false
lsi: true
include:
- _pages
markdown: kramdown
theme: minimal-mistakes-jekyll
liquid:
error_mode: strict
# experimental
incremental: false
paginate: 10
paginate_path: "/page:num"
gems:
- jekyll-feed
- jekyll-paginate
exclude:
- Gemfile
- Gemfile.lock
- README.md
- Makefile
defaults:
- scope:
path: ""
values:
layout: single
excerpt_separator: ""
sidebar: []
header:
overlay_color: "#222"
author_profile: true
read_time: false
comments: false
share: true
related: true

5
_data/authors.yml

@ -1,5 +0,0 @@
---
hannes:
name: Hannes Körber
avatar: "/assets/images/me.jpg"
bio: ""

37
_data/social.yml

@ -1,37 +0,0 @@
---
sites:
- fa_icon: fa-map-marker
name: Ansbach, Germany
- url: "https://www.tradebyte.com/"
fa_icon: " fa-suitcase"
name: Tradebyte Software GmbH
- url: "https://github.com/hakoerber"
fa_icon: "fa-github"
name: Github
- url: "https://gitlab.com/whatevsz"
fa_icon: "fa-gitlab"
name: Gitlab
- url: "https://code.haktec.de/explore/projects"
fa_icon: "fa-code"
name: Code
- url: "https://www.linkedin.com/in/hannes-k%C3%B6rber-479ab5122"
fa_icon: "fa-linkedin-square"
name: LinkedIn
- url: "https://www.xing.com/profile/Hannes_Koerber"
fa_icon: "fa-xing-square"
name: Xing
- url: "https://twitter.com/whatevsz"
fa_icon: "fa-twitter-square"
name: Twitter
- url: "https://keybase.io/hakoerber"
fa_icon: "fa-lock"
name: Keybase
- url: "mailto:hannes.koerber@gmail.com"
fa_icon: "fa-envelope"
name: E-Mail
- url: "https://status.haktec.de"
fa_icon: "fa-plus-circle"
name: Status
- url: "https://blog.haktec.de/resume"
fa_icon: "fa-file-text-o"
name: Resume

1
_data/ui-text.yml

@ -1 +0,0 @@
en-US:

44
_includes/author-profile.html

@ -1,44 +0,0 @@
{% if page.author and site.data.authors[page.author] %}
{% assign author = site.data.authors[page.author] %}
{% else %}
{% assign author = site.data.authors[site.author] %}
{% endif %}
<div itemscope itemtype="http://schema.org/Person">
{% if author.avatar %}
<div class="author__avatar">
{% if author.avatar contains "://" %}
<img src="{{ author.avatar }}" alt="{{ author.name }}" itemprop="image">
{% else %}
<img src="{{ author.avatar | absolute_url }}" class="author__avatar" alt="{{ author.name }}" itemprop="image">
{% endif %}
</div>
{% endif %}
<div class="author__content">
<h3 class="author__name" itemprop="name">{{ author.name }}</h3>
{% if author.bio %}
<p class="author__bio" itemprop="description">
{{ author.bio }}
</p>
{% endif %}
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">{{ site.data.ui-text[site.locale].follow_label | remove: ":" | default: "Follow" }}</button>
<ul class="author__urls social-icons">
{% for link in site.data.social.sites %}
<li>
{% if link.url %}
<a href="{{ link.url }}" itemprop="url">
{% endif %}
<i class="fa fa-fw {{ link.fa_icon }}" aria-hidden="true"></i> {{ link.name }}
{% if link.url %}
</a>
{% endif %}
</li>
{% endfor %}
</ul>
</div>
</div>

53
_includes/page__hero.html

@ -1,53 +0,0 @@
{% if page.header.image contains "://" %}
{% capture img_path %}{{ page.header.image }}{% endcapture %}
{% else %}
{% capture img_path %}{{ page.header.image | absolute_url }}{% endcapture %}
{% endif %}
{% if page.header.cta_url contains "://" %}
{% capture cta_path %}{{ page.header.cta_url }}{% endcapture %}
{% else %}
{% capture cta_path %}{{ page.header.cta_url | absolute_url }}{% endcapture %}
{% endif %}
{% if page.header.overlay_image contains "://" %}
{% capture overlay_img_path %}{{ page.header.overlay_image }}{% endcapture %}
{% elsif page.header.overlay_image %}
{% capture overlay_img_path %}{{ page.header.overlay_image | absolute_url }}{% endcapture %}
{% endif %}
{% if page.header.overlay_filter contains "rgba" %}
{% capture overlay_filter %}{{ page.header.overlay_filter }}{% endcapture %}
{% elsif page.header.overlay_filter %}
{% capture overlay_filter %}rgba(0, 0, 0, {{ page.header.overlay_filter }}){% endcapture %}
{% endif %}
<div class="page__hero{% if page.header.overlay_color or page.header.overlay_image %}--overlay{% endif %}"
style="{% if page.header.overlay_color %}background-color: {{ page.header.overlay_color | default: 'transparent' }};{% endif %} {% if overlay_img_path %}background-image: {% if overlay_filter %}linear-gradient({{ overlay_filter }}, {{ overlay_filter }}), {% endif %}url('{{ overlay_img_path }}');{% endif %}"
>
{% if page.header.overlay_color or page.header.overlay_image %}
<div class="wrapper">
<h1 class="page__title" itemprop="headline">
{% if paginator %}
{{ page.title | default: site.title }}{% unless paginator.page == 1 %} {{ site.data.ui-text[site.locale].page | default: "Page" }} {{ paginator.page }}{% endunless %}
{% else %}
{{ page.title | default: site.title | markdownify | remove: "<p>" | remove: "</p>" }}
{% endif %}
</h1>
{% if page.excerpt %}
<p class="page__lead">{{ page.excerpt | markdownify | remove: "<p>" | remove: "</p>" }}</p>
{% endif %}
{% if site.read_time and page.read_time %}
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i> {% include read-time.html %}</p>
{% endif %}
{% if page.header.cta_url %}
<p><a href="{{ cta_path }}" class="btn btn--light-outline btn--large">{{ page.header.cta_label | default: site.data.ui-text[site.locale].more_label | default: "Learn More" }}</a></p>
{% endif %}
</div>
{% else %}
<img src="{{ img_path }}" alt="{{ page.title }}" class="page__hero-image">
{% endif %}
{% if page.header.caption %}
<span class="page__hero-caption">{{ page.header.caption | markdownify | remove: "<p>" | remove: "</p>" }}</span>
{% endif %}
</div>

5
_pages/about.md

@ -1,5 +0,0 @@
---
layout: single
title: About
permalink: /about/
---

5
_pages/contact.md

@ -1,5 +0,0 @@
---
permalink: /contact/
---
# HEY

6
_pages/software.md

@ -1,6 +0,0 @@
---
layout: single
permalink: /software/
---
# Cool software

6
archetypes/default.md

@ -0,0 +1,6 @@
---
title = "{{ replace .TranslationBaseName "-" " " | title }}"
date = "{{ .Date }}"
description = "About the page"
draft = true
---

85
config.yaml

@ -0,0 +1,85 @@
# baseURL: http://blog.haktec.de/
baseURL: http://192.168.1.103:1313/
title: My Blog
uglyurls: false
disablePathToLower: true
languageCode: en-US
canonifyURLs: false
pygmentsStyle: "monokai"
pygmentsCodefences: true
pygmentsUseClasses: true
MetaDataFormat: yaml
taxonomies:
tag: tags
category: categories
related:
threshold: 50
includeNewer: true
toLower: true
indices:
- name: tags
weight: 100
- name: keywords
weight: 50
- name: date
weight: 10
author: Hannes Körber
params:
description: "Blog description"
author: Hannes Körber
social:
- name: github
link: https://github.com/hakoerber
icon: fa-github
style: fab
- name: gitlab
link: https://gitlab.com/whatevsz
icon: fa-gitlab
style: fab
- name: linkedin
link: https://www.linkedin.com/in/hannes-k%C3%B6rber-479ab5122
icon: fa-linkedin
style: fab
- name: xing
link: https://www.xing.com/profile/Hannes_Koerber
icon: fa-xing
style: fab
- name: keybase
link: https://keybase.io/hakoerber
icon: fa-key
style: fas
# - name: twitter
# link: https://twitter.com/whatevsz
# icon: fa-twitter
# style: fab
- name: E-Mail
link: mailto:hannes.koerber@gmail.com
icon: fa-envelope
style: fas
description: Send me a mail!
- name: RSS
link: /blog/index.xml
icon: fa-rss
style: fas
description: Follow my blog on RSS!
permalinks:
blog: /:section/:year/:month/:day/:title/
menu:
main:
- name: "Blog"
weight: 1
url : "/blog/"
- name: "Projects"
weight: 2
url : "/projects/"
- name: "Work"
weight: 4
url : "/work/"

10
content/_index.md

@ -0,0 +1,10 @@
---
---
## Hello!
I'm Hannes Körber. If you want to know what I am up to, look here:
* <a href="/about">See the latest blog posts</a>
* <a href="/about">Read about me</a>
* <a href="/about">Read about me</a>

21
content/about.md

@ -0,0 +1,21 @@
---
title: "About Me"
description: "About Hannes Körber"
date: 2018-07-04
type: static
menu: main
---
<img class="center" src="/assets/images/me.jpg" style="width:25%;">
I'm Hannes Körber, currently working as a system operator at [Tradebyte Software GmbH](https://www.tradebyte.com/) in Ansbach, Germany.
I started working with computers when I was around ten years old. In the beginning, I mainly used them for gaming, but got more and more interested in the internals --- how a computer actually works.
In school, I started programming (Visual Basic and C#) and was completely blown away that I could TELL the computer what to do, whatever it was. I then began building my own computers, and after the german "Abitur" (comparable to a high school degree), I started studying Information and communications technology at Friedrich-Alexander-Universität Erlangen-Nürnberg.
During my university years, I first came in contact with Linux. It was like discovering computers all over again. With Linux, I was free to do everything I wanted with my computer. A few months after having my first contact with Linux, I abandoned Windows for good and have not looked back. I quickly learned everything I could about Linux and computer science in general. By choosing computer science courses over Electrical engineering courses (which I still like and do as a hobby) I decided on my career path: Information Technology.
During my mandatory internship I worked at Tradebyte Software GmbH, a startup-become-medium-sized company offering SaaS solutions for eCommerce in Ansbach. After my internship, I stayed as a working student while finishing my master's thesis and started working full time right after graduation (ok, a one-month holiday in New Zealand was necessary!)

12
_posts/2015-09-27-about-this-blog.md → content/blog/2015-09-27-about-this-blog.md

@ -1,12 +1,14 @@
---
title: About This Blog
date: 2015-09-27T12:08:15+01:00
tags: meta hexo nginx
date: 2015-09-27
excerpt: How this blog is run
tags:
- meta
- hexo
- nginx
title: About This Blog
toc: true
---
{% include toc %}
I am going to start this blog with a post about the blog itself.
In my opinion, simple text files and command line tools is where it's at, so after some googling, I stumbled about Hexo, and just decided to try it out, because I wanted to get experience with blogging and the accompanying software.

19
_posts/2015-09-27-elk-stack-with-rsyslog.md → content/blog/2015-09-27-elk-stack-with-rsyslog.md

@ -1,19 +1,26 @@
---
title: Using The ELK Stack With Rsyslog
date: 2015-09-27T18:06:15+01:00
tags: homelab logging elk elasticsearch logstash rsyslog json grok
date: 2015-09-27
excerpt: Combining Rsyslog, Logstash and Kibana to make nice logging dashboards
tags:
- homelab
- logging
- elk
- elasticsearch
- logstash
- rsyslog
- json
- grok
title: Using The ELK Stack With Rsyslog
toc: true
---
{% include toc %}
This post will detail my setup that uses [rsyslog](http://www.rsyslog.com/) to send JSON-formatted log messages to an [ELK stack](https://www.elastic.co/webinars/introduction-elk-stack).
## The result
Let's start with an overview of what we get in the end:
![ScreenShot]({{ site.url }}/assets/images/kibana.png)
![ScreenShot](/assets/images/kibana.png)
## The log structure

14
_posts/2015-12-29-homelab-centos-package-management.md → content/blog/2015-12-29-homelab-centos-package-management.md

@ -1,13 +1,15 @@
---
date: 2015-12-29
excerpt: Using a local package repository and automating updates of a dozen machines
tags:
- homelab
- package
- yum
- saltstack
title: Homelab CentOS Package Management
date: 2015-12-29T23:01:18+01:00
tags: homelab package yum saltstack
excerpt: >
Using a local package repository and automating updates of a dozen machines
toc: true
---
{% include toc %}
Keeping a dozen virtual machines up-to-date can be quite a task. In this post, I will show how to do it automatically and efficiently using yum-cron, a local mirror with rsync, and saltstack.
I will also describe the setup of a "custom" RPM repository to distribute packages built with the awesome [fpm](https://github.com/jordansissel/fpm)

14
_posts/2016-09-08-ceph-single-node-deployment.md → content/blog/2016-09-08-ceph-single-node-deployment.md

@ -1,12 +1,16 @@
---
title: CEPH Single Node Deployment
date: 2016-09-08 22:44:43+01:00
tags: homelab ceph cobbler ansible libvirt
date: 2016-09-08
excerpt: Setting up a CEPH cluster on a single host for testing purposes
tags:
- homelab
- ceph
- cobbler
- ansible
- libvirt
title: CEPH Single Node Deployment
toc: true
---
{% include toc %}
I wanted to try out Ceph at home, but hesitated, because it usually requires several physical boxes containing several disks to tap its full potential. Still, because the old virtualized ZFS setup proved quite complicated and inflexible, I decided to give Ceph a try. In the end, it still proved to be complicated, but offeres many unique benefits, such as easy storage expansion as well as efficient and fine-tuneable space usage.
For this, we will run the Ceph daemons, mainly monitors and OSDs, in separate virtual machines managed by `libvirt`. The cluster will then provide RBDs to libvirt, used to store the other virtual machines.

12
_posts/2017-08-19-ansible-puppet-why-not-both.md → content/blog/2017-08-19-ansible-puppet-why-not-both.md

@ -1,12 +1,14 @@
---
title: Ansible or Puppet? Why not both!
date: 2017-12-22 09:58:25+02:00
tags: ansible puppet config
date: 2017-08-19
excerpt: Using the right tool for the right job
tags:
- ansible
- puppet
- config
title: Ansible or Puppet? Why not both!
toc: true
---
{% include toc %}
# Introduction
At the [7th DevOps Camp](https://devops-camp.de/devops-camp-12-14-mai-2017/) in May 2017 I listened to a very interesting talk by [Frank Prechtel](https://twitter.com/frankprechtel) and [Andreas Heidoetting](https://www.xing.com/profile/andreas_heidoetting) called "Welche Software für Infrastructure as Code? --- Puppet vs. Chef vs. Ansible vs. Saltstack - welches Tool für welchen Einsatzzweck?" (Which software for Infrastructure as Code? --- Puppet vs. Chef vs. Ansible vs. Saltstack - which tool for what use case?).

7
_posts/2017-08-22-clone-disk-over-network.md → content/blog/2017-08-22-clone-disk-over-network.md

@ -1,8 +1,11 @@
---
title: Cloning a hard disk over the network
date: 2017-08-22
tags: linux netcat
excerpt: This is why I love linux!
tags:
- linux
- netcat
title: Cloning a hard disk over the network
toc: false
---
This is going to be short: My old trusty laptop began showing signs of old age. The screen started flickering, a problem I already knew. Last time, I bought a new screen from Alibaba for ~100€, but wasn't going to spend that much on a three year old laptop.

8
_posts/2018-04-22-drone-kubernetes-docker-in-docker-mtu-issues.md → content/blog/2018-04-22-drone-kubernetes-docker-in-docker-mtu-issues.md

@ -1,7 +1,11 @@
---
title: "Drone on Kubernetes: MTU issues with Docker"
date: 2018-04-22
tags: linux netcat
except: MTU issues with Docker
tags:
- linux
- netcat
title: 'Troubles with Drone on Kubernetes'
toc: false
---
Currently, I am trying out [drone](https://drone.io/) to automate building of docker images for my kubernetes cluster.

12
_posts/2018-06-03-ansible-is-not-yet-perfect.md → content/blog/2018-06-03-ansible-is-not-yet-perfect.md

@ -1,12 +1,14 @@
---
title: "Ansible Is Not (Yet) Perfect"
date: 2018-06-03T13:21:23+02:00
tags: ansible puppet config
date: 2018-06-03
excerpt: A Review of Ansible in Production
tags:
- ansible
- puppet
- config
title: Ansible Is Not (Yet) Perfect
toc: true
---
{% include toc %}
# Introduction
I have been using Ansible for over a year now, both at work and at home (for example to configure my Kubernetes cluster using [kubespray](https://github.com/kubernetes-incubator/kubespray).

47
content/blog/2018-07-01-rabbithole-proc-self-mountstats.md

@ -0,0 +1,47 @@
---
date: 2018-07-02
excerpt: The rabbithole that is /proc/self/mountstats
tags:
- linux
- kernel
- prometheus
- golang
- go
title: Prometheus NFS client monitoring for UDP
toc: false
---
Everything started with a simple idea: Get per-client NFS statistics into [Prometheus](https://prometheus.io/).
I found out that the [Node Exporter](https://github.com/prometheus/node_exporter) is already able to export NFS client metrics via the `mountstats` collector. It gathers metrics from `/proc/self/mountstats` and exports them nicely for prometheus to scrape. Nice! Let's try this out:
```bash
./node_exporter --collector.mountstats
failed to parse mountstats: invalid NFS transport stats 1.1 statement: [740 1 881477 875055 5946 2888414103 286261 16 258752 2080886]
```
Hmm, that does not look good. After a lot of digging throught the code, I found out that the collector seems not to support NFS mounts via UDP! This is due to a different format of the `mountstats` file depending on the protocol. [Here](https://utcc.utoronto.ca/%7Ecks/space/blog/linux/NFSMountstatsXprt) is an awesome writeup about the `mountstats` file format, which is seemingly now documented anywhere else. A big thanks to Chris Siebenmann!
m,i
The problem lies in the `xprt` line in `/proc/self/mountstats`, which contains transport statistics and looks like this for TCP:
```
xprt: tcp 695 1 1 0 16 96099368 96091328 6383 341933213458 1504192
```
All fields are explained in the link above. The crux is the following part:
> For the udp RPC transport there is no connection count, connect idle time, or idle time (fields #3, #4, and #5); all other fields are the same.
This means that for UDP, the line contains three fewer fields than for TCP. The mountstats exporter always expects the same number of fields and therefore breaks for UDP.
Another tricky thing is the `statvers` variable in `/proc/self/mountpoints` that specifies which version the statistics refer to. `statvers=1.1` added three more fields to the end, 11, 12 and 13 in the link above. I was not sure how this was handled for UDP, but after digging through kernel code and git logs, I found [this commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=15a4520621824a3c2eb2de2d1f3984bc1663d3c8), which shows that the three fields were added for both UDP and TCP.
I coded up the changes (learning some golang in the process) and opened a pull request with the procfs project in Prometheus at https://github.com/prometheus/procfs/pull/100, so the component now exports the statistics correctly for TCP and UDP. The fields that are missing in UDP are simply set to zero to ensure the same number of fields for both protocols. I also added a field specifiying the protocol, either "tcp" or "udp".
<!--
TODO
After getting that merged, I opened another pull request with the node exporter to actually export these statistics. Also, the NFS metrics now have a new label indicating the protocol, using the new field mentioned above!
Because these are breaking changes, they will be released with the next version of node exporter. As soon as they do, NFS client metrics will also be available for UDP mounts!
-->

3
content/blog/_index.md

@ -0,0 +1,3 @@
---
---
This is an overview over all posts

88
content/blog/test-pls-ignore.md

@ -0,0 +1,88 @@
---
date: 2017-12-12
excerpt: Pls ignore
tags:
- homelab
- logging
- elk
- elasticsearch
- logstash
- rsyslog
- json
- grok
title: a very very long title and so on this is prometheus stuff
toc: true
---
# blabla
This post will `detail` my setup that uses [rsyslog](http://www.rsyslog.com/) to send JSON-formatted log messages to an [ELK stack](https://www.elastic.co/webinars/introduction-elk-stack).
## The log structure
* `host`: identifes the host that sent the message, subfields are `ip` and `name`
* `type`: can either be `syslog` or `application` and distinguishes a syslog entry from an application logfile
* `content`: the actual log message
```go
func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats, error) {
switch statVersion {
case statVersion10:
if len(ss) != fieldTransport10Len {
return nil, fmt.Errorf("invalid NFS transport stats 1.0 statement: %v", ss)
}
case statVersion11:
if len(ss) != fieldTransport11Len {
return nil, fmt.Errorf("invalid NFS transport stats 1.1 statement: %v", ss)
}
default:
return nil, fmt.Errorf("unrecognized NFS transport stats version: %q", statVersion)
}
// Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay
// in a v1.0 response.
//
// Note: slice length must be set to length of v1.1 stats to avoid a panic when
// only v1.0 stats are present.
// See: https://github.com/prometheus/node_exporter/issues/571.
ns := make([]uint64, fieldTransport11Len)
for i, s := range ss {
n, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return nil, err
}
ns[i] = n
}
return &NFSTransportStats{
Port: ns[0],
Bind: ns[1],
Connect: ns[2],
ConnectIdleTime: ns[3],
IdleTime: time.Duration(ns[4]) * time.Second,
Sends: ns[5],
Receives: ns[6],
BadTransactionIDs: ns[7],
CumulativeActiveRequests: ns[8],
CumulativeBacklog: ns[9],
MaximumRPCSlotsUsed: ns[10],
CumulativeSendingQueue: ns[11],
CumulativePendingQueue: ns[12],
}, nil
}
and this is a very long line that is supposed to be wrapped and this is a very long line that is supposed to be wrapped and this is a very long line that is supposed to be wrapped and this is a very long line that is supposed to be wrapped and this is a very long line that is supposed to be wrapped
andthisisaverylonglinethatissupposedtobewrappedandthisisaverylonglinethatissupposedtobewrappedandthisisaverylonglinethatissupposedtobewrappedandthisisaverylonglinethatissupposedtobewrappedandthisisaverylonglinethatissupposedtobewrapped
```
and this is a very long line that is supposed to be wrapped and this is a very long line that is supposed to be wrapped and this is a very long line that is supposed to be wrapped and this is a very long line that is supposed to be wrapped and this is a very long line that is supposed to be wrapped
andthisisaverylonglinethatissupposedtobewrappedandthisisaverylonglinethatissupposedtobewrappedandthisisaverylonglinethatissupposedtobewrappedandthisisaverylonglinethatissupposedtobewrappedandthisisaverylonglinethatissupposedtobewrapped
## The result
Let's start with an overview of what we get in the end:
![ScreenShot](/assets/images/kibana.png)

5
content/events/2018-global-game-jam.md

@ -0,0 +1,5 @@
---
title: GGJ 2018
date: 2018-01-01
location: Berlin
---

11
content/events/_index.md

@ -0,0 +1,11 @@
---
infos:
- date
- event
- location
menu: main
title: Events
weight: 3
---
Here are events I attended.

7
content/events/dev-night-22.md

@ -0,0 +1,7 @@
---
title: /dev/night 22
date: 2018-01-01
location: Tradebyte Software GmbH Ansbach
---
About kubernetes

7
content/events/devops-meetup-paessler.md

@ -0,0 +1,7 @@
---
title: DevOps Meetup
date: 2018-07-03
tags:
- devops
location: Paessler Nürnberg
---

5
content/events/itsa-2017.md

@ -0,0 +1,5 @@
---
title: itsa 2018
date: 2018-01-01
location: Berlin
---

7
content/events/osdc-2018.md

@ -0,0 +1,7 @@
---
title: OSDC 2018
date: 2018-01-01
location: Berlin
---

13
content/projects/something.md

@ -0,0 +1,13 @@
---
date: 2018-07-03
tags:
- linux
- kernel
- prometheus
- golang
- go
title: Some cool project
toc: false
---
This is nice!

9
content/talks/_index.md

@ -0,0 +1,9 @@
---
infos:
- date
- event
- location
menu: main
title: Talks
weight: 4
---

17
content/talks/prometheus-unifying-infrastructure-application-monitoring.md

@ -0,0 +1,17 @@
---
title: "Prometheus: Unifying Infrastructure and Application Monitoring"
date: 2018-11-01
tags:
- prometheus
- monitoring
---
# About
# Recording
{{< youtube id="w7Ft2ymGmfc" autoplay="false" >}}
# Slides
* [PDF]({{< staticRef "assets/presentations/prometheus/slides.pdf" >}})
* [HTML]({{< staticRef "assets/presentations/prometheus/slides.html" >}})

4
index.html

@ -1,4 +0,0 @@
---
layout: home
title: Welcome!
---

9
layouts/404.html

@ -0,0 +1,9 @@
{{ define "header" }}{{ partial "header.html" . }}{{ end }}
{{ define "main" }}
<article class="center cf pv5 measure-wide-l">
<h3>
404 File Not Found
</h3>
<h3 id="title"><a href="{{ "/" | relURL }}">Go Home</a></h1>
</article>
{{ end }}

29
layouts/_default/baseof.html

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="{{ $.Site.LanguageCode | default "en" }}">
<head>
<meta charset="utf-8">
<meta name="author" content="{{ $.Site.Params.author }}">
<meta name="description" content="{{ $.Site.Params.description }}">
<title>{{ .Params.Title }}</title>
{{ .Hugo.Generator }}
{{ if eq (getenv "HUGO_ENV") "production" | or (eq .Site.Params.env "production") }}
<meta name="robots" content="all">
{{ else }}
<meta name="robots" content="noindex, nofollow">
{{ end }}
<link rel="stylesheet" href="/css/main.css" >
<link rel="stylesheet" href="/fonts/fontawesome/css/all.css">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
</head>
<body>
{{ block "header" . }}{{ partial "header.html" .}}{{ end }}
<main class="main">
{{ block "main" . }}{{ end }}
</main>
{{ block "footer" . }}{{ partial "site-footer.html" . }}{{ end }}
</body>
</html>

5
layouts/_default/list.html

@ -0,0 +1,5 @@
{{ define "main" }}
{{- .Content -}}
{{- partial "pagelist-default.html" . -}}
{{- partial "taglist.html" . -}}
{{ end }}

34
layouts/_default/single.html

@ -0,0 +1,34 @@
{{ define "main" }}
<article>
<div class="content-prefix">
<h1 class="heading">
{{- title .Title -}}
</h1>
{{- if .Params.toc -}}
<div class="toc">
<aside>
<h3>Content</h2>
{{ .TableOfContents }}
</aside>
</div>
{{- end -}}
<time class="date" datetime="{{- .Date.Format "2006-01-02" -}}">
{{- .Date.Format "2006-01-02" -}}
</time>
</div>
<div class="content">
{{- .Content -}}
</div>
<div class="content-postfix">
<div class="tags">
<h3>Tags</h3>
{{- partial "tags.html" . -}}
</div>
<div class="related">
<h3>See also</h3>
{{- partial "related.html" . -}}
</div>
</div>
</article>
{{ end }}

17
layouts/index.html

@ -0,0 +1,17 @@
{{ define "main" }}
<h1 class="heading">{{ .Site.Title }}</h1>
<div class="content">
{{ .Content }}
<h2>Sitemap</h2>
<ul>
{{ range .Site.Menus.main }}
<li>
<a href="{{ .URL }}" title="{{ .Name }}">
{{ .Name }}
</a>
</li>
{{ end }}
</ul>
</div>
{{ end }}

9
layouts/partials/header.html

@ -0,0 +1,9 @@
<header class="header">
<a class="title" href="{{ .Site.BaseURL }}">
{{ .Site.Title }}
</a>
<div class="header-right">
{{ partial "site-navigation.html" . }}
{{ partial "social-follow.html" . }}
</div>
</header>

27
layouts/partials/pagelist-default.html

@ -0,0 +1,27 @@
<table class="list">
{{ if isset .Params "infos" }}
<thead>
<tr>
{{ range .Params.infos }}
<th>{{ title . }}</th>
{{ end }}
</tr>
</thead>
{{ end }}
<tbody>
<tr>
{{ range .Paginator.Pages }}
<td>
<time datetime="{{- .Date.Format "2006-01-02" -}}">
{{- .Date.Format "2006-01-02" -}}
</time>
</td>
<td>
<a href="{{ .URL }}">
{{ .Title }}
</a>
</td>
</tr>
{{ end }}
</tbody>
</table>

15
layouts/partials/related.html

@ -0,0 +1,15 @@
{{ $related := .Site.RegularPages.Related . | first 3 }}
{{ with $related }}
<div class="related">
<ul>
{{ range . }}
<li >
<a href="{{ .RelPermalink }}">
{{- .Title -}}
</a>
</li>
{{ end }}
</ul>
</div>
{{ end }}

2
layouts/partials/site-favicon.html

@ -0,0 +1,2 @@
{{ if .Site.Params.favicon }}
{{ end }}

8
layouts/partials/site-footer.html

@ -0,0 +1,8 @@
<footer class="footer" role="contentinfo">
<div class="copyright">
<a href="/about/">
<div class="far fa-copyright"></div> {{ now.Format "2006" }} {{ .Site.Params.author }}
</a>
</div>
{{ partial "social-follow.html" . }}
</footer>

11
layouts/partials/site-navigation.html

@ -0,0 +1,11 @@
<nav class="navigation" role="navigation">
<ul class="list-horizontal">
{{ range .Site.Menus.main }}
<li class="list-horizontal-item">
<a href="{{ .URL }}" title="{{ .Name }}">
{{ .Name }}
</a>
</li>
{{ end }}
</ul>
</nav>

9
layouts/partials/social-follow.html

@ -0,0 +1,9 @@
<div class="social">
<ul class="list-horizontal">
{{ range $social := .Site.Params.social }}
<li class="list-horizontal-item">
<a href="{{ $social.link }}" class="{{ $social.style }} {{ $social.icon }}" title="{{ $social.description | default (printf "Me on %s" $social.name|title) }}"></a>
</li>
{{ end }}
</ul>
</div>

3
layouts/partials/taglist.html

@ -0,0 +1,3 @@
{{ range .Params.tags }}
<a href="{{ "/tags/" }}{{ . | urlize }}"> {{ . }} </a>
{{ end }}

0
layouts/partials/tags.html

7
layouts/robots.txt

@ -0,0 +1,7 @@
User-agent: *
# robotstxt.org - if ENV production variable is false robots will be disallowed.
{{ if eq (getenv "HUGO_ENV") "production" | or (eq .Site.Params.env "production") }}
Disallow:
{{ else }}
Disallow: /
{{ end }}

5
layouts/shortcodes/staticRef.html

@ -0,0 +1,5 @@
{{- .Scratch.Set "path" (.Get 0) -}}
{{- if hasPrefix (.Scratch.Get "path") "/" -}}
{{- .Scratch.Set "path" (slicestr (.Scratch.Get "path") 1) -}}
{{- end -}}
{{- .Scratch.Get "path" | absLangURL -}}

17
layouts/static/single.html

@ -0,0 +1,17 @@
{{ define "main" }}
<article>
<h1>
{{- title .Title -}}
</h1>
{{- if .Params.toc -}}
<div class="toc">
<aside>
<h3>Content</h2>
{{ .TableOfContents }}
</aside>
</div>
{{- end -}}
{{- .Content -}}
</article>
{{ end }}

5
layouts/taxonomy/list.html

@ -0,0 +1,5 @@
{{ define "main" }}
<h1>Here are all entries with the {{ title .Data.Singular }} "{{ .Title }}"</h1>
{{- partial "pagelist-default.html" . -}}
<a href={{ printf "/%s" .Data.Plural }}>List of all {{ .Data.Plural }}</a>
{{ end }}

10
layouts/taxonomy/terms.html

@ -0,0 +1,10 @@
{{ define "main" }}
<h1>Below you will find all {{ title .Data.Plural }}</h1>
<ul id="all-tags">
{{ range $name, $taxonomy := .Site.Taxonomies.tags }}
{{ with $.Site.GetPage (printf "/tags/%s" $name) }}
<li><a href="{{ .Permalink }}">{{ $name }}</a></li>
{{ end }}
{{ end }}
</ul>
{{ end }}

0
assets/images/kibana.png → static/assets/images/kibana.png

Before

Width:  |  Height:  |  Size: 237 KiB

After

Width:  |  Height:  |  Size: 237 KiB

0
assets/images/me.jpg → static/assets/images/me.jpg

Before

Width:  |  Height:  |  Size: 387 KiB

After

Width:  |  Height:  |  Size: 387 KiB

1
static/assets/presentations/prometheus/slides.html

@ -0,0 +1 @@
hi

1
static/assets/presentations/prometheus/slides.pdf

@ -0,0 +1 @@
hi

250
static/css/cache.css

@ -0,0 +1,250 @@
00000000: 62 6f 64 79 20 7b 0a 20 20 20 20 2f 2a 20 62 6f body {. /* bo
00000010: 72 64 65 72 3a 20 62 6c 61 63 6b 3b 20 2a 2f 0a rder: black; */.
00000020: 20 20 20 20 2f 2a 20 62 6f 72 64 65 72 2d 73 74 /* border-st
00000030: 79 6c 65 3a 20 73 6f 6c 69 64 3b 20 2a 2f 0a 20 yle: solid; */.
00000040: 20 20 20 2f 2a 20 62 6f 72 64 65 72 2d 77 69 64 /* border-wid
00000050: 74 68 3a 20 32 70 78 3b 20 2a 2f 0a 20 20 20 20 th: 2px; */.
00000060: 6d 61 72 67 69 6e 3a 20 30 3b 0a 20 20 20 20 66 margin: 0;. f
00000070: 6f 6e 74 2d 73 69 7a 65 3a 20 31 32 70 74 3b 0a ont-size: 12pt;.
00000080: 20 20 20 20 66 6f 6e 74 2d 66 61 6d 69 6c 79 3a font-family:
00000090: 20 73 65 72 69 66 3b 0a 7d 0a 0a 2e 6c 69 73 74 serif;.}...list
000000a0: 2d 68 6f 72 69 7a 6f 6e 74 61 6c 20 7b 0a 20 20 -horizontal {.
000000b0: 20 20 70 61 64 64 69 6e 67 3a 20 30 70 78 3b 0a padding: 0px;.
000000c0: 20 20 20 20 6d 61 72 67 69 6e 3a 20 30 70 78 3b margin: 0px;
000000d0: 0a 20 20 20 20 64 69 73 70 6c 61 79 3a 20 66 6c . display: fl
000000e0: 65 78 3b 0a 20 20 20 20 66 6c 65 78 2d 64 69 72 ex;. flex-dir
000000f0: 65 63 74 69 6f 6e 3a 20 72 6f 77 3b 0a 20 20 20 ection: row;.
00000100: 20 66 6c 65 78 2d 77 72 61 70 3a 20 77 72 61 70 flex-wrap: wrap
00000110: 3b 0a 20 20 20 20 6a 75 73 74 69 66 79 2d 63 6f ;. justify-co
00000120: 6e 74 65 6e 74 3a 20 63 65 6e 74 65 72 3b 0a 7d ntent: center;.}
00000130: 0a 0a 2e 6c 69 73 74 2d 68 6f 72 69 7a 6f 6e 74 ...list-horizont
00000140: 61 6c 2d 69 74 65 6d 20 7b 0a 20 20 20 20 64 69 al-item {. di
00000150: 73 70 6c 61 79 3a 20 69 6e 6c 69 6e 65 2d 62 6c splay: inline-bl
00000160: 6f 63 6b 3b 0a 7d 0a 0a 2e 6e 61 76 69 67 61 74 ock;.}...navigat
00000170: 69 6f 6e 20 2e 6c 69 73 74 2d 68 6f 72 69 7a 6f ion .list-horizo
00000180: 6e 74 61 6c 2d 69 74 65 6d 20 7b 0a 20 20 20 20 ntal-item {.
00000190: 6d 61 72 67 69 6e 2d 72 69 67 68 74 3a 20 32 30 margin-right: 20
000001a0: 70 78 3b 0a 7d 0a 0a 2e 73 6f 63 69 61 6c 20 2e px;.}...social .
000001b0: 6c 69 73 74 2d 68 6f 72 69 7a 6f 6e 74 61 6c 2d list-horizontal-
000001c0: 69 74 65 6d 20 7b 0a 20 20 20 20 6d 61 72 67 69 item {. margi
000001d0: 6e 2d 72 69 67 68 74 3a 20 31 30 70 78 3b 0a 7d n-right: 10px;.}
000001e0: 0a 0a 62 6c 6f 63 6b 71 75 6f 74 65 20 7b 0a 20 ..blockquote {.
000001f0: 20 20 20 62 6f 72 64 65 72 2d 6c 65 66 74 3a 20 border-left:
00000200: 62 6c 61 63 6b 3b 0a 20 20 20 20 62 6f 72 64 65 black;. borde
00000210: 72 2d 6c 65 66 74 2d 73 74 79 6c 65 3a 20 73 6f r-left-style: so
00000220: 6c 69 64 3b 0a 20 20 20 20 62 6f 72 64 65 72 2d lid;. border-
00000230: 6c 65 66 74 2d 77 69 64 74 68 3a 20 32 70 78 3b left-width: 2px;
00000240: 0a 20 20 20 20 70 61 64 64 69 6e 67 2d 6c 65 66 . padding-lef
00000250: 74 3a 20 31 30 70 78 3b 0a 20 20 20 20 6d 61 72 t: 10px;. mar
00000260: 67 69 6e 2d 6c 65 66 74 3a 20 33 30 70 78 3b 0a gin-left: 30px;.
00000270: 7d 0a 0a 63 6f 64 65 20 7b 0a 20 20 20 20 66 6f }..code {. fo
00000280: 6e 74 2d 66 61 6d 69 6c 79 3a 20 6d 6f 6e 6f 73 nt-family: monos
00000290: 70 61 63 65 3b 0a 7d 0a 0a 70 72 65 20 7b 0a 20 pace;.}..pre {.
000002a0: 20 20 20 64 69 73 70 6c 61 79 3a 20 62 6c 6f 63 display: bloc
000002b0: 6b 3b 0a 20 20 20 20 66 6f 6e 74 2d 66 61 6d 69 k;. font-fami
000002c0: 6c 79 3a 20 6d 6f 6e 6f 73 70 61 63 65 3b 0a 20 ly: monospace;.
000002d0: 20 20 20 77 68 69 74 65 2d 73 70 61 63 65 3a 20 white-space:
000002e0: 70 72 65 2d 77 72 61 70 3b 0a 20 20 20 20 6d 61 pre-wrap;. ma
000002f0: 72 67 69 6e 3a 20 32 30 70 78 20 32 30 70 78 3b rgin: 20px 20px;
00000300: 0a 20 20 20 20 62 61 63 6b 67 72 6f 75 6e 64 2d . background-
00000310: 63 6f 6c 6f 72 3a 20 6c 69 67 68 74 67 72 61 79 color: lightgray
00000320: 3b 0a 7d 0a 0a 2e 68 65 61 64 65 72 20 7b 0a 20 ;.}...header {.
00000330: 20 20 20 6d 61 72 67 69 6e 2d 62 6f 74 74 6f 6d margin-bottom
00000340: 3a 20 34 30 70 78 3b 0a 7d 0a 0a 2e 66 6f 6f 74 : 40px;.}...foot
00000350: 65 72 20 7b 0a 20 20 20 20 6d 61 72 67 69 6e 2d er {. margin-
00000360: 74 6f 70 3a 20 34 30 70 78 3b 0a 7d 0a 0a 2e 68 top: 40px;.}...h
00000370: 65 61 64 65 72 2c 20 2e 66 6f 6f 74 65 72 20 7b eader, .footer {
00000380: 0a 20 20 20 20 2f 2a 20 62 6f 72 64 65 72 3a 20 . /* border:
00000390: 67 72 65 65 6e 3b 20 2a 2f 0a 20 20 20 20 2f 2a green; */. /*
000003a0: 20 62 6f 72 64 65 72 2d 73 74 79 6c 65 3a 20 73 border-style: s
000003b0: 6f 6c 69 64 3b 20 2a 2f 0a 20 20 20 20 2f 2a 20 olid; */. /*
000003c0: 62 6f 72 64 65 72 2d 77 69 64 74 68 3a 20 32 70 border-width: 2p
000003d0: 78 3b 20 2a 2f 0a 20 20 20 20 66 6f 6e 74 2d 66 x; */. font-f
000003e0: 61 6d 69 6c 79 3a 20 73 61 6e 73 3b 0a 20 20 20 amily: sans;.
000003f0: 20 70 61 64 64 69 6e 67 3a 20 31 30 70 78 3b 0a padding: 10px;.
00000400: 20 20 20 20 70 61 64 64 69 6e 67 2d 74 6f 70 3a padding-top:
00000410: 20 31 35 70 78 3b 0a 20 20 20 20 70 61 64 64 69 15px;. paddi
00000420: 6e 67 2d 62 6f 74 74 6f 6d 3a 20 31 35 70 78 3b ng-bottom: 15px;
00000430: 0a 20 20 20 20 6f 76 65 72 66 6c 6f 77 3a 20 61 . overflow: a
00000440: 75 74 6f 3b 0a 20 20 20 20 62 61 63 6b 67 72 6f uto;. backgro
00000450: 75 6e 64 2d 63 6f 6c 6f 72 3a 20 6c 69 67 68 74 und-color: light
00000460: 67 72 61 79 3b 0a 20 20 20 20 64 69 73 70 6c 61 gray;. displa
00000470: 79 3a 20 66 6c 65 78 3b 0a 20 20 20 20 61 6c 69 y: flex;. ali
00000480: 67 6e 2d 69 74 65 6d 73 3a 20 63 65 6e 74 65 72 gn-items: center
00000490: 3b 0a 20 20 20 20 66 6c 65 78 2d 64 69 72 65 63 ;. flex-direc
000004a0: 74 69 6f 6e 3a 20 72 6f 77 3b 0a 20 20 20 20 66 tion: row;. f
000004b0: 6c 65 78 2d 77 72 61 70 3a 20 77 72 61 70 3b 0a lex-wrap: wrap;.
000004c0: 7d 0a 0a 2e 68 65 61 64 65 72 20 61 3a 68 6f 76 }...header a:hov
000004d0: 65 72 2c 20 2e 66 6f 6f 74 65 72 20 61 3a 68 6f er, .footer a:ho
000004e0: 76 65 72 20 7b 0a 09 74 65 78 74 2d 64 65 63 6f ver {..text-deco
000004f0: 72 61 74 69 6f 6e 3a 20 6e 6f 6e 65 3b 0a 20 20 ration: none;.
00000500: 20 20 63 6f 6c 6f 72 3a 20 64 69 6d 67 72 61 79 color: dimgray
00000510: 3b 0a 7d 0a 0a 75 6c 20 7b 0a 20 20 20 20 6c 69 ;.}..ul {. li
00000520: 73 74 2d 73 74 79 6c 65 2d 74 79 70 65 3a 20 73 st-style-type: s
00000530: 71 75 61 72 65 3b 0a 7d 0a 0a 2e 68 65 61 64 65 quare;.}...heade
00000540: 72 20 61 2c 20 2e 66 6f 6f 74 65 72 20 61 2c 20 r a, .footer a,
00000550: 2e 74 61 67 73 20 61 20 7b 0a 20 20 20 20 74 65 .tags a {. te
00000560: 78 74 2d 64 65 63 6f 72 61 74 69 6f 6e 3a 20 6e xt-decoration: n
00000570: 6f 6e 65 3b 0a 20 20 20 20 63 6f 6c 6f 72 3a 20 one;. color:
00000580: 62 6c 61 63 6b 0a 7d 0a 0a 2e 74 61 67 73 20 75 black.}...tags u
00000590: 6c 20 7b 0a 20 20 20 20 6c 69 73 74 2d 73 74 79 l {. list-sty
000005a0: 6c 65 3a 20 6e 6f 6e 65 3b 0a 20 20 20 20 70 61 le: none;. pa
000005b0: 64 64 69 6e 67 2d 6c 65 66 74 3a 20 32 30 70 78 dding-left: 20px
000005c0: 3b 0a 7d 0a 0a 2e 74 61 67 73 20 2e 6c 69 73 74 ;.}...tags .list
000005d0: 2d 62 75 6c 6c 65 74 20 7b 0a 20 20 20 20 70 61 -bullet {. pa
000005e0: 64 64 69 6e 67 2d 72 69 67 68 74 3a 20 35 70 78 dding-right: 5px
000005f0: 3b 0a 20 20 20 20 64 69 73 70 6c 61 79 3a 20 69 ;. display: i
00000600: 6e 6c 69 6e 65 3b 0a 7d 0a 0a 2e 72 65 6c 61 74 nline;.}...relat
00000610: 65 64 20 75 6c 20 7b 0a 20 20 20 20 70 61 64 64 ed ul {. padd
00000620: 69 6e 67 2d 6c 65 66 74 3a 20 34 30 70 78 3b 0a ing-left: 40px;.
00000630: 7d 0a 0a 2e 68 65 61 64 65 72 2d 72 69 67 68 74 }...header-right
00000640: 20 7b 0a 20 20 20 20 2f 2a 20 62 6f 72 64 65 72 {. /* border
00000650: 3a 20 72 65 64 3b 20 2a 2f 0a 20 20 20 20 2f 2a : red; */. /*
00000660: 20 62 6f 72 64 65 72 2d 73 74 79 6c 65 3a 20 73 border-style: s
00000670: 6f 6c 69 64 3b 20 2a 2f 0a 20 20 20 20 2f 2a 20 olid; */. /*
00000680: 62 6f 72 64 65 72 2d 77 69 64 74 68 3a 20 32 70 border-width: 2p
00000690: 78 3b 20 2a 2f 0a 20 20 20 20 64 69 73 70 6c 61 x; */. displa
000006a0: 79 3a 20 66 6c 65 78 3b 0a 20 20 20 20 61 6c 69 y: flex;. ali
000006b0: 67 6e 2d 69 74 65 6d 73 3a 20 63 65 6e 74 65 72 gn-items: center
000006c0: 3b 0a 7d 0a 0a 2e 6e 61 76 69 67 61 74 69 6f 6e ;.}...navigation
000006d0: 20 7b 0a 20 20 20 20 2f 2a 20 62 6f 72 64 65 72 {. /* border
000006e0: 3a 20 6f 72 61 6e 67 65 3b 20 2a 2f 0a 20 20 20 : orange; */.
000006f0: 20 2f 2a 20 62 6f 72 64 65 72 2d 73 74 79 6c 65 /* border-style
00000700: 3a 20 73 6f 6c 69 64 3b 20 2a 2f 0a 20 20 20 20 : solid; */.
00000710: 2f 2a 20 62 6f 72 64 65 72 2d 77 69 64 74 68 3a /* border-width:
00000720: 20 32 70 78 3b 20 2a 2f 0a 20 20 20 20 66 6f 6e 2px; */. fon
00000730: 74 2d 73 69 7a 65 3a 20 32 30 70 78 3b 0a 20 20 t-size: 20px;.
00000740: 20 20 6d 61 72 67 69 6e 2d 72 69 67 68 74 3a 20 margin-right:
00000750: 33 30 70 78 0a 7d 0a 0a 40 6d 65 64 69 61 20 28 30px.}..@media (
00000760: 6d 61 78 2d 77 69 64 74 68 3a 20 31 30 30 30 70 max-width: 1000p
00000770: 78 29 20 7b 0a 20 20 20 20 2e 68 65 61 64 65 72 x) {. .header
00000780: 20 7b 0a 20 20 20 20 20 20 20 20 66 6c 65 78 2d {. flex-
00000790: 64 69 72 65 63 74 69 6f 6e 3a 20 63 6f 6c 75 6d direction: colum
000007a0: 6e 3b 0a 20 20 20 20 7d 0a 20 20 20 20 2e 68 65 n;. }. .he
000007b0: 61 64 65 72 2d 72 69 67 68 74 20 7b 0a 20 20 20 ader-right {.
000007c0: 20 20 20 20 20 66 6c 65 78 2d 64 69 72 65 63 74 flex-direct
000007d0: 69 6f 6e 3a 20 63 6f 6c 75 6d 6e 3b 0a 20 20 20 ion: column;.
000007e0: 20 20 20 20 20 6d 61 72 67 69 6e 2d 74 6f 70 3a margin-top:
000007f0: 20 32 30 70 78 3b 0a 20 20 20 20 7d 0a 20 20 20 20px;. }.
00000800: 20 2e 73 6f 63 69 61 6c 2c 20 2e 6e 61 76 69 67 .social, .navig
00000810: 61 74 69 6f 6e 20 7b 0a 20 20 20 20 20 20 20 20 ation {.
00000820: 74 65 78 74 2d 61 6c 69 67 6e 3a 20 63 65 6e 74 text-align: cent
00000830: 65 72 3b 0a 20 20 20 20 20 20 20 20 6d 61 72 67 er;. marg
00000840: 69 6e 2d 72 69 67 68 74 3a 20 30 70 78 3b 0a 20 in-right: 0px;.
00000850: 20 20 20 7d 0a 20 20 20 20 2e 6e 61 76 69 67 61 }. .naviga
00000860: 74 69 6f 6e 20 7b 0a 20 20 20 20 20 20 20 20 6d tion {. m
00000870: 61 72 67 69 6e 2d 72 69 67 68 74 3a 20 30 70 78 argin-right: 0px
00000880: 0a 20 20 20 20 7d 0a 20 20 20 20 2e 73 6f 63 69 . }. .soci
00000890: 61 6c 20 7b 0a 20 20 20 20 20 20 20 20 6d 61 72 al {. mar
000008a0: 67 69 6e 2d 74 6f 70 3a 20 31 30 70 78 3b 0a 20 gin-top: 10px;.
000008b0: 20 20 20 7d 0a 20 20 20 20 2e 68 65 61 64 65 72 }. .header
000008c0: 2d 72 69 67 68 74 20 2e 6c 69 73 74 2d 68 6f 72 -right .list-hor
000008d0: 69 7a 6f 6e 74 61 6c 2d 69 74 65 6d 20 7b 0a 20 izontal-item {.
000008e0: 20 20 20 20 20 20 20 70 61 64 64 69 6e 67 2d 6c padding-l
000008f0: 65 66 74 3a 20 31 30 70 78 3b 0a 20 20 20 20 20 eft: 10px;.
00000900: 20 20 20 70 61 64 64 69 6e 67 2d 72 69 67 68 74 padding-right
00000910: 3a 20 31 30 70 78 3b 0a 20 20 20 20 20 20 20 20 : 10px;.
00000920: 70 61 64 64 69 6e 67 2d 74 6f 70 3a 20 33 70 78 padding-top: 3px
00000930: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 2e 6d 61 69 ;. }. .mai
00000940: 6e 20 7b 0a 20 20 20 20 20 20 20 20 77 69 64 74 n {. widt
00000950: 68 3a 20 39 35 25 3b 0a 20 20 20 20 7d 0a 20 20 h: 95%;. }.
00000960: 20 20 2e 63 6f 6e 74 65 6e 74 2d 70 72 65 66 69 .content-prefi
00000970: 78 2c 0a 20 20 20 20 2e 63 6f 6e 74 65 6e 74 2d x,. .content-
00000980: 70 6f 73 74 66 69 78 20 7b 0a 20 20 20 20 20 20 postfix {.
00000990: 20 20 77 69 64 74 68 3a 20 39 35 25 3b 0a 20 20 width: 95%;.
000009a0: 20 20 7d 0a 20 20 20 20 2e 74 69 74 6c 65 20 7b }. .title {
000009b0: 0a 20 20 20 20 20 20 20 20 6d 61 72 67 69 6e 2d . margin-
000009c0: 6c 65 66 74 3a 20 61 75 74 6f 0a 20 20 20 20 7d left: auto. }
000009d0: 0a 7d 0a 0a 2e 73 6f 63 69 61 6c 20 7b 0a 20 20 .}...social {.
000009e0: 20 20 2f 2a 20 62 6f 72 64 65 72 3a 20 67 72 65 /* border: gre
000009f0: 79 3b 20 2a 2f 0a 20 20 20 20 2f 2a 20 62 6f 72 y; */. /* bor
00000a00: 64 65 72 2d 73 74 79 6c 65 3a 20 73 6f 6c 69 64 der-style: solid
00000a10: 3b 20 2a 2f 0a 20 20 20 20 2f 2a 20 62 6f 72 64 ; */. /* bord
00000a20: 65 72 2d 77 69 64 74 68 3a 20 32 70 78 3b 20 2a er-width: 2px; *
00000a30: 2f 0a 20 20 20 20 66 6f 6e 74 2d 73 69 7a 65 3a /. font-size:
00000a40: 20 31 38 70 78 3b 0a 7d 0a 0a 0a 2e 74 69 74 6c 18px;.}....titl
00000a50: 65 20 7b 0a 20 20 20 20 2f 2a 20 62 6f 72 64 65 e {. /* borde
00000a60: 72 3a 20 62 6c 75 65 3b 20 2a 2f 0a 20 20 20 20 r: blue; */.
00000a70: 2f 2a 20 62 6f 72 64 65 72 2d 73 74 79 6c 65 3a /* border-style:
00000a80: 20 73 6f 6c 69 64 3b 20 2a 2f 0a 20 20 20 20 2f solid; */. /
00000a90: 2a 20 62 6f 72