[{"data":1,"prerenderedAt":209},["ShallowReactive",2],{"seo-verification":3,"blog-installer-gitlab-ce-vps-ma-fr":6,"promo-bar-likely":208},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-installer-gitlab-ce-vps-ma-fr",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":29,"intro":32,"sections":33,"ctaTitle":151,"ctaBody":152,"ctaButton":153,"ctaUrl":154,"relatedPosts":155},235,"installer-gitlab-ce-vps",{"fr":10,"en":12,"ar":13,"es":14},"install-gitlab-ce-on-a-vps-complete-guide","تثبيت-gitlab-ce-على-vps-دليل-شامل","instalar-gitlab-ce-en-un-vps-guia-completa","Installer GitLab CE sur VPS : guide complet","Déployez GitLab CE sur VPS avec Docker Compose. Inclut le patch CVE-2026-90970 (CVSS 9.9) : AI Gateway RCE, versions vulnérables et commandes de mise à jour.",18,7,false,"2026-08-07T00:00:00+00:00","2026-10-20T23:18:07+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},3,"Déploiement","deploiement","bg-success\u002F10 text-success",[28],{"id":23,"name":24,"slug":25,"color":26,"icon":25},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Finstaller-gitlab-ce-vps-poster.svg","GitHub et Bitbucket hébergent vos dépôts, mais ils imposent leurs règles : minutes de CI contingentées, propriété du code incertaine, prix qui grimpent avec l'équipe. GitLab CE (Community Edition, licence MIT\u002FEE Core) réunit sur un seul serveur une forge git complète, un moteur CI\u002FCD sans limite de minutes, un registry Docker privé et des wikis — sans abonnement SaaS. Ce guide vous montre comment l'installer en moins de trente minutes sur un VPS avec Docker Compose, configurer le SMTP, connecter un runner et éviter les pièges classiques : GITLAB_OMNIBUS_CONFIG mal configuré, SSL qui expire faute d'ACME activé, runner non enregistré.",[34,38,50,53,84,87,90,93,96,99,102,105,107,110,148],{"type":35,"title":36,"body":37},"h2","Pourquoi GitLab CE plutôt que GitHub ou Bitbucket","GitHub et Bitbucket sont des services gérés : pratiques au démarrage, mais leur modèle tarifaire évolue avec la taille de l'équipe, les minutes CI sont comptées sur les offres gratuites, et votre code est hébergé sur une infrastructure tierce. GitLab CE renverse cette équation : vous déployez la forge sur votre VPS, vous gardez la maîtrise totale du code et des données, et la CI\u002FCD est incluse sans quota de minutes imposé par un tiers — seule la capacité de votre machine limite le nombre de jobs parallèles. Pour une agence ou une équipe de développeurs qui facture au client ou traite des données sensibles, ce contrôle est souvent non négociable. GitLab CE est aujourd'hui l'une des forges git les plus déployées en self-hosted : sa base de code est publique, son noyau est libre, et ses dix ans d'existence lui ont valu une communauté de contributeurs qui maintient l'outil actif entre deux releases Enterprise.",{"type":39,"title":40,"items":41},"ul","Ce que GitLab CE inclut d'emblée",[42,43,44,45,46,47,48,49],"**Forge git complète** : dépôts privés et publics, merge requests, code review, protection de branches et CODEOWNERS.","**CI\u002FCD intégrée** sans limite de minutes imposée : pipelines YAML (`.gitlab-ci.yml`), environments, deploy tokens et artifacts.","**Registry Docker privé** hébergé sur votre domaine : `docker pull git.votredomaine.com\u002Fgroupe\u002Fimage:tag` sans compte Docker Hub.","**Wikis et pages** par projet et par groupe, avec rendu Markdown complet.","**Gestion d'issues et milestones** : tableau kanban, labels, itérations et burndown chart inclus.","**Runners parallèles** : enregistrez autant de runners que vous voulez sur votre infra ou vos CI workers.","**Webhooks** pour notifier un outil tiers (Slack, PagerDuty, votre serveur de déploiement) à chaque push ou merge.","**RBAC granulaire** avec cinq niveaux d'accès (Guest, Reporter, Developer, Maintainer, Owner) et support LDAP\u002FSAML optionnel.",{"type":35,"title":51,"body":52},"Prérequis : ce qu'il faut avant de commencer","GitLab CE est gourmand en mémoire — c'est l'un de ses inconvénients les plus cités par rapport à Forgejo ou Gitea. Prévoyez **4 Go de RAM minimum** pour un usage léger (moins de dix utilisateurs actifs) ; **8 Go sont recommandés** dès que vous ajoutez des runners sur la même machine ou que vous activez le registry Docker. En dessous de 4 Go, Puma et Sidekiq se disputent la mémoire et GitLab répond en 502 sous charge. Côté disque, comptez au moins 20 Go pour l'installation et les dépôts initiaux — prévoir 50 Go si vous comptez stocker des images Docker dans le registry. Vous avez également besoin : d'un nom de domaine pointant vers l'IP du VPS (par exemple `git.votredomaine.com`) pour que Let's Encrypt puisse émettre le certificat TLS ; des ports 80, 443 et 22 ouverts dans votre pare-feu (le port 22 est utilisé par GitLab pour les push SSH — si votre daemon SSH système écoute aussi sur 22, vous devrez le déplacer sur un autre port) ; de Docker Engine et du plugin Compose v2 installés (`docker compose version` doit répondre `v2.x`).",{"type":54,"title":55,"steps":56},"steps","De l'installation à votre premier projet",[57,60,63,66,69,72,75,78,81],{"title":58,"body":59},"Créer l'arborescence de dossiers","Créez un dossier dédié et les trois volumes persistants que GitLab utilise : `mkdir -p \u002Fopt\u002Fgitlab\u002F{config,logs,data}`. Ces dossiers seront montés dans le conteneur ; sans eux, la configuration et les dépôts disparaissent à chaque `docker compose down`.",{"title":61,"body":62},"Écrire le fichier docker-compose.yml","Créez `\u002Fopt\u002Fgitlab\u002Fdocker-compose.yml`. La clé `GITLAB_OMNIBUS_CONFIG` concentre toute la configuration spécifique à votre instance — remplacez `git.votredomaine.com` par votre domaine réel. Définissez le service gitlab avec l'image `gitlab\u002Fgitlab-ce:17.2.1-ce.0`, `restart: unless-stopped`, le hostname, les variables d'environnement (dont `GITLAB_OMNIBUS_CONFIG` contenant `external_url`, la configuration Let's Encrypt et les paramètres SMTP), les ports 80, 443 et 22, les volumes `\u002Fopt\u002Fgitlab\u002Fconfig:\u002Fetc\u002Fgitlab`, `\u002Fopt\u002Fgitlab\u002Flogs:\u002Fvar\u002Flog\u002Fgitlab` et `\u002Fopt\u002Fgitlab\u002Fdata:\u002Fvar\u002Fopt\u002Fgitlab`, `shm_size: 256m` et `env_file: .env`. **Note importante** : la valeur de `external_url` détermine si GitLab génère des URLs en `http:\u002F\u002F` ou en `https:\u002F\u002F`, et si Let's Encrypt est tenté. Elle doit correspondre exactement au nom de domaine résolvable depuis Internet — une valeur incorrecte est la première cause d'erreur d'accès.",{"title":64,"body":65},"Renseigner GITLAB_OMNIBUS_CONFIG","Dans `GITLAB_OMNIBUS_CONFIG`, définissez au minimum : `external_url 'https:\u002F\u002Fgit.votredomaine.com'` ; `letsencrypt['enable'] = true` avec `letsencrypt['contact_emails'] = ['admin@votredomaine.com']` ; les paramètres SMTP — `gitlab_rails['smtp_enable'] = true`, `gitlab_rails['smtp_address']`, `gitlab_rails['smtp_port'] = 587`, `gitlab_rails['smtp_user_name']`, `gitlab_rails['smtp_password'] = ENV['GITLAB_SMTP_PASSWORD']`, `gitlab_rails['smtp_authentication'] = 'login'`, `gitlab_rails['smtp_enable_starttls_auto'] = true`, `gitlab_rails['gitlab_email_from']` ; et si vous activez le registry : `registry_external_url 'https:\u002F\u002Fregistry.votredomaine.com'`. Toutes ces lignes doivent être **dans** le bloc `GITLAB_OMNIBUS_CONFIG` et non définies comme variables d'environnement séparées — une clé hors du bloc est silencieusement ignorée.",{"title":67,"body":68},"Créer le fichier .env pour les secrets","Créez `\u002Fopt\u002Fgitlab\u002F.env` et restreignez ses permissions : `touch \u002Fopt\u002Fgitlab\u002F.env && chmod 600 \u002Fopt\u002Fgitlab\u002F.env`. Ajoutez-y vos variables sensibles — au minimum `GITLAB_SMTP_PASSWORD=votre_mot_de_passe_smtp`. Ne mettez jamais de mot de passe en clair dans le fichier Compose : il sera versionné ou partagé. Ajoutez `.env` à votre `.gitignore` si vous versionnez la configuration.",{"title":70,"body":71},"Démarrer GitLab et attendre l'initialisation","Lancez la stack : `docker compose -f \u002Fopt\u002Fgitlab\u002Fdocker-compose.yml up -d`. Le premier démarrage est long : GitLab initialise la base de données, compile les assets et configure Nginx et Puma. **Attendez environ 5 minutes** avant d'accéder à l'interface web. Suivez l'avancement avec `docker compose -f \u002Fopt\u002Fgitlab\u002Fdocker-compose.yml logs -f gitlab` et attendez le message `gitlab Reconfigured!`.",{"title":73,"body":74},"Récupérer le mot de passe root initial","À la première initialisation, GitLab génère un mot de passe temporaire pour le compte `root`. Récupérez-le avec : `docker exec -it gitlab-gitlab-1 grep 'Password:' \u002Fetc\u002Fgitlab\u002Finitial_root_password`. Ce fichier est **supprimé automatiquement 24 heures après** le premier démarrage — notez le mot de passe immédiatement.",{"title":76,"body":77},"Se connecter, changer le mot de passe et désactiver l'inscription ouverte","Ouvrez `https:\u002F\u002Fgit.votredomaine.com` dans votre navigateur. Connectez-vous avec `root` et le mot de passe récupéré. Rendez-vous dans **User Settings → Password** et définissez un nouveau mot de passe fort. Créez ensuite votre premier utilisateur non-root : **Admin Area → Users → New User**. Si GitLab est à usage interne, désactivez l'inscription publique : **Admin Area → Settings → General → Sign-up restrictions → décochez « Sign-up enabled »**.",{"title":79,"body":80},"Enregistrer un GitLab Runner","Les pipelines CI\u002FCD nécessitent au moins un runner. Installez `gitlab-runner` sur le VPS ou une machine dédiée (binaire téléchargeable depuis la page officielle GitLab Runner). Récupérez le token d'enregistrement dans **Admin Area → Runners** (runner partagé) ou dans **Settings → CI\u002FCD → Runners** de votre projet. Enregistrez le runner avec : `gitlab-runner register --url https:\u002F\u002Fgit.votredomaine.com --registration-token VOTRE_TOKEN --executor docker --docker-image alpine:latest`. Une fois enregistré, le runner apparaît en vert dans l'interface et vos pipelines `.gitlab-ci.yml` peuvent s'exécuter.",{"title":82,"body":83},"Vérifier l'envoi d'emails","Testez la configuration SMTP depuis la console Rails de GitLab : `docker exec -it gitlab-gitlab-1 gitlab-rails console` puis tapez `Notify.test_email('votre@email.com', 'Test GitLab', 'Bonjour').deliver_now`. Si le mail n'arrive pas, vérifiez que les clés `smtp_*` sont bien à l'intérieur de `GITLAB_OMNIBUS_CONFIG` et consultez les logs : `docker exec -it gitlab-gitlab-1 tail -f \u002Fvar\u002Flog\u002Fgitlab\u002Fgitlab-rails\u002Fproduction.log`.",{"type":85,"body":86},"tip","**Sauvegardes automatiques.** GitLab embarque une commande de sauvegarde complète (dépôts, base de données, uploads) : `docker exec -t gitlab-gitlab-1 gitlab-backup create`. Planifiez-la dans `crontab -e` avec la ligne `0 3 * * * docker exec -t gitlab-gitlab-1 gitlab-backup create CRON=1`. Les archives sont créées dans `\u002Fvar\u002Fopt\u002Fgitlab\u002Fbackups` (monté dans `\u002Fopt\u002Fgitlab\u002Fdata\u002Fbackups` sur l'hôte) et versionnées par timestamp. Synchronisez ce dossier vers un stockage externe (S3, rclone) — une sauvegarde locale n'est pas une sauvegarde.",{"type":35,"title":88,"body":89},"Configurer le runner Docker et écrire votre premier pipeline CI\u002FCD","L'executor Docker est le choix recommandé pour la plupart des projets : chaque job s'exécute dans un conteneur isolé, sans polluer l'environnement du runner. Après l'enregistrement du runner (étape 8 ci-dessus), son fichier de configuration `\u002Fetc\u002Fgitlab-runner\u002Fconfig.toml` contient un bloc `[runners.docker]`. Ajoutez-y `volumes = [\"\u002Fcache\"]` pour conserver le cache entre les builds, et `pull_policy = [\"if-not-present\"]` pour ne pas retirer l'image à chaque job si elle est déjà présente localement — cela réduit sensiblement la durée des premiers stages.\n\nUn pipeline de base pour un projet Node.js ou PHP tient en une vingtaine de lignes dans `.gitlab-ci.yml` à la racine du dépôt :\n\n```yaml\nstages:\n  - test\n  - build\n  - deploy\n\nvariables:\n  DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA\n\ntest:unit:\n  stage: test\n  image: node:20-alpine\n  cache:\n    key: $CI_COMMIT_REF_SLUG\n    paths:\n      - node_modules\u002F\n  script:\n    - npm ci\n    - npm test\n  only:\n    - merge_requests\n    - main\n\nbuild:image:\n  stage: build\n  image: docker:26\n  services:\n    - docker:26-dind\n  before_script:\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n  script:\n    - docker build -t $DOCKER_IMAGE .\n    - docker push $DOCKER_IMAGE\n  only:\n    - main\n\ndeploy:prod:\n  stage: deploy\n  image: alpine:latest\n  before_script:\n    - apk add --no-cache openssh-client\n    - eval $(ssh-agent -s)\n    - echo \"$SSH_PRIVATE_KEY\" | ssh-add -\n  script:\n    - ssh -o StrictHostKeyChecking=no user@votreserveur.com \"docker pull $DOCKER_IMAGE && docker compose up -d\"\n  only:\n    - main\n  when: manual\n```\n\nLes variables `CI_REGISTRY_USER`, `CI_REGISTRY_PASSWORD` et `CI_REGISTRY` sont **injectées automatiquement** par GitLab CE pour le registry intégré — aucune configuration manuelle. La variable `SSH_PRIVATE_KEY` est à définir dans **Settings → CI\u002FCD → Variables** du projet, marquée **Masked** pour qu'elle n'apparaisse pas dans les logs. Le job `deploy:prod` est positionné en `when: manual` : il ne se déclenche pas automatiquement mais attend un clic dans l'interface ou via l'API — un garde de sécurité minimal avant d'écrire en production.\n\nPour vérifier que le runner a bien décroché le job, rendez-vous dans **CI\u002FCD → Jobs** : chaque job affiche son runner assigné, sa durée et son code de sortie. Un job bloqué sur « pending » indique que le runner n'a pas de slot disponible (vérifier `concurrent` dans `\u002Fetc\u002Fgitlab-runner\u002Fconfig.toml`, défaut à 1) ou qu'il est offline.",{"type":35,"title":91,"body":92},"Configurer les notifications SMTP en détail","GitLab envoie des emails à chaque merge request, mention, pipeline terminé ou alerte de sécurité. Une configuration SMTP absente ou erronée coupe silencieusement ces notifications — les utilisateurs ne le remarquent qu'après un incident.\n\nLe bloc complet à placer dans `GITLAB_OMNIBUS_CONFIG` pour un relais SMTP authentifié (exemple avec un serveur compatible STARTTLS sur le port 587) :\n\n```ruby\ngitlab_rails['smtp_enable'] = true\ngitlab_rails['smtp_address'] = 'smtp.votredomaine.com'\ngitlab_rails['smtp_port'] = 587\ngitlab_rails['smtp_user_name'] = 'gitlab@votredomaine.com'\ngitlab_rails['smtp_password'] = ENV['GITLAB_SMTP_PASSWORD']\ngitlab_rails['smtp_authentication'] = 'login'\ngitlab_rails['smtp_enable_starttls_auto'] = true\ngitlab_rails['gitlab_email_from'] = 'gitlab@votredomaine.com'\ngitlab_rails['gitlab_email_reply_to'] = 'noreply@votredomaine.com'\n```\n\nSi votre relais exige TLS direct (port 465), remplacez `smtp_enable_starttls_auto = true` par `smtp_tls = true` et ajustez le port. Pour les relais qui n'exigent pas d'authentification (serveur interne, Postfix local), posez `smtp_authentication = false` et supprimez `smtp_user_name` et `smtp_password`.\n\nPrincipaux pièges :\n- **Clé hors du bloc omnibus.** Une clé `GITLAB_SMTP_ADDRESS` définie comme variable d'environnement Docker n'est **pas** lue par Omnibus — elle est ignorée sans avertissement. Toute configuration Rails passe par le bloc Ruby dans `GITLAB_OMNIBUS_CONFIG`.\n- **Indentation YAML dans docker-compose.yml.** Si `GITLAB_OMNIBUS_CONFIG` est un bloc multilignes YAML, chaque retour à la ligne doit être explicitement représenté (`\\n` ou bloc `|`). Une erreur d'indentation peut couper le bloc au milieu et laisser GitLab sans SMTP sans générer d'erreur au démarrage.\n- **Test depuis la console Rails.** Après chaque modification, relancez le conteneur (`docker compose restart gitlab`) et testez immédiatement : `docker exec -it gitlab-gitlab-1 gitlab-rails console -e production` puis `Notify.test_email('you@example.com', 'Test', 'OK').deliver_now`. Lisez la réponse — une exception SMTP apparaît dans la console avant même que l'email parte.",{"type":35,"title":94,"body":95},"Sauvegarder et restaurer GitLab","GitLab CE embarque une commande de sauvegarde complète qui archive en un seul fichier tar les dépôts git, la base de données PostgreSQL, les uploads, les artefacts CI et les clés de configuration. La commande de référence :\n\n```bash\ndocker exec -t gitlab-gitlab-1 gitlab-backup create\n```\n\nL'archive est créée dans `\u002Fvar\u002Fopt\u002Fgitlab\u002Fbackups\u002F` à l'intérieur du conteneur, soit `\u002Fopt\u002Fgitlab\u002Fdata\u002Fbackups\u002F` sur l'hôte si vous avez monté le volume comme indiqué. Elle porte un nom de la forme `\u003Ctimestamp>_\u003Cversion>_gitlab_backup.tar`.\n\n**Attention** : la sauvegarde `gitlab-backup create` **n'inclut pas** deux fichiers critiques — `\u002Fetc\u002Fgitlab\u002Fgitlab.rb` (la configuration Omnibus) et `\u002Fetc\u002Fgitlab\u002Fgitlab-secrets.json` (les clés de chiffrement). Sans ces fichiers, une restauration échoue ou déchiffre mal les tokens. Sauvegardez-les séparément :\n\n```bash\ntar czf \u002Fopt\u002Fgitlab\u002Fconfig-secrets-$(date +%Y%m%d).tar.gz \\\n  \u002Fopt\u002Fgitlab\u002Fconfig\u002Fgitlab.rb \\\n  \u002Fopt\u002Fgitlab\u002Fconfig\u002Fgitlab-secrets.json\n```\n\n**Restaurer** une instance depuis une sauvegarde nécessite trois étapes dans l'ordre :\n\n1. Installez une instance GitLab CE de la **même version mineure** que celle qui a produit la sauvegarde. La restauration entre versions différentes n'est pas supportée.\n2. Copiez l'archive tar dans `\u002Fopt\u002Fgitlab\u002Fdata\u002Fbackups\u002F` et restaurez `gitlab.rb` et `gitlab-secrets.json` dans `\u002Fopt\u002Fgitlab\u002Fconfig\u002F`.\n3. Arrêtez les services qui écrivent en base, puis lancez la restauration :\n\n```bash\ndocker exec -it gitlab-gitlab-1 gitlab-ctl stop puma\ndocker exec -it gitlab-gitlab-1 gitlab-ctl stop sidekiq\ndocker exec -it gitlab-gitlab-1 gitlab-backup restore BACKUP=\u003Ctimestamp>_\u003Cversion>\ndocker exec -it gitlab-gitlab-1 gitlab-ctl restart\ndocker exec -it gitlab-gitlab-1 gitlab-rake gitlab:check SANITIZE=true\n```\n\nLa commande `gitlab:check` à la fin vérifie l'intégrité de l'installation et signale les dépôts corrompus ou les permissions incorrectes. Planifiez la sauvegarde complète à 3 h du matin et synchronisez vers un stockage externe (S3 via rclone, bucket OVH, NAS distant) : une sauvegarde locale qui brûle avec le VPS n'est pas une sauvegarde.",{"type":35,"title":97,"body":98},"Dépannage : les trois pannes les plus fréquentes","**502 Bad Gateway au démarrage.** GitLab met environ 5 minutes à être pleinement opérationnel. Si le 502 persiste, vérifiez que Puma a démarré : `docker exec gitlab-gitlab-1 gitlab-ctl status puma`. Un manque de RAM est la cause la plus fréquente — assurez-vous d'avoir au moins 4 Go disponibles. **SMTP ne fonctionne pas.** La première chose à vérifier : le bloc `gitlab_rails['smtp_*']` est-il bien à l'intérieur de `GITLAB_OMNIBUS_CONFIG`, et non défini comme variable d'environnement séparée ? Une indentation incorrecte dans le YAML ou une clé hors du bloc omnibus est silencieuse — GitLab démarre normalement mais ignore la configuration SMTP. Testez depuis la console Rails (étape 9). **Runner non connecté.** Si le runner s'affiche en gris ou « offline », vérifiez qu'il peut joindre votre instance : `gitlab-runner verify --url https:\u002F\u002Fgit.votredomaine.com`. Un certificat TLS auto-signé ou un DNS non résolvable depuis la machine du runner sont les causes habituelles. Vérifiez également que le token utilisé à l'enregistrement est celui du bon niveau (instance, groupe ou projet).",{"type":35,"title":100,"body":101},"Dépannage avancé : Sidekiq bloqué, Unicorn timeout et OOM sur Gitaly","**Sidekiq queue stuck — jobs bloqués indéfiniment.** Sidekiq traite les jobs asynchrones de GitLab (emails, imports, webhooks, indexation). Si des jobs s'accumulent sans être consommés, vérifiez d'abord l'état du worker :\n\n```bash\ndocker exec gitlab-gitlab-1 gitlab-ctl status sidekiq\ndocker exec gitlab-gitlab-1 gitlab-rake gitlab:sidekiq:check\n```\n\nUne queue bloquée tient souvent à un job qui a levé une exception non rattrapée et s'est mis en « retry » infini. Pour vider une queue spécifique sans redémarrer GitLab : `docker exec -it gitlab-gitlab-1 gitlab-rails console -e production` puis `Sidekiq::Queue.new('mailers').clear`. Si Sidekiq consomme plus de 1 Go de RAM, `docker exec gitlab-gitlab-1 gitlab-ctl restart sidekiq` le ré-initialise sans affecter les jobs en attente (ils restent dans Redis).\n\n**Puma \u002F Unicorn timeout — 503 intermittents sous charge.** Les timeouts Puma (appels lents à la base, requêtes Rails mal optimisées) se lisent dans `\u002Fvar\u002Flog\u002Fgitlab\u002Fpuma\u002Fpuma_stderr.log`. La première action est d'augmenter le timeout si le VPS est lent mais fonctionnel : dans `GITLAB_OMNIBUS_CONFIG`, ajoutez `puma['worker_timeout'] = 90` (défaut 60 s). Si les timeouts persistent, la cause est presque toujours un manque de RAM ou un nombre de workers inadapté — voir la section optimisation RAM ci-dessous.\n\n**OOM sur Gitaly — dépôts inaccessibles après un kill.** Gitaly est le service qui répond aux opérations git (clone, fetch, push). Si le noyau le tue par OOM (vérifiable dans `dmesg | grep -i kill`), tous les accès git tombent en erreur jusqu'au redémarrage du service. Gitaly consomme environ 200 à 400 Mo sur une installation légère ; avec des dépôts volumineux ou des opérations de repack simultanées, il peut dépasser 1 Go. Surveillez sa consommation avec `docker exec gitlab-gitlab-1 gitlab-ctl status gitaly` et, si le VPS est juste en RAM, envisagez de limiter les tâches de maintenance automatique dans `GITLAB_OMNIBUS_CONFIG` : `gitaly['configuration']['git']['catfile_cache_size'] = 5` (défaut 100) réduit les objets git gardés en cache. En cas d'OOM répété, la solution durable est d'augmenter la RAM ou d'ajouter du swap (voir ci-dessous).\n\n**Container exited au démarrage.** Si le conteneur sort immédiatement après `docker compose up`, consultez les logs avant la sortie : `docker compose logs gitlab | tail -50`. Les causes les plus fréquentes sont un conflit de port 22 (daemon SSH système actif), un volume non accessible en écriture (`chown -R 998:998 \u002Fopt\u002Fgitlab\u002Fdata`) ou un `GITLAB_OMNIBUS_CONFIG` avec une syntaxe Ruby invalide (une virgule manquante, un guillemet non fermé).",{"type":35,"title":103,"body":104},"Sécurité : CVE-2026-90970 et mise à jour critique","Le 2 octobre 2026, GitLab a divulgué **CVE-2026-90970**, une vulnérabilité critique (CVSS 9.9) affectant l'**AI Gateway** des déploiements self-hosted. La faille est une injection de template côté serveur (SSTI) dans les templates de flux personnalisés : un utilisateur authentifié disposant d'un accès à la plateforme Duo Agent peut soumettre une configuration de flux contrefaite pour s'échapper du sandbox et **exécuter des commandes arbitraires sur l'hôte**.\n\n**Ce qui est touché.** Uniquement les instances self-hosted qui déploient le composant AI Gateway. GitLab.com et les instances Dedicated ont été patchées automatiquement. L'exploitation n'est pas triviale (accès Duo Agent Platform requis) et aucune exploitation dans la nature n'a été rapportée au moment de la divulgation.\n\n**Versions vulnérables et versions corrigées.**\n\n| Branche | Dernière version vulnérable | Version corrigée |\n|---|---|---|\n| 19.4.x | 19.4.0 | **19.4.1** |\n| 19.3.x | 19.3.1 | **19.3.2** |\n| 18.1.6 – 19.2.x | 19.2.3 | **19.2.4** |\n\n**Mettre à jour l'AI Gateway sous Docker.**\n\n```bash\n# Arrêter et supprimer le conteneur existant\ndocker stop gitlab-ai-gateway && docker rm gitlab-ai-gateway\n\n# Tirer l'image corrigée (remplacez le tag par votre branche)\ndocker pull registry.gitlab.com\u002Fgitlab-org\u002Fmodelops\u002Fapigw\u002Fself-hosted-v19.4.1-ee\n# ou : self-hosted-v19.3.2-ee \u002F self-hosted-v19.2.4-ee\n\n# Redémarrer avec les mêmes variables d'environnement\ndocker run -d --name gitlab-ai-gateway \\\n  --restart unless-stopped \\\n  [vos options habituelles] \\\n  registry.gitlab.com\u002Fgitlab-org\u002Fmodelops\u002Fapigw\u002Fself-hosted-v19.4.1-ee\n\n# Vérifier la version déployée\ndocker ps --format '{{.Image}}' | grep ai-gateway\n```\n\n**Mettre à jour sous Helm \u002F Kubernetes.** Mettez à jour `image.tag` dans vos values Helm pour pointer vers la version corrigée et posez `imagePullPolicy: Always`, puis déclenchez un `helm upgrade`.\n\nPour vérifier après mise à jour que le conteneur tourne bien sur l'image patchée : `docker inspect \u003Ccontainer> --format '{{.Config.Image}}'`.",{"type":85,"body":106},"**Désactiver l'AI Gateway si vous ne l'utilisez pas.** Si votre instance GitLab CE n'utilise pas les fonctionnalités Duo (complétion de code IA, chat), l'AI Gateway peut être simplement stoppé et retiré de votre `docker-compose.yml`. Un composant non déployé n'est pas exposé. Vérifiez d'abord qu'aucun pipeline ne dépend de l'API Gateway avant de le retirer.",{"type":35,"title":108,"body":109},"Optimiser la RAM : swap et workers Puma","GitLab CE en configuration par défaut alloue plusieurs workers Puma et autant de threads Sidekiq qu'il détecte de cœurs CPU. Sur un VPS de 4 Go avec 2 vCPU, cela peut dépasser la mémoire disponible dès qu'un pipeline lourd tourne en parallèle. Deux leviers immédiats.\n\n**Réduire les workers Puma.** Dans `GITLAB_OMNIBUS_CONFIG` :\n\n```ruby\npuma['worker_processes'] = 2\npuma['min_threads'] = 1\npuma['max_threads'] = 4\n```\n\nChaque worker Puma consomme environ 200 à 300 Mo. Deux workers suffisent pour moins de quinze utilisateurs actifs simultanés. Un seul worker (`worker_processes = 0`) est possible mais retire la tolérance aux pannes de worker.\n\n**Ajouter du swap.** GitLab recommande d'avoir au minimum autant de swap que de RAM. Sur un VPS sans swap préconfiguré :\n\n```bash\nfallocate -l 4G \u002Fswapfile\nchmod 600 \u002Fswapfile\nmkswap \u002Fswapfile\nswapon \u002Fswapfile\necho '\u002Fswapfile none swap sw 0 0' >> \u002Fetc\u002Ffstab\n```\n\nLe swap ne remplace pas la RAM — il évite le crash OOM quand un pic de charge momentané déborde — mais il ralentit GitLab si le système doit y recourir en permanence. Si `free -h` montre une utilisation swap régulière au repos, c'est le signe que le VPS est sous-dimensionné.\n\n**Recommandations RAM et CPU par taille d'équipe**\n\n| Taille d'équipe | RAM recommandée | vCPU | Notes |\n|---|---|---|---|\n| 1–5 développeurs | 4 Go | 2 | Runners sur la même machine possibles avec swap |\n| 5–15 développeurs | 8 Go | 4 | Runner dédié conseillé dès 8+ pipelines\u002Fjour |\n| 15–30 développeurs | 16 Go | 8 | Registry Docker actif, Gitaly sous charge |\n| 30+ développeurs | 32 Go+ | 16+ | Séparer Gitaly et Sidekiq sur des machines dédiées |\n\nCes valeurs correspondent à un GitLab CE avec registry Docker actif et pipelines CI réguliers. Sans CI (runners absents), divisez par deux les valeurs de RAM. Avec un registry très sollicité (images > 2 Go fréquentes), comptez 50 Go de disque supplémentaire et surveillez `df -h \u002Fopt\u002Fgitlab\u002Fdata` — un disque plein stoppe GitLab sans avertissement préalable.",{"type":111,"title":112,"headers":113,"rows":117},"comparison","GitLab CE, Forgejo ou Gitea : comment choisir",[114,115,116],"Critère","GitLab CE","Forgejo \u002F Gitea",[118,122,126,130,134,136,140,144],[119,120,121],"Licence","MIT \u002F EE Core","MIT",[123,124,125],"RAM au repos","300–600 Mo (Puma + Sidekiq)","30–50 Mo",[127,128,129],"CI\u002FCD native","Oui (`.gitlab-ci.yml`, runners)","Forgejo : oui via Woodpecker CI ; Gitea : non native",[131,132,133],"Registry Docker intégré","Oui","Forgejo : oui ; Gitea : non natif",[135,132,132],"Wikis par projet",[137,138,139],"LDAP \u002F SAML","Oui (CE)","Forgejo : oui ; Gitea : LDAP oui, SAML non",[141,142,143],"Courbe d'apprentissage","Élevée (interface riche)","Faible à moyenne",[145,146,147],"Idéal pour","Équipes 5+ avec CI, registry et RBAC","Équipes légères, forge simple, faible empreinte RAM",{"type":35,"title":149,"body":150},"Quand choisir GitLab CE, quand choisir Forgejo","GitLab CE est le bon choix si votre équipe a besoin d'une CI\u002FCD robuste directement intégrée à la forge, d'un registry Docker privé sur votre domaine, de pipelines de déploiement avec environments et deploy tokens, ou d'une gestion de projet avec issues, milestones et kanban sans outil tiers. Son empreinte mémoire (4–8 Go) est le prix de cette richesse fonctionnelle. Forgejo ou Gitea s'imposent quand la mémoire est la contrainte principale, quand la forge est l'unique besoin (pas de CI intégrée) et que vous pilotez la CI avec un outil externe (Woodpecker, Drone, GitHub Actions via un runner). Sur un VPS de 2 Go, GitLab CE n'est pas viable ; Forgejo tourne sur 256 Mo. Sur un VPS de 8 Go dédié à une équipe de développeurs, GitLab CE offre un environnement complet que GitHub met sur sa plateforme SaaS — sous votre contrôle et sans abonnement mensuel par utilisateur.","Un VPS prêt pour GitLab CE","GitLab CE a besoin d'un VPS de 4 à 8 Go de RAM, d'un disque généreux et d'une IP dédiée. Nos VPS ServOrbit sont livrés au choix sous Ubuntu 24.04 LTS, Ubuntu 22.04 LTS ou Debian 12 avec accès root immédiat — de quoi avoir votre forge en ligne en trente minutes.","Voir les VPS ServOrbit","\u002Fsolutions\u002Fdeveloppeurs",[156,176,192],{"id":157,"slug":158,"slugs":159,"title":163,"excerpt":164,"readTime":165,"views":166,"isPinned":19,"noindex":19,"publishedAt":167,"updatedAt":168,"category":169,"categories":173,"featuredImage":29,"bgImage":30,"posterImage":175,"relatedSolution":29},212,"woodpecker-ci-pipeline-vps-forgejo",{"fr":158,"en":160,"ar":161,"es":162},"woodpecker-ci-and-forgejo-cicd-pipeline-on-a-vps","woodpecker-ci-وforgejo-خط-أنابيب-cicd-على-خادم-vps","woodpecker-ci-forgejo-pipeline-cicd-vps","Woodpecker CI et Forgejo : pipeline CI\u002FCD sur VPS","Déployez Woodpecker CI v3 avec Forgejo sur votre VPS : installation Docker Compose, pipeline YAML, secrets, runners multi-arch et dépannage OAuth.",12,2,"2026-08-02T00:00:00+00:00","2026-11-08T01:13:13+00:00",{"id":166,"name":170,"slug":171,"color":172,"icon":171},"Automatisation","automatisation","bg-brand-action\u002F10 text-brand-action",[174],{"id":166,"name":170,"slug":171,"color":172,"icon":171},"\u002Fblog\u002Fcovers\u002Fwoodpecker-ci-pipeline-vps-forgejo-poster.svg",{"id":177,"slug":178,"slugs":179,"title":183,"excerpt":184,"readTime":165,"views":185,"isPinned":19,"noindex":19,"publishedAt":186,"updatedAt":187,"category":188,"categories":189,"featuredImage":29,"bgImage":30,"posterImage":191,"relatedSolution":29},229,"docker-compose-production-checklist",{"fr":178,"en":180,"ar":181,"es":182},"docker-compose-in-production-10-point-checklist","docker-compose-في-الإنتاج-قائمة-التحقق-من-10-نقاط","checklist-docker-compose-en-produccion","Docker Compose en production : checklist des 10 points","Docker Compose en production : 10 réglages, health checks, secrets, rollback, dépannage et passage de docker-compose v1 à docker compose sur Ubuntu 26.04.",1,"2026-08-06T00:00:00+00:00","2026-10-23T13:27:09+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[190],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Fdocker-compose-production-checklist-poster.svg",{"id":193,"slug":194,"slugs":195,"title":199,"excerpt":200,"readTime":201,"views":166,"isPinned":19,"noindex":19,"publishedAt":202,"updatedAt":203,"category":204,"categories":205,"featuredImage":29,"bgImage":30,"posterImage":207,"relatedSolution":29},207,"k3s-kubernetes-leger-vps",{"fr":194,"en":196,"ar":197,"es":198},"k3s-lightweight-kubernetes-on-your-vps","k3s-كوبيرنيتيس-خفيف-على-vps-الخاص-بك","k3s-kubernetes-ligero-en-un-vps","K3s : Kubernetes léger sur votre VPS","Déployez un cluster Kubernetes certifié CNCF sur un VPS modeste avec K3s, la distribution Rancher\u002FSUSE qui tient en 60 Mo.",4,"2026-08-01T00:00:00+00:00","2026-09-07T11:26:10+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[206],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Fk3s-kubernetes-leger-vps-poster.svg",true,1794270739002]