How to use OpenVPN in GitHub Action workflows?
One of our clients requires a VPN connection to access their servers and we want to auto-deploy the app with a GitHub Action workflow. So let's dig in and fix it.
Prepare the .ovpn File
The approach involves separating credentials from configuration. Rather than committing credentials directly, external files are referenced in the .ovpn file:
- Replace
<ca>...</ca>withca ca.crt(store content inCA_CRTsecret) - Replace
<cert>...</cert>withcert user.crt(store content inUSER_CRTsecret) - Replace
<key>...</key>withkey user.key(store content inUSER_KEYsecret) - Replace
<tls-auth>...</tls-auth>withtls-auth tls.key(store content inTLS_KEYsecret)
For authentication, add:
auth-user-pass secret.txt
Workflow Implementation
Step 1: Install OpenVPN
- name: Install OpenVPN
run: |
sudo apt-get update
sudo apt-get --assume-yes --no-install-recommends install openvpn
Step 2: Setup VPN Config
- name: Setup VPN config
run: |
echo "${{ secrets.CA_CRT }}" > ca.crt
echo "${{ secrets.USER_CRT }}" > user.crt
echo "${{ secrets.USER_KEY }}" > user.key
echo "${{ secrets.SECRET_USERNAME_PASSWORD }}" > secret.txt
echo "${{ secrets.TLS_KEY }}" > tls.key
Step 3: Connect VPN
- name: Connect VPN
run: sudo openvpn --config ".github/vpn/config.ovpn" --log "vpn.log" --daemon
The --daemon flag runs OpenVPN in the background. The --log flag captures output to a file.
Step 4: Wait for VPN Connection
- name: Wait for a VPN connection
timeout-minutes: 1
run: until ping -c1 your-server-address; do sleep 2; done
Step 5: Deploy
- name: Deploy
run: some-command
Step 6: Cleanup
- name: Kill VPN connection
if: always()
run: |
sudo chmod 777 vpn.log
sudo killall openvpn
The if: always() condition ensures execution regardless of previous step outcomes.
Step 7: Upload Logs
- name: Upload VPN logs
uses: actions/upload-artifact@v2
if: always()
with:
name: VPN logs
path: vpn.log
Makes VPN logs available as build artifacts for debugging.
Originally published on norday.tech.