Gitlab

Déploiement natif

Cette méthode de déploiement automatisé réalise les étapes d’installation / mise à jour / configuration à destination de projets qui seront instanciés nativement sur le serveur.

Elle peut s’intégrer dans une pipeline de la CI de Gitlab, et son principe repose simplement sur Git, en indiquant la branche à partir de laquelle on souhaite déployer le code dans le fichier .gitlab-ci.yml.

Sources

Le projet est hébergé dans un Gitlab, dans un répertoire nommé “web”. Les étapes de l’intégration continue sont décrites dans le fichier .gitlab-ci.yml.

web/
.gitlab-ci.yml

Le script de deploiement s’appelle via la commande deploy que vous pouvez préfixer ainsi pour le déploiement en production: PROD=true deploy

Variables d’environnement

  • Les variables obligatoires pour le déploiement sont définies par Bearstech:

    • DEPLOY_HOST : nom de la machine hôte
    • DEPLOY_USER : utilisateur autorisé à déployer
    • DEPLOY_KEY : clé de l’utilisateur
    • DEPLOY_HOST_KEY : permet d’authentifier l’hôte
  • Des variables spécifiques peuvent être définies dans les settings CI/CD du projet et seront propagées vers un fichier .env à la racine du repository (ex : DEPLOY_MYTOKEN défini dans Gitlab deviendra MYTOKEN dans le fichier ~/root/.env)

    Variables uilisées par la CI dans Gitlab

Processus de déploiement

  • Pour le premier déploiement, le repository est cloné dans le $HOME/root du serveur
  • Pour les déploiements suivants, un “nettoyage” (checkout) du repository sur le serveur cible est réalisé pour s’assurer de ne pas avoir de conflits, puis mise-à-jour du repository (pull) vers le commit correspondant au déploiement (checkout)
  • Le dépôt git doit contenir un répertoire (“web”) qui stocke les fichiers à exposer publiquement
  • Dans un cas ultra-simple de déploiement d’un projet de type LAMP, le DocumentRoot pointe vers ~/root/web, le code se met-à-jour via le git pull, les développeurs doivent juste bien penser à maintenir le .gitignore pour éviter de surcharger le repository Git avec des assets statiques (par exemple, on exclue bien son web/wp-content/uploads).

Post-deploy

  • Il est possible de définir des scripts “post-deploy” qui seront exécutés à la fin du déploiement (par exemple pour vider les caches de l’application). Ils doivent être définis dans l’ordre, dans un dossier .deploy.d. Toutes les variables DEPLOY_* sont accessibles lors de l’exécution de ces scripts

  • Attention, les 4 variables obligatoires définies ci-dessus (HOST, USER, …) sont réservées et ne sont pas propagées dans le .env. Si l’application a besoin d’une de ces variables, il faut gérer ce cas particulier dans un script dans le dossier .deploy.d.

    Par exemple, pour définir une variable d’environnement qui définit un HOST personnalisé pour votre application (un domaine racine différent du HOST du serveur), on peut l’ajouter au .env de cette manière, via ce script my-super-project/.deploy.d/011-set-host-variable :

    #! /bin/bash
    
    export HOST="${MY_HOST}"
    echo "HOST=${MY_HOST}" >> ~/root/.env
    

Instancier un service

Si l’application doit être lancée sur le serveur (pour les applications Nodejs, Python, …), les dévelopeurs ont accès à Systemd au niveau utilisateur et peuvent donc gérer eux-mêmes les actions sur le service et son évolution:

  • Créer un service et le versionner dans le projet my-super-project/systemd/my-super-service.service :

    [Unit]
    Description=My super service for my super project
    
    [Service]
    ExecStart=~/root/start-server.sh
    Restart=always
    RestartSec=180
    
    [Install]
    WantedBy=default.target
    
  • Créer un script “post-deploy” et le versionner dans le dossier .deploy.d du projet (my-super-project/.deploy.d/022-install-service):

    #! /bin/bash
    
    mkdir -p ~/.config/systemd/user/
    cp ~/root/systemd/my-super-service.service ~/.config/systemd/user/my-super-service.service
    systemctl --user daemon-reload
    systemctl restart my-super-service
    

Tâches planifiées

On peut déployer ses tâches planifiées via un timer systemd (voir au dessus) ou une classique crontab versionnée dans votre dépôt:

  • Définir la tâche qui lancera le cronjob dans my-super-project/crontab
0 * * * * /bin/bash $HOME/root/hourly-script
  • Créer un script “post-deploy” pour installer le cronjob my-super-project/.deploy.d/033-install-cron:
#! /bin/bash
crontab ~/root/crontab

Déploiement sur un serveur mutualisé

S’applique dans le cas d’un serveur avec plusieurs applications et multi-environnements. Les variables sont à définir dans les settings CI/CD du projet.

  • Forcer la variable DEPLOY_USER à ‘deploy’, cet utilisateur spécial à les droits de création d’environnements
  • Il faut spécifier l’URL du site au script de déploiement en argument (script: deploy my-super-site.com)
  • Vous pouvez aussi utiliser les variables suivantes:
    • DEPLOY_ALIASES: domaines à utiliser comme aliases (les redirections adéquates sont à gérer dans votre .htaccess)
    • DEPLOY_SSH_KEY_FILE: chemin vers un fichier contenant les clefs SSH à autoriser (peut être versionné dans votre repository par exemple)
    • DEPLOY_BASIC_AUTH: mot de passe pour une basic auth (l’utilisateur est le nom de votre projet gitlab comme il apparaît dans l’url: https://[GITLAB_URL]/[GROUP]/[PROJECT] -> GROUP-PROJECT)
    • DEPLOY_ENABLE_PHP: définit si l’environnement utilise du PHP (par défaut à true)
    • DEPLOY_ENABLE_MYSQL: définit si l’environnement a besoin d’une base MySQL (par défaut à true)

Gestion des certificats

  • DEPLOY_TLS_MODE: mode TLS (none, letsencrypt ou manual), par défaut à none (certificat “snakeoil”)
  • DEPLOY_TLS_CERTIFICATE: certificat à utiliser si TLS_MODE est défini à manual (par défaut à /etc/ssl/certs/DOMAIN.TLD.crt)
  • DEPLOY_TLS_KEY: fichier clef à utiliser si TLS_MODE est défini à manual (par défaut à /etc/ssl/private/DOMAIN.TLD.key)
  • DEPLOY_TLS_CHAIN: chaîne de certificats à utiliser si TLS_MODE est défini à manual (par défaut à /etc/ssl/certs/DOMAIN.TLD.chain)

Utilisation dans le fichier .gitlab-ci.yml

A la racine du projet, placer le fichier .gitlab-ci.yml. Avec l’exemple ci-dessous, la préproduction sera déployée dans un serveur mutualisé, et la production sur un dédié:

default:
  image: bearstech/deploy

stages:
  - deploy-preprod
  - deploy-prod

staging:
  stage: deploy-preprod
  environment:
    name: preprod
  script:
    - deploy my-super-site-preprod.bearstech.dev

production:
  stage: deploy-prod
  environment:
    name: prod
  script:
    - PROD=true deploy
  only:
    refs:
      - main
  when: manual

Ici, le déploiement se fait automatiquement sur la préproduction à chaque commit. Pour la production, le déploiement se déclenche uniquement pour les commits sur la branche ‘main’ et via une action manuelle de votre part.

Top