Compare commits
16 Commits
b0b63df44e
...
v4
| Author | SHA1 | Date | |
|---|---|---|---|
| 66901b9299 | |||
| aece26e893 | |||
|
|
571a4190d5 | ||
|
|
c11e3f4a7a | ||
|
|
c6896befa7 | ||
|
|
42bff6acee | ||
|
|
f42e30024d | ||
|
|
de7309dae4 | ||
|
|
4a1c31938f | ||
|
|
d161a86020 | ||
|
|
054089ec17 | ||
|
|
b511dfa07a | ||
|
|
303645f3a5 | ||
|
|
58ea6686dd | ||
|
|
5d2efccfe5 | ||
|
|
4bab7d0d86 |
73
.gitea/workflows/build-deploy.yml
Normal file
73
.gitea/workflows/build-deploy.yml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
name: Build and Push Quartz Wiki
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- v4
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: "gitea.vorpax.dev"
|
||||||
|
IMAGE_NAME: "vorpax/wiki"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Log in to Gitea Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ gitea.actor }}
|
||||||
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels)
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=sha,prefix=
|
||||||
|
type=raw,value=latest,enable=${{ gitea.ref == format('refs/heads/{0}', 'v4') }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
file: ./Dockerfile.prod
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
- name: Image digest
|
||||||
|
run: echo "Image built and pushed successfully"
|
||||||
|
|
||||||
|
#- name: Trigger Komodo Webhook
|
||||||
|
# run: ../scripts/komodo-webhook.sh
|
||||||
|
# Optional: Add deployment step
|
||||||
|
# Uncomment and configure this section if you want automatic deployment
|
||||||
|
# deploy:
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# needs: build-and-push
|
||||||
|
# steps:
|
||||||
|
# - name: Deploy to server
|
||||||
|
# uses: appleboy/ssh-action@v1.0.0
|
||||||
|
# with:
|
||||||
|
# host: ${{ secrets.DEPLOY_HOST }}
|
||||||
|
# username: ${{ secrets.DEPLOY_USER }}
|
||||||
|
# key: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||||
|
# script: |
|
||||||
|
# cd /path/to/quartz
|
||||||
|
# docker compose pull
|
||||||
|
# docker compose up -d
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
name: Build and Push Quartz
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Login to Gitea Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ${{ github.server_url }}
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and Push
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
tags: |
|
|
||||||
${{ github.server_url }}/${{ github.repository }}/quartz:${{ github.sha }}
|
|
||||||
${{ github.server_url }}/${{ github.repository }}/quartz:latest
|
|
||||||
221
DEPLOYMENT.md
Normal file
221
DEPLOYMENT.md
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
# Déploiement Quartz Wiki
|
||||||
|
|
||||||
|
Ce document explique comment déployer le site Quartz sur votre infrastructure homelab.
|
||||||
|
|
||||||
|
## 📋 Prérequis
|
||||||
|
|
||||||
|
- Instance Gitea avec Gitea Actions activé
|
||||||
|
- Gitea Container Registry configuré
|
||||||
|
- Secret `REGISTRY_TOKEN` configuré dans votre dépôt Gitea
|
||||||
|
- Serveur avec Docker et Docker Compose
|
||||||
|
- Traefik configuré comme reverse proxy (réseau `public`)
|
||||||
|
|
||||||
|
## 🔧 Configuration Initiale
|
||||||
|
|
||||||
|
### 1. Créer le Token Registry Gitea
|
||||||
|
|
||||||
|
1. Aller dans **Settings → Applications** de votre compte Gitea
|
||||||
|
2. Créer un nouveau token avec les permissions `write:package`
|
||||||
|
3. Ajouter ce token comme secret `REGISTRY_TOKEN` dans votre dépôt
|
||||||
|
|
||||||
|
### 2. Configurer Traefik (Optionnel)
|
||||||
|
|
||||||
|
Si vous utilisez Traefik, ajoutez ces labels dans `docker-compose.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
quartz:
|
||||||
|
image: gitea.vorpax.dev/vorpax/quartz-wiki:latest
|
||||||
|
container_name: quartz-wiki
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- public
|
||||||
|
|
||||||
|
labels:
|
||||||
|
# Enable Traefik
|
||||||
|
- "traefik.enable=true"
|
||||||
|
|
||||||
|
# HTTP Router
|
||||||
|
- "traefik.http.routers.quartz.rule=Host(`wiki.vorpax.dev`)"
|
||||||
|
- "traefik.http.routers.quartz.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.quartz.tls=true"
|
||||||
|
- "traefik.http.routers.quartz.tls.certresolver=letsencrypt"
|
||||||
|
|
||||||
|
# Service
|
||||||
|
- "traefik.http.services.quartz.loadbalancer.server.port=80"
|
||||||
|
|
||||||
|
# HTTP to HTTPS redirect
|
||||||
|
- "traefik.http.routers.quartz-http.rule=Host(`wiki.vorpax.dev`)"
|
||||||
|
- "traefik.http.routers.quartz-http.entrypoints=web"
|
||||||
|
- "traefik.http.routers.quartz-http.middlewares=redirect-to-https"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Déploiement
|
||||||
|
|
||||||
|
### Workflow Automatique (Recommandé)
|
||||||
|
|
||||||
|
1. **Commit et Push vers v4**:
|
||||||
|
```bash
|
||||||
|
git add .
|
||||||
|
git commit -m "Update content"
|
||||||
|
git push origin v4
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Le workflow Gitea Actions va automatiquement**:
|
||||||
|
- Builder l'image Docker
|
||||||
|
- Pusher vers `gitea.vorpax.dev/vorpax/quartz-wiki`
|
||||||
|
- Tagger avec `latest`, `v4`, et le SHA du commit
|
||||||
|
|
||||||
|
3. **Sur votre serveur de production**:
|
||||||
|
```bash
|
||||||
|
# Se connecter au registry Gitea
|
||||||
|
docker login gitea.vorpax.dev
|
||||||
|
|
||||||
|
# Pull la nouvelle image
|
||||||
|
docker compose pull
|
||||||
|
|
||||||
|
# Redémarrer le container
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build Local (Pour Testing)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build l'image localement
|
||||||
|
docker compose build
|
||||||
|
|
||||||
|
# Ou utiliser Dockerfile.prod directement
|
||||||
|
docker build -f Dockerfile.prod -t quartz-wiki:local .
|
||||||
|
|
||||||
|
# Lancer
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Développement Local
|
||||||
|
|
||||||
|
Pour le développement avec hot-reload:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Option 1: npx quartz
|
||||||
|
npx quartz build --serve
|
||||||
|
# Accessible sur http://localhost:8080
|
||||||
|
|
||||||
|
# Option 2: Docker dev
|
||||||
|
docker build -f Dockerfile.dev -t quartz-dev .
|
||||||
|
docker run -p 8080:8080 quartz-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 Structure du Projet
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── content/ # Contenu du site
|
||||||
|
│ ├── blog/ # Articles de blog
|
||||||
|
│ ├── homelab/ # Documentation homelab
|
||||||
|
│ │ ├── hardware/ # Pages hardware
|
||||||
|
│ │ ├── infrastructure/ # Infra docs
|
||||||
|
│ │ ├── services/ # Services docs
|
||||||
|
│ │ └── guides/ # Guides
|
||||||
|
│ └── templates/ # Templates Templater (non publiés)
|
||||||
|
├── quartz/ # Code source Quartz
|
||||||
|
├── quartz.config.ts # Configuration Quartz
|
||||||
|
├── quartz.layout.ts # Layout et composants
|
||||||
|
├── Dockerfile.prod # Dockerfile production (Nginx)
|
||||||
|
├── Dockerfile.dev # Dockerfile dev (--serve)
|
||||||
|
├── nginx.conf # Config Nginx
|
||||||
|
├── docker-compose.yml # Orchestration Docker
|
||||||
|
└── .gitea/workflows/ # CI/CD Gitea Actions
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 Workflow de Publication
|
||||||
|
|
||||||
|
### Avec Obsidian
|
||||||
|
|
||||||
|
1. **Éditer dans Obsidian**:
|
||||||
|
- Ouvrir le vault pointant vers `/content`
|
||||||
|
- Utiliser les templates dans `content/templates/`
|
||||||
|
- Ajouter `publish: true` dans le frontmatter
|
||||||
|
|
||||||
|
2. **Utiliser Templater**:
|
||||||
|
- Installer le plugin Templater dans Obsidian
|
||||||
|
- Configurer le dossier de templates: `content/templates`
|
||||||
|
- Créer une nouvelle note avec un template (Ctrl+P → "Templater: Create new note from template")
|
||||||
|
|
||||||
|
3. **Publier**:
|
||||||
|
```bash
|
||||||
|
git add content/
|
||||||
|
git commit -m "Add new blog post"
|
||||||
|
git push origin v4
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sans Obsidian
|
||||||
|
|
||||||
|
Créer un fichier markdown dans `content/blog/` ou `content/homelab/`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: "Mon Article"
|
||||||
|
publish: true
|
||||||
|
date: 2026-01-05
|
||||||
|
tags:
|
||||||
|
- homelab
|
||||||
|
- docker
|
||||||
|
description: "Description courte"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Contenu ici
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🏷️ Tags d'Images Disponibles
|
||||||
|
|
||||||
|
Le workflow crée plusieurs tags:
|
||||||
|
|
||||||
|
- `gitea.vorpax.dev/vorpax/quartz-wiki:latest` - Dernière version de la branche v4
|
||||||
|
- `gitea.vorpax.dev/vorpax/quartz-wiki:v4` - Tag de branche
|
||||||
|
- `gitea.vorpax.dev/vorpax/quartz-wiki:<sha>` - Tag par commit SHA
|
||||||
|
|
||||||
|
## 🔍 Troubleshooting
|
||||||
|
|
||||||
|
### L'image ne se build pas dans Gitea Actions
|
||||||
|
|
||||||
|
Vérifier que:
|
||||||
|
- Le secret `REGISTRY_TOKEN` est configuré
|
||||||
|
- Gitea Container Registry est activé
|
||||||
|
- Le runner Gitea Actions fonctionne
|
||||||
|
|
||||||
|
### Les changements n'apparaissent pas
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Forcer un nouveau pull
|
||||||
|
docker compose down
|
||||||
|
docker compose pull
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# Vérifier les logs
|
||||||
|
docker logs quartz-wiki
|
||||||
|
```
|
||||||
|
|
||||||
|
### 404 sur certaines pages
|
||||||
|
|
||||||
|
Vérifier que:
|
||||||
|
- La page a `publish: true` dans le frontmatter
|
||||||
|
- Le fichier est dans `content/`
|
||||||
|
- Les wikilinks utilisent le bon chemin
|
||||||
|
|
||||||
|
## 📊 Métriques
|
||||||
|
|
||||||
|
Le site est configuré avec Plausible Analytics sur `wiki.vorpax.dev`. Vérifiez `quartz.config.ts:15-17` pour la configuration.
|
||||||
|
|
||||||
|
## 🔐 Sécurité
|
||||||
|
|
||||||
|
- Les fichiers dans `content/templates/` ne sont jamais publiés
|
||||||
|
- Les fichiers dans `content/private/` sont exclus du build
|
||||||
|
- Le dossier `.obsidian/` n'est pas versionné
|
||||||
|
- Nginx inclut des headers de sécurité (X-Frame-Options, X-Content-Type-Options, etc.)
|
||||||
|
|
||||||
|
## 📚 Resources
|
||||||
|
|
||||||
|
- [Documentation Quartz](https://quartz.jzhao.xyz/)
|
||||||
|
- [Gitea Actions Docs](https://docs.gitea.com/usage/actions/overview)
|
||||||
|
- [Gitea Container Registry](https://docs.gitea.com/usage/packages/container)
|
||||||
35
Dockerfile.prod
Normal file
35
Dockerfile.prod
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Stage 1: Build Quartz site
|
||||||
|
FROM node:22-slim AS builder
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package.json package-lock.json* ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build Quartz (this generates the static site in /public)
|
||||||
|
RUN npx quartz build
|
||||||
|
|
||||||
|
# Stage 2: Serve with Nginx
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
# Copy the built static files from builder stage
|
||||||
|
COPY --from=builder /usr/src/app/public /usr/share/nginx/html
|
||||||
|
|
||||||
|
# Copy custom nginx configuration
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# Expose port 80
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
|
CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1
|
||||||
|
|
||||||
|
# Start nginx
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
19
compose.yaml
Normal file
19
compose.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
services:
|
||||||
|
quartz:
|
||||||
|
# Option 1: Pull from Gitea Container Registry (recommended for production)
|
||||||
|
image: gitea.vorpax.dev/vorpax/wiki:latest
|
||||||
|
|
||||||
|
# Option 2: Build locally (uncomment for local development)
|
||||||
|
# build:
|
||||||
|
# context: .
|
||||||
|
# dockerfile: Dockerfile.prod
|
||||||
|
|
||||||
|
container_name: quartz-wiki
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- public
|
||||||
|
|
||||||
|
networks:
|
||||||
|
public:
|
||||||
|
external: true
|
||||||
0
content/GLiNet Beryl AX.md
Normal file
0
content/GLiNet Beryl AX.md
Normal file
19
content/blog/index.md
Normal file
19
content/blog/index.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
title: Blog
|
||||||
|
publish: true
|
||||||
|
---
|
||||||
|
|
||||||
|
Welcome to my technical blog! Here you'll find articles, tutorials, and writeups on various topics including:
|
||||||
|
|
||||||
|
- System Administration
|
||||||
|
- DevOps & Automation
|
||||||
|
- Containerization (Docker, Kubernetes)
|
||||||
|
- Self-hosting & Homelab
|
||||||
|
- Networking & Security
|
||||||
|
- Programming & Scripting
|
||||||
|
|
||||||
|
All blog posts are listed below, sorted by date. You can also use tags to filter content by topic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> **Note**: This is a folder page. All blog posts in the `blog/` directory will be automatically listed below by Quartz.
|
||||||
11
content/homelab/Proxmox hosts.md
Normal file
11
content/homelab/Proxmox hosts.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
publish: true
|
||||||
|
title: My Physical Nodes
|
||||||
|
---
|
||||||
|
|
||||||
|
# All my nodes
|
||||||
|
|
||||||
|
My main cluster is composed of 3 Physical Nodes :
|
||||||
|
- [[littleboy|Littleboy]] which is a Firebat T8 Pro Plus
|
||||||
|
- [[optiplex|Optiplex]] which is an Optiplex 7070 SFF with an i7-9700 and 64GB of RAM
|
||||||
|
- [[fatman|Fatman]] which is a custom built gaming PC repurposed into a beefy GPU workhorse
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
---
|
||||||
|
title: Connecting a Travel Router to eduroam with 802.1X on OpenWrt
|
||||||
|
publish: true
|
||||||
|
date: 2026-01-05
|
||||||
|
tags:
|
||||||
|
- guide
|
||||||
|
- network
|
||||||
|
description: A guide on how to connect to 802.1X on OpenWRT
|
||||||
|
---
|
||||||
|
|
||||||
|
# Connecting a Travel Router to eduroam with 802.1X on OpenWrt
|
||||||
|
|
||||||
|
## The Problem
|
||||||
|
|
||||||
|
Universities use eduroam, a secure roaming WiFi service that requires 802.1X authentication.
|
||||||
|
This presents a challenge when you want to connect multiple devices or run infrastructure like a homelab node in a dorm room.
|
||||||
|
Most consumer devices expect simple WPA2-PSK networks where you just enter a password, but eduroam requires each device to authenticate individually with a username and certificate validation.
|
||||||
|
|
||||||
|
The typical solution is to authenticate each device separately, but this becomes impractical when you need to connect servers, or devices that lack proper 802.1X supplicant support.
|
||||||
|
|
||||||
|
A travel router solves this by authenticating once to eduroam and then providing a standard local network for your devices.
|
||||||
|
|
||||||
|
## Understanding 802.1X and eduroam
|
||||||
|
|
||||||
|
The 802.1X standard defines port-based network access control. When you connect to an 802.1X network, the access point acts as an authenticator that forwards your credentials to a RADIUS server. The RADIUS server verifies your identity and either grants or denies network access.
|
||||||
|
|
||||||
|
eduroam uses 802.1X with EAP-TTLS or PEAP as the outer authentication method and typically PAP or MSCHAPv2 for the inner authentication.
|
||||||
|
The outer method creates an encrypted tunnel using TLS, and your actual credentials travel through this tunnel to the RADIUS server. This provides strong security even on an open wireless network.
|
||||||
|
|
||||||
|
The authentication flow involves presenting a username in the format `user@institution.domain`, an anonymous identity to protect your real username during the initial handshake, and validating the RADIUS server certificate against a trusted CA certificate. This last step prevents attackers from impersonating the authentication server.
|
||||||
|
|
||||||
|
## Why a Travel Router
|
||||||
|
|
||||||
|
A travel router is a compact router designed for mobile use.
|
||||||
|
|
||||||
|
In our case, it serves as a translation layer between the complex 802.1X requirements of eduroam and the simpler networking expectations of our devices.
|
||||||
|
|
||||||
|
You authenticate the router once to eduroam, and it provides a local network over Ethernet and wifi where you can connect servers, development machines, or any IoT devices without each device needing to understand 802.1X.
|
||||||
|
|
||||||
|
This approach provides several advantages.
|
||||||
|
You can run services that require static IPs or specific network configurations. You can connect devices that lack 802.1X support entirely. You avoid repeatedly entering credentials on multiple devices.
|
||||||
|
|
||||||
|
Most importantly, you gain control over your local network segment, enabling you to run monitoring tools, configure custom DNS, or set up VLANs as needed.
|
||||||
|
|
||||||
|
## Hardware and Software Selection
|
||||||
|
|
||||||
|
This guide uses the GL.iNet Beryl AX (GL-MT3000) running OpenWrt 24.10 with a MediaTek MT7981 chipset.
|
||||||
|
|
||||||
|
Like most Mediatek chipsets, The MT7981 has mature driver support shipped with recent Linux Kernel and hence is well supported on OpenWrt, moreover it handles 802.1X authentication reliably.
|
||||||
|
|
||||||
|
OpenWrt is a Linux-based router firmware that replaces vendor firmware with a fully configurable system. Unlike consumer router interfaces, OpenWrt exposes the full Linux networking stack and uses the `wpa_supplicant` (along with `hostapd`) for 802.1X support.
|
||||||
|
|
||||||
|
The choice of OpenWrt over the stock GL.iNet firmware ensures we are working with well-documented, upstream software.
|
||||||
|
|
||||||
|
## Building a Custom OpenWrt Image
|
||||||
|
|
||||||
|
Rather than flashing a stock image and installing packages afterward, building a custom image ensures all necessary packages are included from the start. This is important because you need working internet connection to install additional packages, creating a chicken-and-egg problem.
|
||||||
|
|
||||||
|
Visit the OpenWrt firmware selector at `https://firmware-selector.openwrt.org/` and search for "GL-MT3000"
|
||||||
|
Then, in the package customization field, you need to make one critical change and add several packages.
|
||||||
|
|
||||||
|
The default OpenWrt image includes `wpad-basic-mbedtls`, which is a minimal WiFi configuration tool that lacks 802.1X support.
|
||||||
|
You **must remove this package** and **replace it with the full version**. Enter `-wpad-basic-mbedtls` (note the minus sign) to remove it, then add `wpad-mbedtls` to install the full version with EAP support.
|
||||||
|
|
||||||
|
Add these additional packages in the same field: `ca-certificates` for validating SSL certificates, `vim` and `bash` if you prefer these over the default `vi` and `ash` shells. The complete package customization string should read:
|
||||||
|
|
||||||
|
```
|
||||||
|
base-files
|
||||||
|
ca-bundle
|
||||||
|
dnsmasq
|
||||||
|
dropbear
|
||||||
|
firewall4
|
||||||
|
fitblk
|
||||||
|
fstools
|
||||||
|
kmod-crypto-hw-safexcel
|
||||||
|
kmod-gpio-button-hotplug
|
||||||
|
kmod-leds-gpio
|
||||||
|
kmod-nft-offload
|
||||||
|
kmod-phy-aquantia
|
||||||
|
libc
|
||||||
|
libgcc
|
||||||
|
libustream-mbedtls
|
||||||
|
logd
|
||||||
|
mtd
|
||||||
|
netifd
|
||||||
|
nftables
|
||||||
|
odhcp6c
|
||||||
|
odhcpd-ipv6only
|
||||||
|
opkg
|
||||||
|
ppp
|
||||||
|
ppp-mod-pppoe
|
||||||
|
procd-ujail
|
||||||
|
uboot-envtools
|
||||||
|
uci
|
||||||
|
uclient-fetch
|
||||||
|
urandom-seed
|
||||||
|
urngd
|
||||||
|
kmod-mt7915e
|
||||||
|
kmod-mt7981-firmware
|
||||||
|
mt7981-wo-firmware
|
||||||
|
kmod-hwmon-pwmfan
|
||||||
|
kmod-usb3
|
||||||
|
kmod-usb-net
|
||||||
|
kmod-usb-net-ipheth
|
||||||
|
luci
|
||||||
|
wpad-mbedtls
|
||||||
|
usbmuxd
|
||||||
|
libimobiledevice
|
||||||
|
vim
|
||||||
|
bash
|
||||||
|
usbutils
|
||||||
|
```
|
||||||
|
|
||||||
|
Request the build and download the resulting firmware image. Flash this to your router following the standard flashing procedure for your model.
|
||||||
|
|
||||||
|
## Obtaining eduroam Credentials
|
||||||
|
|
||||||
|
Your institution should provide an eduroam configuration tool, typically through the eduroam Configuration Assistant Tool at `cat.eduroam.org`.
|
||||||
|
|
||||||
|
Download the Linux installer for your institution, it's a rather convenient Python script which we will extract the configuration parameters from.
|
||||||
|
|
||||||
|
Look for the configuration section near the end. You need these specific values: the EAP outer method (likely TTLS or PEAP), the inner authentication method (likely PAP or MSCHAPv2), the RADIUS server hostname, the anonymous identity, and the CA certificate.
|
||||||
|
|
||||||
|
The CA certificate appears in the script as a multi-line string starting with `-----BEGIN CERTIFICATE-----`.
|
||||||
|
|
||||||
|
Copy this certificate exactly, preserving all line breaks, and save it to a file. This certificate will be used to validate that you are connecting to your institution's legitimate RADIUS server.
|
||||||
|
|
||||||
|
## Initial Router Configuration
|
||||||
|
|
||||||
|
Connect to your router over Ethernet after flashing. The default IP is typically `192.168.8.1` or `192.168.1.1`. SSH to the router as root (password may need to be set on first boot through the web interface).
|
||||||
|
|
||||||
|
Create the CA certificate file in the appropriate location. Copy your institution's CA certificate and save it to `/etc/ssl/certs/institution-ca.crt`. Set the permissions to be world-readable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod 644 /etc/ssl/certs/institution-ca.crt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuring the WiFi Interface
|
||||||
|
|
||||||
|
OpenWrt uses the UCI (Unified Configuration Interface) system for configuration. The wireless configuration file is `/etc/config/wireless`.
|
||||||
|
|
||||||
|
You can edit this file directly or use UCI commands. The UCI approach is safer as it validates syntax.
|
||||||
|
First, determine which radio to use. Run `wifi status` to see available radios.
|
||||||
|
|
||||||
|
The Beryl AX typically has `radio0` for 2.4GHz and `radio1` for 5GHz. Choose based on which band eduroam uses at your location. The 5GHz band often has less interference but shorter range.
|
||||||
|
|
||||||
|
Create the eduroam interface configuration:
|
||||||
|
```bash
|
||||||
|
uci set wireless.eduroam=wifi-iface
|
||||||
|
uci set wireless.eduroam.device='radio1'
|
||||||
|
uci set wireless.eduroam.network='wan'
|
||||||
|
uci set wireless.eduroam.mode='sta'
|
||||||
|
uci set wireless.eduroam.ssid='eduroam'
|
||||||
|
uci set wireless.eduroam.encryption='wpa2+ccmp'
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a station mode interface (meaning the router acts as a WiFi client) associated with the WAN network.
|
||||||
|
|
||||||
|
Now add the 802.1X parameters:
|
||||||
|
```bash
|
||||||
|
uci set wireless.eduroam.eap_type='ttls'
|
||||||
|
uci set wireless.eduroam.auth='PAP'
|
||||||
|
uci set wireless.eduroam.identity='your.username@institution.domain'
|
||||||
|
uci set wireless.eduroam.anonymous_identity='anonymous@institution.domain'
|
||||||
|
uci set wireless.eduroam.password='your_password'
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace the identity and password with your actual credentials. The anonymous identity protects your username during the initial handshake. Replace `institution.domain` with your institution's actual domain.
|
||||||
|
|
||||||
|
The certificate validation is where many configurations fail. In theory, you should validate the RADIUS server certificate against the CA:
|
||||||
|
```bash
|
||||||
|
uci set wireless.eduroam.ca_cert='/etc/ssl/certs/institution-ca.crt'
|
||||||
|
uci set wireless.eduroam.domain_suffix_match='radius.institution.domain'
|
||||||
|
```
|
||||||
|
|
||||||
|
However, many institution certificates lack proper Subject Alternative Name (SAN) fields, causing modern TLS implementations to reject them.
|
||||||
|
|
||||||
|
If you encounter authentication failures with certificate validation errors in the logs, you may need to disable certificate validation.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uci delete wireless.eduroam.domain_suffix_match
|
||||||
|
```
|
||||||
|
|
||||||
|
Commit the changes and reload the wireless configuration:
|
||||||
|
```bash
|
||||||
|
uci commit wireless
|
||||||
|
wifi reload
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuring the Network Interface
|
||||||
|
|
||||||
|
The wireless interface connects to eduroam, but you need to ensure the WAN interface uses this connection. Check the current WAN device:
|
||||||
|
```bash
|
||||||
|
uci show network.wan
|
||||||
|
```
|
||||||
|
|
||||||
|
The default configuration often sets the WAN device to `eth0` (the Ethernet port), but you need it to use the WiFi interface. Change it to the wireless interface name:
|
||||||
|
```bash
|
||||||
|
uci set network.wan.device='phy1-sta0'
|
||||||
|
uci commit network
|
||||||
|
ifup wan
|
||||||
|
```
|
||||||
|
|
||||||
|
The interface name `phy1-sta0` corresponds to `radio1` in station mode. If you used `radio0` instead, adjust accordingly.
|
||||||
|
|
||||||
|
After bringing up the WAN interface, verify it obtained an IP address:
|
||||||
|
```bash
|
||||||
|
ifstatus wan
|
||||||
|
ip addr show phy1-sta0
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see an IPv4 address assigned via DHCP. Test internet connectivity:
|
||||||
|
```bash
|
||||||
|
ping -c 4 1.1.1.1
|
||||||
|
ping -c 4 google.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Understanding the Authentication Flow
|
||||||
|
|
||||||
|
Watch the authentication process using the system log:
|
||||||
|
```bash
|
||||||
|
logread -f | grep -i "wpa\|eap"
|
||||||
|
```
|
||||||
|
|
||||||
|
A successful authentication shows this sequence: the supplicant tries to authenticate with the access point, the access point responds, EAP authentication starts, the TTLS method is selected, the TLS handshake completes (or fails with certificate errors), inner authentication occurs, and finally `CTRL-EVENT-EAP-SUCCESS` appears followed by `CTRL-EVENT-CONNECTED`.
|
||||||
|
|
||||||
|
If you see `CTRL-EVENT-EAP-FAILURE`, examine the lines immediately before it. Certificate validation errors mention hostnames or certificate chains. Authentication failures with valid certificates usually indicate wrong credentials. Connection attempts that timeout suggest the RADIUS server is unreachable or the configuration parameters are incorrect.
|
||||||
|
|
||||||
|
## Troubleshooting Common Issues
|
||||||
|
|
||||||
|
Authentication failures usually stem from three issues: incorrect credentials, certificate validation problems, or wrong EAP method parameters.
|
||||||
|
|
||||||
|
If logs show certificate validation errors mentioning hostnames or missing SANs, your institution's certificate lacks modern TLS extensions. Disable certificate validation as described earlier. This is a common problem with older certificate authorities.
|
||||||
|
|
||||||
|
If authentication fails after the TLS handshake completes, verify your username format matches your institution's requirements. Most institutions use `username@domain`. Check with your IT department.
|
||||||
|
|
||||||
|
If the connection succeeds but you have no internet access, the problem lies in the network interface configuration. Verify the WAN interface uses the correct device with `uci show network.wan`. Ensure DHCP is enabled on WAN with `uci set network.wan.proto='dhcp'`. Restart the network service after changes.
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
The router stores your password in plain text in the UCI configuration files. These files are only readable by root, but anyone with root access can read them. Avoid sharing configuration backups publicly and use strong router passwords.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
This setup provides a robust solution for connecting homelab infrastructure to enterprise WiFi networks. The travel router handles the complex 802.1X authentication, presenting a standard local network to your devices. This approach works well in university dorms, campus offices, or any environment using certificate-based network authentication.
|
||||||
|
|
||||||
|
*Published on January 05, 2026*
|
||||||
32
content/homelab/hardware/end-devices/index.md
Normal file
32
content/homelab/hardware/end-devices/index.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
title: My everyday devices
|
||||||
|
publish: true
|
||||||
|
tags:
|
||||||
|
-
|
||||||
|
---
|
||||||
|
|
||||||
|
# What are my daily drivers
|
||||||
|
|
||||||
|
|
||||||
|
## Why the hell am I running MacOS ?
|
||||||
|
|
||||||
|
Here is something quite controversial : I find Mac better than most laptops out there.
|
||||||
|
|
||||||
|
I know this is quite a controversial statement but, after having struggled for hours trying to make WSL work along with both mosh and my Yubikey, I basically gave up.
|
||||||
|
|
||||||
|
Though I'm still and I will always be a Linux enjoyer, you can't deny that both Mac as a piece of hardware and MacOS as an OS get the job done.
|
||||||
|
|
||||||
|
Here are the key points:
|
||||||
|
- It enables you to access the Office Suite (I know, OSS alternatives, have you ever managed to setup a Microsoft Exchange Email Client on any other app than Outlook ? I did not.)
|
||||||
|
- It natively takes advantages of it's ARM CPU architecture, offering substantially better battery performance than any x86 machine while remaining light and thin.
|
||||||
|
- MacOS as a BSD derivative is actually quite close to Linux in a daily usage. Though you might not have access to some of `ps` obscure flags, the ability to install GNU Core Utils and to use those, only by prefixing your command with `g` (`gls`, `gcat`,`gcp` and even `gchroot`) is actually pretty great.
|
||||||
|
- Mac is the only option if you need substantial amounts of RAM for both GPU and CPU usage.
|
||||||
|
- `brew` is really convenient, trust me.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Ipad is great for maths
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## You know what,
|
||||||
42
content/homelab/hardware/proxmox-nodes/fatman.md
Normal file
42
content/homelab/hardware/proxmox-nodes/fatman.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
title: Fatman - GPU Workhorse
|
||||||
|
publish: true
|
||||||
|
tags:
|
||||||
|
- homelab
|
||||||
|
- hardware
|
||||||
|
- proxmox
|
||||||
|
- gpu
|
||||||
|
---
|
||||||
|
|
||||||
|
# Fatman
|
||||||
|
|
||||||
|
**Type**: Custom built gaming PC repurposed as GPU workhorse
|
||||||
|
|
||||||
|
## Specifications
|
||||||
|
|
||||||
|
- **CPU**:
|
||||||
|
- **RAM**:
|
||||||
|
- **GPU**:
|
||||||
|
- **Storage**:
|
||||||
|
- **Network**:
|
||||||
|
|
||||||
|
## Role in Cluster
|
||||||
|
|
||||||
|
This node is part of the main Proxmox cluster, serving as a GPU-accelerated workstation for compute-intensive tasks.
|
||||||
|
|
||||||
|
## Services Running
|
||||||
|
|
||||||
|
- GPU-accelerated workloads
|
||||||
|
- List specific services/VMs/containers
|
||||||
|
|
||||||
|
## GPU Passthrough
|
||||||
|
|
||||||
|
Configuration details for GPU passthrough if applicable.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
Add any additional notes, configuration details, or special considerations for this node.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Back to [[Proxmox hosts|Physical Nodes]]
|
||||||
36
content/homelab/hardware/proxmox-nodes/gerboise.md
Normal file
36
content/homelab/hardware/proxmox-nodes/gerboise.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
title: Gerboise - GmkTec K12
|
||||||
|
publish: true
|
||||||
|
tags:
|
||||||
|
- homelab
|
||||||
|
- hardware
|
||||||
|
- proxmox
|
||||||
|
---
|
||||||
|
|
||||||
|
# Littleboy
|
||||||
|
|
||||||
|
**Model**: GmkTec K12
|
||||||
|
|
||||||
|
## Specifications
|
||||||
|
|
||||||
|
- **CPU**: AMD
|
||||||
|
- **RAM**: $1\times 32 \text{Go} + 1\times 16 \text{Go} \, \, \text{DDR5 SO-DIMM}$
|
||||||
|
- **Storage**: 1To NVME for Now
|
||||||
|
- **Network**: 2\*2.5Gbe Ethernet + 1 Mediatek Wifi + Bluetooth card (It's currently plugged into my [[GLiNet Beryl AX | GLiNet Beryl AX travel router]] and [[Connecting a Travel Router to eduroam with 802.1X on OpenWrt | connected to eduroam]] )
|
||||||
|
|
||||||
|
## Role in Cluster
|
||||||
|
|
||||||
|
This node has a peculiar role in my cluster as it is the only node away from my parent's place.
|
||||||
|
I carry it along with me at HEC, it serves as a local experimentation test bench and as a secondary source of daily computing power along with my [[Macbook Pro]].
|
||||||
|
|
||||||
|
## Services Running
|
||||||
|
|
||||||
|
- List services/VMs/containers running on this node
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
Add any additional notes, configuration details, or special considerations for this node.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Back to [[Proxmox hosts|Physical Nodes]]
|
||||||
35
content/homelab/hardware/proxmox-nodes/littleboy.md
Normal file
35
content/homelab/hardware/proxmox-nodes/littleboy.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
title: Littleboy - Firebat T8 Pro Plus
|
||||||
|
publish: true
|
||||||
|
tags:
|
||||||
|
- homelab
|
||||||
|
- hardware
|
||||||
|
- proxmox
|
||||||
|
---
|
||||||
|
|
||||||
|
# Littleboy
|
||||||
|
|
||||||
|
**Model**: Firebat T8 Pro Plus
|
||||||
|
|
||||||
|
## Specifications
|
||||||
|
|
||||||
|
- **CPU**:
|
||||||
|
- **RAM**:
|
||||||
|
- **Storage**:
|
||||||
|
- **Network**:
|
||||||
|
|
||||||
|
## Role in Cluster
|
||||||
|
|
||||||
|
This node is part of the main Proxmox cluster.
|
||||||
|
|
||||||
|
## Services Running
|
||||||
|
|
||||||
|
- List services/VMs/containers running on this node
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
Add any additional notes, configuration details, or special considerations for this node.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Back to [[Proxmox hosts|Physical Nodes]]
|
||||||
35
content/homelab/hardware/proxmox-nodes/optiplex.md
Normal file
35
content/homelab/hardware/proxmox-nodes/optiplex.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
title: Optiplex - Dell Optiplex 7070 SFF
|
||||||
|
publish: true
|
||||||
|
tags:
|
||||||
|
- homelab
|
||||||
|
- hardware
|
||||||
|
- proxmox
|
||||||
|
---
|
||||||
|
|
||||||
|
# Optiplex
|
||||||
|
|
||||||
|
**Model**: Dell Optiplex 7070 SFF
|
||||||
|
|
||||||
|
## Specifications
|
||||||
|
|
||||||
|
- **CPU**: Intel Core i7-9700
|
||||||
|
- **RAM**: 64GB
|
||||||
|
- **Storage**:
|
||||||
|
- **Network**:
|
||||||
|
|
||||||
|
## Role in Cluster
|
||||||
|
|
||||||
|
This node is part of the main Proxmox cluster.
|
||||||
|
|
||||||
|
## Services Running
|
||||||
|
|
||||||
|
- List services/VMs/containers running on this node
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
Add any additional notes, configuration details, or special considerations for this node.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Back to [[Proxmox hosts|Physical Nodes]]
|
||||||
8
content/homelab/index.md
Normal file
8
content/homelab/index.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
title: Everything related to my homelab
|
||||||
|
publish: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Here are all the things related to my Homelab !!!
|
||||||
|
|
||||||
|
Hiii
|
||||||
0
content/homelab/infrastructure/pangolin.md
Normal file
0
content/homelab/infrastructure/pangolin.md
Normal file
0
content/homelab/infrastructure/step-ca
Normal file
0
content/homelab/infrastructure/step-ca
Normal file
0
content/homelab/infrastructure/tailscale.md
Normal file
0
content/homelab/infrastructure/tailscale.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
title: Gitea Webhook and CI CD using Komodo
|
||||||
|
publish: true
|
||||||
|
tags:
|
||||||
|
-
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gitea Webhook and CI CD using Komodo
|
||||||
|
|
||||||
|
You need to whitelist the url you're sending a webhook to in the `config/app.ini` file.
|
||||||
|
|
||||||
|
The `[webhook]` section might look something like that
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[webhook]
|
||||||
|
|
||||||
|
ALLOWED_HOST_LIST = loopback,private,*.vorpax.dev
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
To my own dismay Gitea doesn't offer granular configuration for webhook dispatch (for instance, to trigger your webhook only when some actions are completed).
|
||||||
|
|
||||||
|
Neither does Komodo enables you to easily verify some basic parameters inside of the webhook's json body.
|
||||||
|
|
||||||
|
In the future, I'll probably setup all of that in CI/CD runners like Gitea Actions, though I would likely trade convenience for a much larger potential to extend CI/CD usage in my Homelab.
|
||||||
|
|
||||||
|
I'm actually contemplating an eventual deployment of GitLab on Gerboise, I don't really know if it is worth the ressource overhead...
|
||||||
18
content/homelab/memos/macos, ssh and Yubikey.md
Normal file
18
content/homelab/memos/macos, ssh and Yubikey.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
title: How to make your Yubikey work with MacOS's ssh client
|
||||||
|
publish: true
|
||||||
|
tags:
|
||||||
|
- macos
|
||||||
|
- ssh
|
||||||
|
- fido
|
||||||
|
---
|
||||||
|
|
||||||
|
# The quick and easy fix
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew tap theseal/ssh-askpass
|
||||||
|
brew install michaelroosz/ssh/libsk-libfido2-install
|
||||||
|
```
|
||||||
|
|
||||||
|
https://github.com/Yubico/libfido2/issues/464#issuecomment-2588422088
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
---
|
||||||
|
title: Trust a certificate from a private local certificate authority
|
||||||
|
publish: true
|
||||||
|
date: 2026-01-11
|
||||||
|
tags:
|
||||||
|
- guide
|
||||||
|
- step-ca
|
||||||
|
- runbook
|
||||||
|
description:
|
||||||
|
---
|
||||||
|
|
||||||
|
# Trust a certificate from a private local certificate authority
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Make your device trust your private CA for TLS encryption.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- A local CA running (in our case step-ca) and reachable at `CA_URL`, for instance `https://local-ca.homelab.internal:443`
|
||||||
|
- An end device with access to a normal shell (*eww, Powershell*).
|
||||||
|
- very basic understanding of what a PKI is and how certificate trust works.
|
||||||
|
|
||||||
|
|
||||||
|
### Initial problem
|
||||||
|
|
||||||
|
When doing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl $CA_URL
|
||||||
|
```
|
||||||
|
|
||||||
|
you get :
|
||||||
|
|
||||||
|
```
|
||||||
|
curl: (60) SSL certificate problem: unable to get local issuer certificate
|
||||||
|
More details here: https://curl.se/docs/sslcerts.html
|
||||||
|
|
||||||
|
curl failed to verify the legitimacy of the server and therefore could not
|
||||||
|
establish a secure connection to it. To learn more about this situation and
|
||||||
|
how to fix it, please visit the webpage mentioned above.
|
||||||
|
```
|
||||||
|
|
||||||
|
Which is normal as your root Certificate authority uses a self-signed certificate.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
### Step 1: Setup
|
||||||
|
|
||||||
|
If not already done, install step cli on your end-device :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install step
|
||||||
|
```
|
||||||
|
|
||||||
|
refer to official documentation https://smallstep.com/docs/step-ca/installation/ for additional installation details for your OS.
|
||||||
|
|
||||||
|
### Step 2 : get CA fingerprint
|
||||||
|
|
||||||
|
`CA_FINGERPRINT` is the fingerprint of your root certificate.
|
||||||
|
|
||||||
|
If you don't have any other device than Step CA with the CA configured, run
|
||||||
|
|
||||||
|
Inside of your host/container running step CA (or any client with step ca already configured)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
step certificate fingerprint <(step ca root)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Bootstrap cert
|
||||||
|
|
||||||
|
You'll need to run :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
step ca bootstrap --ca-url $CA_URL --fingerprint $CA_FINGERPRINT
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
where `CA_URL` is the address of the CA with protocol
|
||||||
|
|
||||||
|
### Step 3 : Install certificate
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
step certificate install <(step ca root)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Step 4: Verification
|
||||||
|
|
||||||
|
In most modern distributions and *UNIX* derivatives, curl (particularly when installed by default) is configured to run with the system trust store
|
||||||
|
|
||||||
|
Now after running
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl $CA_URL
|
||||||
|
```
|
||||||
|
|
||||||
|
you get
|
||||||
|
|
||||||
|
`404 page not found`
|
||||||
|
|
||||||
|
Which is completely fine.
|
||||||
|
|
||||||
|
### You successfuly installed a certificate.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- https://smallstep.com/docs/step-ca/installation/
|
||||||
|
- Related resources
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Created: 2026-01-11*
|
||||||
@@ -1,6 +1,25 @@
|
|||||||
---
|
---
|
||||||
title: Welcome to Quartz
|
title: Welcome to Vorpax Wiki
|
||||||
|
publish: true
|
||||||
---
|
---
|
||||||
|
|
||||||
This is a blank Quartz installation.
|
Welcome to my personal wiki and technical blog! This site serves as both documentation for my homelab infrastructure and a platform to share technical insights, guides, and experiences.
|
||||||
See the [documentation](https://quartz.jzhao.xyz) for how to get started.
|
|
||||||
|
## 🏠 [[homelab/index|Homelab]]
|
||||||
|
|
||||||
|
Explore the architecture, services, and infrastructure of my self-hosted homelab cluster. From virtualization to networking, find detailed documentation on how everything is set up and maintained.
|
||||||
|
|
||||||
|
## 📝 [[blog/index|Blog]]
|
||||||
|
|
||||||
|
Technical articles, tutorials, and writeups on various topics including system administration, DevOps, containerization, and more.
|
||||||
|
|
||||||
|
## 🔍 What You'll Find Here
|
||||||
|
|
||||||
|
- **Infrastructure Documentation**: Detailed specs and configurations of my homelab hardware and software
|
||||||
|
- **Service Guides**: How-to guides for deploying and managing self-hosted services
|
||||||
|
- **Technical Articles**: Deep dives into interesting technical topics and solutions
|
||||||
|
- **Project Writeups**: Documentation of personal projects and experiments
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Use the search bar above or the explorer on the left to navigate through the wiki.*
|
||||||
|
|||||||
40
content/templates/blog-post.md
Normal file
40
content/templates/blog-post.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
title: "<% tp.file.title %>"
|
||||||
|
publish: true
|
||||||
|
date: <% tp.date.now("YYYY-MM-DD") %>
|
||||||
|
tags:
|
||||||
|
-
|
||||||
|
description:
|
||||||
|
---
|
||||||
|
|
||||||
|
# <% tp.file.title %>
|
||||||
|
|
||||||
|
> **TL;DR**: Brief summary of the article
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
Introduce the topic and what the reader will learn.
|
||||||
|
|
||||||
|
## Main Content
|
||||||
|
|
||||||
|
### Section 1
|
||||||
|
|
||||||
|
Content goes here.
|
||||||
|
|
||||||
|
### Section 2
|
||||||
|
|
||||||
|
More content.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
Wrap up the article and key takeaways.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- Links to related resources
|
||||||
|
- Documentation
|
||||||
|
- Related articles
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Published on <% tp.date.now("MMMM DD, YYYY") %>*
|
||||||
81
content/templates/guide.md
Normal file
81
content/templates/guide.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
title: "<% tp.file.title %>"
|
||||||
|
publish: true
|
||||||
|
date: <% tp.date.now("YYYY-MM-DD") %>
|
||||||
|
tags:
|
||||||
|
- guide
|
||||||
|
description:
|
||||||
|
---
|
||||||
|
|
||||||
|
# <% tp.file.title %>
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
What this guide covers and what you'll accomplish.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Requirement 1
|
||||||
|
- Requirement 2
|
||||||
|
- Required knowledge
|
||||||
|
|
||||||
|
## What You'll Need
|
||||||
|
|
||||||
|
- Hardware/software requirements
|
||||||
|
- Tools
|
||||||
|
- Access requirements
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
### Step 1: Setup
|
||||||
|
|
||||||
|
Detailed instructions for the first step.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Example commands
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Configuration
|
||||||
|
|
||||||
|
Continue with configuration steps.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# More commands
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Verification
|
||||||
|
|
||||||
|
How to verify everything is working.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Verification commands
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Issue 1
|
||||||
|
|
||||||
|
**Problem**: Description of the problem
|
||||||
|
|
||||||
|
**Solution**: How to fix it
|
||||||
|
|
||||||
|
### Issue 2
|
||||||
|
|
||||||
|
**Problem**: Description
|
||||||
|
|
||||||
|
**Solution**: Fix
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- What to do after completing this guide
|
||||||
|
- Related guides
|
||||||
|
- Advanced configurations
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- Links to documentation
|
||||||
|
- Related resources
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Created: <% tp.date.now("YYYY-MM-DD") %>*
|
||||||
79
content/templates/homelab-doc.md
Normal file
79
content/templates/homelab-doc.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
---
|
||||||
|
title: "<% tp.file.title %>"
|
||||||
|
publish: true
|
||||||
|
tags:
|
||||||
|
- homelab
|
||||||
|
description:
|
||||||
|
---
|
||||||
|
|
||||||
|
# <% tp.file.title %>
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Brief description of this service/infrastructure component.
|
||||||
|
|
||||||
|
## Specifications
|
||||||
|
|
||||||
|
- **Type**:
|
||||||
|
- **Version**:
|
||||||
|
- **Hardware**:
|
||||||
|
- **OS**:
|
||||||
|
- **Resources**:
|
||||||
|
- CPU:
|
||||||
|
- RAM:
|
||||||
|
- Storage:
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
Steps or notes on how this was installed.
|
||||||
|
|
||||||
|
### Configuration Files
|
||||||
|
|
||||||
|
Important configuration details.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Example configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
```bash
|
||||||
|
KEY=value
|
||||||
|
```
|
||||||
|
|
||||||
|
## Network Configuration
|
||||||
|
|
||||||
|
- **IP Address**:
|
||||||
|
- **Ports**:
|
||||||
|
- **Domain**:
|
||||||
|
- **Access**:
|
||||||
|
|
||||||
|
## Services/Features
|
||||||
|
|
||||||
|
- Feature 1
|
||||||
|
- Feature 2
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
### Backup Strategy
|
||||||
|
|
||||||
|
How this service is backed up.
|
||||||
|
|
||||||
|
### Update Procedure
|
||||||
|
|
||||||
|
How to update this service.
|
||||||
|
|
||||||
|
## Related Services
|
||||||
|
|
||||||
|
- Links to related documentation
|
||||||
|
- Dependencies
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
Common issues and solutions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: <% tp.date.now("YYYY-MM-DD") %>*
|
||||||
10
content/templates/page.md
Normal file
10
content/templates/page.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
title: "<% tp.file.title %>"
|
||||||
|
publish: true
|
||||||
|
tags:
|
||||||
|
-
|
||||||
|
---
|
||||||
|
|
||||||
|
# <% tp.file.title %>
|
||||||
|
|
||||||
|
Content goes here.
|
||||||
43
nginx.conf
Normal file
43
nginx.conf
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Custom 404 page
|
||||||
|
error_page 404 /404.html;
|
||||||
|
|
||||||
|
# Compression
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json application/javascript;
|
||||||
|
gzip_disable "MSIE [1-6]\.";
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main location block
|
||||||
|
# Quartz generates URLs without .html extension, so we need to handle that
|
||||||
|
location / {
|
||||||
|
# Try to serve the file directly, then with .html extension,
|
||||||
|
# then as a directory, finally 404
|
||||||
|
try_files $uri $uri.html $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Disable access to hidden files
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
access_log off;
|
||||||
|
log_not_found off;
|
||||||
|
}
|
||||||
|
}
|
||||||
4970
pnpm-lock.yaml
generated
4970
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -8,15 +8,15 @@ import * as Plugin from "./quartz/plugins"
|
|||||||
*/
|
*/
|
||||||
const config: QuartzConfig = {
|
const config: QuartzConfig = {
|
||||||
configuration: {
|
configuration: {
|
||||||
pageTitle: "Quartz 4",
|
pageTitle: "Vorpax Wiki",
|
||||||
pageTitleSuffix: "",
|
pageTitleSuffix: " | Vorpax Wiki",
|
||||||
enableSPA: true,
|
enableSPA: true,
|
||||||
enablePopovers: true,
|
enablePopovers: true,
|
||||||
analytics: {
|
analytics: {
|
||||||
provider: "plausible",
|
provider: "plausible",
|
||||||
},
|
},
|
||||||
locale: "en-US",
|
locale: "en-US",
|
||||||
baseUrl: "quartz.jzhao.xyz",
|
baseUrl: "wiki.vorpax.dev",
|
||||||
ignorePatterns: ["private", "templates", ".obsidian"],
|
ignorePatterns: ["private", "templates", ".obsidian"],
|
||||||
defaultDateType: "modified",
|
defaultDateType: "modified",
|
||||||
theme: {
|
theme: {
|
||||||
@@ -29,26 +29,26 @@ const config: QuartzConfig = {
|
|||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
lightMode: {
|
lightMode: {
|
||||||
light: "#faf8f8",
|
light: "#eff1f5",
|
||||||
lightgray: "#e5e5e5",
|
lightgray: "#e6e9ef",
|
||||||
gray: "#b8b8b8",
|
gray: "#9ca0b0",
|
||||||
darkgray: "#4e4e4e",
|
darkgray: "#4c4f69",
|
||||||
dark: "#2b2b2b",
|
dark: "#1e1e2e",
|
||||||
secondary: "#284b63",
|
secondary: "#7287fd",
|
||||||
tertiary: "#84a59d",
|
tertiary: "#8839ef",
|
||||||
highlight: "rgba(143, 159, 169, 0.15)",
|
highlight: "rgba(114, 135, 253, 0.15)",
|
||||||
textHighlight: "#fff23688",
|
textHighlight: "#7287fd88",
|
||||||
},
|
},
|
||||||
darkMode: {
|
darkMode: {
|
||||||
light: "#161618",
|
light: "#1e1e2e",
|
||||||
lightgray: "#393639",
|
lightgray: "#313244",
|
||||||
gray: "#646464",
|
gray: "#585b70",
|
||||||
darkgray: "#d4d4d4",
|
darkgray: "#a6adc8",
|
||||||
dark: "#ebebec",
|
dark: "#cdd6f4",
|
||||||
secondary: "#7b97aa",
|
secondary: "#b4befe",
|
||||||
tertiary: "#84a59d",
|
tertiary: "#94e2d5",
|
||||||
highlight: "rgba(143, 159, 169, 0.15)",
|
highlight: "rgba(180, 190, 254, 0.15)",
|
||||||
textHighlight: "#b3aa0288",
|
textHighlight: "#b4befe88",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -61,8 +61,8 @@ const config: QuartzConfig = {
|
|||||||
}),
|
}),
|
||||||
Plugin.SyntaxHighlighting({
|
Plugin.SyntaxHighlighting({
|
||||||
theme: {
|
theme: {
|
||||||
light: "github-light",
|
light: "catppuccin-latte",
|
||||||
dark: "github-dark",
|
dark: "catppuccin-mocha",
|
||||||
},
|
},
|
||||||
keepBackground: false,
|
keepBackground: false,
|
||||||
}),
|
}),
|
||||||
@@ -73,7 +73,7 @@ const config: QuartzConfig = {
|
|||||||
Plugin.Description(),
|
Plugin.Description(),
|
||||||
Plugin.Latex({ renderEngine: "katex" }),
|
Plugin.Latex({ renderEngine: "katex" }),
|
||||||
],
|
],
|
||||||
filters: [Plugin.RemoveDrafts()],
|
filters: [Plugin.RemoveDrafts(), Plugin.ExplicitPublish()],
|
||||||
emitters: [
|
emitters: [
|
||||||
Plugin.AliasRedirects(),
|
Plugin.AliasRedirects(),
|
||||||
Plugin.ComponentResources(),
|
Plugin.ComponentResources(),
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ export const sharedPageComponents: SharedLayout = {
|
|||||||
afterBody: [],
|
afterBody: [],
|
||||||
footer: Component.Footer({
|
footer: Component.Footer({
|
||||||
links: {
|
links: {
|
||||||
GitHub: "https://github.com/jackyzha0/quartz",
|
// Add your custom links here
|
||||||
"Discord Community": "https://discord.gg/cRFFHYye7t",
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@@ -41,6 +40,12 @@ export const defaultContentPageLayout: PageLayout = {
|
|||||||
Component.Explorer(),
|
Component.Explorer(),
|
||||||
],
|
],
|
||||||
right: [
|
right: [
|
||||||
|
Component.RecentNotes({
|
||||||
|
title: "Recent Posts",
|
||||||
|
limit: 5,
|
||||||
|
filter: (page) => page.slug?.startsWith("blog/") ?? false,
|
||||||
|
linkToMore: "blog" as any,
|
||||||
|
}),
|
||||||
Component.Graph(),
|
Component.Graph(),
|
||||||
Component.DesktopOnly(Component.TableOfContents()),
|
Component.DesktopOnly(Component.TableOfContents()),
|
||||||
Component.Backlinks(),
|
Component.Backlinks(),
|
||||||
|
|||||||
3
scripts/komodo-webhook.sh
Normal file
3
scripts/komodo-webhook.sh
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
curl -X POST -d ${1} -H "Authorization: Bearer ${2}"
|
||||||
Reference in New Issue
Block a user