Configure Quartz for production

This commit is contained in:
vorpax
2026-01-05 22:41:39 +01:00
parent f3622751a1
commit 4bab7d0d86
19 changed files with 778 additions and 9 deletions

View File

@@ -0,0 +1,67 @@
name: Build and Push Quartz Wiki
on:
push:
branches:
- v4
env:
REGISTRY: "gitea.vorpax.dev"
IMAGE_NAME: "vorpax/quartz-wiki"
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- 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: .
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"
# 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

221
DEPLOYMENT.md Normal file
View 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
View 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
content/blog/index.md Normal file
View 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.

View File

@@ -0,0 +1,11 @@
---
publish: true
title: My Physical Nodes
---
# All my nodes
My main cluster is composed of 3 Physical Nodes :
- [[hardware/littleboy|Littleboy]] which is a Firebat T8 Pro Plus
- [[hardware/optiplex|Optiplex]] which is an Optiplex 7070 SFF with an i7-9700 and 64GB of RAM
- [[hardware/fatman|Fatman]] which is a custom built gaming PC repurposed into a beefy GPU workhorse

View 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]]

View 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]]

View 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
View File

@@ -0,0 +1,8 @@
---
title: Everything related to my homelab
publish: true
---
# Here are all the things related to my Homelab !!!
Hiii

View File

@@ -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.*

View 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") %>*

View 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") %>*

View 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
View File

@@ -0,0 +1,10 @@
---
title: "<% tp.file.title %>"
publish: true
tags:
-
---
# <% tp.file.title %>
Content goes here.

19
docker-compose.yml Normal file
View File

@@ -0,0 +1,19 @@
services:
quartz:
# Option 1: Pull from Gitea Container Registry (recommended for production)
image: gitea.vorpax.dev/vorpax/quartz-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

43
nginx.conf Normal file
View 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;
}
}

View File

@@ -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: {
@@ -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(),

View File

@@ -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(),