Skip to content

Commit

Permalink
✨ (post): Added a post about how I did my homelab
Browse files Browse the repository at this point in the history
  • Loading branch information
theobori committed Jun 6, 2024
1 parent dd94051 commit cdada19
Show file tree
Hide file tree
Showing 14 changed files with 189 additions and 8 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ _site
.certificates
scripts/deploy.sh
/bak

graphs/
Binary file added assets/authentik_proxy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/authentik_users.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/dashy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/media_stack.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/monitoring_stack.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions blog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ title: Blog
Simply to document the things that interest me. Writing them forces me to be more precise and to understand and go deeper into certain concepts.
 
Below you can find posts about some projects I did. I also archive what I do and I make some of my notes public.
 
No IA is involved in this blog.

<!-- posts are below -->
4 changes: 3 additions & 1 deletion posts/chezmoi.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ data:
&nbsp;

For the moment the repository is only compatible with Fedora and Arch Linux, however it is easy to implement other distributions.
&nbsp;

## Apply from a different machine
&nbsp;

To apply my configuration from another machine, simply run the following commands.

Expand All @@ -60,6 +60,8 @@ chezmoi init https://github.com/theobori/dotfiles.git
chezmoi apply -v
```

&nbsp;

## Links

[https://github.com/theobori/dotfiles](https://github.com/theobori/dotfiles)
Expand Down
2 changes: 2 additions & 0 deletions posts/ebpf.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ The verification process ensures the eBPF bytecode is safe.
It tests every possible execution paths, it pushes copy of the regs onto a stack and explore one of the possible paths.

It is optimized to avoid evaluating the instructions with something called state pruning, it avoids reevaluating path (record registers state and if it arrives on the same instruction with a matching state, there is no need to verify the rest of path).
&nbsp;

## XDP

Expand All @@ -121,6 +122,7 @@ XDP stands for eXpress Data Path, it is a programmable kernel-integrated packet
> *"The packet processor is the in-kernel component for XDP programs that processes packets on the receive (RX) queue directly as they are presented by the NIC.*"
XDP programs can make decision (drop, pass, etc..) on the received packets.
&nbsp;

## Important Linux concepts

Expand Down
172 changes: 172 additions & 0 deletions posts/homelab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
title: My homelab
date: "2024-06-06"
---

I've got an old laptop that I don't use anymore, so I thought I'd turn it into a server and deploy some free, open-source web services on it.

The aim is to create a private homelab, i.e. the machine should only be accessible via the local network. None of the services are exposed to the Internet, with the exception of Wireguard, which lets me access the services from the outside.

My laptop is an [ASUS ROG G750](https://laptopmedia.com/series/asus-rog-g750/) with 8GB of memory and 2 HDDs of around 600GB each. It hasn't been used for about five or six years and the battery is dead.
&nbsp;

## First steps

First, I decided to make an old USB key bootable. I install [Ventoy](https://www.ventoy.net/) on it to be able to load different image disks (ISO) without having to rewrite each time directly on the USB key.

I put [Memtest86+](https://www.memtest.org/) to test the memory, [shredos.x86_64](https://github.com/PartialVolume/shredos.x86_64) to wipe the HDDs and finally [Debian 12](https://cdimage.debian.org/debian-cd/12.5.0/amd64/iso-cd/) which will be the main OS.

So when I boot on the USB key, it loads the "multiboot" boot-loader (Ventoy) and I can then load one of the three programs.
&nbsp;

## Pre configuration

To be able to deploy the system configuration and reproduce it later, I'm writing an Ansible playbook and testing it on a local VM (`virt-manager` + KVM).

The entire configuration is available at the bottom of the page.
&nbsp;

## TLS certificates

I want communication with web applications to be encrypted and secure, so I need an HTTPS server, so I need TLS certificates and, to make things easier, a domain name.

For the domain name I used [Duck DNS](https://www.duckdns.org/) and reserved the sub-domain [theobori.duckdns.org](https://theobori.duckdns.org) which for the moment corresponds to the IPv4 of my virtual machine accessible only from the host system.

In fact, I only need to manage one certificate with two SANs:
- `theobori.duckdns.org`
- `*.theobori.duckdns.org`
&nbsp;

## Services

Every application is deployed with the Ansible playbook are conteuneurized and managed with Docker.

They are accessible only through port 443 managed by [Traefik](https://traefik.io/). Each sub-domain of [theobori.duckdns.org](https://theobori.duckdns.org) corresponds to a service, with the exception of the homepage, which is associated with the domain itself.
&nbsp;

## Firewall

To filter incoming network traffic, I manipulate iptables with the ufw tool. There are only four ports open as declared below in the Ansible playbook configuration.

```yaml
- role: weareinteractive.ufw
tags: ufw
ufw_enabled: true
ufw_packages: ["ufw"]
ufw_rules:
- logging: "full"
- rule: allow
to_port: "443"
- rule: allow
to_port: "80"
- rule: allow
{% raw %} to_port: "{{ ssh_port }}" {% endraw %}
# Wireguard
- rule: allow
to_port: "51820"
proto: udp
# Delete default rule
- rule: allow
name: Anywhere
delete: true
ufw_manage_config: true
ufw_config:
IPV6: "yes"
DEFAULT_INPUT_POLICY: DROP
DEFAULT_OUTPUT_POLICY: ACCEPT
DEFAULT_FORWARD_POLICY: DROP
DEFAULT_APPLICATION_POLICY: SKIP
MANAGE_BUILTINS: "no"
IPT_SYSCTL: /etc/ufw/sysctl.conf
IPT_MODULES: ""
```
&nbsp;
## Identity provider
Services with integration for protocols to verify user identity or determine permissions are all linked to the [Authentik](https://goauthentik.io/) user directory.
I needed OAuth2 for [Portainer](https://www.portainer.io/) and LDAP for several other services such as [Owncloud](https://owncloud.com/).
If I remember correctly, the OAuth2 Outpost is embedded in the application by default, whereas the LDAP Outpost had to be configured with specific parameters for Docker.
Here's a diagram of several services trying to retrieve the identity of an [Authentik](https://goauthentik.io/) user.
&nbsp;
<p align="center" width="100%">
<img src="/authentik_users.png">
</p>
&nbsp;
## Access management
With [Authentik](https://goauthentik.io/), group policies have been created to authorize only certain groups of users to access certain services.
For example, for [Jellyfin](https://jellyfin.org/), only users in the `Jellyfin` group are authorized to connect.

In this way, I was able to secure all administration services by authorizing only users in groups reserved for administration.

I also used [Traefik](https://traefik.io/) and [Authentik](https://goauthentik.io/) to secure access to services not protected by authentication.

I added middleware to the reverse proxy to enable HTTP ForwardAuth with [Authentik](https://goauthentik.io/). In practical terms, this places a connection portal in front of the targeted web services.

Let's say I want to access [duplicati.theobori.duckdns.org](https://duplicati.theobori.duckdns.org), it could be schematized as follows.
&nbsp;

<p align="center" width="100%">
<img src="/authentik_proxy.png">
</p>
&nbsp;

## Media stack

One of the main objectives was to be able to manage movies and series and watch them from any device on the local network.

So I set up a stack for managing and downloading media, which would then be streamed to devices by [Jellyfin](https://jellyfin.org/).

Here's what the media stack looks like.
&nbsp;

<p align="center" width="100%">
<img src="/media_stack.png">
</p>
&nbsp;

## Backup and restore

To back up container data, I use [Duplicati](https://duplicati.com/). It lets you encrypt data and manage retention very easily via a web interface.

These backups can then be restored on my old computer.
&nbsp;

## Monitoring

To keep abreast of service status, I've opted for [Uptime Kuma](https://uptime.kuma.pet/), which will alert me via Discord when a service is down for n seconds.

I also have a [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/) stack that lets me collect metrics on the system and on Docker containers. As for [Uptime Kuma](https://uptime.kuma.pet/), I'm alerted by Discord according to limits defined for RAM and available storage space, for example.

This is how the monitoring stack looks.

<p align="center" width="100%">
<img src="/monitoring_stack.png">
</p>

&nbsp;

## Final home page

Here's an overview of the dashboard, featuring all the services exposed to the local network. In a way it's the end result of service implementation.

<p align="center" width="100%">
<img src="/dashy.png" width="650px">
</p>

&nbsp;

## Links

[https://github.com/theobori/homelab](https://github.com/theobori/homelab)

&nbsp;
5 changes: 3 additions & 2 deletions posts/lox.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ For the moment I'm not quite done, I've implemented the features below.
- *Functions with parameters*
- *Closures*
- *Static variable resolution and error detection*
&nbsp;

## What is lox ?

To sum up [this page](https://craftinginterpreters.com/the-lox-language.html), Lox is a small, high-level scripting language, with dynamic types and automatic memory management. It is similar to Javascript, Lua and Scheme.

A cool fact is that Lox is Turing complete, it means it is able to run a Turing machine.
&nbsp;

## Essentials basics

Expand Down Expand Up @@ -109,8 +111,6 @@ We use rules to generate strings that are in the grammar, it is called derivatio
Each production has a head (its name) and a body (a list of symbols).

&nbsp;

A symbol can be:
- A terminal, it is like an endpoint, it simply produces it.
- A non-terminal, it refers to other rule in the grammar.
Expand All @@ -131,6 +131,7 @@ bread → "toast" | "biscuits" | "English muffin" ;
```

