Deploy website with Gitlab-CI

Assumptions

Let say we want to deploy content for https://site.asqatasun.ovh/

Prerequisites ===============================================================

INFOMANIAK: create SSH access

  • Manager > Web Hosting > (hosting-name) > FTP/SSH
  • Add an account. Let says our user is named deploy-user

INFOMANIAK: create SSH keys

Create the SSH key-pair for the newly created user.

  • Connect to the hosting: ssh deploy-user@xxxx.ftp.infomaniak.com
  • Generate the key-pair: ssh-keygen -t ed25519
  • the key-pair is stored in /home/clients/xxxxxxxxxx/.ssh/
  • Add public key to authorized keys: cd ~/.ssh/ && cat ed25519.pub >>authorized_keys

Hosting configuration =======================================================

1. DNS Zone for asqatasun.ovh

  • Set TTL to 120 (yes this is very short!)
  • Set entry site.asqatasun.ovh to the Infomaniak IP address

2. INFOMANIAK: add website

  • Manager > Web Hosting > (hosting-name) > My sites > Sites management: Add web site site.asqatasun.ovh (choose: use sub-domain)
  • Expand Advanced options
    • Tick add SSL certificate
    • Untick both domain options
    • Select PHP 8.0

3. DNS Zone for asqatasun.ovh

  • Set TTL back to 3660

CI configuration ============================================================

4. GITLAB: Configure Gitlab-CI variables

Get to the Gitlab repos, then Settings > CI/CD > Variables to create variables. Make them Protected; this is important as this prevents any contributor from stealing the private key using a merge request. (Masked is available only for one-line variables, hence not suitable for SSH key) See Gitlab doc Add a CI/CD variable to a project

Variable Value
SSH_PRIVATE_KEY Copy content from the private key file /home/clients/xxxxxxxxxx/.ssh/id_ed25519
DEPLOY_HOST Target hostname, xxx.ftp.infomaniak.com
DEPLOY_PATH Absolute path to the directory holding the website, /home/clients/xx/sites/site.asqatasun.ovh
DEPLOY_USER SSH username that can connect to the hosting, here deploy-user
SSH_KNOWN_HOSTS Result of ssh-keyscan of this hosting: ssh-keyscan xxx.ftp.infomaniak.com.
  • Note for SSH_KNOWN_HOSTS: from a security point of view, the ssh-keyscan command should be executed on the hosting itself.

5. Project repository: create CI files

Create a file .gitlab/ci/deploy.yml and place the following content in it:

---
.deploy_common:
  image: debian:buster
  stage: deploy
  before_script:
    ##
    ## Install ssh-agent if not already installed, it is required by Docker.
    ## (change apt-get to yum if you use an RPM-based image)
    ##
    - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'

    ##
    ## Run ssh-agent (inside the build environment)
    ##
    - eval $(ssh-agent -s)

    ##
    ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
    ## We're using tr to fix line endings which makes ed25519 keys work
    ## without extra base64 encoding.
    ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
    ##
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -

    ##
    ## Create the SSH directory and give it the right permissions
    ##
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh

    ##
    ## Assuming you created the SSH_KNOWN_HOSTS variable, uncomment the
    ## following two lines.
    ##
    - echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts

    ##
    ## You can optionally disable host key checking. Be aware that by adding that
    ## you are susceptible to man-in-the-middle attacks.
    ## WARNING: Use this only with the Docker executor, if you use it with shell
    ## you will overwrite your user's SSH config.
    ##
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'

    ## Rsync install in runner
    - apt-get update -y && apt-get install rsync -y

  script:
    - rsync -avz --delete  ./public/ "$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH"

Then add to the .gitlab-ci.yml:

---
stages:
  - deploy

include:
  - local: /.gitlab/ci/deploy.yml

deploy_master:
  extends: .deploy_common
  only:
    refs:
      - master

deploy_manual:
  extends: .deploy_common
  when: manual

Ressources