Skip to content

Install GitLab

bash
sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates tzdata perl

sudo apt-get install -y postfix
sudo dpkg-reconfigure postfix

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash

sudo apt-get install gitlab-ee
sudo apt-get install gitlab-ce

sudo nano /etc/gitlab/gitlab.rb

Change config

ini
external_url 'http://gitlab.local'
nginx['enable'] = false
web_server['external_users'] = ['www-data']

Reload

bash
sudo gitlab-ctl reconfigure

Password

bash
nano /etc/gitlab/initial_root_password

NGINX conf

nginx
upstream gitlab-workhorse {
  server unix:/var/opt/gitlab/gitlab-workhorse/sockets/socket;
}

server {
  listen 80 default_server;
  listen [::]:80 default_server;
  server_name _;
  server_tokens off;
  root /opt/gitlab/embedded/service/gitlab-rails/public;

  access_log  /var/log/nginx/gitlab_access.log;
  error_log   /var/log/nginx/gitlab_error.log;

  location / {
    client_max_body_size 0;
    gzip off;

    proxy_read_timeout      300;
    proxy_connect_timeout   300;
    proxy_redirect          off;

    proxy_http_version 1.1;

    proxy_set_header    Host                $http_host;
    proxy_set_header    X-Real-IP           $remote_addr;
    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    proxy_set_header    X-Forwarded-Proto   $scheme;

    proxy_pass http://gitlab-workhorse;
  }
}

Installing GitLab Runner

Install Runner

bash
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install gitlab-runner
nano /etc/gitlab-runner/config.toml

Install Docker

bash
sudo apt install docker.io

Change user

bash
nano /etc/systemd/system/gitlab-runner.service

Register Runner

bash
sudo gitlab-runner register

Runner config /etc/gitlab-runner/config.toml

yaml
concurrent = 10
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "dev-runner"
  url = "http://92.53.100.212/"
  token = "1vec6K6v93VDdFqeNJnc"
  executor = "docker"
  builds_dir = "/builds"
  cache_dir = "/cache"
  pre_clone_script = "umask 0022"
  #pre_build_script = "sudo chown -R gitlab-runner:gitlab-runner ./"
  environment = [
    "GIT_CLONE_PATH=$CI_BUILDS_DIR/$CI_PROJECT_NAME/$CI_JOB_NAME"
  ]
  [runners.custom_build_dir]
    enabled = true
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]
  [runners.docker]
    tls_verify = false
    image = "127.0.0.1:5000/gitlab-runner-dev:latest"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/var/gitlab-runner/builds:/builds:rw", "/var/gitlab-runner/cache:/cache:rw", "/home/gitlab-runner:/home/gitlab-runner:rw"]
    shm_size = 0
    helper_image = "127.0.0.1:5000/gitlab-runner-helper:latest"
    cpus = "2"

Clear runner list

bash
gitlab-runner verify --delete

Docker Image for Runner

dockerfile
FROM ubuntu:20.04

ENV export DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y --no-install-recommends \
        apt-transport-https \
        build-essential \
        ca-certificates \
        curl \
        wget \
        libssl-dev \
        git \
        gcc \
        g++ \
        python \
        make \
        sudo \
        openssh-client \
        gnupg2

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata php7.4-cli php7.4-curl unzip
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

ENV NVM_DIR /usr/local/nvm
RUN mkdir $NVM_DIR
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash \
    && . $NVM_DIR/nvm.sh \
    && nvm install v10.24.0 \
    && nvm install v12.5.0 \
    && nvm install v15.0.1

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update && apt-get install -y yarn

RUN groupadd --gid 993 gitlab-runner && useradd --uid 993 --gid gitlab-runner --shell /bin/bash --create-home gitlab-runner
RUN echo "gitlab-runner ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers
USER gitlab-runner

CMD ["/bin/bash"]

Docker image for Gitlab Runner Helper

Variant 1

dockerfile
FROM gitlab/gitlab-runner-helper:x86_64-4b9e985a

USER 993:993      

CMD ["sh"]

Variant 2

dockerfile
FROM gitlab/gitlab-runner-helper:x86_64-4b9e985a

RUN addgroup -g 993 gitlab-runner
RUN adduser --system -u 993 -G gitlab-runner --home /home/gitlab-runner gitlab-runner
USER gitlab-runner

CMD ["sh"]

Run registry

