Solution Obsidian → GitLab CI/CD → ISPConfig

Architecture

Flux automatisé :

[Obsidian] → [git push] → [GitLab CI/CD] → [ISPConfig Apache2]
  Windows                    build & deploy   docs.montaigu.io:22022

Principe :

  1. Travail dans Obsidian (vault dans un repo Git)
  2. Git push déclenche automatiquement la pipeline GitLab
  3. GitLab build avec Quartz et déploie via SSH sur ISPConfig
  4. Site docs.montaigu.io mis à jour automatiquement

Étape 1 : Prérequis Windows

Outils nécessaires :

Étape 2 : Configuration SSH

Génération des clés avec PuTTYgen

  1. Ouvrir PuTTYgen
  2. Type de clé : Ed25519
  3. Generate et bouger la souris
  4. Commentaire : gitlab-ci@docs.montaigu.io

Sauvegarde des clés

  1. Clé privée PuTTY : “Save private key” → amontaigudocs.ppk (avec mot de passe pour usage personnel)
  2. Clé privée OpenSSH : Menu “Conversions” → “Export OpenSSH key” → amontaigudocs
    • ⚠️ CRITIQUE : Passphrase → LAISSER VIDE (obligatoire pour GitLab CI/CD)
  3. Clé publique : Copier le texte affiché dans PuTTYgen

Installation dans ISPConfig

  1. Interface ISPConfigSitesWebsitedocs.montaigu.io
  2. OptionsSSH UserAdd new SSH User
  3. Username : amontaigudocs
  4. SSH Key : Coller la clé publique depuis PuTTYgen
  5. Save

Étape 3 : Configuration du projet GitLab

Création du repository local

# Cloner le projet
git clone https://gitlab.com/amontaigu/obsidian-docs.git
cd obsidian-docs
 
# Structure du projet
mkdir docs     # Vault Obsidian
mkdir styles   # Styles personnalisés

Fichiers de configuration avec VS Code

Ouvrir VS Code → File → Open Folder → obsidian-docs

📄 .gitignore

# Obsidian
.obsidian/
.trash/
 
# Système
.DS_Store
*.tmp
 
# Build
node_modules/
public/

📄 .gitlab-ci.yml

stages:
  - build
  - deploy
 
variables:
  NODE_VERSION: "22"
  QUARTZ_VERSION: "v4.5.1"
 
