commit daa932a0ed660d1781524ee0b6b50b59d33e9cf3 Author: syoul Date: Thu Dec 25 15:20:50 2025 +0100 Initial commit: Script MD to Print avec Docker diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..034e9d4 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,49 @@ +# Répertoires de sortie +output/ +logs/ + +# Fichiers Git +.git/ +.gitignore +.gitattributes + +# Documentation (optionnel, décommenter si vous voulez réduire la taille) +# README.md +# CHANGELOG.md + +# Fichiers de configuration personnalisés +config.conf + +# Fichiers temporaires +*.tmp +*.swp +*.swo +*~ + +# Fichiers PDF générés +*.pdf + +# Fichiers de log +*.log + +# Fichiers de sauvegarde +*.bak +*.backup + +# Fichiers système +.DS_Store +Thumbs.db + +# Fichiers IDE +.vscode/ +.idea/ +*.code-workspace + +# Fichiers Docker +docker-compose.yml +docker_run.sh +.docker/ + +# Fichiers de test +documents/test.md + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e3cbd80 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# Fichiers de configuration personnalisés +config.conf + +# Répertoires de sortie +output/ +logs/ + +# Fichiers temporaires +*.tmp +*.swp +*.swo +*~ + +# Fichiers PDF générés (optionnel, décommenter si nécessaire) +# *.pdf + +# Fichiers de log +*.log + +# Fichiers de sauvegarde +*.bak +*.backup + +# Fichiers système +.DS_Store +Thumbs.db + +# Fichiers IDE +.vscode/ +.idea/ +*.code-workspace + +# Fichiers Docker +.docker/ + +# Fichiers de test +documents/test.md + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..57dd3c1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,48 @@ +# Changelog + +Tous les changements notables de ce projet seront documentés dans ce fichier. + +Le format est basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/), +et ce projet adhère à [Semantic Versioning](https://semver.org/lang/fr/). + +## [1.0.0] - 2024-01-XX + +### Ajouté +- Script principal `md_to_print.sh` avec toutes les fonctionnalités de base +- Conversion automatique Markdown → PDF avec Pandoc +- Prévisualisation PDF avant impression (evince/okular/xdg-open) +- Options d'impression avancées: + - Sélection d'imprimante + - Nombre de copies + - Sélection de pages + - Orientation (portrait/paysage) + - Taille de papier + - Qualité d'impression + - Impression couleur/monochrome + - Mode recto-verso +- Fichier de configuration optionnel (format INI) +- Installation automatique des dépendances +- Support Docker complet: + - Dockerfile optimisé + - docker-compose.yml + - Script wrapper docker_run.sh +- Système de logging détaillé avec niveaux (DEBUG, INFO, WARN, ERROR) +- Gestion d'erreurs complète avec codes de retour appropriés +- Makefile avec commandes utiles (build, test, clean, install, uninstall) +- Documentation complète (README.md) +- Fichiers de support (.gitignore, .dockerignore) + +### Sécurité +- Utilisateur non-root dans Docker +- Validation des chemins de fichiers +- Protection contre l'injection de commandes +- Validation des entrées utilisateur + +### Documentation +- README.md complet avec exemples +- CHANGELOG.md pour le suivi des versions +- Commentaires dans le code +- Messages d'aide détaillés + +[1.0.0]: https://github.com/yourusername/MD_to_print/releases/tag/v1.0.0 + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a3becf2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,58 @@ +FROM debian:bookworm-slim + +# Métadonnées +LABEL maintainer="MD_to_Print" +LABEL description="Script automatique Markdown vers PDF et impression" +LABEL version="1.0.0" + +# Variables d'environnement +ENV DEBIAN_FRONTEND=noninteractive \ + TZ=Europe/Paris \ + LANG=fr_FR.UTF-8 \ + LC_ALL=fr_FR.UTF-8 + +# Installation des dépendances système et locales +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + locales \ + && sed -i '/fr_FR.UTF-8/s/^# //g' /etc/locale.gen && \ + locale-gen fr_FR.UTF-8 && \ + apt-get install -y --no-install-recommends \ + pandoc \ + texlive-latex-base \ + texlive-xetex \ + texlive-fonts-recommended \ + texlive-latex-extra \ + texlive-lang-french \ + fonts-dejavu \ + cups \ + cups-client \ + evince \ + curl \ + ca-certificates \ + make \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# Création d'un utilisateur non-root pour sécurité +RUN useradd -m -u 1000 -s /bin/bash mdprint && \ + mkdir -p /workspace/documents /workspace/output /workspace/logs && \ + chown -R mdprint:mdprint /workspace + +# Répertoire de travail +WORKDIR /workspace + +# Copie du script principal +COPY md_to_print.sh /usr/local/bin/md_to_print.sh +RUN chmod +x /usr/local/bin/md_to_print.sh + +# Copie du fichier de configuration exemple +COPY config.example.conf /workspace/config.example.conf + +# Basculer vers l'utilisateur non-root +USER mdprint + +# Point d'entrée +ENTRYPOINT ["/usr/local/bin/md_to_print.sh"] +CMD ["--help"] + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..28833a6 --- /dev/null +++ b/Makefile @@ -0,0 +1,110 @@ +.PHONY: build run shell test clean install uninstall help + +# Variables +IMAGE_NAME=md-to-print +IMAGE_TAG=latest +SCRIPT_NAME=md_to_print.sh +INSTALL_DIR=/usr/local/bin +CONFIG_DIR=/etc/md-to-print + +# Couleurs +GREEN=\033[0;32m +YELLOW=\033[1;33m +NC=\033[0m + +help: + @echo "Commandes disponibles:" + @echo " make build - Construire l'image Docker" + @echo " make shell - Ouvrir un shell interactif dans le conteneur" + @echo " make test - Tester avec un fichier markdown exemple" + @echo " make clean - Nettoyer les fichiers générés (PDFs, logs)" + @echo " make install - Installer le script localement" + @echo " make uninstall - Désinstaller le script" + @echo " make help - Afficher cette aide" + +# Construction de l'image Docker +build: + @echo "$(GREEN)Construction de l'image Docker...$(NC)" + docker build -t $(IMAGE_NAME):$(IMAGE_TAG) . + @echo "$(GREEN)Image construite avec succès$(NC)" + +# Exécution interactive avec shell +shell: build + @echo "$(GREEN)Ouverture d'un shell dans le conteneur...$(NC)" + docker run --rm -it \ + -v $(PWD)/documents:/workspace/documents:ro \ + -v $(PWD)/output:/workspace/output \ + -v $(PWD)/logs:/workspace/logs \ + --network host \ + $(IMAGE_NAME):$(IMAGE_TAG) \ + /bin/bash + +# Test avec un fichier exemple +test: build + @echo "$(GREEN)Création d'un fichier markdown de test...$(NC)" + @mkdir -p documents output logs + @cat > documents/test.md << 'EOF' +# Test Markdown + +Ceci est un test de conversion Markdown vers PDF. + +## Fonctionnalités + +- Conversion automatique +- Impression +- Prévisualisation +- Options avancées + +## Exemple de code + +\`\`\`bash +echo "Hello World" +\`\`\` + +## Liste numérotée + +1. Premier élément +2. Deuxième élément +3. Troisième élément + +**Texte en gras** et *texte en italique*. +EOF + @echo "$(GREEN)Exécution du test...$(NC)" + docker run --rm -it \ + -v $(PWD)/documents:/workspace/documents:ro \ + -v $(PWD)/output:/workspace/output \ + -v $(PWD)/logs:/workspace/logs \ + --network host \ + $(IMAGE_NAME):$(IMAGE_TAG) \ + /workspace/documents/test.md --preview --keep-pdf --verbose + @echo "$(GREEN)Test terminé. Vérifiez le fichier output/test.pdf$(NC)" + +# Nettoyage +clean: + @echo "$(YELLOW)Nettoyage des fichiers générés...$(NC)" + @rm -rf output/*.pdf logs/*.log 2>/dev/null || true + @rm -f documents/test.md 2>/dev/null || true + @echo "$(GREEN)Nettoyage terminé$(NC)" + +# Installation locale +install: + @echo "$(GREEN)Installation du script...$(NC)" + @if [ ! -f "$(SCRIPT_NAME)" ]; then \ + echo "Erreur: $(SCRIPT_NAME) introuvable"; \ + exit 1; \ + fi + @sudo mkdir -p $(INSTALL_DIR) $(CONFIG_DIR) + @sudo cp $(SCRIPT_NAME) $(INSTALL_DIR)/$(SCRIPT_NAME) + @sudo chmod +x $(INSTALL_DIR)/$(SCRIPT_NAME) + @sudo cp config.example.conf $(CONFIG_DIR)/config.example.conf + @echo "$(GREEN)Script installé dans $(INSTALL_DIR)/$(SCRIPT_NAME)$(NC)" + @echo "$(GREEN)Configuration exemple dans $(CONFIG_DIR)/config.example.conf$(NC)" + @echo "$(YELLOW)Créez $(CONFIG_DIR)/config.conf pour personnaliser la configuration$(NC)" + +# Désinstallation +uninstall: + @echo "$(YELLOW)Désinstallation du script...$(NC)" + @sudo rm -f $(INSTALL_DIR)/$(SCRIPT_NAME) + @sudo rm -rf $(CONFIG_DIR) + @echo "$(GREEN)Désinstallation terminée$(NC)" + diff --git a/README.md b/README.md new file mode 100644 index 0000000..b74e73e --- /dev/null +++ b/README.md @@ -0,0 +1,360 @@ +# MD_to_Print - Script automatique Markdown → PDF → Impression + +Application CLI complète pour convertir des fichiers Markdown en PDF et les imprimer automatiquement sur Debian/Linux, avec support Docker, prévisualisation, options d'impression avancées, et gestion d'erreurs robuste. + +## Fonctionnalités + +- **Conversion automatique** Markdown → PDF avec Pandoc +- **Prévisualisation** avant impression (evince/okular/xdg-open) +- **Options d'impression avancées** (copies, pages, orientation, qualité, couleur, recto-verso) +- **Fichier de configuration** optionnel (format INI) +- **Installation automatique** des dépendances +- **Support Docker** pour isolation et portabilité +- **Gestion d'erreurs** complète avec codes de retour appropriés +- **Système de logging** détaillé avec niveaux (DEBUG, INFO, WARN, ERROR) +- **Interface en ligne de commande** avec options complètes + +## Installation + +### Installation locale + +1. Cloner ou télécharger le projet: +```bash +cd MD_to_print +chmod +x md_to_print.sh +``` + +2. Installer les dépendances manuellement ou automatiquement: +```bash +# Installation automatique +./md_to_print.sh --install-deps + +# Ou installation manuelle +sudo apt-get update +sudo apt-get install -y pandoc texlive-latex-base texlive-fonts-recommended \ + texlive-latex-extra texlive-lang-french cups +``` + +3. (Optionnel) Installation système: +```bash +make install +``` + +### Installation avec Docker + +1. Construire l'image Docker: +```bash +make build +# ou +docker build -t md-to-print:latest . +``` + +2. Créer les répertoires nécessaires: +```bash +mkdir -p documents output logs +``` + +## Utilisation + +### Utilisation locale + +#### Commande de base +```bash +./md_to_print.sh document.md +``` + +#### Avec prévisualisation +```bash +./md_to_print.sh document.md --preview +``` + +#### Options avancées +```bash +./md_to_print.sh document.md \ + --printer HP_LaserJet \ + --copies 2 \ + --color \ + --duplex duplex \ + --quality high \ + --pages 1-5 \ + --orientation landscape \ + --keep-pdf +``` + +#### Avec fichier de configuration +```bash +# Créer votre configuration +cp config.example.conf config.conf +# Éditer config.conf selon vos besoins + +# Utiliser la configuration +./md_to_print.sh document.md --config config.conf +``` + +### Utilisation avec Docker + +#### Via le wrapper script +```bash +chmod +x docker_run.sh +./docker_run.sh documents/mon_fichier.md --preview +``` + +#### Directement avec docker +```bash +docker run --rm -it \ + -v $(pwd)/documents:/workspace/documents:ro \ + -v $(pwd)/output:/workspace/output \ + -v $(pwd)/logs:/workspace/logs \ + --network host \ + md-to-print:latest \ + /workspace/documents/document.md --preview +``` + +#### Via Docker Compose +```bash +# Modifier docker-compose.yml si nécessaire +docker-compose run --rm md-to-print \ + /workspace/documents/document.md --preview +``` + +### Via Makefile + +```bash +# Construire l'image +make build + +# Tester avec fichier exemple +make test + +# Ouvrir un shell dans le conteneur +make shell + +# Nettoyer les fichiers générés +make clean +``` + +## Options disponibles + +| Option | Description | Défaut | +|--------|-------------|--------| +| `-p, --preview` | Prévisualiser le PDF avant impression | false | +| `-P, --printer NOM` | Spécifier l'imprimante | Imprimante système | +| `-c, --copies N` | Nombre de copies | 1 | +| `-r, --pages RANGE` | Pages à imprimer (ex: 1-3,5,7-9) | Toutes | +| `-o, --orientation DIR` | Orientation (portrait/landscape) | portrait | +| `-s, --size SIZE` | Taille du papier (A4, A3, Letter, etc.) | A4 | +| `-q, --quality QUALITY` | Qualité (draft, normal, high) | normal | +| `-C, --color` | Impression en couleur | false | +| `-d, --duplex MODE` | Mode recto-verso (none, simplex, duplex) | none | +| `-i, --install-deps` | Installer les dépendances automatiquement | false | +| `-k, --keep-pdf` | Conserver le fichier PDF après impression | false | +| `--config FILE` | Fichier de configuration | Aucun | +| `-v, --verbose` | Mode verbeux (logging DEBUG) | false | +| `-l, --log FILE` | Fichier de log | Aucun | +| `-h, --help` | Afficher l'aide | - | +| `--version` | Afficher la version | - | + +## Configuration + +Le fichier de configuration utilise le format INI avec trois sections: + +### Section `[default]` +Options d'impression par défaut (printer, copies, orientation, size, quality, color, duplex, preview, keep_pdf) + +### Section `[paths]` +Chemins des répertoires (output_dir, log_dir) + +### Section `[logging]` +Paramètres de logging (level, file, verbose) + +Exemple de fichier `config.conf`: +```ini +[default] +printer=HP_LaserJet +copies=1 +orientation=portrait +size=A4 +quality=normal +color=false +duplex=none +preview=false +keep_pdf=false + +[paths] +output_dir=./output +log_dir=./logs + +[logging] +level=INFO +file=md_to_print.log +verbose=false +``` + +## Structure du projet + +``` +MD_to_print/ +├── md_to_print.sh # Script principal +├── config.example.conf # Fichier de configuration exemple +├── Dockerfile # Configuration Docker +├── docker-compose.yml # Configuration Docker Compose +├── docker_run.sh # Wrapper Docker +├── Makefile # Commandes Make +├── .dockerignore # Fichiers à exclure du build Docker +├── .gitignore # Fichiers à ignorer dans Git +├── README.md # Documentation (ce fichier) +├── CHANGELOG.md # Historique des versions +├── documents/ # Fichiers Markdown sources +├── output/ # PDFs générés +└── logs/ # Fichiers de logs +``` + +## Exemples d'utilisation + +### Impression simple +```bash +./md_to_print.sh rapport.md +``` + +### Impression avec prévisualisation +```bash +./md_to_print.sh rapport.md --preview +``` + +### Impression recto-verso en couleur +```bash +./md_to_print.sh rapport.md --duplex duplex --color --copies 2 +``` + +### Impression de pages spécifiques +```bash +./md_to_print.sh rapport.md --pages 1-10,15,20-25 +``` + +### Impression paysage haute qualité +```bash +./md_to_print.sh presentation.md --orientation landscape --quality high +``` + +### Avec logging détaillé +```bash +./md_to_print.sh document.md --verbose --log mon_log.txt +``` + +## Codes de retour + +| Code | Signification | +|------|---------------| +| 0 | Succès | +| 1 | Erreur générale | +| 2 | Fichier introuvable | +| 3 | Dépendances manquantes | +| 4 | Erreur conversion PDF | +| 5 | Erreur impression | +| 6 | Erreur configuration | +| 7 | Erreur Docker | +| 8 | Permissions insuffisantes | +| 9 | Argument invalide | +| 10 | Imprimante non disponible | + +## Configuration de l'impression dans Docker + +Pour que l'impression fonctionne depuis Docker, vous devez configurer l'accès à CUPS: + +1. Installer CUPS sur l'hôte: +```bash +sudo apt-get install cups +``` + +2. Configurer le partage réseau dans `/etc/cups/cupsd.conf`: +``` +Listen localhost:631 +Port 631 +``` + +3. Redémarrer CUPS: +```bash +sudo systemctl restart cups +``` + +4. Le socket CUPS sera monté automatiquement via docker-compose.yml ou docker_run.sh + +## Dépannage + +### Erreur: "pandoc n'est pas installé" +```bash +./md_to_print.sh document.md --install-deps +``` + +### Erreur: "Imprimante non disponible" +```bash +# Lister les imprimantes disponibles +lpstat -p + +# Utiliser l'imprimante par défaut +./md_to_print.sh document.md +``` + +### Erreur: "Permission de lecture refusée" +```bash +# Vérifier les permissions du fichier +ls -l document.md + +# Donner les permissions de lecture +chmod +r document.md +``` + +### Erreur Docker: "Cannot connect to the Docker daemon" +```bash +# Vérifier que Docker est démarré +sudo systemctl status docker + +# Démarrer Docker si nécessaire +sudo systemctl start docker + +# Ajouter votre utilisateur au groupe docker +sudo usermod -aG docker $USER +# Déconnexion/reconnexion nécessaire +``` + +### Prévisualisation ne fonctionne pas dans Docker +La prévisualisation graphique nécessite l'accès X11. Assurez-vous que: +- `DISPLAY` est défini dans votre environnement +- `/tmp/.X11-unix` est accessible +- Les permissions X11 sont correctes: +```bash +xhost +local:docker +``` + +## Dépendances + +### Dépendances système +- pandoc +- texlive-latex-base +- texlive-fonts-recommended +- texlive-latex-extra +- texlive-lang-french (support français) +- cups (pour l'impression) +- evince ou okular (pour la prévisualisation, optionnel) + +Toutes les dépendances sont installées automatiquement avec l'option `--install-deps` ou dans l'image Docker. + +## Contribution + +Les contributions sont les bienvenues! N'hésitez pas à: +- Signaler des bugs +- Proposer des améliorations +- Soumettre des pull requests + +## Licence + +Ce projet est fourni tel quel, sans garantie. + +## Auteur + +MD_to_Print - Script automatique Markdown → PDF → Impression + +## Historique + +Voir [CHANGELOG.md](CHANGELOG.md) pour l'historique des versions. + diff --git a/config.example.conf b/config.example.conf new file mode 100644 index 0000000..07751e0 --- /dev/null +++ b/config.example.conf @@ -0,0 +1,48 @@ +# Configuration exemple pour MD_to_Print +# Copiez ce fichier vers config.conf et modifiez selon vos besoins + +[default] +# Imprimante par défaut (laisser vide pour utiliser l'imprimante système) +printer= + +# Nombre de copies par défaut +copies=1 + +# Orientation: portrait ou landscape +orientation=portrait + +# Taille du papier: A4, A3, Letter, Legal, etc. +size=A4 + +# Qualité d'impression: draft, normal, high +quality=normal + +# Impression en couleur (true/false) +color=false + +# Mode recto-verso: none, simplex, duplex +duplex=none + +# Prévisualiser le PDF avant impression (true/false) +preview=false + +# Conserver le fichier PDF après impression (true/false) +keep_pdf=false + +[paths] +# Répertoire de sortie pour les PDFs générés +output_dir=./output + +# Répertoire pour les fichiers de log +log_dir=./logs + +[logging] +# Niveau de log: DEBUG, INFO, WARN, ERROR +level=INFO + +# Nom du fichier de log (sera placé dans log_dir) +file=md_to_print.log + +# Mode verbeux (true/false) +verbose=false + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..20c27d0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,32 @@ +version: '3.8' + +services: + md-to-print: + build: + context: . + dockerfile: Dockerfile + image: md-to-print:latest + container_name: md-to-print + volumes: + # Monter le répertoire contenant les fichiers markdown (lecture seule) + - ./documents:/workspace/documents:ro + # Monter le répertoire de sortie pour les PDFs + - ./output:/workspace/output + # Monter le répertoire de logs + - ./logs:/workspace/logs + # Accès à l'imprimante via CUPS (nécessite configuration CUPS) + - /var/run/cups:/var/run/cups:ro + # Optionnel: pour la prévisualisation graphique (décommenter si nécessaire) + # - /tmp/.X11-unix:/tmp/.X11-unix:ro + environment: + - TZ=Europe/Paris + - DISPLAY=${DISPLAY:-} + network_mode: host + # Pour l'accès à l'affichage (prévisualisation) + # Décommenter les lignes suivantes si vous avez besoin de la prévisualisation graphique: + # stdin_open: true + # tty: true + # devices: + # - /dev/dri:/dev/dri + restart: "no" + diff --git a/docker_run.sh b/docker_run.sh new file mode 100755 index 0000000..be1fbe5 --- /dev/null +++ b/docker_run.sh @@ -0,0 +1,130 @@ +#!/bin/bash + +# Wrapper pour exécuter le script MD_to_Print dans Docker +# Usage: ./docker_run.sh fichier.md [options...] + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +MD_FILE="${1:-}" + +# Couleurs +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Fonction d'aide +show_help() { + cat << EOF +Wrapper Docker pour MD_to_Print + +Usage: $0 fichier.md [options...] + +Ce script simplifie l'exécution de MD_to_Print dans Docker en gérant: +- Les chemins absolus des fichiers +- Le montage des volumes +- Le passage des arguments +- La gestion des erreurs Docker + +EXEMPLES: + $0 documents/rapport.md --preview + $0 documents/rapport.md --printer HP_LaserJet --copies 2 + $0 documents/rapport.md --config config.conf --verbose + +OPTIONS: + Toutes les options de md_to_print.sh sont supportées. + Utilisez: docker run --rm md-to-print:latest --help + pour voir toutes les options disponibles. +EOF +} + +# Vérification des arguments +if [ -z "$MD_FILE" ] || [ "$MD_FILE" = "-h" ] || [ "$MD_FILE" = "--help" ]; then + show_help + exit 0 +fi + +# Vérifier que Docker est disponible +if ! command -v docker &> /dev/null; then + echo -e "${RED}Erreur: Docker n'est pas installé ou non disponible dans le PATH${NC}" + exit 1 +fi + +# Vérifier que le fichier existe +if [ ! -f "$MD_FILE" ]; then + echo -e "${RED}Erreur: Le fichier '$MD_FILE' n'existe pas${NC}" + exit 2 +fi + +# Obtenir le chemin absolu du fichier +MD_FILE_ABS="$(realpath "$MD_FILE")" +MD_DIR="$(dirname "$MD_FILE_ABS")" +MD_NAME="$(basename "$MD_FILE_ABS")" + +# Vérifier que le fichier est dans le répertoire documents ou un sous-répertoire +if [[ ! "$MD_DIR" =~ ^"$SCRIPT_DIR"/documents ]]; then + echo -e "${YELLOW}Attention: Le fichier n'est pas dans le répertoire documents/${NC}" + echo -e "${BLUE}Le fichier sera accessible via le montage du répertoire parent${NC}" + MD_REL_PATH="$(realpath --relative-to="$SCRIPT_DIR" "$MD_FILE_ABS")" + MD_DIR="$SCRIPT_DIR" + MD_NAME="$MD_REL_PATH" +fi + +# Créer les répertoires nécessaires +mkdir -p "$SCRIPT_DIR/documents" "$SCRIPT_DIR/output" "$SCRIPT_DIR/logs" + +# Vérifier si l'image Docker existe +if ! docker images md-to-print:latest --format "{{.Repository}}:{{.Tag}}" | grep -q "md-to-print:latest"; then + echo -e "${YELLOW}Image Docker non trouvée. Construction de l'image...${NC}" + cd "$SCRIPT_DIR" + docker build -t md-to-print:latest . +fi + +# Construire la commande Docker +DOCKER_CMD=( + docker run + --rm + -it + -v "$SCRIPT_DIR/documents:/workspace/documents:ro" + -v "$SCRIPT_DIR/output:/workspace/output" + -v "$SCRIPT_DIR/logs:/workspace/logs" + --network host +) + +# Ajouter le support X11 si DISPLAY est défini (pour prévisualisation) +if [ -n "${DISPLAY:-}" ]; then + DOCKER_CMD+=( + -e DISPLAY="$DISPLAY" + -v /tmp/.X11-unix:/tmp/.X11-unix:ro + ) +fi + +# Ajouter l'accès CUPS si disponible +if [ -d "/var/run/cups" ]; then + DOCKER_CMD+=(-v /var/run/cups:/var/run/cups:ro) +fi + +DOCKER_CMD+=(md-to-print:latest) + +# Ajouter le fichier markdown et les options +if [[ "$MD_DIR" == "$SCRIPT_DIR" ]]; then + DOCKER_CMD+=("/workspace/$MD_NAME") +else + DOCKER_CMD+=("/workspace/documents/$MD_NAME") +fi + +# Ajouter les options restantes +shift +for arg in "$@"; do + DOCKER_CMD+=("$arg") +done + +# Exécuter +echo -e "${GREEN}Exécution dans Docker...${NC}" +echo -e "${BLUE}Commande: ${DOCKER_CMD[*]}${NC}" +echo "" + +exec "${DOCKER_CMD[@]}" + diff --git a/documents/PLAN_DEPLOIEMENT_ORDRE.md b/documents/PLAN_DEPLOIEMENT_ORDRE.md new file mode 100644 index 0000000..0ed73e7 --- /dev/null +++ b/documents/PLAN_DEPLOIEMENT_ORDRE.md @@ -0,0 +1,885 @@ +# Plan de Déploiement - Ordre Logique - Smart-Motions + +**Date** : Novembre 2025 +**Version** : 1.0 +**Contexte** : Plan complet de déploiement et configuration de l'infrastructure Smart-Motions + +--- + +## 📋 Table des matières + +1. [Vue d'ensemble](#vue-densemble) +2. [Phases de déploiement](#phases-de-déploiement) +3. [Phase 1 : Préparation et Infrastructure de base](#phase-1--préparation-et-infrastructure-de-base) +4. [Phase 2 : Réseau et Sécurité](#phase-2--réseau-et-sécurité) +5. [Phase 3 : Active Directory et Services de base](#phase-3--active-directory-et-services-de-base) +6. [Phase 4 : Services Windows](#phase-4--services-windows) +7. [Phase 5 : Services Infrastructure](#phase-5--services-infrastructure) +8. [Phase 6 : Services applicatifs](#phase-6--services-applicatifs) +7. [Phase 7 : Postes clients et finalisation](#phase-7--postes-clients-et-finalisation) +8. [Checklist complète](#checklist-complète) +9. [Dépendances entre services](#dépendances-entre-services) + +--- + +## Vue d'ensemble + +### Objectif + +Ce document définit l'ordre logique de déploiement et de configuration de toute l'infrastructure Smart-Motions, en tenant compte des dépendances entre les services. + +### Principes + +1. **Infrastructure d'abord** : Réseau, virtualisation, stockage +2. **Services de base** : AD, DNS, DHCP +3. **Services dépendants** : Services qui nécessitent AD +4. **Services applicatifs** : Applications métier +5. **Postes clients** : Déploiement des postes utilisateurs +6. **Finalisation** : Tests, sécurité, documentation + +### Durée estimée + +- **Phase 1-2** : 2-3 jours +- **Phase 3** : 2-3 jours +- **Phase 4** : 3-4 jours +- **Phase 5** : 2-3 jours +- **Phase 6** : 2-3 jours +- **Phase 7** : 2-3 jours +- **Total** : 13-19 jours (environ 3-4 semaines) + +--- + +## Phases de déploiement + +``` +┌─────────────────────────────────────────────────────────┐ +│ PHASE 1 : Préparation et Infrastructure de base │ +│ - Proxmox, Templates, Réseau │ +└─────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────┐ +│ PHASE 2 : Réseau et Sécurité │ +│ - pfSense, VPN Site-to-Site, DMZ │ +└─────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────┐ +│ PHASE 3 : Active Directory et Services de base │ +│ - AD, DNS, DHCP, LAPS │ +└─────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────┐ +│ PHASE 4 : Services Windows │ +│ - Serveur fichiers, RDS, Veeam, GPO │ +└─────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────┐ +│ PHASE 5 : Services Infrastructure │ +│ - GLPI, Zabbix, DNS Split, Déploiement │ +└─────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────┐ +│ PHASE 6 : Services applicatifs │ +│ - Messagerie, Nextcloud, DMZ (FTP/Extranet) │ +└─────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────┐ +│ PHASE 7 : Postes clients et finalisation │ +│ - Déploiement postes, Tests, Pentest, Documentation │ +└─────────────────────────────────────────────────────────┘ +``` + +--- + +## Phase 1 : Préparation et Infrastructure de base + +### Objectif + +Préparer l'infrastructure de virtualisation et créer les templates nécessaires. + +### Étapes + +#### 1.1 Installation et configuration Proxmox + +- [ ] **Installer Proxmox** sur les serveurs physiques (Paris et Lyon) +- [ ] **Configurer les bridges réseau** : + - `vmbr0` : Management (192.168.42.0/24) + - `vmbr1` : WAN (selon configuration) + - `vmbr2` : LAN (10.0.0.0/24 pour Paris, 10.1.0.0/24 pour Lyon) +- [ ] **Configurer le stockage** : Disques locaux ou partagés +- [ ] **Créer les pools de ressources** : Paris, Lyon + +**Documentation** : `docs/proxmox/PROXMOX_NETWORK_CONFIG.md` + +#### 1.2 Création des templates Proxmox + +- [ ] **Template Windows Server 2022** : + - Installer Windows Server 2022 + - Configurer sysprep + - Créer le template +- [ ] **Template Debian 12** : + - Installer Debian 12 + - Configurer cloud-init + - Créer le template +- [ ] **Template Ubuntu 22.04** : + - Installer Ubuntu 22.04 + - Configurer cloud-init + - Créer le template +- [ ] **Template pfSense** : + - Installer pfSense + - Configuration de base + - Créer le template + +**Documentation** : +- `docs/proxmox/PROXMOX_TEMPLATES.md` +- `docs/pfsense/PFSENSE_TEMPLATE.md` + +#### 1.3 Vérification de l'infrastructure + +- [ ] **Tester la connectivité réseau** entre les serveurs Proxmox +- [ ] **Vérifier l'accès aux templates** créés +- [ ] **Valider les ressources** (CPU, RAM, stockage) + +**Durée estimée** : 1-2 jours + +--- + +## Phase 2 : Réseau et Sécurité + +### Objectif + +Déployer et configurer les firewalls pfSense et établir la connectivité entre les sites. + +### Étapes + +#### 2.1 Déploiement des firewalls pfSense + +- [ ] **Déployer PAR-FW1** (10.0.0.1) : + - Créer la VM depuis le template pfSense + - Configurer les interfaces réseau (WAN, LAN, OPT1 pour DMZ) + - Configuration initiale via console +- [ ] **Déployer LYO-FW1** (10.1.0.1) : + - Créer la VM depuis le template pfSense + - Configurer les interfaces réseau + - Configuration initiale via console + +**Documentation** : `docs/pfsense/PFSENSE_INITIAL_CONFIG.md` + +#### 2.2 Configuration manuelle initiale pfSense + +**Pour chaque firewall** : + +- [ ] **Configuration de base** : + - Changer le mot de passe admin + - Configurer l'interface WAN (IP statique ou DHCP) + - Configurer l'interface LAN (10.0.0.1 pour Paris, 10.1.0.1 pour Lyon) + - Activer SSH (optionnel, pour Ansible) +- [ ] **Règles firewall de base** : + - Autoriser le trafic LAN → WAN + - Bloquer le trafic WAN → LAN (sauf exceptions) + - Configurer les règles de base + +**Documentation** : `docs/pfsense/PFSENSE_INITIAL_CONFIG.md` + +#### 2.3 Configuration VPN Site-to-Site + +- [ ] **Configurer IPsec VPN** entre PAR-FW1 et LYO-FW1 : + - Phase 1 (IKE) : Chiffrement, authentification + - Phase 2 (IPsec) : Réseaux à connecter + - Routes statiques +- [ ] **Tester la connectivité** : + - Ping entre les sites + - Vérifier la réplication AD (une fois AD déployé) + +**Documentation** : `docs/pfsense/PFSENSE_SETUP.md` + +#### 2.4 Configuration DMZ + +- [ ] **Créer l'interface DMZ** sur PAR-FW1 (OPT1) +- [ ] **Configurer le réseau DMZ** : 10.0.0.100/24 +- [ ] **Règles firewall DMZ** : + - WAN → DMZ (ports spécifiques) + - DMZ → WAN (accès Internet) + - DMZ → LAN (bloqué par défaut) + +**Documentation** : `docs/pfsense/PFSENSE_SETUP.md` + +#### 2.5 Configuration automatisée pfSense (Ansible) + +- [ ] **Déployer les VMs admin jump hosts** : + - PAR-ADMIN1 (10.0.0.151) + - LYO-ADMIN1 (10.1.0.151) +- [ ] **Configurer les jump hosts** : + - Interfaces réseau (Management + LAN) + - Installation Ansible et collections +- [ ] **Automatiser la configuration pfSense** : + - Règles firewall avancées + - Proxy et filtrage web + - VPN Client (OpenVPN) + - Filtrage géographique (PFBlockerNG) + +**Documentation** : +- `docs/pfsense/PFSENSE_ANSIBLE.md` +- `docs/pfsense/PFSENSE_DEPLOYMENT_ORDER.md` + +**Durée estimée** : 1-2 jours + +--- + +## Phase 3 : Active Directory et Services de base + +### Objectif + +Déployer Active Directory, DNS, DHCP et sécuriser les comptes administrateurs. + +### Étapes + +#### 3.1 Déploiement du premier contrôleur de domaine (PAR-DC1) + +- [ ] **Créer la VM PAR-DC1** (10.0.0.11) : + - 4 cores, 8 Go RAM, 100 Go disque + - Interface LAN (vmbr2) +- [ ] **Installer Windows Server 2022** +- [ ] **Configurer le réseau** : + - IP statique : 10.0.0.11/24 + - DNS : 127.0.0.1 (lui-même) + - Passerelle : 10.0.0.1 (pfSense) +- [ ] **Promouvoir en contrôleur de domaine** : + - Créer la forêt : `smartmotion.ovh` + - Installer les rôles : AD DS, DNS + - Configurer DNS intégré +- [ ] **Vérifier la réplication DNS** : Automatique avec AD + +**Documentation** : `docs/active-directory/ANALYSE_AD_VS_LDAP.md` + +#### 3.2 Déploiement du second contrôleur de domaine (PAR-DC2) + +- [ ] **Créer la VM PAR-DC2** (10.0.0.12) : + - 4 cores, 8 Go RAM, 100 Go disque +- [ ] **Installer Windows Server 2022** +- [ ] **Configurer le réseau** : + - IP statique : 10.0.0.12/24 + - DNS : 10.0.0.11 (PAR-DC1) +- [ ] **Promouvoir en contrôleur de domaine** : + - Joindre le domaine existant : `smartmotion.ovh` + - Installer les rôles : AD DS, DNS +- [ ] **Vérifier la réplication AD** : Automatique +- [ ] **Configurer les forwarders DNS** : 1.1.1.1, 8.8.8.8 + +#### 3.3 Configuration DNS interne + +- [ ] **Créer les enregistrements DNS internes** : + - `dc1.smartmotion.ovh` → 10.0.0.11 + - `dc2.smartmotion.ovh` → 10.0.0.12 + - Enregistrements pour les futurs serveurs +- [ ] **Configurer les zones DNS** : + - Zone `smartmotion.ovh` (intégrée AD) + - Zones de recherche inversée + +**Documentation** : `docs/services/DNS_SPLIT.md` + +#### 3.4 Configuration DHCP + +- [ ] **Installer le rôle DHCP** sur PAR-DC1 +- [ ] **Créer une étendue DHCP** : + - Plage : 10.0.0.100 - 10.0.0.200 + - Passerelle : 10.0.0.1 + - DNS : 10.0.0.11, 10.0.0.12 + - Domaine : `smartmotion.ovh` +- [ ] **Autoriser le serveur DHCP** dans AD +- [ ] **Réservations IP** pour les serveurs fixes + +#### 3.5 Déploiement RODC Lyon (LYO-RODC1) + +- [ ] **Créer la VM LYO-RODC1** (10.1.0.10) : + - 2 cores, 4 Go RAM, 50 Go disque +- [ ] **Installer Windows Server 2022** +- [ ] **Configurer le réseau** : + - IP statique : 10.1.0.10/24 + - DNS : 10.0.0.11 (via VPN) +- [ ] **Promouvoir en RODC** : + - Read-Only Domain Controller + - Pas de modifications AD possibles +- [ ] **Installer DHCP** sur LYO-RODC1 : + - Plage : 10.1.0.100 - 10.1.0.200 + - Passerelle : 10.1.0.1 + +#### 3.6 Configuration Microsoft LAPS + +- [ ] **Installer LAPS** sur PAR-DC1 et PAR-DC2 +- [ ] **Extension du schéma AD** : Automatique +- [ ] **Créer une GPO** pour LAPS : + - Activer la gestion des mots de passe admin locaux + - Configurer les paramètres (longueur, complexité) +- [ ] **Lier la GPO** aux OUs des postes clients +- [ ] **Tester** : Vérifier la rotation des mots de passe + +**Documentation** : `docs/windows/LAPS.md` + +#### 3.7 Création des utilisateurs et groupes AD + +- [ ] **Créer les OUs** : + - `Departements/Direction` + - `Departements/Commercial` + - `Departements/Technique` + - `Departements/Support` + - `Servers/Paris` + - `Servers/Lyon` + - `Clients/Paris` + - `Clients/Lyon` +- [ ] **Créer les groupes de sécurité** : + - `Direction`, `Commercial`, `Technique`, `Support` + - `Chefs-Services` (pour administrateurs locaux) + - `VPN-Users` (pour VPN client) +- [ ] **Créer les comptes utilisateurs** (50 utilisateurs) +- [ ] **Créer les comptes de service** : + - `svc-nextcloud` (pour Nextcloud LDAP) + - `svc-glpi` (pour GLPI LDAP) + - `svc-veeam` (pour Veeam) + +**Durée estimée** : 2-3 jours + +--- + +## Phase 4 : Services Windows + +### Objectif + +Déployer les services Windows : fichiers, RDS, sauvegardes, GPO. + +### Étapes + +#### 4.1 Serveur de fichiers Paris (PAR-FILE1) + +- [ ] **Créer la VM PAR-FILE1** (10.0.0.20) : + - 4 cores, 8 Go RAM, 2 To disque +- [ ] **Installer Windows Server 2022** +- [ ] **Joindre au domaine** : `smartmotion.ovh` +- [ ] **Installer le rôle File Server** +- [ ] **Créer les partages** : + - `\\PAR-FILE1\Departements\` + - `\\PAR-FILE1\Public\` + - `\\PAR-FILE1\Applications\` + - `\\PAR-FILE1\Users\` (pour redirection profils) +- [ ] **Configurer FSRM** : + - Quotas par utilisateur (10 Go standard, 20 Go direction) + - Filtrage de fichiers (bloquer multimédia) +- [ ] **Activer la déduplication** : + - Volume D:\ + - Type : General purpose file server +- [ ] **Activer Shadow Copies** : + - Volume D:\ + - Fréquence : 2 fois par jour +- [ ] **Configurer les permissions** : Par groupes AD + +**Documentation** : `docs/windows/SERVEUR_FICHIERS.md` + +#### 4.2 Serveur de fichiers Lyon (LYO-FILE1) + +- [ ] **Créer la VM LYO-FILE1** (10.1.0.20) : + - 2 cores, 4 Go RAM, 1 To disque +- [ ] **Installer Windows Server 2022** +- [ ] **Joindre au domaine** +- [ ] **Installer le rôle File Server** +- [ ] **Créer les partages locaux** +- [ ] **Configurer FSRM** (quotas) + +#### 4.3 Configuration DFS-R (Réplication) + +- [ ] **Installer DFS Replication** sur PAR-FILE1 et LYO-FILE1 +- [ ] **Créer un groupe de réplication** : + - Nom : `Sylvestre-Replication` +- [ ] **Ajouter les membres** : PAR-FILE1, LYO-FILE1 +- [ ] **Créer un dossier répliqué** : + - `Documents` : Réplication bidirectionnelle +- [ ] **Configurer la topologie** : Hub (Paris) - Spoke (Lyon) +- [ ] **Tester la réplication** : Vérifier la synchronisation + +**Documentation** : `docs/windows/SERVEUR_FICHIERS.md` + +#### 4.4 Remote Desktop Services (PAR-RDS1) + +- [ ] **Créer la VM PAR-RDS1** (10.0.0.60) : + - 8 cores, 16 Go RAM, 100 Go disque +- [ ] **Installer Windows Server 2022** +- [ ] **Joindre au domaine** +- [ ] **Installer les rôles RDS** : + - RD Session Host + - RD Web Access + - RD Gateway + - RD Licensing +- [ ] **Configurer le déploiement RDS** : + - RD Connection Broker : PAR-RDS1 + - RD Session Host : PAR-RDS1 + - RD Web Access : PAR-RDS1 +- [ ] **Publier des applications RemoteApp** : + - Microsoft Office + - Applications métier +- [ ] **Configurer TLS** : Certificat SSL +- [ ] **Tester l'accès** : Via navigateur web + +**Documentation** : `docs/windows/RDS_REMOTE_DESKTOP.md` + +#### 4.5 Veeam Backup & Replication (PAR-VEEAM1) + +- [ ] **Créer la VM PAR-VEEAM1** (10.0.0.50) : + - 4 cores, 8 Go RAM, 5 To disque +- [ ] **Installer Windows Server 2022** +- [ ] **Joindre au domaine** +- [ ] **Installer Veeam Backup & Replication** +- [ ] **Configurer le repository** : + - Chemin : `D:\Backups` + - Espace : 5 To +- [ ] **Créer les jobs de sauvegarde** : + - PAR-DC1, PAR-DC2 : Quotidien + - PAR-FILE1, LYO-FILE1 : Quotidien + - PAR-RDS1 : Quotidien + - Autres serveurs : Hebdomadaire +- [ ] **Configurer la rétention** : 30 jours +- [ ] **Tester une restauration** : Fichier individuel + +**Documentation** : `docs/windows/VEEAM_SAUVEGARDE.md` + +#### 4.6 Group Policy Objects (GPO) + +- [ ] **Créer les GPO de base** : + - `GPO-Departement-Direction` + - `GPO-Departement-Commercial` + - `GPO-Departement-Technique` + - `GPO-Postes-Clients` + - `GPO-Chefs-Services` (administrateurs locaux) +- [ ] **Configurer le déploiement automatique** : + - Imprimantes par département + - Lecteurs réseau mappés + - Redirection de profils (Documents, Desktop, AppData) +- [ ] **Configurer les administrateurs locaux** : + - Groupe `Chefs-Services` → Administrateurs locaux +- [ ] **Tester les GPO** : Sur un poste de test + +**Documentation** : `docs/windows/GPO_GROUP_POLICY.md` + +**Durée estimée** : 3-4 jours + +--- + +## Phase 5 : Services Infrastructure + +### Objectif + +Déployer les services d'infrastructure : GLPI, Zabbix, DNS Split, déploiement. + +### Étapes + +#### 5.1 GLPI - Gestion de parc (PAR-GLPI1) + +- [ ] **Créer la VM PAR-GLPI1** (10.0.0.30) : + - 2 cores, 4 Go RAM, 100 Go disque +- [ ] **Installer Debian 12** +- [ ] **Installer GLPI** : + - Apache, PHP, MariaDB + - GLPI 10.0.7 +- [ ] **Configurer l'intégration AD** : + - LDAP : 10.0.0.11 + - Compte de service : `svc-glpi` + - Synchronisation automatique +- [ ] **Installer OCS Inventory** : + - Serveur OCS + - Agents sur les postes clients +- [ ] **Configurer GLPI + OCS** : + - Plugin OCS dans GLPI + - Synchronisation inventaire +- [ ] **Créer les catégories d'incidents** +- [ ] **Tester la création de tickets** + +**Documentation** : `docs/services/GLPI_GESTION_PARC.md` + +#### 5.2 Zabbix - Supervision (PAR-ZABBIX1) + +- [ ] **Créer la VM PAR-ZABBIX1** (10.0.0.40) : + - 4 cores, 8 Go RAM, 200 Go disque +- [ ] **Installer Ubuntu 22.04** +- [ ] **Installer Zabbix Server** : + - Zabbix 6.0 + - PostgreSQL + - Nginx +- [ ] **Configurer les hôtes** : + - Serveurs Windows (via Zabbix Agent) + - Serveurs Linux (via Zabbix Agent) + - Équipements réseau (via SNMP si supporté) +- [ ] **Créer des tableaux de bord** : + - Dashboard Infrastructure + - Dashboard Réseau + - Dashboard Services +- [ ] **Configurer les alertes** : + - Notifications email + - Seuils d'alerte +- [ ] **Tester les alertes** : Simulation d'incident + +**Documentation** : `docs/services/ZABBIX_SUPERVISION.md` + +#### 5.3 DNS Split (Interne/Externe) + +- [ ] **Acheter un nom de domaine** : + - `smartmotion.ovh` (ou autre) + - Registrar : OVH, Gandi, Online, etc. +- [ ] **Configurer DNS interne (AD)** : + - Enregistrements A pour tous les services + - `www.smartmotion.ovh` → 10.0.0.30 (GLPI) + - `mail.smartmotion.ovh` → 10.0.0.XX (Zimbra) + - `zabbix.smartmotion.ovh` → 10.0.0.40 + - etc. +- [ ] **Configurer DNS externe (Hébergeur)** : + - Enregistrements A pour services exposés + - `www.smartmotion.ovh` → IP publique + - `ftp.smartmotion.ovh` → IP publique DMZ + - Enregistrements MX pour email +- [ ] **Configurer les forwarders DNS** : 1.1.1.1, 8.8.8.8 +- [ ] **Tester la résolution** : + - Interne : `nslookup www.smartmotion.ovh 10.0.0.11` + - Externe : `nslookup www.smartmotion.ovh 8.8.8.8` + +**Documentation** : `docs/services/DNS_SPLIT.md` + +#### 5.4 Solution de déploiement des postes + +- [ ] **Créer la VM PAR-DEPLOY1** (10.0.0.80) : + - 4 cores, 8 Go RAM, 500 Go disque +- [ ] **Installer Windows Server 2022** +- [ ] **Joindre au domaine** +- [ ] **Installer WDS + MDT** : + - Windows Deployment Services + - Microsoft Deployment Toolkit + - Windows ADK +- [ ] **Créer les images de référence** : + - Windows 11 Pro - PC fixes + - Windows 11 Pro - Portables +- [ ] **Configurer les Task Sequences** : + - Installation Windows 11 + - Applications pré-installées + - Jointure au domaine +- [ ] **Tester le déploiement** : Sur un poste de test + +**Documentation** : `docs/services/DEPLOIEMENT_POSTES.md` + +**Durée estimée** : 2-3 jours + +--- + +## Phase 6 : Services applicatifs + +### Objectif + +Déployer les services applicatifs : messagerie, Nextcloud, DMZ. + +### Étapes + +#### 6.1 Service de messagerie (Zimbra ou M365) + +**Option A : Zimbra (hébergé localement)** + +- [ ] **Créer la VM PAR-MAIL1** (10.0.0.XX) : + - 4 cores, 8 Go RAM, 200 Go disque +- [ ] **Installer Zimbra** : + - Debian 12 + - Zimbra Open Source ou Network Edition +- [ ] **Configurer le domaine** : `smartmotion.ovh` +- [ ] **Créer les boîtes mail** : 50 utilisateurs +- [ ] **Configurer l'intégration AD** : LDAP +- [ ] **Configurer les enregistrements DNS** : + - MX : `mail.smartmotion.ovh` + - SPF, DKIM, DMARC + +**Option B : Microsoft 365 (SaaS)** + +- [ ] **Souscrire à Microsoft 365** : + - Plan Business Standard ou Premium + - 50 licences utilisateur +- [ ] **Configurer le domaine** : `smartmotion.ovh` + - Vérification du domaine + - Enregistrements DNS (MX, SPF, etc.) +- [ ] **Synchroniser avec AD** : Azure AD Connect (optionnel) +- [ ] **Créer les boîtes mail** : 50 utilisateurs + +**Documentation** : `docs/messagerie/COMPARAISON_ZIMBRA_M365.md` + +#### 6.2 Nextcloud + +- [ ] **Créer la VM PAR-NEXTCLOUD1** (10.0.0.XX) : + - 2 cores, 4 Go RAM, 500 Go disque +- [ ] **Installer Nextcloud** : + - Debian 12 + - Nextcloud 28+ + - Apache, PHP, MariaDB +- [ ] **Configurer l'intégration AD** : + - LDAP : 10.0.0.11 + - Compte de service : `svc-nextcloud` + - Synchronisation automatique +- [ ] **Configurer les partages** : + - Intégration avec serveur de fichiers + - Quotas par utilisateur +- [ ] **Tester l'accès** : Via navigateur web + +**Documentation** : `docs/active-directory/NEXTCLOUD_LDAP_AD.md` + +#### 6.3 DMZ - FTP et Extranet (PAR-FTP1) + +- [ ] **Créer la VM PAR-FTP1** (10.0.0.70) : + - 2 cores, 2 Go RAM, 100 Go disque + - Interface DMZ (10.0.0.100/24) +- [ ] **Installer Debian 12** +- [ ] **Installer vsftpd** : + - Configuration FTP sécurisé + - Utilisateurs virtuels +- [ ] **Installer Apache** : + - Extranet web + - PHP, base de données +- [ ] **Configurer les règles firewall** : + - WAN → DMZ (ports FTP et HTTP/HTTPS) + - DMZ → LAN (bloqué) +- [ ] **Tester l'accès** : + - FTP depuis Internet + - Extranet depuis Internet + +**Documentation** : `docs/services/DMZ_FTP_EXTRANET.md` + +#### 6.4 VPN Client avec authentification RADIUS + +- [ ] **Configurer NPS (Network Policy Server)** sur PAR-DC1 : + - Installer le rôle NPS + - Créer un RADIUS client (pfSense) + - Créer une Network Policy (groupe VPN-Users) +- [ ] **Configurer OpenVPN sur pfSense** : + - Serveur OpenVPN + - Authentification RADIUS + - Certificats SSL +- [ ] **Créer les profils VPN** : + - Fichiers .ovpn pour les clients +- [ ] **Tester la connexion VPN** : + - Depuis un poste externe + - Authentification avec compte AD + +**Documentation** : `docs/services/VPN_CLIENT_RADIUS.md` + +**Durée estimée** : 2-3 jours + +--- + +## Phase 7 : Postes clients et finalisation + +### Objectif + +Déployer les postes clients, effectuer les tests et finaliser la documentation. + +### Étapes + +#### 7.1 Déploiement des postes clients + +- [ ] **Déployer les 40 PC fixes (Paris)** : + - Via WDS + MDT + - Windows 11 Pro + - Applications pré-installées + - Jointure au domaine +- [ ] **Déployer les 5 portables (Paris)** : + - Via WDS + MDT + - Windows 11 Pro + - Configuration portable +- [ ] **Déployer les 5 portables (Lyon)** : + - Via WDS + MDT (depuis Paris via VPN) + - Windows 11 Pro +- [ ] **Vérifier les GPO** : + - Imprimantes déployées + - Lecteurs réseau mappés + - Redirection de profils active +- [ ] **Vérifier LAPS** : + - Mots de passe admin locaux gérés + - Rotation automatique + +**Documentation** : `docs/services/DEPLOIEMENT_POSTES.md` + +#### 7.2 Tests fonctionnels + +- [ ] **Tests de connectivité** : + - Ping entre tous les serveurs + - Accès aux partages réseau + - Résolution DNS (interne et externe) +- [ ] **Tests de services** : + - Accès GLPI (gestion de parc) + - Accès Zabbix (supervision) + - Accès RDS (bureaux à distance) + - Accès Nextcloud + - Accès messagerie +- [ ] **Tests de réplication** : + - Réplication AD (Paris ↔ Lyon) + - Réplication DFS-R (fichiers) +- [ ] **Tests de sauvegarde** : + - Jobs Veeam fonctionnels + - Restauration test (fichier individuel) + - Shadow Copies accessibles +- [ ] **Tests VPN** : + - VPN Site-to-Site (Paris ↔ Lyon) + - VPN Client (depuis Internet) + +#### 7.3 Tests de sécurité (Pentest) + +- [ ] **Installation des outils** : + - Nmap + - Nessus (Community Edition ou commercial) +- [ ] **Scan réseau avec Nmap** : + - Scan de tous les réseaux (10.0.0.0/24, 10.1.0.0/24) + - Détection des ports ouverts + - Identification des services +- [ ] **Scan de vulnérabilités avec Nessus** : + - Scan de tous les serveurs + - Identification des vulnérabilités + - Classification (Critique, Haute, Moyenne, Faible) +- [ ] **Correction des vulnérabilités** : + - Mises à jour système + - Fermeture de ports inutiles + - Renforcement de la configuration +- [ ] **Nouveau scan de validation** : + - Vérifier que les vulnérabilités sont corrigées +- [ ] **Rapport de pentest** : + - Documenter les résultats + - Liste des vulnérabilités corrigées + - Recommandations + +**Documentation** : `docs/security/PENTEST_NMAP_NESSUS.md` + +#### 7.4 Documentation finale + +- [ ] **Vérifier la documentation** : + - Tous les documents à jour + - Procédures complètes + - Schémas réseau +- [ ] **Créer un guide utilisateur** : + - Accès aux services + - Utilisation de Nextcloud + - Utilisation de la messagerie + - Accès VPN +- [ ] **Créer un guide administrateur** : + - Procédures de maintenance + - Procédures de sauvegarde/restauration + - Procédures de dépannage +- [ ] **Documenter les mots de passe** : + - Stockage sécurisé (Vault) + - Liste des comptes de service + - Accès aux équipements + +**Durée estimée** : 2-3 jours + +--- + +## Checklist complète + +### Phase 1 : Préparation +- [ ] Proxmox installé et configuré +- [ ] Templates créés (Windows, Debian, Ubuntu, pfSense) +- [ ] Réseau configuré (bridges, VLAN) + +### Phase 2 : Réseau et Sécurité +- [ ] pfSense déployé (Paris et Lyon) +- [ ] Configuration manuelle initiale +- [ ] VPN Site-to-Site configuré +- [ ] DMZ configurée +- [ ] Configuration automatisée (Ansible) + +### Phase 3 : Active Directory +- [ ] PAR-DC1 déployé et promu +- [ ] PAR-DC2 déployé et promu +- [ ] LYO-RODC1 déployé et promu +- [ ] DNS interne configuré +- [ ] DHCP configuré (Paris et Lyon) +- [ ] LAPS installé et configuré +- [ ] Utilisateurs et groupes créés + +### Phase 4 : Services Windows +- [ ] PAR-FILE1 déployé et configuré +- [ ] LYO-FILE1 déployé et configuré +- [ ] DFS-R configuré +- [ ] PAR-RDS1 déployé et configuré +- [ ] PAR-VEEAM1 déployé et configuré +- [ ] GPO créées et configurées + +### Phase 5 : Services Infrastructure +- [ ] PAR-GLPI1 déployé et configuré +- [ ] PAR-ZABBIX1 déployé et configuré +- [ ] DNS Split configuré +- [ ] Solution de déploiement configurée + +### Phase 6 : Services applicatifs +- [ ] Messagerie déployée (Zimbra ou M365) +- [ ] Nextcloud déployé et configuré +- [ ] DMZ (FTP/Extranet) déployée +- [ ] VPN Client configuré + +### Phase 7 : Finalisation +- [ ] Postes clients déployés (50 postes) +- [ ] Tests fonctionnels réussis +- [ ] Pentest effectué et vulnérabilités corrigées +- [ ] Documentation complète + +--- + +## Dépendances entre services + +### Graphique des dépendances + +``` +Proxmox + ↓ +pfSense (VPN Site-to-Site) + ↓ +Active Directory (PAR-DC1, PAR-DC2) + ├─→ DNS interne + ├─→ DHCP + ├─→ LAPS + └─→ Utilisateurs/Groups + ↓ + ├─→ GPO + ├─→ Serveur fichiers (FSRM, DFS-R) + ├─→ RDS + ├─→ Veeam + ├─→ GLPI (LDAP) + ├─→ Nextcloud (LDAP) + ├─→ VPN Client (RADIUS/NPS) + └─→ Déploiement postes (jointure domaine) + ↓ + Postes clients +``` + +### Ordre critique + +1. **Proxmox** : Nécessaire pour tout le reste +2. **pfSense** : Nécessaire pour la connectivité réseau +3. **Active Directory** : Nécessaire pour tous les services Windows et authentification +4. **DNS** : Nécessaire pour la résolution de noms +5. **DHCP** : Nécessaire pour l'attribution d'IPs automatiques +6. **Services dépendants** : Tous les autres services + +### Points d'attention + +- ⚠️ **Ne pas déployer de services avant AD** : Tous les services Windows nécessitent AD +- ⚠️ **VPN Site-to-Site avant RODC Lyon** : Le RODC doit pouvoir communiquer avec les DC Paris +- ⚠️ **DNS avant autres services** : La résolution de noms est critique +- ⚠️ **GPO avant déploiement postes** : Les postes doivent être configurés dès le déploiement + +--- + +## Durée totale estimée + +| Phase | Durée | Description | +|-------|-------|-------------| +| **Phase 1** | 1-2 jours | Préparation infrastructure | +| **Phase 2** | 1-2 jours | Réseau et sécurité | +| **Phase 3** | 2-3 jours | Active Directory | +| **Phase 4** | 3-4 jours | Services Windows | +| **Phase 5** | 2-3 jours | Services Infrastructure | +| **Phase 6** | 2-3 jours | Services applicatifs | +| **Phase 7** | 2-3 jours | Postes clients et finalisation | +| **TOTAL** | **13-19 jours** | **3-4 semaines** | + +--- + +*Document créé le : Novembre 2025* +*Version : 1.0* +*Projet : Smart-Motions - Plan de déploiement* + diff --git a/documents/PROCHAINES_ETAPES.md b/documents/PROCHAINES_ETAPES.md new file mode 100644 index 0000000..6550c54 --- /dev/null +++ b/documents/PROCHAINES_ETAPES.md @@ -0,0 +1,326 @@ +# Prochaines Etapes - Deploiement Smart-Motions + +**Date** : Decembre 2025 +**Statut** : En cours - Phase 2 (Reseau et Securite) + +--- + +## Etat actuel de l'infrastructure + +### Ce qui est deploye et operationnel + +| Composant | IP | Statut | Notes | +|-----------|-----|--------|-------| +| Proxmox Paris | 192.168.42.231 | OK | Bridges vmbr0-3 configures | +| PAR-FW1 (pfSense) | WAN: 192.168.254.10, LAN: 10.0.0.1, DMZ: 10.0.10.1 | OK | Config initiale terminee | +| PAR-ADMIN1 (Jump Host) | 192.168.42.225 + 10.0.0.151 | OK | Acces SSH operationnel | + +### Configuration pfSense terminee + +- Hostname et DNS publics (8.8.8.8, 1.1.1.1) - temporaire +- DHCP sur LAN (10.0.0.100-199) +- Regles firewall LAN (Internet, Lyon, DMZ) +- Regles firewall WAN (OpenVPN, NAT vers DMZ) +- Regles firewall DMZ (Internet, Block vers LAN) +- NAT Port Forwards (FTP, HTTP, HTTPS vers DMZ) +- CA "SmartMotions-CA" cree manuellement + +--- + +## Prochaines etapes par priorite + +### ETAPE 0 : Configuration DNS OVH + Cloudflare (OPTIONNEL MAIS RECOMMANDE) + +**Objectif** : Deleguer le DNS vers Cloudflare pendant que la propagation se fait (24-48h) + +**Pourquoi maintenant ?** +- La propagation prend du temps, autant la lancer tot +- Permet de tester le VPN avec un nom de domaine (`vpn.smartmotion.ovh`) +- Aucune dependance avec les autres etapes + +#### 0.1 Creer un compte Cloudflare + +1. Aller sur [dash.cloudflare.com](https://dash.cloudflare.com) +2. Creer un compte (plan Free) +3. Ajouter le site `smartmotion.ovh` +4. Noter les nameservers Cloudflare (ex: `alex.ns.cloudflare.com`, `vera.ns.cloudflare.com`) + +#### 0.2 Modifier les DNS chez OVH + +1. Aller sur [manager.ovh.com](https://www.ovh.com/manager/) +2. Web Cloud > Noms de domaine > `smartmotion.ovh` > Serveurs DNS +3. Remplacer les serveurs OVH par les serveurs Cloudflare +4. Sauvegarder + +#### 0.3 Creer les enregistrements de base dans Cloudflare + +| Type | Name | Content | Proxy | +|------|------|---------|-------| +| A | @ | 45.80.22.46 | ON | +| A | www | 45.80.22.46 | ON | +| A | vpn | 45.80.22.46 | OFF | + +**Duree** : 1-2h de configuration + 24-48h de propagation + +**Documentation complete** : `docs/services/DNS_OVH_CLOUDFLARE_SETUP.md` + +--- + +### ETAPE 1 : VPN Site-to-Site Paris-Lyon (Prerequis pour Lyon) + +**Objectif** : Etablir la connectivite entre les deux sites avant de deployer quoi que ce soit a Lyon. + +#### 1.1 Creer le certificat serveur OpenVPN (sur PAR-FW1) + +1. Aller dans **System > Cert Manager > Certificates** +2. Cliquer **+ Add/Sign** +3. Remplir : + - **Method** : Create an internal Certificate + - **Descriptive Name** : `PAR-FW1-OpenVPN-Server` + - **Certificate Authority** : SmartMotions-CA + - **Certificate Type** : Server Certificate + - **Key Length** : 2048 + - **Common Name** : `par-fw1.smartmotion.ovh` + - **Alternative Names** : `192.168.254.10` +4. **Save** + +#### 1.2 Configurer le serveur OpenVPN (sur PAR-FW1) + +1. Aller dans **VPN > OpenVPN > Servers** +2. Cliquer **+ Add** +3. Configuration : + - **Server mode** : Peer to Peer (SSL/TLS) + - **Protocol** : UDP on IPv4 only + - **Device mode** : tun + - **Interface** : WAN + - **Local port** : 1194 + - **TLS Configuration** : Activer, generer une cle TLS + - **Peer Certificate Authority** : SmartMotions-CA + - **Server Certificate** : PAR-FW1-OpenVPN-Server + - **Encryption Algorithm** : AES-256-GCM + - **IPv4 Tunnel Network** : `10.10.0.0/30` (petit reseau pour P2P) + - **IPv4 Remote Network(s)** : `10.1.0.0/24` (LAN Lyon) + - **Compression** : Omit +4. **Save** + +#### 1.3 Exporter la configuration pour Lyon + +1. Aller dans **System > Cert Manager > CAs** +2. Exporter le CA (icone export) - sauvegarder le fichier +3. Creer un certificat client pour LYO-FW1 : + - **System > Cert Manager > Certificates > Add** + - **Descriptive Name** : `LYO-FW1-OpenVPN-Client` + - **Certificate Type** : User Certificate +4. Noter la cle TLS partagee + +--- + +### ETAPE 2 : Deployer Lyon (LYO-FW1) + +**Prerequis** : VPN configure cote Paris + +#### 2.1 Deployer la VM LYO-FW1 avec Terraform + +```bash +cd "/home/syoul/IPSSI SMARTMOTION/terraform/environments/lyon" +tofu init +tofu plan +tofu apply +``` + +#### 2.2 Configuration manuelle initiale LYO-FW1 + +Via la console Proxmox : +1. Assigner les interfaces : + - vtnet0 = WAN (192.168.254.11/24, GW: 192.168.254.254) + - vtnet1 = LAN (10.1.0.1/24) +2. Activer SSH +3. Changer le mot de passe admin + +#### 2.3 Configurer le client OpenVPN (sur LYO-FW1) + +1. Importer le CA SmartMotions-CA +2. Importer le certificat LYO-FW1-OpenVPN-Client +3. Configurer le client OpenVPN vers 192.168.254.10:1194 +4. Verifier la connectivite : `ping 10.0.0.1` depuis LYO-FW1 + +--- + +### ETAPE 3 : Deployer les Domain Controllers Paris + +**Prerequis** : pfSense Paris operationnel + +#### 3.1 Deployer PAR-DC1 (10.0.0.11) + +```bash +# Ajouter au main.tf de Paris si pas deja fait +cd "/home/syoul/IPSSI SMARTMOTION/terraform/environments/paris" +tofu plan +tofu apply +``` + +Configuration Windows Server : +1. IP statique : 10.0.0.11/24, GW: 10.0.0.1, DNS: 127.0.0.1 +2. Installer le role AD DS +3. Promouvoir en DC : nouvelle foret `smartmotion.ovh` +4. Configurer DNS integre + +#### 3.2 Deployer PAR-DC2 (10.0.0.12) + +1. IP statique : 10.0.0.12/24, GW: 10.0.0.1, DNS: 10.0.0.11 +2. Joindre le domaine `smartmotion.ovh` +3. Promouvoir en DC additionnel + +#### 3.3 Mettre a jour DNS pfSense + +Une fois les DC operationnels : + +```bash +cd "/home/syoul/IPSSI SMARTMOTION/ansible" +ansible-playbook -i inventories/paris.yml playbooks/04b-configure-pfsense-paris-dns.yml +``` + +--- + +### ETAPE 4 : Deployer le serveur DMZ (PAR-FTP1) + +**Prerequis** : pfSense et NAT configures + +#### 4.1 Deployer PAR-FTP1 (10.0.10.70) + +```bash +cd "/home/syoul/IPSSI SMARTMOTION/terraform/environments/paris" +tofu plan +tofu apply +``` + +#### 4.2 Configurer le serveur + +1. IP statique : 10.0.10.70/24, GW: 10.0.10.1, DNS: 8.8.8.8 +2. Installer vsftpd (FTP) +3. Installer Apache/Nginx (Extranet) +4. Tester l'acces depuis Internet via NAT + +--- + +## Ordre de deploiement recommande + +``` +Phase actuelle : Phase 2 (Reseau) - EN COURS + | + v ++--------------------------------------------------+ +| ETAPE 1 : VPN Site-to-Site | +| - Certificat serveur OpenVPN | +| - Serveur OpenVPN sur PAR-FW1 | +| Duree estimee : 1-2 heures | ++--------------------------------------------------+ + | + v ++--------------------------------------------------+ +| ETAPE 2 : Deploiement Lyon | +| - Terraform LYO-FW1 | +| - Config manuelle + Client OpenVPN | +| - Test connectivite VPN | +| Duree estimee : 2-3 heures | ++--------------------------------------------------+ + | + v ++--------------------------------------------------+ +| ETAPE 3 : Domain Controllers Paris | +| - PAR-DC1 (DC primaire, DNS, DHCP) | +| - PAR-DC2 (DC secondaire) | +| - Mise a jour DNS pfSense | +| Duree estimee : 1 jour | ++--------------------------------------------------+ + | + v ++--------------------------------------------------+ +| ETAPE 4 : Serveur DMZ | +| - PAR-FTP1 (FTP + Extranet) | +| - Tests NAT depuis Internet | +| Duree estimee : 2-3 heures | ++--------------------------------------------------+ + | + v ++--------------------------------------------------+ +| ETAPE 5 : RODC Lyon (apres VPN + DC) | +| - LYO-RODC1 (RODC + DNS cache + DHCP) | +| Duree estimee : 3-4 heures | ++--------------------------------------------------+ + | + v + [Suite Phase 4 : Services Windows] +``` + +--- + +## Commandes utiles + +### Acces SSH aux VMs + +```bash +# Via le jump host PAR-ADMIN1 +ssh -J debian@192.168.42.225 admin@10.0.0.1 # pfSense Paris +ssh -J debian@192.168.42.225 debian@10.0.10.70 # PAR-FTP1 (DMZ) +``` + +### Terraform + +```bash +cd "/home/syoul/IPSSI SMARTMOTION/terraform/environments/paris" +tofu plan # Voir les changements +tofu apply # Appliquer +tofu destroy # Supprimer (attention!) +``` + +### Ansible + +```bash +cd "/home/syoul/IPSSI SMARTMOTION/ansible" + +# Installer les collections +ansible-galaxy collection install -r requirements.yml -p ./collections + +# Lancer un playbook +ansible-playbook -i inventories/paris.yml playbooks/04a-configure-pfsense-paris-initial.yml + +# Tester la connectivite +ansible -i inventories/paris.yml paris_firewalls -m ping +``` + +--- + +## Points d'attention + +### VPN Site-to-Site +- Le tunnel doit etre etabli AVANT de deployer quoi que ce soit a Lyon +- Les routes doivent etre configurees des deux cotes +- Tester avec un ping avant de continuer + +### Domain Controllers +- PAR-DC1 doit etre operationnel avant PAR-DC2 +- Attendre la replication AD avant de deployer le RODC +- Ne pas oublier de mettre a jour les DNS sur pfSense + +### DMZ +- Le serveur DMZ ne doit PAS avoir acces au LAN +- Tester le blocage : depuis PAR-FTP1, `ping 10.0.0.11` doit echouer +- Tester le NAT depuis une IP externe + +--- + +## Ressources + +- Architecture : `docs/architecture/architecture.md` +- Plan complet : `docs/deployment/PLAN_DEPLOIEMENT_ORDRE.md` +- Config pfSense : `docs/pfsense/PFSENSE_SETUP.md` +- Config VPN : `docs/services/VPN_CLIENT_RADIUS.md` +- DMZ : `docs/services/DMZ_FTP_EXTRANET.md` +- **DNS OVH + Cloudflare** : `docs/services/DNS_OVH_CLOUDFLARE_SETUP.md` +- **NAT Freebox + OpenWRT** : `docs/network/NAT_FREEBOX_OPENWRT.md` + +--- + +*Document cree le : Decembre 2025* +*Derniere mise a jour : 13 Decembre 2025* diff --git a/md_to_print.sh b/md_to_print.sh new file mode 100755 index 0000000..ded9efd --- /dev/null +++ b/md_to_print.sh @@ -0,0 +1,670 @@ +#!/bin/bash + +# Script automatique : Markdown → PDF → Prévisualisation → Impression +# Usage: ./md_to_print.sh fichier.md [options] + +set -euo pipefail + +# Version +VERSION="1.0.0" + +# Codes de retour +EXIT_SUCCESS=0 +EXIT_GENERAL=1 +EXIT_FILE_NOT_FOUND=2 +EXIT_DEPS_MISSING=3 +EXIT_PDF_CONVERSION=4 +EXIT_PRINT_ERROR=5 +EXIT_CONFIG_ERROR=6 +EXIT_DOCKER_ERROR=7 +EXIT_PERMISSIONS=8 +EXIT_INVALID_ARG=9 +EXIT_PRINTER_UNAVAILABLE=10 + +# Couleurs pour les messages +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Variables par défaut +PREVIEW=false +PRINTER="" +COPIES=1 +PAGES="" +ORIENTATION="portrait" +SIZE="A4" +QUALITY="normal" +COLOR=false +DUPLEX="none" +INSTALL_DEPS=false +KEEP_PDF=false +CONFIG_FILE="" +VERBOSE=false +LOG_FILE="" +LOG_LEVEL="INFO" + +# Répertoires +OUTPUT_DIR="./output" +LOG_DIR="./logs" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Fonction de logging +log() { + local level="$1" + shift + local message="$*" + local timestamp=$(date '+%Y-%m-%d %H:%M:%S') + local log_entry="[${timestamp}] [${level}] ${message}" + + case "$level" in + DEBUG) + if [ "$VERBOSE" = true ] || [ "$LOG_LEVEL" = "DEBUG" ]; then + echo -e "${BLUE}${log_entry}${NC}" >&2 + fi + ;; + INFO) + echo -e "${GREEN}${log_entry}${NC}" >&2 + ;; + WARN) + echo -e "${YELLOW}${log_entry}${NC}" >&2 + ;; + ERROR) + echo -e "${RED}${log_entry}${NC}" >&2 + ;; + esac + + if [ -n "$LOG_FILE" ] && [ -f "$LOG_FILE" ]; then + echo "${log_entry}" >> "$LOG_FILE" + fi +} + +# Fonction d'aide +show_help() { + cat << EOF +MD_to_Print v${VERSION} - Conversion Markdown → PDF → Impression + +Usage: $0 fichier.md [OPTIONS] + +OPTIONS: + -p, --preview Prévisualiser le PDF avant impression + -P, --printer NOM Spécifier l'imprimante + -c, --copies N Nombre de copies (défaut: 1) + -r, --pages RANGE Pages à imprimer (ex: 1-3,5,7-9) + -o, --orientation DIR Orientation: portrait ou landscape (défaut: portrait) + -s, --size SIZE Taille: A4, A3, Letter, etc. (défaut: A4) + -q, --quality QUALITY Qualité: draft, normal, high (défaut: normal) + -C, --color Impression en couleur + -d, --duplex MODE Mode recto-verso: none, simplex, duplex (défaut: none) + -i, --install-deps Installer les dépendances automatiquement + -k, --keep-pdf Conserver le fichier PDF après impression + --config FILE Fichier de configuration + -v, --verbose Mode verbeux (logging DEBUG) + -l, --log FILE Fichier de log + -h, --help Afficher cette aide + --version Afficher la version + +EXEMPLES: + $0 document.md --preview + $0 document.md --printer HP_LaserJet --copies 2 --color + $0 document.md --pages 1-5 --orientation landscape + $0 document.md --duplex duplex --quality high --config myconfig.conf + +CONFIGURATION: + Le fichier de configuration utilise le format INI avec les sections: + [default], [paths], [logging] + Voir config.example.conf pour un exemple. + +CODES DE RETOUR: + 0 : Succès + 1 : Erreur générale + 2 : Fichier introuvable + 3 : Dépendances manquantes + 4 : Erreur conversion PDF + 5 : Erreur impression + 6 : Erreur configuration + 7 : Erreur Docker + 8 : Permissions insuffisantes + 9 : Argument invalide + 10 : Imprimante non disponible +EOF +} + +# Fonction de chargement de configuration +load_config() { + local config_path="$1" + + if [ ! -f "$config_path" ]; then + log ERROR "Fichier de configuration introuvable: $config_path" + return $EXIT_CONFIG_ERROR + fi + + log INFO "Chargement de la configuration depuis: $config_path" + + while IFS='=' read -r key value || [ -n "$key" ]; do + # Ignorer les commentaires et lignes vides + [[ "$key" =~ ^[[:space:]]*# ]] && continue + [[ -z "${key// }" ]] && continue + + # Supprimer les espaces + key=$(echo "$key" | tr -d '[:space:]') + value=$(echo "$value" | tr -d '[:space:]') + + case "$key" in + printer) + [ -z "$PRINTER" ] && PRINTER="$value" + ;; + copies) + [ "$COPIES" = 1 ] && COPIES="$value" + ;; + orientation) + [ "$ORIENTATION" = "portrait" ] && ORIENTATION="$value" + ;; + size) + [ "$SIZE" = "A4" ] && SIZE="$value" + ;; + quality) + [ "$QUALITY" = "normal" ] && QUALITY="$value" + ;; + color) + [ "$COLOR" = false ] && COLOR=$( [ "$value" = "true" ] && echo true || echo false ) + ;; + duplex) + [ "$DUPLEX" = "none" ] && DUPLEX="$value" + ;; + preview) + [ "$PREVIEW" = false ] && PREVIEW=$( [ "$value" = "true" ] && echo true || echo false ) + ;; + keep_pdf) + [ "$KEEP_PDF" = false ] && KEEP_PDF=$( [ "$value" = "true" ] && echo true || echo false ) + ;; + output_dir) + OUTPUT_DIR="$value" + ;; + log_dir) + LOG_DIR="$value" + ;; + level) + LOG_LEVEL="$value" + ;; + file) + [ -z "$LOG_FILE" ] && LOG_FILE="$LOG_DIR/$value" + ;; + verbose) + [ "$VERBOSE" = false ] && VERBOSE=$( [ "$value" = "true" ] && echo true || echo false ) + ;; + esac + done < <(grep -v '^\[' "$config_path" | grep -v '^[[:space:]]*$') + + log INFO "Configuration chargée avec succès" + return $EXIT_SUCCESS +} + +# Fonction d'installation des dépendances +install_dependencies() { + log INFO "Vérification et installation des dépendances..." + + if ! command -v apt-get &> /dev/null; then + log ERROR "apt-get non disponible. Installation manuelle requise." + return $EXIT_DEPS_MISSING + fi + + log INFO "Mise à jour de la liste des paquets..." + if ! sudo apt-get update -qq; then + log ERROR "Échec de la mise à jour des paquets" + return $EXIT_DEPS_MISSING + fi + + local deps_to_install=() + + if ! command -v pandoc &> /dev/null; then + deps_to_install+=("pandoc") + fi + + if ! command -v pdflatex &> /dev/null; then + deps_to_install+=("texlive-latex-base" "texlive-fonts-recommended" "texlive-latex-extra") + fi + + if ! command -v lp &> /dev/null; then + deps_to_install+=("cups") + fi + + if [ ${#deps_to_install[@]} -gt 0 ]; then + log INFO "Installation: ${deps_to_install[*]}" + if ! sudo apt-get install -y "${deps_to_install[@]}"; then + log ERROR "Échec de l'installation des dépendances" + return $EXIT_DEPS_MISSING + fi + log INFO "Dépendances installées avec succès" + else + log INFO "Toutes les dépendances sont déjà installées" + fi + + return $EXIT_SUCCESS +} + +# Fonction de vérification des dépendances +check_dependencies() { + local missing_deps=() + + if ! command -v pandoc &> /dev/null; then + missing_deps+=("pandoc") + fi + + if ! command -v pdflatex &> /dev/null; then + missing_deps+=("texlive-latex-base") + fi + + if ! command -v lp &> /dev/null; then + missing_deps+=("cups") + fi + + if [ ${#missing_deps[@]} -gt 0 ]; then + log ERROR "Dépendances manquantes: ${missing_deps[*]}" + log INFO "Utilisez l'option --install-deps pour installer automatiquement" + return $EXIT_DEPS_MISSING + fi + + return $EXIT_SUCCESS +} + +# Fonction de prévisualisation +preview_pdf() { + local pdf_file="$1" + + if [ ! -f "$pdf_file" ]; then + log ERROR "Fichier PDF introuvable pour prévisualisation: $pdf_file" + return $EXIT_FILE_NOT_FOUND + fi + + log INFO "Ouverture de la prévisualisation..." + + if command -v evince &> /dev/null; then + evince "$pdf_file" 2>/dev/null & + log DEBUG "Utilisation de evince pour la prévisualisation" + elif command -v okular &> /dev/null; then + okular "$pdf_file" 2>/dev/null & + log DEBUG "Utilisation de okular pour la prévisualisation" + elif command -v xdg-open &> /dev/null; then + xdg-open "$pdf_file" 2>/dev/null & + log DEBUG "Utilisation de xdg-open pour la prévisualisation" + else + log WARN "Aucun visualiseur PDF trouvé. Installation recommandée: evince ou okular" + return $EXIT_DEPS_MISSING + fi + + log INFO "Appuyez sur Entrée pour continuer avec l'impression..." + read -r + return $EXIT_SUCCESS +} + +# Fonction de liste des imprimantes +list_printers() { + log INFO "Imprimantes disponibles:" + if command -v lpstat &> /dev/null; then + lpstat -p 2>/dev/null | grep -E "^printer" | awk '{print " - " $2}' || log WARN "Aucune imprimante trouvée" + else + log WARN "lpstat non disponible, impossible de lister les imprimantes" + fi +} + +# Fonction de validation de l'imprimante +check_printer() { + local printer_name="$1" + + if [ -z "$printer_name" ]; then + return $EXIT_SUCCESS + fi + + if ! command -v lpstat &> /dev/null; then + log WARN "lpstat non disponible, impossible de vérifier l'imprimante" + return $EXIT_SUCCESS + fi + + if lpstat -p "$printer_name" &>/dev/null; then + log DEBUG "Imprimante '$printer_name' disponible" + return $EXIT_SUCCESS + else + log WARN "Imprimante '$printer_name' non disponible" + list_printers + return $EXIT_PRINTER_UNAVAILABLE + fi +} + +# Parsing des arguments +MD_FILE="" +ARGS=("$@") + +while [[ $# -gt 0 ]]; do + case $1 in + -p|--preview) + PREVIEW=true + shift + ;; + -P|--printer) + if [ -z "${2:-}" ]; then + log ERROR "Option --printer nécessite un argument" + exit $EXIT_INVALID_ARG + fi + PRINTER="$2" + shift 2 + ;; + -c|--copies) + if [ -z "${2:-}" ]; then + log ERROR "Option --copies nécessite un argument" + exit $EXIT_INVALID_ARG + fi + COPIES="$2" + shift 2 + ;; + -r|--pages) + if [ -z "${2:-}" ]; then + log ERROR "Option --pages nécessite un argument" + exit $EXIT_INVALID_ARG + fi + PAGES="$2" + shift 2 + ;; + -o|--orientation) + if [ -z "${2:-}" ]; then + log ERROR "Option --orientation nécessite un argument" + exit $EXIT_INVALID_ARG + fi + ORIENTATION="$2" + shift 2 + ;; + -s|--size) + if [ -z "${2:-}" ]; then + log ERROR "Option --size nécessite un argument" + exit $EXIT_INVALID_ARG + fi + SIZE="$2" + shift 2 + ;; + -q|--quality) + if [ -z "${2:-}" ]; then + log ERROR "Option --quality nécessite un argument" + exit $EXIT_INVALID_ARG + fi + QUALITY="$2" + shift 2 + ;; + -C|--color) + COLOR=true + shift + ;; + -d|--duplex) + if [ -z "${2:-}" ]; then + log ERROR "Option --duplex nécessite un argument" + exit $EXIT_INVALID_ARG + fi + DUPLEX="$2" + shift 2 + ;; + -i|--install-deps) + INSTALL_DEPS=true + shift + ;; + -k|--keep-pdf) + KEEP_PDF=true + shift + ;; + --config) + if [ -z "${2:-}" ]; then + log ERROR "Option --config nécessite un argument" + exit $EXIT_INVALID_ARG + fi + CONFIG_FILE="$2" + shift 2 + ;; + -v|--verbose) + VERBOSE=true + LOG_LEVEL="DEBUG" + shift + ;; + -l|--log) + if [ -z "${2:-}" ]; then + log ERROR "Option --log nécessite un argument" + exit $EXIT_INVALID_ARG + fi + LOG_FILE="$2" + shift 2 + ;; + -h|--help) + show_help + exit $EXIT_SUCCESS + ;; + --version) + echo "MD_to_Print v${VERSION}" + exit $EXIT_SUCCESS + ;; + -*) + log ERROR "Option inconnue: $1" + show_help + exit $EXIT_INVALID_ARG + ;; + *) + if [ -z "$MD_FILE" ]; then + MD_FILE="$1" + else + log ERROR "Trop de fichiers spécifiés: $MD_FILE et $1" + exit $EXIT_INVALID_ARG + fi + shift + ;; + esac +done + +# Vérification du fichier markdown +if [ -z "$MD_FILE" ]; then + log ERROR "Aucun fichier markdown spécifié" + show_help + exit $EXIT_INVALID_ARG +fi + +# Résolution du chemin absolu +if [[ "$MD_FILE" != /* ]]; then + MD_FILE="$(realpath "$MD_FILE" 2>/dev/null || echo "$MD_FILE")" +fi + +if [ ! -f "$MD_FILE" ]; then + log ERROR "Le fichier '$MD_FILE' n'existe pas" + exit $EXIT_FILE_NOT_FOUND +fi + +# Vérification des permissions de lecture +if [ ! -r "$MD_FILE" ]; then + log ERROR "Permission de lecture refusée pour '$MD_FILE'" + exit $EXIT_PERMISSIONS +fi + +# Création des répertoires nécessaires +mkdir -p "$OUTPUT_DIR" "$LOG_DIR" + +# Initialisation du fichier de log si spécifié +if [ -n "$LOG_FILE" ]; then + mkdir -p "$(dirname "$LOG_FILE")" + touch "$LOG_FILE" +fi + +# Chargement de la configuration si spécifiée +if [ -n "$CONFIG_FILE" ]; then + if ! load_config "$CONFIG_FILE"; then + exit $EXIT_CONFIG_ERROR + fi +elif [ -f "$SCRIPT_DIR/config.conf" ]; then + log DEBUG "Chargement de la configuration par défaut: $SCRIPT_DIR/config.conf" + load_config "$SCRIPT_DIR/config.conf" || true +fi + +# Installation des dépendances si demandée +if [ "$INSTALL_DEPS" = true ]; then + if ! install_dependencies; then + exit $EXIT_DEPS_MISSING + fi +fi + +# Vérification des dépendances +if ! check_dependencies; then + exit $EXIT_DEPS_MISSING +fi + +# Génération du nom du fichier PDF +MD_BASENAME=$(basename "$MD_FILE" .md) +PDF_FILE="$OUTPUT_DIR/${MD_BASENAME}.pdf" + +log INFO "=== Conversion Markdown → PDF ===" +log INFO "Fichier source: $MD_FILE" +log INFO "Fichier PDF: $PDF_FILE" + +# Conversion Markdown → PDF avec options +# Détection du moteur PDF disponible (xelatex gère mieux Unicode) +PDF_ENGINE="pdflatex" +if command -v xelatex &> /dev/null; then + PDF_ENGINE="xelatex" + log DEBUG "Utilisation de xelatex pour meilleure gestion Unicode" +fi + +PANDOC_OPTS=( + "$MD_FILE" + -o "$PDF_FILE" + --pdf-engine="$PDF_ENGINE" + -V geometry:margin=2cm + -V fontsize=11pt + -V documentclass=article + -V papersize="$SIZE" +) + +# Options spécifiques pour xelatex (meilleure gestion Unicode) +if [ "$PDF_ENGINE" = "xelatex" ]; then + PANDOC_OPTS+=( + -V mainfont="DejaVu Sans" + -V monofont="DejaVu Sans Mono" + ) +fi + +if [ "$ORIENTATION" = "landscape" ]; then + PANDOC_OPTS+=(-V geometry:landscape) +fi + +log DEBUG "Exécution: pandoc ${PANDOC_OPTS[*]}" + +if ! pandoc "${PANDOC_OPTS[@]}" 2>&1 | while IFS= read -r line; do log DEBUG "$line"; done; then + log ERROR "Erreur lors de la conversion en PDF" + exit $EXIT_PDF_CONVERSION +fi + +if [ ! -f "$PDF_FILE" ]; then + log ERROR "Le fichier PDF n'a pas été créé" + exit $EXIT_PDF_CONVERSION +fi + +log INFO "PDF créé avec succès: $PDF_FILE" + +# Vérification de l'imprimante si spécifiée +if [ -n "$PRINTER" ]; then + if ! check_printer "$PRINTER"; then + log WARN "Tentative d'utilisation de l'imprimante par défaut" + PRINTER="" + fi +fi + +# Prévisualisation si demandée +if [ "$PREVIEW" = true ]; then + if ! preview_pdf "$PDF_FILE"; then + log WARN "Échec de la prévisualisation, continuation avec l'impression" + fi +fi + +# Préparation des options d'impression +LP_OPTS=() + +if [ -n "$PRINTER" ]; then + LP_OPTS+=(-d "$PRINTER") +else + log INFO "Utilisation de l'imprimante par défaut" + list_printers +fi + +LP_OPTS+=(-n "$COPIES") + +if [ -n "$PAGES" ]; then + LP_OPTS+=(-o page-ranges="$PAGES") +fi + +if [ "$ORIENTATION" = "landscape" ]; then + LP_OPTS+=(-o orientation-requested=4) +fi + +LP_OPTS+=(-o media="$SIZE") + +case "$QUALITY" in + draft) + LP_OPTS+=(-o print-quality=3) + ;; + high) + LP_OPTS+=(-o print-quality=5) + ;; + *) + LP_OPTS+=(-o print-quality=4) + ;; +esac + +if [ "$COLOR" = true ]; then + LP_OPTS+=(-o ColorMode=Color) +else + LP_OPTS+=(-o ColorMode=Monochrome) +fi + +case "$DUPLEX" in + simplex) + LP_OPTS+=(-o sides=one-sided) + ;; + duplex) + LP_OPTS+=(-o sides=two-sided-long-edge) + ;; + *) + LP_OPTS+=(-o sides=one-sided) + ;; +esac + +# Impression +log INFO "=== Impression ===" +log INFO "Options:" +log INFO " - Copies: $COPIES" +log INFO " - Taille: $SIZE" +log INFO " - Orientation: $ORIENTATION" +log INFO " - Qualité: $QUALITY" +log INFO " - Couleur: $([ "$COLOR" = true ] && echo "Oui" || echo "Non")" +log INFO " - Recto-verso: $DUPLEX" +[ -n "$PAGES" ] && log INFO " - Pages: $PAGES" +[ -n "$PRINTER" ] && log INFO " - Imprimante: $PRINTER" + +log DEBUG "Exécution: lp ${LP_OPTS[*]} $PDF_FILE" + +if ! lp "${LP_OPTS[@]}" "$PDF_FILE" 2>&1 | while IFS= read -r line; do log DEBUG "$line"; done; then + log ERROR "Erreur lors de l'impression" + log INFO "Le fichier PDF a été conservé: $PDF_FILE" + exit $EXIT_PRINT_ERROR +fi + +log INFO "Impression lancée avec succès!" + +# Gestion du fichier PDF +if [ "$KEEP_PDF" = false ]; then + read -p "Supprimer le fichier PDF temporaire? (o/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Oo]$ ]]; then + rm "$PDF_FILE" + log INFO "Fichier PDF supprimé" + else + log INFO "Fichier PDF conservé: $PDF_FILE" + fi +else + log INFO "Fichier PDF conservé: $PDF_FILE" +fi + +log INFO "=== Opération terminée avec succès ===" +exit $EXIT_SUCCESS +