bash
docker run -d -p 5000:5000 --name registry registry:2
sudo iptables -I FORWARD 1 -d 172.17.0.2 -p tcp --dport 5000 -j DROP

Instead of closing the port, it is better to specify a local port when starting the container

Запретить доступ к контейнеру из вне

bash
iptables -I DOCKER-USER -i eth0 -p tcp --dport 5000 -j DROP

Push image

bash
docker build -t 127.0.0.1:5000/gitlab-runner-dev:latest .
docker image push 127.0.0.1:5000/gitlab-runner-dev:latest

docker build -t 127.0.0.1:5000/gitlab-runner-helper:latest .
docker image push 127.0.0.1:5000/gitlab-runner-helper:latest

Settings host

Generate ssh-key

bash
ssh-keygen -t rsa
echo 'StrictHostKeyChecking=no' >> /root/.ssh/config

usermod -aG sudo gitlab-runner
su - gitlab-runner
ssh-keygen -t rsa
echo 'StrictHostKeyChecking=no' >> /home/gitlab-runner/.ssh/config

.docker-ci.yml

Example

yaml
stages:
  - deploy
  - revert
  
variables:
  DEV_HOST: $DEV_HOST
  DEV_USER: $DEV_USER
  DEV_ROOT: $DEV_ROOT
  PROD_HOST: $PROD_HOST
  PROD_USER: $PROD_USER
  PROD_PASSWORD: $PROD_PASSWORD
  PROD_ROOT: $PROD_ROOT
  FRONT_NODE_VERSION: $FRONT_NODE_VERSION
  ADMIN_FRONT_NODE_VERSION: $ADMIN_FRONT_NODE_VERSION

deploy-production:
  stage: deploy
  only:
    - master
  when: manual  
  cache:
    key:
      files:
        - local/templates/volhovec/_frontend/package.json
      prefix: "$CI_PROJECT_NAME-$CI_JOB_NAME" 
    paths:
      - local/templates/volhovec/_frontend/node_modules
  script:
    - echo "Deploying $CI_JOB_NAME $CI_COMMIT_BRANCH..."
    # Composer install
    - composer install --no-interaction --ignore-platform-reqs
    # Front install
    - ". /usr/local/nvm/nvm.sh"
    - if [ -d ../node_modules_$CI_JOB_NAME ]; then mv -fv ../node_modules_$CI_JOB_NAME local/templates/volhovec/_frontend/node_modules; fi
    - nvm use $FRONT_NODE_VERSION && cd local/templates/volhovec/_frontend && yarn install && yarn run prod && cd ../../../../
    - mv -fv local/templates/volhovec/_frontend/node_modules ../node_modules_$CI_JOB_NAME
    # Create tar.gz
    - mkdir artifacts_release && tar -czf ./artifacts_release/release.tar.gz --exclude="./artifacts_release" --exclude="./.git" --exclude="./local/templates/volhovec/_frontend/node_modules" ./
    # Download tar.gz
    - sshpass -p $PROD_PASSWORD scp ./artifacts_release/release.tar.gz $PROD_USER@$PROD_HOST:$PROD_ROOT
    - rm -rf artifacts_release
    # Deploy
    - |
      sshpass -p $PROD_PASSWORD ssh $PROD_USER@$PROD_HOST <<EOF
        cd $PROD_ROOT
        rm -rf old_release
        mkdir release && mv release.tar.gz release
        cd release && tar -xzf release.tar.gz && rm release.tar.gz
        ln -s ../bitrix bitrix && ln -s ../upload upload
        php bitrix/tools/migrate apply -f
        cd ..
        mv last_release old_release
        mv release last_release
      EOF