build_site:
  stage: build
  image: node:${NODE_VERSION}  # Debian-based image
  cache:
    paths:
      - quartz/node_modules/
  before_script:
    - apt-get update && apt-get install -y git rsync  # Use apt instead of apk
  script:
    # Nettoyer et cloner Quartz
    - rm -rf quartz
    - git clone --depth 1 --branch ${QUARTZ_VERSION} https://github.com/jackyzha0/quartz.git
    - cd quartz
    - npm ci --prefer-offline
    
    # Copier le contenu Obsidian
    - rsync -av --exclude='.obsidian/' ../docs/ ./content/
    
    # Copier la configuration
    - cp ../quartz.config.ts ./quartz.config.ts
    
    # Build du site
    - npx quartz build
    
    # Préparer l'artifact
    - mkdir -p ../public
    - cp -r ./public/* ../public/
    
  artifacts:
    paths:
      - public/
    expire_in: 1 hour
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
 
deploy_to_server:
  stage: deploy
  image: alpine:latest
  dependencies:
    - build_site
  before_script:
    - apk add --no-cache openssh-client rsync
    - eval $(ssh-agent -s)
    - chmod 400 "$SSH_PRIVATE_KEY"
    - ssh-add "$SSH_PRIVATE_KEY"
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    
    # Configuration SSH pour port personnalisé
    - echo "Host $DEPLOY_HOST" > ~/.ssh/config
    - echo "  Port $SSH_PORT" >> ~/.ssh/config
    - echo "  StrictHostKeyChecking no" >> ~/.ssh/config
    - echo "  UserKnownHostsFile /dev/null" >> ~/.ssh/config
    - chmod 600 ~/.ssh/config
    
  script:
    # Déployer vers le serveur ISPConfig
    - rsync -avz --delete ./public/ $DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/
    
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  environment:
    name: production
    url: https://docs.montaigu.io

📄 quartz.config.ts

import { QuartzConfig } from "./quartz/cfg"
import * as Plugin from "./quartz/plugins"
 
const config: QuartzConfig = {
  configuration: {
    pageTitle: "docs.montaigu.io",
    enableSPA: true,
    enablePopovers: true,
    analytics: null,
    baseUrl: "docs.montaigu.io",
    ignorePatterns: ["private", "templates", ".obsidian"],
    defaultDateType: "created",
    theme: {
      cdnCaching: true,
      typography: {
        header: "Schibsted Grotesk",
        body: "Source Sans Pro",
        code: "IBM Plex Mono",
      },
      colors: {
        lightMode: {
          light: "#faf8f8",
          lightgray: "#e5e5e5",
          gray: "#b8b8b8",
          darkgray: "#4e4e4e",
          dark: "#2b2b2b",
          secondary: "#284b63",
          tertiary: "#84a59d",
          highlight: "rgba(143, 159, 169, 0.15)",
        },
        darkMode: {
          light: "#161618",
          lightgray: "#393639",
          gray: "#646464",
          darkgray: "#d4d4d4",
          dark: "#ebebec",
          secondary: "#7b97aa",
          tertiary: "#84a59d",
          highlight: "rgba(143, 159, 169, 0.15)",
        },
      },
    },
  },
  plugins: {
    transformers: [
      Plugin.FrontMatter(),
      Plugin.TableOfContents(),
      Plugin.CreatedModifiedDate({
        priority: ["frontmatter", "filesystem"],
      }),
      Plugin.Latex({ renderEngine: "katex" }),
      Plugin.SyntaxHighlighting(),
      Plugin.ObsidianFlavoredMarkdown({ enableInHtmlEmbed: false }),
      Plugin.GitHubFlavoredMarkdown(),
      Plugin.CrawlLinks({ markdownLinkResolution: "shortest" }),
      Plugin.Description(),
    ],
    filters: [Plugin.RemoveDrafts()],
    emitters: [
      Plugin.AliasRedirects(),
      Plugin.ComponentResources({ fontOrigin: "googleFonts" }),
      Plugin.ContentPage(),
      Plugin.FolderPage(),
      Plugin.TagPage(),
      Plugin.ContentIndex({
        enableSiteMap: true,
        enableRSS: true,
      }),
      Plugin.Assets(),
      Plugin.Static(),
      Plugin.NotFoundPage(),
    ],
  },
}
 
export default config

📄 README.md

# Documentation Obsidian → GitLab CI/CD → ISPConfig
 
Automatisation de la publication de notes Obsidian vers docs.montaigu.io
 
## Workflow
1. Modifier les notes dans `docs/` avec Obsidian
2. Commit et push avec Git
3. GitLab CI/CD déploie automatiquement
 
## Structure
- `docs/` : Contenu Obsidian
- `styles/` : Styles CSS personnalisés
- `.gitlab-ci.yml` : Pipeline de déploiement
- `quartz.config.ts` : Configuration Quartz

Étape 4 : Configuration GitLab

Variables CI/CD

GitLabhttps://gitlab.com/amontaigu/obsidian-docs/-/settings/ci_cd → Variables

VariableTypeProtectedValeur
SSH_PRIVATE_KEYFile[clé OpenSSH complète + ligne vide à la fin]
DEPLOY_HOSTVariabledocs.montaigu.io
DEPLOY_USERVariableamontaigudocs
DEPLOY_PATHVariable/var/www/docs.montaigu.io/web
SSH_PORTVariable22022

⚠️ Important pour SSH_PRIVATE_KEY :

  • Type “File” (pas “Variable”)
  • Contenu : Clé OpenSSH depuis KeePassXC (format texte)
  • Doit se terminer par une ligne vide (appuyer sur Entrée à la fin)

Premier commit

git add .
git commit -m "Initial setup: Obsidian → GitLab CI/CD → ISPConfig"
git push -u origin main

Étape 5 : Configuration Obsidian

  1. Ouvrir Obsidian
  2. “Ouvrir un dossier comme coffre”
  3. Sélectionner : obsidian-docs/docs/
  4. Créer votre première note : index.md

Étape 6 : Configuration Apache2 pour Quartz

Configuration via ISPConfig

  1. Interface ISPConfigSitesWebsitedocs.montaigu.io
  2. Onglet OptionsApache Directives
  3. Ajouter cette configuration :
# Configuration pour Quartz - Gestion des liens Obsidian
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME}.html -f
    RewriteRule ^(.+)$ $1.html [L,QSA]
</IfModule>
 
# Cache des assets Quartz pour performance
<FilesMatch "\.(css|js|woff|woff2)$">
    ExpiresActive On
    ExpiresDefault "access plus 1 month"
</FilesMatch>
  1. Save et attendre la regénération Apache par ISPConfig

Étape 7 : Tests et vérifications

Test SSH

# Tester la connexion avec le bon port
ssh -p 22022 amontaigudocs@docs.montaigu.io "echo 'SSH OK'"
 
# Tester l'accès au répertoire
ssh -p 22022 amontaigudocs@docs.montaigu.io "ls -la /var/www/docs.montaigu.io/web/"

Test de la pipeline

  1. Modifier une note dans Obsidian
  2. Commit et push
  3. Vérifier la pipeline : https://gitlab.com/amontaigu/obsidian-docs/-/pipelines
  4. Tester le site : https://docs.montaigu.io

Workflow quotidien

Avec VS Code (recommandé)

  1. Éditer dans Obsidian (dossier docs/)
  2. Ouvrir VS Code sur le projet obsidian-docs
  3. Source Control (Ctrl+Shift+G)
  4. Stage All ChangesCommit messageCommit & Push
  5. Attendre 2-3 minutes → Site automatiquement mis à jour

En ligne de commande

cd obsidian-docs
git add .
git commit -m "Mise à jour documentation"
git push origin main

Structure finale du projet

obsidian-docs/
├── docs/                    # Vault Obsidian (notes markdown)
├── .gitlab-ci.yml           # Pipeline CI/CD
├── quartz.config.ts         # Configuration Quartz
├── quartz.layout.ts         # Layout pleine page (configuration propre)
├── .gitignore
└── README.md

URLs importantes

Avantages

Simple : Obsidian + Git + VS Code
Automatique : Push = déploiement immédiat
Sécurisé : Clés SSH dédiées, variables GitLab chiffrées
Versionné : Historique complet dans Git
Performant : Site statique optimisé par Quartz
ISPConfig compatible : Utilisateur SSH du site, configuration via interface web
Lecture optimisée : Affichage pleine page avec styles personnalisés

Installer la derniere version de node sur debian 12

The official NVM installation method is the same for Debian 12. Here it is:

# Install NVM (official method)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
 
# Reload shell
source ~/.bashrc
 
# Verify
command -v nvm
 
# Install Node.js 22 (current LTS)
nvm install 22
 
# Set as default
nvm alias default 22
 
# Verify
node --version
npm --version

This is the official installation method from the NVM project and works perfectly on Debian 12. The NVM project doesn’t have a Debian-specific installation method - this curl/bash script method is universal across all Linux distributions including Debian.

To make NVM and a specific Node.js version available to all users on Debian 12, you need to install it system-wide. Here’s the clean approach:

# Install NVM system-wide
export NVM_DIR="/usr/local/nvm"
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
 
# Install Node.js 22 LTS
export NVM_DIR="/usr/local/nvm"
source "$NVM_DIR/nvm.sh"
nvm install 22
nvm alias default 22
 
# Make NVM available to all users by adding to system profile
cat >> /etc/profile.d/nvm.sh << 'EOF'
export NVM_DIR="/usr/local/nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
EOF
 
# Set proper permissions
chmod 755 /etc/profile.d/nvm.sh
chmod -R 755 /usr/local/nvm

Now all users will have access to NVM and Node.js 22 when they log in. They can verify with:

node --version
npm --version

Note: Each user will need to log out and back in (or run source /etc/profile.d/nvm.sh) for the changes to take effect.

Here’s how to properly install NVM system-wide for all users on Debian 12:

# 1. Install NVM to a system location as root
sudo su -
export NVM_DIR="/usr/local/nvm"
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
 
# 2. Source NVM and install Node.js 22
source "$NVM_DIR/nvm.sh"
nvm install 22
nvm alias default 22
 
# 3. Create profile script for all users
cat > /etc/profile.d/nvm.sh << 'EOF'
export NVM_DIR="/usr/local/nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
EOF
 
# 4. Set permissions so all users can read/execute
chmod 755 /etc/profile.d/nvm.sh
chmod -R 755 /usr/local/nvm
 
# 5. Also add to /etc/bash.bashrc for non-login shells
cat >> /etc/bash.bashrc << 'EOF'
 
# Load NVM
export NVM_DIR="/usr/local/nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
EOF
 
# 6. Exit root
exit

Now test as your regular user:

# Start a new shell or source the config
bash
node -v
nvm ls

All users should now have access to Node.js 22 via NVM.