不建议使用docker in docker,会有安全风险。
在.gitlab-ci.yml
中,在job里面定义tags
就可以用设置了某个tag的runner来执行。对于同时有多个runner而且executor类型不同的情况下是很有必要的。
获取token
每个runner都需要自己的token。
- 首先以管理员账户登录gitlab,然后点击“Configure GitLab”,点左侧CI/CD,子菜单点击Runners
- 点击右上角New instance runner,根据自己的需求填内容(比如钩上Run untagged jobs)
- 拉到页面最下面,点击Create,记下token。
Virtualbox
以Archlinux作为Host,安装Ubuntu 22.04 LTS作为Guest。内容主要参考自:
- Setting Up a Self Managed GitLab Runner with the VirtualBox Executor - Lup Peng
- Unattended Headless Install of Ubuntu Server 22.04 on VirtualBox 7 via VBoxManage CLI - Lup Peng
安装Virtualbox
根据Archwiki VirtualBox,安装virtualbox
及内核模块virtualbox-host-dkms
。由于使用unattended installation,所以需要安装AUR上的virtualbox-unattended-templates。然后手动执行以下命令加载内核模块:
1
sudo vboxreload
初步安装虚拟机
使用vboxmanage list ostypes
来寻找Ubuntu对应的ID是什么,通常来说是Ubuntu_64
。
接下来就要确定是使用gitlab-runner用户还是用root来使用虚拟机了。我们直接使用gitlab-runner用户来使用虚拟机。在Archlinux上,gitlab-runner
包会创建一个gitlab-runner用户,通过sudo grep gitlab-runner /etc/passwd
可知它的HOME目录在/var/lib/gitlab-runner
。接下来多数的操作都会在这个目录下执行。
首先是创建基本的配置文件、配置内存和CPU数量 1 :
1
2
3
4
5
6
# 新建并注册虚拟机
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner vboxmanage createvm --name gitlab-runner --ostype Ubuntu_64 --register
# 配置内存为4096M
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner vboxmanage modifyvm gitlab-runner --memory 4096
# 配置CPU数量为2
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner vboxmanage modifyvm gitlab-runner --cpus 2
完成这三步后会有以下目录和文件:
/var/lib/gitlab-runner/
`-- 'VirtualBox VMs'/
`-- gitlab-runner/
`-- gitlab-runner.vbox
`-- virtualbox的一些配置文件...
接下来要创建虚拟机的磁盘并连接到虚拟机。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 给虚拟机创建磁盘控制器
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage storagectl gitlab-runner --name "SATA" --add sata --bootable on --hostiocache off
# 创建目录用来存放磁盘
sudo -u gitlab-runner \
mkdir -p /var/lib/gitlab-runner/vmdisks
# 创建40GB容量的动态扩展磁盘(Standard类型)
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage createmedium \
--filename "/var/lib/gitlab-runner/vmdisks/VirtualBox VMs/gitlab-runner/gitlab-runner.vdi" \
--size 40000 \
--variant Standard
# 连接到磁盘控制器
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage storageattach gitlab-runner \
--storagectl "SATA" --port 0 --device 0 \
--type hdd \
--medium "/var/lib/gitlab-runner/vmdisks/VirtualBox VMs/gitlab-runner/gitlab-runner.vdi"
现在的目录结构有:
/var/lib/gitlab-runner/
|-- VirtualBox VMs/
| `-- gitlab-runner/
| |-- gitlab-runner.vbox
| |-- virtualbox的一些配置文件...
| `-- virtualbox的一些配置文件...
`-- vmdisks/
`-- VirtualBox VMs/
`-- gitlab-runner/
`-- gitlab-runner.vdi
为了能够无人参与自动完成安装,需要写一个autoinstall的配置文件并且用Python起一个HTTP文件服务器让虚拟机能够读取这个文件。关于autoinstall的配置文件,可以参考Ubuntu的配置文档:Automated Server install quickstart。作为中国用户,除了username
、password
之外还需要关注apt源;因为是headless模式,所以需要安装ssh才能在安装好之后操作虚拟机。此外,还需要用whois
包中的mkpasswd
来将明文密码加密成password
项的内容:
1
2
# 生成password项内容
mkpasswd --method=SHA-512 明文密码
这里是一个示例配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#cloud-config
autoinstall:
version: 1
identity:
hostname: gitlab-runner
# 注意,用双引号括起来是必须的,不要省略掉
password: "之前的mkpasswd命令的输出结果"
username: 虚拟机内用户名
apt:
preserve_sources_list: false
mirror-selection:
primary:
# 用清华的apt镜像源加速安装过程
- uri: "http://mirrors.tuna.tsinghua.edu.cn/ubuntu/"
fallback: abort
ssh:
install-server: true
# 设置时区
timezone: "Asia/Shanghai"
将autoinstall的配置文件放在一个目录里(这里是新建了一个www目录),然后用python启动一个http服务器来serve这个文件:
1
2
3
4
5
6
7
8
9
# 新建目录
sudo -u gitlab-runner mkdir /var/lib/gitlab-runner/www
# 将配置文件放在www目录下的user-data文件里
# 然后启动python
cd /var/lib/gitlab-runner/www
python3 -m http.server 3003
# 测试是否能获取内容,自己替换IP
curl http://host的IP:3003/user-data
# 输出跟你的配置文件内容一样的话就可以继续了
现在终于可以启动无人值守安装了(请自己替换host的IP
):
1
2
3
4
5
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage unattended install gitlab-runner \
--iso UbuntuISO文件的路径 \
--extra-install-kernel-parameters="autoinstall cloud-config-url=http://host的IP:3003/user-data ds=nocloud-net\;s=http://host的IP:3003/" \
--start-vm=headless
接下来就是等待并用以下命令检查是否安装完毕。在虚拟机完成安装、重启进入系统之前,ResetCounter都会是0,所以变成1的时候就是可以了:
1
2
3
4
# 如果不记得名字,可以用这个命令来看
# sudo -u gitlab-runner HOME=/var/lib/gitlab-runner vboxmanage list runningvms
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage guestproperty enumerate gitlab-runner
配置虚拟机
SSH连接虚拟机
默认配置下虚拟机是用NAT来共享主机的网络以及和主机通讯的。那么就需要新建一个NAT端口转发来实现从主机上连接虚拟机。假设我们要将主机上的2222端口映射到虚拟机的22端口来实现ssh通讯,那么就用以下命令:
1
2
3
4
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage controlvm gitlab-runner natpf1 "guestssh,tcp,,2222,,22"
# 虚拟机是停机状态,就要用modifyvm了
# sudo -u gitlab-runner HOME=/var/lib/gitlab-runner vboxmanage modifyvm gitlab-runner natpf1 "guestssh,tcp,,2222,,22"
现在我们就可以用以下ssh命令连接虚拟机了:
1
2
# 这里会提示输入密码
ssh localhost -p 2222 -l 用户名
配置环境
这里说的是安装未来的Pipeline运行的时候需要的软件,特别是安装gitlab-runner
2来提供上传下载artifacts的功能。
如果你要用docker3,那就要配置root的ssh key登录了。怎么生成keypair并部署的文章很多,这里就不说了。
需要注意的是,需要把~/.bash_logout
文件的下面几行去掉4:
1
2
3
if [ "$SHLVL" = 1 ]; then
[ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q
fi
Host Key Verify
我们在ssh某个主机的时候,如果是第一次连接,都会提示是否信任这个主机。但是在non-interactive的情况下,如果不提前做verify就会直接连接失败。gitlab-runner的virtualbox executor是通过ssh连接虚拟机的,自然也会遇到这个问题,所以需要我们提前做verify。在主机上运行:
1
2
sudo -u gitlab-runner mkdir -p /var/lib/gitlab-runner/.ssh
sudo -u gitlab-runner ssh-keyscan -p 2222 -H localhost >> /var/lib/gitlab-runner/.ssh/known_hosts
虚拟机连接主机
很多时候可能我们需要让虚拟机能够连接主机,比如访问主机上的http服务,或者SSH回主机发布文件之类的。我们需要用到host-only模式的网卡来实现我们的目的。但是virtualbox似乎在这方面有bug,vboxnet0经常什么都行就是ssh会提示protocol not available
。所以我们连续创建两个host-only并使用第二个来避免这个问题:
1
2
3
4
5
6
7
8
9
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage hostonlyif create
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage hostonlyif create
# 命令通常会输出Interface 'vboxnetX' was successfully created,X是数字
# 一般来说是按顺序的,所以我们使用vboxnet1
# 看vboxnet1的IP范围来确定我们后面要在虚拟机里配置的static IP
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage list hostonlyifs
其中list hostonlyifs
会有类似如下输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Name: vboxnet0
GUID: 786f6276-656e-4074-8000-0a0027000000
DHCP: Disabled
IPAddress: 192.168.56.1
NetworkMask: 255.255.255.0
IPV6Address:
IPV6NetworkMaskPrefixLength: 0
HardwareAddress: 0a:00:27:00:00:00
MediumType: Ethernet
Wireless: No
Status: Up
VBoxNetworkName: HostInterfaceNetworking-vboxnet0
Name: vboxnet1
GUID: 786f6276-656e-4174-8000-0a0027000001
DHCP: Disabled
IPAddress: 192.168.57.1
NetworkMask: 255.255.255.0
IPV6Address:
IPV6NetworkMaskPrefixLength: 0
HardwareAddress: 0a:00:27:00:00:01
MediumType: Ethernet
Wireless: No
Status: Up
VBoxNetworkName: HostInterfaceNetworking-vboxnet1
可见vboxnet1的Gateway是192.168.57.1,可用范围是192.168.57.2-192.168.57.254。现在把虚拟机关机并把网卡连上去:
1
2
3
4
5
6
7
8
9
# 关机,你也可以用SSH登录之后关机
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage controlvm gitlab-runner poweroff
# 上网卡
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage modifyvm gitlab-runner --nic2 hostonly --hostonlyadapter2 vboxnet1
# 开机
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
vboxmanage startvm gitlab-runner --type headless
开机之后SSH登录,配置netplan来设置static IP:
1
2
3
# 首先要知道是哪个网卡,一般来说是enp开头的,但是还没有IP地址的那个
ip a
# 记下名字,我的情况是enp0s8
然后编辑虚拟机内的/etc/netplan
,你可以在这个目录下新建形如两位数字-字母.yaml
的文件来写配置,也可以直接编辑已有的00-installer-config.yaml
。我们新建一个01-hostonly.yaml
来写配置:
1
2
3
4
5
6
7
8
9
10
11
network:
ethernets:
enp0s8:
dhcp4: no
addresses: [192.168.57.2/24]
routes:
- to: 192.168.57.0/24
via: 192.168.57.1
nameservers:
addresses: [192.168.57.1]
version: 2
保存之后执行netplan apply
,此时执行ip a
就应该看到enp0s8
有我们配置的IP地址(192.168.57.2)了。
Tips and Tricks
- 你可以在/etc/hosts里增一条记录
192.168.57.1 tohost
,然后在其他需要用指向host的ip的地方用tohost来代替(比如将ssh 192.168.57.1
换成ssh tohost
)。这样的话未来host-only网卡的地址有所变化,也只需要改一个地方就行了。 - 从虚拟机non-interactive SSH连接主机,也是要提前做host key verify的。
- 用
systemd-analyze critical-chain
可以看是谁让启动速度摸爆。通常来说都是systemd-networkd-wait-online.service,其实只需要把它的ExecStart
改成ExecStart=/lib/systemd/systemd-networkd-wait-online -4 --any
就行了。 - 如果要配置
http_proxy
等环境变量,可以编辑/etc/envrionment
来全系统生效。 - 在配置完成、做了
apt upgrade
等,反正就是你觉得自己做了一个很fantastic的变更,当前状态是适合某个大头虾rm -rf /
之后回退到的环境,那就可以用vboxmanage snapshot gitlab-runner take "Base State $(date)"
来创建一个snapshot。记得加上适当的sudo前缀5。- 如果是开机状态,加上
--live
参数(仅限创建,所有的回退都需要关机再执行) - 回退到最近的snapshot是
vboxmanage snapshot gitlab-runner restorecurrent
- 列出所有snapshot是
vboxmanage snapshot gitlab-runner list
- 如果是开机状态,加上
注册runner
注册
使用以下命令来注册runner:
1
2
3
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner \
gitlab-runner register --url 你的gitlab的url \
--token 之前获取的token
根据提示来输入回答,主要是executor需要输入virtualbox,虚拟机名字要输对(按本文例子就是gitlab-runner);至于SSH用户、密码、key,输错了或者想改的话可以直接修改/var/lib/gitlab-runner/.gitlab-runner/config.toml
的[runners.ssh]
:
- 对于密码认证,需要设置
user
和password
- 对于密钥认证,需要设置
user
和identity_file
,后者是密钥文件的路径
注册完成之后,需要做一份修改版的gitlab-runner.service
来负责后台运行。
systemd service
由于我们是用gitlab-runner这个用户来创建的虚拟机,所以原装的gitlab-runner.service用root启动的不好使,要搞一份自定义版:sudo cp /usr/lib/systemd/system/gitlab-runner.service /etc/systemd/system/gitlab-runner-vm.service
,然后修改/etc/systemd/system/gitlab-runner-vm.service
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Unit]
Description=GitLab Runner Running VM
After=syslog.target network.target
ConditionFileIsExecutable=/usr/bin/gitlab-runner
[Service]
User=gitlab-runner
StartLimitInterval=5
StartLimitBurst=10
ExecStart=/usr/bin/gitlab-runner "run" "--working-directory" "/var/lib/gitlab-runner" "--config" "/var/lib/gitlab-runner/.gitlab-runner/config.toml"
Restart=always
RestartSec=120
SyslogIdentifier=gitlab-runner-vm
[Install]
WantedBy=multi-user.target
主要是修改User,修改ExecStart。改好了之后sudo systemctl daemon-reload
,然后就可以sudo systemctl enable --now gitlab-runner-vm.service
了。在gitlab的runner页面,这个runner应该会绿灯了。
自动启动虚拟机
根据今天的观测,貌似如果不提前启动,pipeline会报错说验证server SSL失败,没有CA什么的。在我手动启动了VM之后就没事了。所以这里附上开机启动虚拟机的systemd service:
1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=Start VirtualBox VM: gitlab-runner
After=network.target
[Service]
User=gitlab-runner
ExecStart=/usr/bin/VBoxManage startvm gitlab-runner --type headless
ExecStop=/usr/bin/VBoxManage controlvm gitlab-runner acpipowerbutton
Restart=on-failure
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Docker
首先要安装gitlab-runner和docker,怎么安装就不在这里讲了。然后可以先不启动systemd service,先注册。下面的流程是创建instance runner的。
注册
执行sudo gitlab-runner register
,根据提示输入gitlab实例的url、刚才的token、runner的备注,主要是executor类型需要选择docker。完成注册之后还可以编辑/etc/gitlab-runner/config.toml
加入一些额外内容。
-
在
[[runners]]
下面新增一行clone_url,内容建议是你的url的https版本,例如clone_url = "https://git.mutebot.net"
。这是因为runner们用的token认证方式是要求用https的,而因为各种配置错误可能会导致gitlab生成http的链接,导致连clone都做不了,直接提示HTTP Basic Auth Denied。 -
在
[[runners.docker]]
下面,可以添加extra_hosts,作用跟docker-compose.yaml里的extra_hosts一样。例如添加这行就可以让后面执行pipeline的时候可以用host.internal来访问host:extra_hosts = ["host.internal:host-gateway"]
其实这个很有用,特别是在host上提供代理服务,让git能够用proxy来执行,加速很多;或者让alpine用proxy来处理apk,真的快很多。
-
搭配2,添加以下内容让gitlab-runner的docker和git能用proxy:
1 2
pre_get_sources_script = "git config --global http.proxy $HTTP_PROXY; git config --global https.proxy $HTTPS_PROXY" environment = ["https_proxy=http://host.internal:8888", "http_proxy=http://host.internal:8888", "HTTPS_PROXY=host.internal:8888", "HTTP_PROXY=host.internal:8888"]
配置gitlab-runner的proxy
首先是gitlab-runner.service的代理设置,其实就是配置Environment。用sudo systemctl edit gitlab-runner.service
,在适当位置填入以下内容:
1
2
3
4
5
6
[Service]
Environment="HTTP_PROXY=http://docker0_interface_ip:8888/"
Environment="HTTPS_PROXY=http://docker0_interface_ip:8888/"
Environment="http_proxy=http://docker0_interface_ip:8888/"
Environment="https_proxy=http://docker0_interface_ip:8888/"
Environment="NO_PROXY=localhost,docker,*.lan,*.mutebot.net"
记得把docker0_interface_ip
改成你的机子上的docker0的ip(用ip a
可以看到)。这个配置也意味着你的代理软件监听这个ip或者就是监听0.0.0.0(建议监听0.0.0.0,因为容器的网络可能会变,跟docker0的ip不一样,这样前面的配置就没用了)。防火墙记得放行。
然后是配置docker client,首先看看gitlab-runner的用户的home目录,用sudo grep gitlab-runner /etc/passwd
来看。比如它的home目录是/home/gitlab-runner
,那么执行以下命令来创建docker client会读取的config.json:
1
2
sudo -u gitlab-runner mkdir -p /home/gitlab-runner/.docker
sudo -u gitlab-runner vim /home/gitlab-runner/.docker/config.json
内容是(docker0_interface_ip
同上需要根据你的情况替换):
1
2
3
4
5
6
7
8
9
10
11
{
"proxies":
{
"default":
{
"httpProxy": "http://docker0_interface_ip:8888",
"httpsProxy": "http://docker0_interface_ip:8888",
"noProxy": "localhost,docker,*.lan,*.mutebot.net"
}
}
}
启动gitlab-runner
sudo systemctl enable --now gitlab-runner
。
杂项
CI的proxy问题
关于在CI里面用proxy的问题,比如用alpine,那就要手动export才行,比如:
1
2
3
4
5
6
7
8
image: alpine
stages:
- clone
clone:
stage: clone
script:
- export http_proxy=http://host.internal:8888
- export https_proxy=http://host.internal:8888
CI的SSH
参考官方文档可以实现。主要是三步:
- 生成ssh keypair并分发到对应的机子上
- 生成known_hosts
- 配置相应的variables并修改CI配置。
生成SSH Keypair和生成known_hosts
1
ssh-keygen -t ed25519 -C "备注"
记得生成无密码的key,不然无法解锁。然后把.pub结尾的文件的内容放到server的目标用户的~/.ssh/authorized_keys
里面。
然后要用ssh-keyscan
来获取known_hosts的内容。这里有一些技巧:
-
你可以在任何机子上用
ssh-keyscan 服务器的IP或域名
来获取known_hosts,甚至可以在目标上对自己使用ssh-keyscan 127.0.0.1
-
如果不是标准22端口,那么用
-p 端口号
来设置 -
但是如果runner用来访问目标的IP或者域名不同于1.的命令的话,就需要修改一下输出内容了。例如目标就是运行runner的docker的host,在host上对自己使用了
ssh-keyscan 127.0.0.1
生成了以下内容(具体key内容用****
隐藏了):1 2 3 4 5 6 7 8
# 127.0.0.1:22 SSH-2.0-OpenSSH_9.5 # 127.0.0.1:22 SSH-2.0-OpenSSH_9.5 [127.0.0.1]:22 ssh-ed25519 **** # 127.0.0.1:22 SSH-2.0-OpenSSH_9.5 [127.0.0.1]:22 ssh-rsa **** # 127.0.0.1:22 SSH-2.0-OpenSSH_9.5 [127.0.0.1]:22 ecdsa-sha2-nistp256 **** # 127.0.0.1:22 SSH-2.0-OpenSSH_9.5
但是通过前面的配置步骤,runner的docker是用
host.internal
来访问host的话,就应该改成下面这个样子:1 2 3 4 5 6 7 8
# host.internal:22 SSH-2.0-OpenSSH_9.5 # host.internal:22 SSH-2.0-OpenSSH_9.5 [host.internal]:22 ssh-ed25519 **** # host.internal:22 SSH-2.0-OpenSSH_9.5 [host.internal]:22 ssh-rsa **** # host.internal:22 SSH-2.0-OpenSSH_9.5 [host.internal]:22 ecdsa-sha2-nistp256 **** # host.internal:22 SSH-2.0-OpenSSH_9.5
端口号也会根据你用的
-p
而不同,请根据实际情况改。
设置Variable
在仓库的左栏,点击Settings,CI/CD,然后点Variables,创建两个File类型的Variable:
- Key是
SSH_KNOWN_HOSTS
,Value是前面生成的known_hosts,Type是File - Key是
SSH_PRIVATE_KEY
,Value是前面生成的无密码的Key的内容,Type是File。注意结尾一定要有一个空行,不然会导致导入失败。
就可以了,使用方式参见下例。
rsync将结果复制到目标机上
这个ci配置的效果是将一个空的html复制到host上的/var/www/default/index.html
。假设已经将前文的public key部署到host上的someuser的home目录的.ssh/authorized_keys
里面了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
image: alpine
stages:
- clone
variables:
GIT_DEPTH: "3"
clone:
stage: clone
before_script:
- export http_proxy=http://host.internal:8888
- export https_proxy=http://host.internal:8888
# 安装openssh和rsync
- apk add openssh rsync
# 启动ssh-agent
- eval $(ssh-agent -s)
# 添加SSH的private key到ssh-agent
- chmod 400 "$SSH_PRIVATE_KEY"
- ssh-add "$SSH_PRIVATE_KEY"
# 创建.ssh目录并配置好权限
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
# 把known_hosts复制到目标位置
- cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- export http_proxy=http://host.internal:8888
- export https_proxy=http://host.internal:8888
- touch test.html
- rsync -rvzh --delete -e 'ssh -p 22' test.html someuser@host.internal:/var/www/default/index.html
反正就,很神奇地就自动调用ssh-agent里面的private key来认证了。
参考
-
生成SSH Keypair:Generating a new SSH key and adding it to the ssh-agent - Github
-
Docker Executor使用SSH:Gitlab Docs - SSH Keys
-
Virtualbox的snapshot用法:vboxmanage snapshot - oracle
-
关于vboxmanage的modifyvm指令可以配置的内容可以参考:VBoxManage modifyvm。 ↩
-
https://www.fosstechnix.com/install-gitlab-runner-on-ubuntu-22-04-lts/或者 https://docs.gitlab.com/runner/install/linux-repository.html ↩
-
https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository ↩
-
https://docs.gitlab.com/runner/shells/#shell-profile-loading ↩
-
所有vboxmanage命令都需要用对应的用户来do,而且因为sudo对HOME环境变量的处理不一,所以都需要手动设定HOME,比如
sudo -u gitlab-runner HOME=/var/lib/gitlab-runner
↩