deploy-develop:
  stage: deploy
  only:
    - develop
  when: always
  cache:
    key:
      files:
        - local/templates/volhovec/_frontend/package.json
      prefix: "$CI_PROJECT_NAME-$CI_JOB_NAME"
    paths:
      - local/templates/volhovec/_frontend/node_modules
  script:
    - echo "Deploying $CI_JOB_NAME $CI_COMMIT_BRANCH..."
    # Composer install
    - composer install --no-interaction --ignore-platform-reqs
    # Front install
    - ". /usr/local/nvm/nvm.sh"
    - nvm use $FRONT_NODE_VERSION
    - cd local/templates/volhovec/_frontend && yarn install && yarn run prod && cd ../../../../
    # Create tar.gz
    - mkdir artifacts_release
    - tar -czf ./artifacts_release/release.tar.gz --exclude="./artifacts_release" --exclude="./.git" --exclude="./local/templates/volhovec/_frontend/node_modules" ./
    # Download tar.gz
    - sshpass -p $PROD_PASSWORD scp ./artifacts_release/release.tar.gz $DEV_USER@$DEV_HOST:$DEV_ROOT
    - rm -rf artifacts_release
    # Deploy
    - |
      ssh $DEV_USER@$DEV_HOST <<EOF
        cd $DEV_ROOT
        rm -rf old_release
        mkdir release && mv release.tar.gz release
        cd release && tar -xzf release.tar.gz && rm release.tar.gz
        cd ..
        mv last_release old_release
        mv release last_release
      EOF

revert-production:
  stage: revert
  when: manual
  only:
    - master
  needs: ["deploy-production"]
  script:
    - |
      sshpass -p $PROD_PASSWORD ssh $PROD_USER@$PROD_HOST <<EOF
        cd $PROD_ROOT
        mv last_release fail_release
        mv old_release last_release
        rm -rf fail_release
      EOF

Notify telegram chat

bash
#!/bin/bash

TIME="10"
URL="https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage"
TEXT="Deploy status: $1%0A-- -- -- -- --%0AJob:+$CI_JOB_NAME%0ABranch:+$CI_COMMIT_REF_SLUG%0AProject:+$CI_PROJECT_TITLE%0AURL:+$CI_PROJECT_URL/pipelines/$CI_PIPELINE_ID/"

curl -s --max-time $TIME -d "chat_id=$TELEGRAM_CHAT_ID&disable_web_page_preview=1&text=$TEXT" $URL >/dev/null
yaml
variables:
  TELEGRAM_BOT_TOKEN: $TELEGRAM_BOT_TOKEN
  TELEGRAM_CHAT_ID: $TELEGRAM_CHAT_ID

notify-error:
  stage: notify
  variables:
    GIT_STRATEGY: none
  script:
    - sh /home/gitlab-runner/ci-notify.sh 
  when: on_failure

Automerge

yaml
stages:
  - merge
  
merge-to-develop:
  stage: merge
  only:
    - bajdakov
    - /task_.*/
  when: always  
  script:
    - echo "Merge to develop $CI_JOB_NAME $CI_COMMIT_BRANCH..."
    - git pull "http://gitlab-ci-token:$PROJECT_ACCESS_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git" develop
    - git push "http://gitlab-ci-token:$PROJECT_ACCESS_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git" HEAD:develop
    # git@$CI_SERVER_HOST:$CI_PROJECT_PATH.git
    
merge-from-develop:
  stage: merge
  only:
    - develop
  when: always  
  script:
    - echo "Merge from develop $CI_JOB_NAME $CI_COMMIT_BRANCH..."
    - git push "http://gitlab-ci-token:$PROJECT_ACCESS_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git" HEAD:bajdakov
    # git@$CI_SERVER_HOST:$CI_PROJECT_PATH.git

Backup and restore GitLab

Backup

bash
sudo gitlab-backup create SKIP=builds,artifacts

0 2 * * * /opt/gitlab/bin/gitlab-backup create CRON=1

Recovery

bash
sudo cp 11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar /var/opt/gitlab/backups/
sudo chown git:git /var/opt/gitlab/backups/11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar

sudo gitlab-ctl stop puma
sudo gitlab-ctl stop sidekiq
# Verify
sudo gitlab-ctl status

sudo gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce

sudo gitlab-ctl reconfigure
sudo gitlab-ctl restart
sudo gitlab-rake gitlab:check SANITIZE=true

Reset runner registration tokens

bash
sudo gitlab-rails dbconsole --database main

UPDATE projects SET runners_token = null, runners_token_encrypted = null;
UPDATE namespaces SET runners_token = null, runners_token_encrypted = null;
UPDATE application_settings SET runners_registration_token_encrypted = null;
UPDATE application_settings SET encrypted_ci_jwt_signing_key = null;
UPDATE ci_runners SET token = null, token_encrypted = null;

UPDATE ci_builds SET token = null, token_encrypted = null;

Check ports

bash
sudo lsof -i -P -n

Block port

bash
iptables -I FORWARD -p tcp --dport 9000 -j DROP