The ponctuations is based on the regex behaviors, as example, the `?` means it is optional.
&nbsp;

So here, a valid strings could be the one below.

Expand Down
5 changes: 2 additions & 3 deletions posts/openbsd_ports.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ I was getting interested in BSD systems, more specifically OpenBSD, its firewall
I thought it could be interesting to port/package some games I've played during my childhood such as [Super Mario War](http://smwstuff.net) or [VVVVVV](https://thelettervsixtim.es/index.html).

Before making the game compatible with the distribution, it's best to fetch the port tree ([doc](https://www.openbsd.org/faq/ports/ports.html)) and read the official documentation ([doc](https://www.openbsd.org/faq/ports/guide.html)) to get the essentials.
&nbsp;

## OpenBSD environment
&nbsp;

My test environment is a virtual machine managed by `virt-manager` (using libvirt to interact with KVM) on which [OpenBSD 7.4](https://www.openbsd.org/74.html) has been installed, following the steps [here](https://www.openbsdhandbook.com/installation/).

&nbsp;

To manage X displays, I used `xenodm` which is installed by default on OpenBSD. You can activate its system service with the following command.

```bash
Expand All @@ -26,6 +24,7 @@ rcctl enable xenodm
&nbsp;

And for the windows manager, there's a basic one (cwm) but I opted for i3wm anyway.
&nbsp;

## Porting VVVVVV

Expand Down
3 changes: 2 additions & 1 deletion posts/terraform_chaos_doom.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ date: "2023-06-03"
---

I first saw [kubedoom](https://github.com/storax/kubedoom) and thought it was pretty cool, so I decided to do the same for Terraform, knowing that I was working with it for professional projects.
&nbsp;

The principle is very simple, each enemy represents a Terraform resource, if an enemy dies, the associated resource is destroyed.
&nbsp;

## How does it work?

Expand Down
2 changes: 1 addition & 1 deletion posts/terraform_chaos_teeworlds.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ date: "2024-06-05"
After doing some [chaos engineering for Terraform with the DOOM game](/posts/terraform_chaos_doom/), I wanted to make a version for Teeworlds, specifically for its version 0.7 (its latest version).

The difference with the DOOM version is that in this project, a player must capture the flag for a Terraform resource to be randomly destroyed.
&nbsp;

## How does it work?

When configuring a Teeworlds server, the values below can be entered.
&nbsp;

```bash
# Econ configuration
Expand Down

0 comments on commit cdada19

Please sign in to comment.