Help - Deploying same code to multiple prod servers at same time

Hi all.

I’ve spent several days trying to figure this out, so apologies if I’m missing something. I’m sure what I’m trying to do is pretty standard, so it’s likely just me not understanding how to use the tool set properly.

We have multiple production servers. My goal is when we push to master branch, I would like Gitlab to deploy the latest version of code to all of these servers automatically.

I have successfully setup the process of deploying to a single staging server, with the following script:

stages:
- deploy

deploy_staging:
  stage: deploy
  environment: 
    name: Staging
    url: http://###.###.lan
  only:
  - staging
  variables:
    HOSTNAME: ###.###.lan
  script:
  - mkdir -p build
  - tar -c public | gzip -9 > build/app.tar.gz
  - ssh gitlab@$HOSTNAME "mkdir -p /srv/###/releases/${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA:0:8}"
  - scp build/app.tar.gz gitlab@$HOSTNAME:/srv/###/releases/${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA:0:8}
  - ssh gitlab@$HOSTNAME "tar -zxvf /srv/###/releases/${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA:0:8}/app.tar.gz -C /srv/###/releases/${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA:0:8}/"
  - ssh gitlab@$HOSTNAME "rm /srv/###/releases/${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA:0:8}/app.tar.gz"
  - ssh gitlab@$HOSTNAME "mkdir -p /srv/###/releases/${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA:0:8}/public/sites/default/files"
  - ssh gitlab@$HOSTNAME "mkdir -p /srv/###/releases/${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA:0:8}/public/sites/default/files_private"
  - ssh gitlab@$HOSTNAME "cd /srv/###/releases/${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA:0:8}/public/sites/default/ && ln -s staging.settings.php settings.php"
  - ssh gitlab@$HOSTNAME "ln -sf /srv/###/releases/${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA:0:8}/public /srv/###/"
  - ssh gitlab@$HOSTNAME "chmod -R 775 /srv/###/public"

I can’t get my head around how I would have the same thing working, but for all prod servers. The only way I can get it to work is setup a task for each server I want to push to, but this just feels wrong, clearly isn’t scale-able and is very repetitive.

I’ve looked at building a single deploy-production.sh script, and having the hostname passed in as a variable. This reduces the amount of code in the Gitlab-ci.yaml file down to single “jobs” for each server all calling the same script with different variables, but again, it doesn’t feel like I’m doing it properly.

The remote servers are VM’s in a business environment. Using Docker or Kubernetes isn’t an option here unfortunately. Any advice or guidance on where I can do some further reading would be great.

Thank you

So it seems the neatest solution I’ve been able to come up with is triggering an ansible playback to deal with the deployment to the multiple hosts.

It’s kept code to a minimum whilst having full verbosity in the pipeline output logs.

I’d prefer to keep the amount of tools we use to a minimum but I just couldn’t figure out a way of keeping it all in gitlab.