Deploy your Drupal website from Gitlab
Learn how to set up a basic deployment script to deploy your Drupal 11 website from Gitlab to your server.
When it comes to storing my code in repositories Gitlab is my partner of choice. The platform works really well and the Drupal Association uses GitLab as its primary collaboration and DevOps platform, hosting all Drupal projects on its own self-hosted GitLab instance and now enabling GitLab CI for all projects on Drupal.org.
The role of our deployment script is that it safely updates your Drupal site, protects your data with backups, and keeps downtime minimal. This should all happen automatically.
Setting this up involves four parts:
In this post I assume your server has access to your Gitlab repository. You can learn how to set this up in this post (part: Access GIT repo from server).
The deployment script below is a simple implementation that has the following steps:
In this particular case we deploy manually.
The deploy.sh script is stored in the deploy directory (deploy/deploy.sh).
#!/bin/bash
set -e
set -o pipefail
# Config
PROJECT_DIR="/the/location/where/your/project/lives/on/the/server"
DB_BACKUP_DIR="/the/location/where/your/database/bcps/live/on/the/server/db-bcp"
BACKUP_KEEP=5
# Paths to binaries
DRUSH="path/to/drush" # Discover with which drush
COMPOSER="path/to/composer" # Discover with which composer
# Multisite projects
PROJECTS=("default") # Add more like: ("default" "site1" "site2")
cd "$PROJECT_DIR"
echo "=== Pull latest code ==="
git pull origin main
echo "=== Install dependencies ==="
$COMPOSER install --no-interaction --prefer-dist --optimize-autoloader
# Loop through multisites
for PROJECT in "${PROJECTS[@]}"; do
echo "==============================="
echo "=== Processing site: $PROJECT ==="
echo "==============================="
TIMESTAMP=$(date +'%Y%m%d-%H%M%S')
PROJECT_BACKUP_DIR="$DB_BACKUP_DIR/$PROJECT"
mkdir -p "$PROJECT_BACKUP_DIR"
echo "=== Maintenance mode ON ($PROJECT) ==="
$DRUSH -l "$PROJECT" state:set system.maintenance_mode 1 -y
$DRUSH -l "$PROJECT" cr
echo "=== Database backup ($PROJECT) ==="
BACKUP_FILE="$PROJECT_BACKUP_DIR/db-${PROJECT}-${TIMESTAMP}.sql"
$DRUSH -l "$PROJECT" sql-dump > "$BACKUP_FILE"
echo "Backup saved to $BACKUP_FILE"
echo "=== Run Drupal deploy tasks ($PROJECT) ==="
$DRUSH -l "$PROJECT" deploy -y
echo "=== Maintenance mode OFF ($PROJECT) ==="
$DRUSH -l "$PROJECT" state:set system.maintenance_mode 0 -y
$DRUSH -l "$PROJECT" cr
echo "=== Cleaning old backups ($PROJECT) ==="
ls -1t "$PROJECT_BACKUP_DIR"/db-${PROJECT}-*.sql | tail -n +$((BACKUP_KEEP + 1)) | xargs -r rm --
echo "Old backups cleaned for $PROJECT, keeping last $BACKUP_KEEP backups."
done
echo "=== Deployment complete for all projects ==="A .gitlab-ci.yml file is the configuration file that defines automated CI/CD pipelines for a project in GitLab.
In short, it tells GitLab what jobs to run (e.g., build, test, deploy), when to run them (manual, on push, merge request, etc.) and how to run them (scripts, tools, environments).
It uses YAML syntax and the .gitlab-ci.yml is stored in the project root.
stages:
- deploy
deploy:
stage: deploy
script:
# Ensure ssh-agent is available
- "which ssh-agent || ( apt-get update -y && apt-get install -y openssh-client )"
- eval $(ssh-agent -s)
# Set up SSH key securely
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo "$SSH_KEY" | base64 -d > ~/.ssh/gitlab_deploy
- chmod 600 ~/.ssh/gitlab_deploy
- ssh-add ~/.ssh/gitlab_deploy
# Add remote host to known_hosts
- ssh-keyscan -p $SSH_PORT $SSH_HOST >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
# Run deployment script on remote host
- ssh -i ~/.ssh/gitlab_deploy -p $SSH_PORT $SSH_USER@$SSH_HOST 'bash -s' < ./deploy/deploy.sh
# Optional: remove the private key after use
- rm -f ~/.ssh/gitlab_deploy
when: manual
only:
- main
As Gitlab needs to access the server it needs the SSH_KEY, I advice you to generate a separate key on your server for this (without a passphrase).
ssh-keygen -t ed25519 -C "gitlab-deploy-key" -f ~/.ssh/gitlab_deploy_key
And add the public key to your server
cat ~/.ssh/gitlab_deploy_key.pub >> ~/.ssh/authorized_keys
We can't store the private key hidden and masked in gitlab so you should encode it:
cat ~/.ssh/gitlab_deploy_key | base64 -w0
This value we store in SSH_KEY in Gitlab.
You need to define 4 variables in Gitlab CI (under Settings > CI/CD > Variables):
Now that everything is setup we can deploy from Gitlab.
Go to your pipelines (Build > Pipelines) and click the play button.
When you click Deploy the deploy script is executed.
Disclaimer: In this Insight I don't touch rolling back deployments, deploying to a development or staging environment, etc. This is on purpose to limit the scope of the insight. That doesn't mean this isn't important and should be setup properly in your own workflow.