Connect VPN during CI/CD

Hello,

I need to connect to a VPN server during my deployment in .gitlab-ci.yml
I’m using openvpn but my issue is that openvpn command keep console with no return and my CI still running for ever.

I would need that my process continue if connection is ok.

Do you have an idea?

Here is my command:
sudo /usr/sbin/openvpn /home/gitlab-runner/myconf.conf

I have tried with & to put in background. Process go forward but still running at the end.

Note: I added this command in /etc/sudoers for my gitlab-runner user.

Thank you for your help

Hi Louis,

Have you tried running openvn as a deamon ?

Your command would become:
sudo /usr/sbin/openvpn --config /home/gitlab-runner/myconf.conf --daemon

Also, if your server requires authentication with a username and password, you can create a secrets.txt file with your credentials and add this to your command.
sudo /usr/sbin/openvpn --config /home/gitlab-runner/myconf.conf --auth-user-pass secrets.txt --daemon

–secrets.txt–

username
password

After this you can continue with your deploy actions.

If you have more questions, please feel free to ask.

1 Like

I would recommend you to use FastestVPN, it works very well on all platforms, further they have 7 days money back policy so in case if you have any issue, so you can refund your money back.

I know this is an old thread, but it is google result #1 when looking for this topic so I’ll share my solution here.

before_script:
  ##
  ## VPN
  ## Inspiration from: https://torguard.net/knowledgebase.php?action=displayarticle&id=138
  ## And http://forum.gitlab.com/t/connect-vpn-during-ci-cd/7585
  ## Content from Variables to files: https://stackoverflow.com/a/49418265/4396362
  ## Waiting for opnevpn connect would be better than sleeping, the closest would be https://askubuntu.com/questions/28733/how-do-i-run-a-script-after-openvpn-has-connected-successfully
  ## Maybe this would work https://unix.stackexchange.com/questions/403202/create-bash-script-to-wait-and-then-run
  ##
  - which openvpn || (apt-get update -y -qq && apt-get install -y -qq openvpn) # Install openvpn if not available.
  - cat <<< $CLIENT_OVPN > /etc/openvpn/client.conf # Move vpn config from gitlab variable to config file.
  - cat <<< $VPN_U > /etc/openvpn/pass.txt # Move vpn user from gitlab variable to pass file.
  - cat <<< $VPN_P >> /etc/openvpn/pass.txt # Move vpn password from gitlab variable to pass file.
  - cat <<< "auth-user-pass /etc/openvpn/pass.txt" >> /etc/openvpn/client.conf # Tell vpn config to use password file.
  - cat <<< "log /etc/openvpn/client.log" >> /etc/openvpn/client.conf # Tell vpn config to use log file.
  - openvpn --config /etc/openvpn/client.conf --daemon # Start openvpn with config as a deamon.
  - sleep 30s # Wait for some time so the vpn can connect before doing anything else.
  - cat /etc/openvpn/client.log # Print the vpn log.
  - ping -c 1 <IP> # Ping the server I want to deploy to. If not available this stops the deployment process.

  ##
  ## SSH
  ## Inspiration for gitlab from https://docs.gitlab.com/ee/ci/ssh_keys/
  ## Inpsiration for new key from https://www.thomas-krenn.com/de/wiki/OpenSSH_Public_Key_Authentifizierung_unter_Ubuntu
  ##
  - which ssh-agent || (apt-get update -y -qq && apt-get install openssh-client -y -qq) # Install ssh-agent if not available.
  - eval $(ssh-agent -s) # Run ssh-agent.
  - mkdir -p ~/.ssh # Create ssh directory.
  - cat <<< $SSH_PRIVATE_KEY > ~/.ssh/id_rsa # Move ssh key from gitlab variable to file.
  - chmod 700 ~/.ssh/id_rsa  # Set permissions so only I am allowed to access my ssh key.
  - ssh-add # Add the key (no params -> default file name assumed).
  - cat <<< $SSH_KNOWN_HOSTS_DMS > ~/.ssh/known_hosts # Add the servers SSH Key to known_hosts prevent man in the middle attack.

When you add this before_script you are connected via VPN and you can simply use ssh and rsync as:
ssh username@ ‘command to execute’

I’m not completely happy with the sleep, but it was the easiest, yet reliable thing I could come up with.
If you have any suggestions for improvements let me know :slight_smile:

HTH

2 Likes

This is good, however my VPN connection expects Authenticator code as well

1 Like

@bechtold did you run this on a gitlab shared runner? Asking because I’m getting the error

Options error: You must define TUN/TAP device (--dev)

which I believe is caused by the docker environment not passing the network devices, or something like that. I don’t fully understand it though since shared runners are running in privileged mode so should have full access.

Yes, I did and didn’t setup anything else. Maybe something changed on the shared runners? Haven’t been working on that project for a while, so I can’t say if it still works.

Thanks for your reply! Would you mind sharing your .gitlab-ci.yml if you still have it? Much appreciated.

Perfect! It worked to me! Thanks!
However later I will try to make a solution to get rid of the sleep

I have applied this script to use as part of a deployment step that needs to happen over a VPN connection but cannot get it to work. From what I have googled it seams a very hit or miss thing, with some saying it just works and others saying just to use X or Y flag. But nothing fits the bill.

Has anyone had any luck getting this to operate on a shared runner?

I have a shared runner on a server with:

  • Ubuntu 20.04, up to date
  • GitLab Runner
    • Version: 13.5.0
    • Git revision: ece86343
    • Git branch: 13-5-stable
    • GO version: go1.13.8
    • Built: 2020-10-20T12:05:22+0000
    • OS/Arch: linux/amd64
  • Docker 19.03.13, build 4484c46d9d

My current config.toml file has

[runners.docker]
tls_verify = false
image = "ubuntu:20.04"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache"]
shm_size = 0
devices = ["/dev/net/tun"]

I have tried various combinations before my current config above:

privileged = true/false
devices = ["/dev/net/tun"]
cap_add = ["NET_ADMIN"]

From my understanding using privileged = true should make using cap_add unneeded but I tried both as well anyways

Running the original script resulted in an error of

Thu Oct 22 16:22:11 2020 ERROR: Cannot open TUN/TAP dev /dev/net/tun: No such file or directory (errno=2)

Doing some googling I applied the following suggestion to the before_script section of my .gitlab-ci.yml file:

  • mkdir -p /dev/net
  • mknod /dev/net/tun c 10 200
  • chmod 600 /dev/net/tun

This resulted in a new error of

Thu Oct 22 16:26:37 2020 ERROR: Cannot ioctl TUNSETIFF tun: Operation not permitted (errno=1)

More googling says to just run the openvpn command via sudo but docker does not like that, even in privileged mode.

Any ideas?

Did you figure if this is possible?

For me it worked with

[runners.docker]
tls_verify = false
image = “ruby:2.5”
privileged = false
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = [“/cache”]
shm_size = 0
devices = [“/dev/net/tun”]
cap_add = [“NET_ADMIN”]