Initial commit
11
.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
### Hugo ###
|
||||||
|
# Generated files by hugo
|
||||||
|
/public/
|
||||||
|
/resources/_gen/
|
||||||
|
/assets/jsconfig.json
|
||||||
|
hugo_stats.json
|
||||||
|
|
||||||
|
# Temporary lock file while building
|
||||||
|
.hugo_build.lock
|
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "themes/hugo-profile"]
|
||||||
|
path = themes/hugo-profile
|
||||||
|
url = https://github.com/BluemediaGER/hugo-profile.git
|
6
archetypes/default.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
title: "{{ replace .Name "-" " " | title }}"
|
||||||
|
date: {{ .Date }}
|
||||||
|
draft: true
|
||||||
|
---
|
||||||
|
|
160
config.yaml
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
baseURL: https://staging.bluemedia.dev/
|
||||||
|
languageCode: en-us
|
||||||
|
title: Bluemedia
|
||||||
|
theme: hugo-profile
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
home:
|
||||||
|
- "HTML"
|
||||||
|
- "RSS"
|
||||||
|
- "JSON"
|
||||||
|
page:
|
||||||
|
- "HTML"
|
||||||
|
- "RSS"
|
||||||
|
|
||||||
|
Paginate: 3
|
||||||
|
enableRobotsTXT: true
|
||||||
|
|
||||||
|
markup:
|
||||||
|
goldmark:
|
||||||
|
renderer:
|
||||||
|
unsafe: true
|
||||||
|
|
||||||
|
Menus:
|
||||||
|
main:
|
||||||
|
- identifier: blog
|
||||||
|
name: Blog
|
||||||
|
title: Blog posts
|
||||||
|
url: /blog
|
||||||
|
weight: 1
|
||||||
|
|
||||||
|
params:
|
||||||
|
# General settings
|
||||||
|
title: "Bluemedia"
|
||||||
|
description: Text about my cool site
|
||||||
|
favicon: "/fav.png"
|
||||||
|
useBootstrapCDN: false
|
||||||
|
|
||||||
|
singlePages:
|
||||||
|
readTime:
|
||||||
|
enable: true
|
||||||
|
content: "min read"
|
||||||
|
scrollprogress:
|
||||||
|
enable: true
|
||||||
|
|
||||||
|
# Design settings
|
||||||
|
animate: true
|
||||||
|
color:
|
||||||
|
textColor: "#23282f"
|
||||||
|
secondaryTextColor: "#23282f"
|
||||||
|
primaryColor: "#23282f"
|
||||||
|
|
||||||
|
font:
|
||||||
|
fontSize: 1.2rem
|
||||||
|
fontWeight: 500
|
||||||
|
|
||||||
|
navbar:
|
||||||
|
menus:
|
||||||
|
disableExperience: true
|
||||||
|
disableEducation: true
|
||||||
|
disableAchievements: true
|
||||||
|
|
||||||
|
# Hero
|
||||||
|
hero:
|
||||||
|
enable: true
|
||||||
|
intro: "Hi there! My name is"
|
||||||
|
title: "Oliver aka Bluemedia"
|
||||||
|
subtitle: "I'm a sysadmin, hacker, and open-source enthusiast"
|
||||||
|
image: /images/hero.jpg
|
||||||
|
button:
|
||||||
|
enable: true
|
||||||
|
name: "Find out more"
|
||||||
|
url: "#about"
|
||||||
|
download: false
|
||||||
|
newPage: false
|
||||||
|
socialLinks:
|
||||||
|
fontAwesomeIcons:
|
||||||
|
- icon: fab fa-github
|
||||||
|
url: https://github.com/BluemediaGER
|
||||||
|
- icon: fab fa-mastodon
|
||||||
|
url: https://chaos.social/@Bluemedia
|
||||||
|
- icon: fa fa-link
|
||||||
|
url: https://bluemedia.dev/social
|
||||||
|
|
||||||
|
# About
|
||||||
|
about:
|
||||||
|
enable: true
|
||||||
|
title: "About Me"
|
||||||
|
image: "/images/about.jpg"
|
||||||
|
content: |-
|
||||||
|
Whether at my main job, at events of the Chaos Computer Club, or with my own AS in the DN42 network: I do a lot of stuff with technology.
|
||||||
|
And I'm always curious to discover even more.
|
||||||
|
|
||||||
|
Using that knowledge I try to create something valuable for myself and others. Whether it is a small project of my own, or a contribution to a larger project.
|
||||||
|
skills:
|
||||||
|
enable: true
|
||||||
|
title: "Here are a few technologies I've been using recently:"
|
||||||
|
items:
|
||||||
|
- "PowerDNS"
|
||||||
|
- "MariaDB Galera"
|
||||||
|
- "MinIO"
|
||||||
|
- "Keycloak"
|
||||||
|
- "Ansible"
|
||||||
|
- "Checkmk"
|
||||||
|
|
||||||
|
# Projects
|
||||||
|
projects:
|
||||||
|
enable: true
|
||||||
|
items:
|
||||||
|
- title: ScanOS
|
||||||
|
content: A modern operating system for enterprise-grade network image scanners.
|
||||||
|
image: /images/projects/scan-os.png
|
||||||
|
badges:
|
||||||
|
- "Embedded Systems"
|
||||||
|
- "Python 3"
|
||||||
|
- "FastAPI"
|
||||||
|
- "Vue.js 3"
|
||||||
|
- "Tailwind CSS"
|
||||||
|
links:
|
||||||
|
- icon: fab fa-github
|
||||||
|
url: https://github.com/BluemediaGER/ScanOS
|
||||||
|
|
||||||
|
- title: Fancy Gatus
|
||||||
|
content: A simplified and modern status page based on data from a Gatus instance. The goal is to only display the most important information in a way that is understandable for end users.
|
||||||
|
image: /images/projects/fancy-gatus.png
|
||||||
|
featured:
|
||||||
|
name: Demo
|
||||||
|
link: https://status.bluemedia.dev
|
||||||
|
badges:
|
||||||
|
- "Gatus"
|
||||||
|
- "Status page"
|
||||||
|
- "Vue.js 3"
|
||||||
|
links:
|
||||||
|
- icon: fab fa-github
|
||||||
|
url: https://github.com/BluemediaGER/fancy-gatus
|
||||||
|
|
||||||
|
- title: Keycloak Modern Login
|
||||||
|
content: A clean and modern Keycloak login theme that's built using Vue.js 3, Tailwind CSS and Typescript. It is easily extensible and bypasses the complexity of FreeMarker templates.
|
||||||
|
image: /images/projects/keycloak-modern-login.jpg
|
||||||
|
badges:
|
||||||
|
- "Keycloak"
|
||||||
|
- "Vue.js 3"
|
||||||
|
- "Tailwind CSS"
|
||||||
|
links:
|
||||||
|
- icon: fab fa-github
|
||||||
|
url: https://git.bluemedia.dev/Bluemedia/keycloak-modern-login
|
||||||
|
|
||||||
|
# Contact
|
||||||
|
contact:
|
||||||
|
enable: true
|
||||||
|
content: My inbox is always open. Feel free to contact me if you have a question or just want to talk about cool computer stuff. I'll try my best to get back to you!
|
||||||
|
email: hi@bluemedia.dev
|
||||||
|
btnName: Say hi!
|
||||||
|
|
||||||
|
footer:
|
||||||
|
recentPosts:
|
||||||
|
path: "blog"
|
||||||
|
count: 3
|
||||||
|
title: Recent Posts
|
||||||
|
enable: true
|
||||||
|
disableFeaturedImage: false
|
73
content/blog/authorative-dns-server-using-powerdns.md
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
---
|
||||||
|
title: "Hosting your own authoritative DNS servers using PowerDNS"
|
||||||
|
date: 2021-12-22T13:25:44+01:00
|
||||||
|
draft: false
|
||||||
|
author: "Bluemedia (Oliver)"
|
||||||
|
tags:
|
||||||
|
- Cloud
|
||||||
|
- Docker
|
||||||
|
- Hosting
|
||||||
|
- DNS
|
||||||
|
- PowerDNS
|
||||||
|
image: "/images/general/server-rack.jpg"
|
||||||
|
summary: "In this post, I'd like to discuss my idea and plans for running my own authoritative DNS server based on PowerDNS."
|
||||||
|
socialShare: false
|
||||||
|
toc:
|
||||||
|
---
|
||||||
|
|
||||||
|
## Intro
|
||||||
|
|
||||||
|
A quick disclaimer at first: This post is not intended to be a complete guide on how to build your own system. It is more intended as an example of how I solved my personal requirements. PowerDNS is a very powerful tool and offers many ways to solve problems in different ways. In the end, everyone has to decide for themselves what they think is an ideal configuration and whether they want to leave it to the “big bad internet” like this.
|
||||||
|
|
||||||
|
**Should you run your own authoritative DNS servers?**
|
||||||
|
*In most cases, probably not.*
|
||||||
|
**Am I doing it anyway?**
|
||||||
|
*Of course I do.*
|
||||||
|
**Why, you may ask?**
|
||||||
|
*Because I can, and it’s a good way to learn more about DNS.*
|
||||||
|
|
||||||
|
I’m generally a big fan of having important services under my own control, as you may have noticed already from some other posts. This allows me to customize them exactly as I want to. My infrastructure is mostly automated, so I don’t have to waste my free time on maintaining it. Unfortunately, my registrar, where I get almost all my domain names, doesn’t have a particularly great API for managing DNS records. This is, of course, a problem in such a case.
|
||||||
|
|
||||||
|
Because of this, I’ve been using Cloudflare as my DNS provider for a while now. The free package with the included features is quite usable, and they have a really great API. After the second major outage of Cloudflare, however, I realized that it might not be the best idea to make half of the Internet depend on one provider. For this reason and also because I’m generally interested in the topic from a technical perspective, it ended up on my to-do list at some point.
|
||||||
|
|
||||||
|
## Starting off with a plan
|
||||||
|
|
||||||
|
So what are the things you need to consider if you really want to run such a service yourself?
|
||||||
|
|
||||||
|
In my opinion, you should know what you are doing before you actually start doing it. Accordingly, the topic has started for me by first reading up on “best practices” for DNS and the documentation of my desired software ([PowerDNS](https://www.powerdns.com/)) over a good cup of coffee. While doing so, a more or less finished concept formed in my head, which I’m fairly certain is perfectly acceptable as is.
|
||||||
|
|
||||||
|
Based on my initial starting position, I knew it had to be highly available, fault-tolerant, and relatively inexpensive. These things are not necessarily opposed to each other here.
|
||||||
|
|
||||||
|
To meet my requirements, I’m using two small servers at different providers (Hetzner and Netcup) located at different sites (Nuremberg and Falkenstein). Furthermore, because both servers are in different top-level domains (.dev and.re), even the theoretical failure of an entire top-level domain can be compensated.
|
||||||
|
|
||||||
|
Each server runs a MariaDB instance and PowerDNS with a minimal configuration. NS1 is the primary system, which is also used for administration. NS2 hosts a read-only replica of the PowerDNS database and PowerDNS itself. Both externally accessible PowerDNS instances have read-only access to the database and no enabled special functions, such as the HTTP API. They merely act as “dumb” resolvers.
|
||||||
|
|
||||||
|
On NS1, there is also another PowerDNS instance running inside Docker, this time with write access to the database and an enabled HTTP API, as well as an instance of [PowerDNS-Admin](https://github.com/PowerDNS-Admin/PowerDNS-Admin) for the actual administration. From the outside, PowerDNS-Admin is accessible via an Nginx reverse proxy that takes care of things like TLS termination and logging. Both servers are connected by a WireGuard tunnel for the MariaDB replication traffic.
|
||||||
|
|
||||||
|
PowerDNS-Admin is a comprehensive administration toolkit for PowerDNS. It provides full multi-tenancy in terms of zone management and can manage API keys restricted to individual zones. It also provides a well-organized web interface for the overall administration.
|
||||||
|
|
||||||
|
This is how my finished concept looks on the drawing board:
|
||||||
|
![](/images/posts/authorative-dns-server-using-powerdns/pdns-architecture.png)
|
||||||
|
|
||||||
|
## Keeping security in mind
|
||||||
|
|
||||||
|
If you operate such a service publicly, you should also take some time to think about security. After all, you don’t want your own infrastructure to be immediately taken over by the next best troll or abused for DDoS.
|
||||||
|
|
||||||
|
Therefore, it is necessary to think about the following rules:
|
||||||
|
- Only absolutely necessary services should be accessible from external sources
|
||||||
|
- Systems must be protected against unauthorized access (e.g., SSH only via public key authentication)
|
||||||
|
- Always use strong passwords and 2FA everywhere (in this case, PowerDNS-Admin)
|
||||||
|
- All software should be kept up-to-date and patches should be installed in a timely manner after their release
|
||||||
|
|
||||||
|
With DNS, there are some additional things that will save you and others from trouble:
|
||||||
|
- Both PowerDNS instances are authoritative-only and do not allow recursive queries
|
||||||
|
- Zone transfer (AXFR) should be disabled if not required, or at least restricted to certain IPs. This prevents all DNS entries (entire zones) from being retrieved at once
|
||||||
|
- You should configure appropriate rate limits in PowerDNS to make it as difficult as possible for attackers to abuse your servers for DNS reflection attacks (DDoS amplification)
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
With a bit of ingenuity, the right planning, and the relevant documentation, an idea like this can certainly become a reality. This opens up countless possibilities to customize the system to your own needs. You need an additional DNS server? Just set up another replica. If necessary, all of this can also be automated.
|
||||||
|
|
||||||
|
By now, I’ve been running my two DNS servers productively for almost two months and have already survived the first failures without any problems. Both servers were offline for a short period of time due to problems with their respective host systems, but due to the separation of the two instances, it was still possible to resolve the domains at any time.
|
||||||
|
|
||||||
|
Because PowerDNS is very resource-saving and I don’t expect many DNS requests anyway, I can use the smallest server size that the respective hosting company offers. This brings my total cost to about 6 euros per month, which is still quite impressive in my opinion.
|
58
content/blog/custom-boot-images-oracle-cloud.md
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
---
|
||||||
|
title: "Custom boot images in the Oracle Cloud Free Tier"
|
||||||
|
date: 2023-10-15T22:56:59+02:00
|
||||||
|
draft: false
|
||||||
|
author: "Bluemedia (Oliver)"
|
||||||
|
tags:
|
||||||
|
- Cloud
|
||||||
|
- Hosting
|
||||||
|
- QuickTip
|
||||||
|
image: "/images/general/hdd-open.jpg"
|
||||||
|
summary: "I recently tinkered with the Oracle cloud platform and managed to use custom boot images even in the Free Tier. Check out this post if you’re also missing your favorite OS image!"
|
||||||
|
socialShare: false
|
||||||
|
toc:
|
||||||
|
---
|
||||||
|
|
||||||
|
## Intro
|
||||||
|
|
||||||
|
I recently started using the Oracle Cloud Free Tier to host some lab servers and external monitoring. The overall package is quite nice: You get 4 Ampere A1 (arm64) CPU cores and 24 GB of RAM, two AMD (x86) VMs with 1 core and 512 MB of RAM each, 200 GB of block volume space, as well as some databases, a load balacer, and other stuff. All for free.
|
||||||
|
|
||||||
|
When creating a compute instance, there are some common OS images to choose from, like Oracle Linux, Ubuntu, Rocky Linux, and more. But my personal favorite, Debian, is unfortunately not part of the portfolio.
|
||||||
|
|
||||||
|
The Oracle Cloud platform offers a way to upload custom images, but this feature is not available in the free tier as it requires a pay-as-you-go account. Somebody sane would now choose one of the available images and call it a day, but instead I started to test some things…
|
||||||
|
|
||||||
|
## Messing around with block volumes
|
||||||
|
|
||||||
|
Taking a look at how volumes work, we can note the following things:
|
||||||
|
- There are “block volumes” and “boot volumes”
|
||||||
|
- We can attach multiple volumes to a single compute instance
|
||||||
|
- We can’t select block volumes (created in the "Storage" -> "Block Storage" section) as a boot volume when creating a compute instance
|
||||||
|
- When deleting a compute instance, we can opt to keep the boot volume
|
||||||
|
- Boot volumes have additional metadata that shows which OS image is installed on them
|
||||||
|
- Detached boot volumes from deleted instances can be attached to other instances like any other block volume
|
||||||
|
|
||||||
|
Thinking about the constraints above, I got an idea how we might be able to use custom images. The plan looks as follows:
|
||||||
|
- Create a compute instance
|
||||||
|
- Delete the compute instance, while keeping the boot volume
|
||||||
|
- Attach the now detached boot volume as a secondary volume to any other compute instance
|
||||||
|
- Write the custom image to the secondary volume
|
||||||
|
- Detatch the secondary volume
|
||||||
|
- Create a new compute instance using the detached boot volume instead of an OS image
|
||||||
|
- Profit!
|
||||||
|
|
||||||
|
## Checking if it actually works
|
||||||
|
|
||||||
|
Kind of hyped to have found a loophole that might actually work, I started to test if it indeed does:
|
||||||
|
- I downloaded the Debian Bookworm “genericcloud-arm64” image in the qcow2 format to an existing compute instance
|
||||||
|
- After that, I created a new Ampere A1 instance, selected Ubuntu as the OS image and deleted it right after provisioning
|
||||||
|
- I then attached the detached boot volume to my existing instance and wrote the qcow2 image to that volume using `qemu-img`:
|
||||||
|
`qemu-img convert -f qcow2 -O raw debian-12-genericcloud-arm64.qcow2 /dev/sdb`
|
||||||
|
- As the last step, I detached the volume again and created another compute instance using that volume as its boot volume
|
||||||
|
|
||||||
|
And there we go! The instance booted without any problems and I was able to log in over SSH as usual. It seems that the Oracle Cloud platform just uses standard cloudinit, so even the injection of my SSH key worked.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
The approach described is definitely not as nice as simply uploading your own images. If you want to provision instances automatically (e.g. with OpenTofu), this is not suitable. It is definitely not supported by Oracle and may not work with any image. However, since I only use the Oracle Cloud for testing purposes anyway, it’s fine for me.
|
||||||
|
|
||||||
|
By default, metrics like CPU and RAM usage will probably be missing in the cloud portal because the Oracle agent is missing in the custom image. However, this has the funny side effect that the instance is apparently no longer reclaimed if it idles for too long.
|
39
content/blog/revisited-authoritative-dns-using-powerdns.md
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
title: "Revisited: Authoritative DNS servers using PowerDNS"
|
||||||
|
date: 2023-10-15T20:28:55+02:00
|
||||||
|
draft: false
|
||||||
|
author: "Bluemedia (Oliver)"
|
||||||
|
tags:
|
||||||
|
- Cloud
|
||||||
|
- Docker
|
||||||
|
- Hosting
|
||||||
|
- DNS
|
||||||
|
- PowerDNS
|
||||||
|
image: "/images/general/server-rack.jpg"
|
||||||
|
summary: "My DNS setup has changed quite a bit since I wrote about it two years ago. Time to take a look at how it evolved!"
|
||||||
|
socialShare: false
|
||||||
|
toc:
|
||||||
|
---
|
||||||
|
|
||||||
|
## Intro
|
||||||
|
|
||||||
|
About two years ago, I wrote an article about how I host my own authoritative DNS servers using PowerDNS. They are still running, but the setup has evolved quite a bit since then. So I think it’s time for a short update!
|
||||||
|
|
||||||
|
## From multi to single TLD
|
||||||
|
|
||||||
|
Originally, both servers resided in different TLDs (.dev and .re). Since the renewal price for the .re domain increased, I decided to ditch the multi-TLD setup and move both servers to the same TLD. After all, the chances that all DNS servers for the whole .dev TLD become unavailable are quite low.
|
||||||
|
|
||||||
|
I also used this opportunity to rename both servers to match my new naming concept. They now live on as ns1.dns.infra.bluemedia.dev and ns2.dns.infra.bluemedia.dev.
|
||||||
|
|
||||||
|
## More containers!
|
||||||
|
|
||||||
|
In the original design, PowerDNS as well as the database were installed directly on the host operating system. Additionally, the first server also hosted a dockerized management environment. This design proved to be quite clunky and hard to maintain. Because of this, I decided to move everything inside containers and also get rid of the second PowerDNS instance on the management host.
|
||||||
|
|
||||||
|
## Full high availability
|
||||||
|
|
||||||
|
Back when I started with the project, only the first server hosted the management environment. The second server was configured solely as a read-only replica. Since I wanted to take a closer look at MariaDB Galera anyways, I decided to move to full high availibility.
|
||||||
|
|
||||||
|
In the current setup, both servers form a multi-primary MariaDB Galera cluster. To maintain quorum, I additionally added Galera Arbitrator (garbd) running on a third server. This setup now allows me to run the management environment on both servers and perform load balancing between them. The load balancing uses DNS round-robin, enhanced with PowerDNS Lua records, so that the DNS records of an unavailable server get automatically dropped from the zone.
|
||||||
|
|
||||||
|
The new design looks like this:
|
||||||
|
![](/images/posts/revisited-authoritative-dns-using-powerdns/new-pdns-architecture.jpg)
|
BIN
static/fav.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
static/images/about.jpg
Normal file
After Width: | Height: | Size: 1.7 MiB |
BIN
static/images/general/hdd-open.jpg
Normal file
After Width: | Height: | Size: 262 KiB |
BIN
static/images/general/server-rack.jpg
Normal file
After Width: | Height: | Size: 641 KiB |
BIN
static/images/hero.jpg
Normal file
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 93 KiB |
BIN
static/images/projects/fancy-gatus.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
static/images/projects/keycloak-modern-login.jpg
Normal file
After Width: | Height: | Size: 198 KiB |
BIN
static/images/projects/scan-os.png
Normal file
After Width: | Height: | Size: 44 KiB |