diff --git a/add-client-openvpn.yaml b/add-client-openvpn.yaml
new file mode 100644
index 0000000..e67333a
--- /dev/null
+++ b/add-client-openvpn.yaml
@@ -0,0 +1,14 @@
+- name: Add OpenVPN client
+ hosts: clubelec_ovh_vm2
+ vars_prompt:
+ - name: client
+ prompt: Name of the OpenVPN client
+ private: false
+ tasks:
+ - name: Create an .ovpn file for the user
+ script: ./bash/add-client-openvpn.sh {{ client }}
+ - name: Retrive .ovpn file
+ fetch:
+ src: ./{{ client }}.ovpn
+ dest: ./{{ client }}.ovpn
+ flat: yes
\ No newline at end of file
diff --git a/ansible.cfg b/ansible.cfg
new file mode 100644
index 0000000..83ca37a
--- /dev/null
+++ b/ansible.cfg
@@ -0,0 +1,8 @@
+[defaults]
+inventory = ./inventory.ini
+
+[privilege_escalation]
+become=True
+become_method=sudo
+become_ask_pass=True
+become_user=root
\ No newline at end of file
diff --git a/bash/add-client-openvpn.sh b/bash/add-client-openvpn.sh
new file mode 100644
index 0000000..a03f265
--- /dev/null
+++ b/bash/add-client-openvpn.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+# Get username
+USER=$1
+
+# Get current folder
+FOLDER=$(pwd)
+
+# Add user
+USEREXISTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c -E "/CN=$USER\$")
+if [[ $USEREXISTS == '1' ]]; then
+ exit 0
+else
+ cd /etc/openvpn/easy-rsa/ || return
+ ./easyrsa --batch build-client-full "$USER" nopass
+fi
+
+cd "$FOLDER" || exit
+
+# Generate client file
+cp /etc/openvpn/client-template.txt "$FOLDER/$USER.ovpn"
+{
+ echo ""
+ cat "/etc/openvpn/easy-rsa/pki/ca.crt"
+ echo ""
+ echo ""
+ awk '/BEGIN/,/END CERTIFICATE/' "/etc/openvpn/easy-rsa/pki/issued/$USER.crt"
+ echo ""
+ echo ""
+ cat "/etc/openvpn/easy-rsa/pki/private/$USER.key"
+ echo ""
+ echo ""
+ cat /etc/openvpn/tls-crypt.key
+ echo ""
+} >>"$FOLDER/$USER.ovpn"
diff --git a/bash/install-openvpn.sh b/bash/install-openvpn.sh
new file mode 100644
index 0000000..94b76ab
--- /dev/null
+++ b/bash/install-openvpn.sh
@@ -0,0 +1,156 @@
+#!/bin/bash
+
+IP=$(curl -s https://ifconfig.me)
+PORT=443
+PROTOCOL=tcp
+
+# Get the "public" interface from the default route
+NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)
+
+# Install OpenVPN
+apt-get install -y openvpn wget curl
+
+# Install the latest version of easy-rsa from source
+wget -O ~/easy-rsa.tgz https://github.com/OpenVPN/easy-rsa/releases/download/v3.1.2/EasyRSA-3.1.2.tgz
+mkdir -p /etc/openvpn/easy-rsa
+tar xzf ~/easy-rsa.tgz --strip-components=1 --no-same-owner --directory /etc/openvpn/easy-rsa
+rm -f ~/easy-rsa.tgz
+cd /etc/openvpn/easy-rsa/ || return
+echo "set_var EASYRSA_ALGO ec" >/etc/openvpn/easy-rsa/pki/vars
+echo "set_var EASYRSA_CURVE prime256v1" >>/etc/openvpn/easy-rsa/pki/vars
+
+# Generate a random, alphanumeric identifier of 16 characters for CN and one for server name
+SERVER_CN="cn_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"
+SERVER_NAME="server_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"
+
+# Create the PKI, set up the CA, the DH params and the server certificate
+./easyrsa init-pki
+./easyrsa --batch --req-cn="$SERVER_CN" build-ca nopass
+./easyrsa --batch build-server-full "$SERVER_NAME" nopass
+EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
+openvpn --genkey --secret /etc/openvpn/tls-crypt.key
+
+# Move all the generated files
+cp pki/ca.crt pki/private/ca.key "pki/issued/$SERVER_NAME.crt" "pki/private/$SERVER_NAME.key" /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn
+
+# Make cert revocation list readable for non-root
+chmod 644 /etc/openvpn/crl.pem
+
+# Generate server.conf
+echo "port $PORT" >/etc/openvpn/server.conf
+echo "proto $PROTOCOL" >>/etc/openvpn/server.conf
+echo "dev tun
+user nobody
+group nogroup
+persist-key
+persist-tun
+keepalive 10 120
+topology subnet
+server 10.8.0.0 255.255.255.0
+ifconfig-pool-persist ipp.txt" >>/etc/openvpn/server.conf
+sed -ne 's/^nameserver[[:space:]]\+\([^[:space:]]\+\).*$/\1/p' '/etc/resolv.conf' | while read -r line; do
+ echo "push \"dhcp-option DNS $line\"" >>/etc/openvpn/server.conf
+done
+echo "push \"redirect-gateway def1 bypass-dhcp\"
+dh none
+ecdh-curve prime256v1
+tls-crypt tls-crypt.key
+crl-verify crl.pem
+ca ca.crt
+cert $SERVER_NAME.crt
+key $SERVER_NAME.key
+auth SHA256
+cipher AES-128-GCM
+ncp-ciphers AES-128-GCM
+tls-server
+tls-version-min 1.2
+tls-cipher TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256
+client-config-dir /etc/openvpn/ccd
+status /var/log/openvpn/status.log
+verb 3" >>/etc/openvpn/server.conf
+
+# Create client-config-dir dir
+mkdir -p /etc/openvpn/ccd
+
+# Create log dir
+mkdir -p /var/log/openvpn
+
+# Enable routing
+echo 'net.ipv4.ip_forward=1' >/etc/sysctl.d/99-openvpn.conf
+
+# Apply sysctl rules
+sysctl --system
+
+# Don't modify package-provided service
+cp /lib/systemd/system/openvpn\@.service /etc/systemd/system/openvpn\@.service
+
+# Workaround to fix OpenVPN service on OpenVZ
+sed -i 's|LimitNPROC|#LimitNPROC|' /etc/systemd/system/openvpn\@.service
+
+# Another workaround to keep using /etc/openvpn/
+sed -i 's|/etc/openvpn/server|/etc/openvpn|' /etc/systemd/system/openvpn\@.service
+
+systemctl daemon-reload
+systemctl enable openvpn@server
+systemctl restart openvpn@server
+
+# Add iptables rules in two scripts
+mkdir -p /opt/holepunch-openvpn-iptables
+
+# Script to add rules
+echo "#!/bin/sh
+iptables -t nat -I POSTROUTING 1 -s 10.8.0.0/24 -o $NIC -j MASQUERADE
+iptables -I INPUT 1 -i tun0 -j ACCEPT
+iptables -I FORWARD 1 -i $NIC -o tun0 -j ACCEPT
+iptables -I FORWARD 1 -i tun0 -o $NIC -j ACCEPT
+iptables -I INPUT 1 -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >/opt/holepunch-openvpn-iptables/add-openvpn-rules.sh
+
+# Script to remove rules
+echo "#!/bin/sh
+iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o $NIC -j MASQUERADE
+iptables -D INPUT -i tun0 -j ACCEPT
+iptables -D FORWARD -i $NIC -o tun0 -j ACCEPT
+iptables -D FORWARD -i tun0 -o $NIC -j ACCEPT
+iptables -D INPUT -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >/opt/holepunch-openvpn-iptables/remove-openvpn-rules.sh
+
+chmod +x /opt/holepunch-openvpn-iptables/add-openvpn-rules.sh
+chmod +x /opt/holepunch-openvpn-iptables/remove-openvpn-rules.sh
+
+# Handle the rules via a systemd script
+echo "[Unit]
+Description=iptables rules for OpenVPN
+Before=network-online.target
+Wants=network-online.target
+[Service]
+Type=oneshot
+ExecStart=/opt/holepunch-openvpn-iptables/add-openvpn-rules.sh
+ExecStop=/opt/holepunch-openvpn-iptables/remove-openvpn-rules.sh
+RemainAfterExit=yes
+[Install]
+WantedBy=multi-user.target" >/etc/systemd/system/holepunch-openvpn-iptables.service
+
+# Enable service and apply rules
+systemctl daemon-reload
+systemctl enable holepunch-openvpn-iptables
+systemctl start holepunch-openvpn-iptables
+
+# Generate a template for client
+echo "client
+proto tcp-client
+remote $IP $PORT
+dev tun
+resolv-retry infinite
+nobind
+persist-key
+persist-tun
+remote-cert-tls server
+verify-x509-name $SERVER_NAME name
+auth SHA256
+auth-nocache
+cipher AES-128-GCM
+tls-client
+tls-version-min 1.2
+tls-cipher TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256
+ignore-unknown-option block-outside-dns
+setenv opt block-outside-dns # Prevent Windows 10 DNS leak
+verb 3" >>/etc/openvpn/client-template.txt
diff --git a/bash/revoke-client-openvpn.sh b/bash/revoke-client-openvpn.sh
new file mode 100644
index 0000000..1ad6b0f
--- /dev/null
+++ b/bash/revoke-client-openvpn.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# Get username
+USER=$1
+
+# Get current folder
+FOLDER=$(pwd)
+
+# Remove user
+cd /etc/openvpn/easy-rsa/ || return
+./easyrsa --batch revoke "$USER"
+EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
+rm -f /etc/openvpn/crl.pem
+cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
+chmod 644 /etc/openvpn/crl.pem
+rm "$FOLDER/$USER.ovpn"
+sed -i "/^$USER,.*/d" /etc/openvpn/ipp.txt
+cp /etc/openvpn/easy-rsa/pki/index.txt{,.bk}
+exit
diff --git a/install-openvpn.yaml b/install-openvpn.yaml
new file mode 100644
index 0000000..80e6b9a
--- /dev/null
+++ b/install-openvpn.yaml
@@ -0,0 +1,5 @@
+- name: Install OpenVPN
+ hosts: clubelec_ovh_vm2
+ tasks:
+ - name: Copy and execute bash script
+ script: ./bash/install-openvpn.sh
\ No newline at end of file
diff --git a/inventory.ini b/inventory.ini
new file mode 100644
index 0000000..2c6005b
--- /dev/null
+++ b/inventory.ini
@@ -0,0 +1,2 @@
+[clubelec_ovh_vm2]
+clubelec-ovh-vm2
\ No newline at end of file
diff --git a/revoke-client-openvpn.yaml b/revoke-client-openvpn.yaml
new file mode 100644
index 0000000..4c366da
--- /dev/null
+++ b/revoke-client-openvpn.yaml
@@ -0,0 +1,9 @@
+- name: Revoke OpenVPN client
+ hosts: clubelec_ovh_vm2
+ vars_prompt:
+ - name: client
+ prompt: Name of the OpenVPN client to revoke
+ private: false
+ tasks:
+ - name: Revoke OpenVPN client
+ script: ./bash/revoke-client-openvpn.sh {{ client }}
\ No newline at end of file