Parcourir la source

Merge pull request #117 from YunoHost-Apps/testing

Testing | Packaging v2 + generate config during upgrade + Add hook scripts
HgO il y a 1 an
Parent
commit
c86c653298

+ 1 - 1
ALL_README.md

@@ -1,6 +1,6 @@
 # All available README files by language
 
 - [Read the README in English](README.md)
+- [Irakurri README euskaraz](README_eu.md)
 - [Lire le README en français](README_fr.md)
 - [Le o README en galego](README_gl.md)
-- [Leggi il “README” in italiano](README_it.md)

+ 4 - 7
README.md

@@ -9,14 +9,14 @@ It shall NOT be edited by hand.
 
 [![Install VPN Client with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=vpnclient)
 
-*[Read this README is other languages.](./ALL_README.md)*
+*[Read this README in other languages.](./ALL_README.md)*
 
 > *This package allows you to install VPN Client quickly and simply on a YunoHost server.*  
 > *If you don't have YunoHost, please consult [the guide](https://yunohost.org/install) to learn how to install it.*
 
 ## Overview
 
-* Install a VPN connection on your self-hosted server.
+Install a VPN connection on your self-hosted server.
 * Useful for hosting your server behind a filtered (and/or non-neutral) internet access.
 * Useful to have static IP addresses (IPv6 and IPv4).
 * Useful to easily move your server anywhere.
@@ -25,18 +25,15 @@ It shall NOT be edited by hand.
 
 
 
-**Shipped version:** 2.1.2~ynh1
+**Shipped version:** 2.2~ynh1
 
 ## Screenshots
 
 ![Screenshot of VPN Client](./doc/screenshots/vpnclient.png)
 
-## Disclaimers / important information
-
-Please note that this application is designed to interface with **dedicated, public IP VPNs accepting inbound traffic**, preferably with an associated `.cube` (or `.ovpn/.conf`) configuration file. **Do not** expect that any VPN you randomly bought on the Internet can be used! Checkout the [list of known compatible providers](https://yunohost.org/providers/vpn) for more info.
-
 ## Documentation and resources
 
+- Official app website: <https://labriqueinter.net>
 - YunoHost Store: <https://apps.yunohost.org/app/vpnclient>
 - Report a bug: <https://github.com/YunoHost-Apps/vpnclient_ynh/issues>
 

+ 52 - 0
README_eu.md

@@ -0,0 +1,52 @@
+<!--
+Ohart ongi: README hau automatikoki sortu da <https://github.com/YunoHost/apps/tree/master/tools/readme_generator>ri esker
+EZ editatu eskuz.
+-->
+
+# VPN Client YunoHost-erako
+
+[![Integrazio maila](https://dash.yunohost.org/integration/vpnclient.svg)](https://dash.yunohost.org/appci/app/vpnclient) ![Funtzionamendu egoera](https://ci-apps.yunohost.org/ci/badges/vpnclient.status.svg) ![Mantentze egoera](https://ci-apps.yunohost.org/ci/badges/vpnclient.maintain.svg)
+
+[![Instalatu VPN Client YunoHost-ekin](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=vpnclient)
+
+*[Irakurri README hau beste hizkuntzatan.](./ALL_README.md)*
+
+> *Pakete honek VPN Client YunoHost zerbitzari batean azkar eta zailtasunik gabe instalatzea ahalbidetzen dizu.*  
+> *YunoHost ez baduzu, kontsultatu [gida](https://yunohost.org/install) nola instalatu ikasteko.*
+
+## Aurreikuspena
+
+Install a VPN connection on your self-hosted server.
+* Useful for hosting your server behind a filtered (and/or non-neutral) internet access.
+* Useful to have static IP addresses (IPv6 and IPv4).
+* Useful to easily move your server anywhere.
+* Strong firewalling (internet access and self-hosted services only available through the VPN, not leaking to your commercial ISP)
+* Combine with the [Hotspot app](https://github.com/YunoHost-Apps/hotspot_ynh) to broadcast VPN-protected WiFi to other laptops without any further technical configuration needed.
+
+
+
+**Paketatutako bertsioa:** 2.2~ynh1
+
+## Pantaila-argazkiak
+
+![VPN Client(r)en pantaila-argazkia](./doc/screenshots/vpnclient.png)
+
+## Dokumentazioa eta baliabideak
+
+- Aplikazioaren webgune ofiziala: <https://labriqueinter.net>
+- YunoHost Denda: <https://apps.yunohost.org/app/vpnclient>
+- Eman errore baten berri: <https://github.com/YunoHost-Apps/vpnclient_ynh/issues>
+
+## Garatzaileentzako informazioa
+
+Bidali `pull request`a [`testing` abarrera](https://github.com/YunoHost-Apps/vpnclient_ynh/tree/testing).
+
+`testing` abarra probatzeko, ondorengoa egin:
+
+```bash
+sudo yunohost app install https://github.com/YunoHost-Apps/vpnclient_ynh/tree/testing --debug
+edo
+sudo yunohost app upgrade vpnclient -u https://github.com/YunoHost-Apps/vpnclient_ynh/tree/testing --debug
+```
+
+**Informazio gehiago aplikazioaren paketatzeari buruz:** <https://yunohost.org/packaging_apps>

+ 3 - 6
README_fr.md

@@ -16,7 +16,7 @@ Il NE doit PAS être modifié à la main.
 
 ## Vue d’ensemble
 
-* Installez une connexion VPN sur votre serveur auto-hébergé
+Installez une connexion VPN sur votre serveur auto-hébergé
 * Utile pour héberger votre serveur derrière un accès internet filtré (et/ou non-neutre)
 * Utile pour obtenir une IP statique (v4 et v6)
 * Utile pour pouvoir facilement déplacer votre serveur
@@ -25,18 +25,15 @@ Il NE doit PAS être modifié à la main.
 
 
 
-**Version incluse :** 2.1.2~ynh1
+**Version incluse :** 2.2~ynh1
 
 ## Captures d’écran
 
 ![Capture d’écran de VPN Client](./doc/screenshots/vpnclient.png)
 
-## Avertissements / informations importantes
-
-Notez que cette application est prévue pour fonctionner avec des **VPN dédiés et à IP publique qui acceptent le traffic entrant**, et de préférence avec un fichier de configuration `.cube` (ou `.ovpn/.conf`) associé. Un VPN acheté au hasard sur Internet ne fonctionnera sans doute pas ! Consultez [la liste des fournisseurs connus et compatibles](https://yunohost.org/providers/vpn) pour plus d'infos.
-
 ## Documentations et ressources
 
+- Site officiel de l’app : <https://labriqueinter.net>
 - YunoHost Store : <https://apps.yunohost.org/app/vpnclient>
 - Signaler un bug : <https://github.com/YunoHost-Apps/vpnclient_ynh/issues>
 

+ 3 - 6
README_gl.md

@@ -16,7 +16,7 @@ NON debe editarse manualmente.
 
 ## Vista xeral
 
-* Install a VPN connection on your self-hosted server.
+Install a VPN connection on your self-hosted server.
 * Useful for hosting your server behind a filtered (and/or non-neutral) internet access.
 * Useful to have static IP addresses (IPv6 and IPv4).
 * Useful to easily move your server anywhere.
@@ -25,18 +25,15 @@ NON debe editarse manualmente.
 
 
 
-**Versión proporcionada:** 2.1.2~ynh1
+**Versión proporcionada:** 2.2~ynh1
 
 ## Capturas de pantalla
 
 ![Captura de pantalla de VPN Client](./doc/screenshots/vpnclient.png)
 
-## Avisos / información importante
-
-Please note that this application is designed to interface with **dedicated, public IP VPNs accepting inbound traffic**, preferably with an associated `.cube` (or `.ovpn/.conf`) configuration file. **Do not** expect that any VPN you randomly bought on the Internet can be used! Checkout the [list of known compatible providers](https://yunohost.org/providers/vpn) for more info.
-
 ## Documentación e recursos
 
+- Web oficial da app: <https://labriqueinter.net>
 - Tenda YunoHost: <https://apps.yunohost.org/app/vpnclient>
 - Informar dun problema: <https://github.com/YunoHost-Apps/vpnclient_ynh/issues>
 

+ 0 - 16
check_process

@@ -1,16 +0,0 @@
-;; Test complet
-    ; Manifest
-    ; Checks
-        pkg_linter=1
-        setup_sub_dir=0
-        setup_root=0
-        setup_nourl=1
-        setup_private=0
-        setup_public=0
-        upgrade=1
-        upgrade=1   from_commit=0d2a6b1d9a71f63dedfc2b05b35c93c73a130886
-        backup_restore=1
-        multi_instance=0
-        incorrect_path=0
-        port_already_use=0
-        change_url=0

+ 0 - 3
conf/openvpn_run-parts.sh

@@ -1,3 +0,0 @@
-#!/bin/bash
-
-run-parts -v /etc/openvpn/scripts/$1.d/

+ 40 - 0
conf/scripts/route-down.d/10-vpnclient-unset-firewall

@@ -0,0 +1,40 @@
+#!/bin/bash
+
+is_firewall_set() {
+  ip6tables -w -nvL OUTPUT | grep vpnclient_out | grep -q "${wired_device}" \
+  && iptables -w -nvL OUTPUT | grep vpnclient_out | grep -q "${wired_device}"
+}
+
+wired_device=$(ip route | awk '/default via/ { print $5; }')
+
+if is_firewall_set; then
+  rm -f /etc/yunohost/hooks.d/post_iptable_rules/90-vpnclient
+  
+  # IPv4
+
+  iptables -w -D INPUT -i "${wired_device}" -j vpnclient_in
+  iptables -w -D OUTPUT -o "${wired_device}" -j vpnclient_out
+  iptables -w -D FORWARD -o "${wired_device}" -j vpnclient_fwd
+
+  iptables -w -F vpnclient_in
+  iptables -w -F vpnclient_out
+  iptables -w -F vpnclient_fwd
+
+  iptables -w -X vpnclient_in
+  iptables -w -X vpnclient_out
+  iptables -w -X vpnclient_fwd
+
+  # IPv6
+  
+  ip6tables -w -D INPUT -i "${wired_device}" -j vpnclient_in
+  ip6tables -w -D OUTPUT -o "${wired_device}" -j vpnclient_out
+  ip6tables -w -D FORWARD -o "${wired_device}" -j vpnclient_fwd
+
+  ip6tables -w -F vpnclient_in
+  ip6tables -w -F vpnclient_out
+  ip6tables -w -F vpnclient_fwd
+
+  ip6tables -w -X vpnclient_in
+  ip6tables -w -X vpnclient_out
+  ip6tables -w -X vpnclient_fwd
+fi

+ 28 - 0
conf/scripts/route-down.d/20-vpnclient-unset-dns

@@ -0,0 +1,28 @@
+#!/bin/bash
+
+is_dns_set() {
+  if [[ "$ynh_dns_method" != "custom" ]]; then
+    return 0
+  fi
+
+  current_dns=$(grep -o -P '^\s*nameserver\s+\K[abcdefABCDEF\d.:]+$' /etc/resolv.dnsmasq.conf | sort | uniq)
+  wanted_dns=$(echo "${ynh_dns}" | sed 's/,/\n/g'  | sort | uniq)
+  [[ -e /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient ]] \
+  && [[ "$current_dns" == "$wanted_dns" ]]
+}
+
+if is_dns_set; then
+  resolvconf=/etc/resolv.dnsmasq.conf
+  
+  rm -f /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient
+  if [[ -e "${resolvconf}.ynh" ]]; then
+    mv "${resolvconf}.ynh" "${resolvconf}"
+  fi
+
+  # FIXME : this situation happened to a user ...
+  # We could try to force regen the dns conf 
+  # (though for now it's tightly coupled to dnsmasq)
+  if ! grep -q "^nameserver\s" "${resolvconf}"; then
+    echo "${resolvconf} does not have any nameserver line !?" >&2
+  fi
+fi

+ 36 - 0
conf/scripts/route-down.d/30-vpnclient-unset-server-ipv6-route

@@ -0,0 +1,36 @@
+#!/bin/bash
+
+is_serverip6route_set() {
+  local server_ip6s=${1}
+
+  if [[ -z "${server_ip6s}" ]]; then
+    return 0
+  fi
+
+  for server_ip6 in ${server_ip6s}; do
+    if ! ip -6 route | grep -q "^${server_ip6}"; then
+      return 1
+    fi
+  done
+}
+
+unset_serverip6route() {
+  local server_ip6s=${1}
+  local ip6_gw=${2}
+  local wired_device=${3}
+
+  for server_ip6 in ${server_ip6s}; do
+    ip route delete "${server_ip6}/128" via "${ip6_gw}" dev "${wired_device}"
+  done
+}
+
+old_ip6_gw=$(yunohost app setting vpnclient ip6_gw)
+old_wired_device=$(yunohost app setting vpnclient wired_device)
+old_server_ip6=$(yunohost app setting vpnclient server_ip6)
+
+# Check old state of the server ipv6 route
+if [[ -n "${old_server_ip6}" && -n "${old_ip6_gw}" && -n "${old_wired_device}" ]]; then
+  if is_serverip6route_set "${old_server_ip6}"; then
+    unset_serverip6route "${old_server_ip6}" "${old_ip6_gw}" "${old_wired_device}"
+  fi
+fi

+ 11 - 0
conf/scripts/route-down.d/40-vpnclient-unset-ipv6

@@ -0,0 +1,11 @@
+#!/bin/bash
+
+is_ip6addr_set() {
+  local ip6_addr=${1}
+  ip address show dev tun0 2> /dev/null | grep -q "${ip6_addr}/"
+}
+
+ip6_addr=$(yunohost app setting "vpnclient" "ip6_addr")
+if [[ -n "${ip6_addr}" ]] && [[ "${ip6_addr}" != none ]] && is_ip6addr_set "${ip6_addr}"; then
+  ip address delete "${ip6_addr}/64" dev tun0
+fi

+ 20 - 0
conf/scripts/route-up.d/10-vpnclient-set-firewall

@@ -0,0 +1,20 @@
+#!/bin/bash
+
+is_firewall_set() {
+  local wired_device=$(ip route | awk '/default via/ { print $5; }')
+
+  ip6tables -w -nvL OUTPUT | grep vpnclient_out | grep -q "${wired_device}" \
+  && iptables -w -nvL OUTPUT | grep vpnclient_out | grep -q "${wired_device}"
+}
+
+if ! is_firewall_set; then
+  bash /etc/yunohost/apps/vpnclient/conf/hook_post-iptable-rules
+  cp /etc/yunohost/apps/vpnclient/conf/hook_post-iptable-rules /etc/yunohost/hooks.d/post_iptable_rules/90-vpnclient
+fi
+
+if is_firewall_set; then
+  echo "[ OK ] IPv6/IPv4 firewall set"
+else
+  echo "[FAIL] No IPv6/IPv4 firewall set" >&2
+  exit 1
+fi

+ 35 - 0
conf/scripts/route-up.d/20-vpnclient-set-dns

@@ -0,0 +1,35 @@
+#!/bin/bash
+
+is_dns_set() {
+  if [[ "$ynh_dns_method" != "custom" ]]; then
+    return 0
+  fi
+
+  current_dns=$(grep -o -P '^\s*nameserver\s+\K[a-fA-F\d.:]+$' /etc/resolv.dnsmasq.conf | sort | uniq)
+  wanted_dns=$(echo "${ynh_dns}" | sed 's/,/\n/g'  | sort | uniq)
+  [[ -e /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient ]] \
+  && [[ "$current_dns" == "$wanted_dns" ]]
+}
+
+ynh_dns_method=$(yunohost app setting vpnclient dns_method)
+ynh_dns=$(yunohost app setting vpnclient nameservers)
+
+# Set host DNS resolvers
+if ! is_dns_set; then
+  resolvconf=/etc/resolv.dnsmasq.conf
+
+  cp -fa "${resolvconf}" "${resolvconf}.ynh"
+  if [[ "$ynh_dns_method" == "custom" ]]; then
+    cat << EOF > /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient
+echo "${ynh_dns}" | sed 's/,/\n/g' | sort | uniq | sed 's/^/nameserver /g' > ${resolvconf}
+EOF
+    bash /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient
+  fi
+fi
+
+if is_dns_set; then
+  echo "[ OK ] Host DNS correctly set"
+else
+  echo "[FAIL] No host DNS set" >&2
+  exit 1
+fi

+ 90 - 0
conf/scripts/route-up.d/30-vpnclient-set-server-ipv6-route

@@ -0,0 +1,90 @@
+#!/bin/bash
+
+has_nativeip6() {
+  ip -6 route | grep -q "default via"
+}
+
+is_serverip6route_set() {
+  local server_ip6s=${1}
+
+  if [[ -z "${server_ip6s}" ]]; then
+    return 0
+  fi
+
+  for server_ip6 in ${server_ip6s}; do
+    if ! ip -6 route | grep -q "^${server_ip6}"; then
+      return 1
+    fi
+  done
+}
+
+set_serverip6route() {
+  local server_ip6s=${1}
+  local ip6_gw=${2}
+  local wired_device=${3}
+
+  for server_ip6 in ${server_ip6s}; do
+    ip route add "${server_ip6}/128" via "${ip6_gw}" dev "${wired_device}"
+  done
+}
+
+unset_serverip6route() {
+  local server_ip6s=${1}
+  local ip6_gw=${2}
+  local wired_device=${3}
+
+  for server_ip6 in ${server_ip6s}; do
+    ip route delete "${server_ip6}/128" via "${ip6_gw}" dev "${wired_device}"
+  done
+}
+
+old_ip6_gw=$(yunohost app setting vpnclient ip6_gw)
+old_wired_device=$(yunohost app setting vpnclient wired_device)
+old_server_ip6=$(yunohost app setting vpnclient server_ip6)
+
+new_ip6_gw=$(ip -6 route | awk '/default via/ { print $3 }')
+new_wired_device=$(ip route | awk '/default via/ { print $5; }')
+ynh_server_names=$(grep -o -P '^\s*remote\s+\K([^\s]+)' /etc/openvpn/client.conf | sort | uniq)
+new_server_ip6=$(dig AAAA +short $ynh_server_names @127.0.0.1 | grep -v '\.$' | grep -v "timed out" | sort | uniq)
+
+for i in $ynh_server_names; do
+  if [[ "${i}" =~ : ]] && [[ ! "$new_server_ip6" == *"${i}"* ]] ; then
+    new_server_ip6+=" ${i}"
+  fi
+done
+
+echo "[INFO] Autodetected internet interface: ${new_wired_device} (last start: ${old_wired_device})"
+echo "[INFO] Autodetected IPv6 address for the VPN server: ${new_server_ip6} (last start: ${old_server_ip6})"
+
+# Check old state of the server ipv6 route
+if [[ -n "${old_server_ip6}" && -n "${old_ip6_gw}" && -n "${old_wired_device}" ]]; then
+  if [[ "${new_server_ip6}" != "${old_server_ip6}" || "${new_ip6_gw}" != "${old_ip6_gw}" || "${new_wired_device}" != "${old_wired_device}" ]]; then
+    if is_serverip6route_set "${old_server_ip6}"; then
+      unset_serverip6route "${old_server_ip6}" "${old_ip6_gw}" "${old_wired_device}"
+    fi
+  fi
+fi
+
+# Set the new server ipv6 route
+if has_nativeip6; then
+  if ! is_serverip6route_set "${new_server_ip6}"; then
+    set_serverip6route "${new_server_ip6}" "${new_ip6_gw}" "${new_wired_device}"
+  fi
+
+  echo "[INFO] Native IPv6 detected"
+  echo "[INFO] Autodetected native IPv6 gateway: ${new_ip6_gw} (last start: ${old_ip6_gw})"
+
+  if is_serverip6route_set "${new_server_ip6}"; then
+    echo "[ OK ] IPv6 server route correctly set"
+  else
+    echo "[FAIL] No IPv6 server route set" >&2
+    exit 1
+  fi
+else
+  echo "[INFO] No native IPv6 detected"
+  echo "[INFO] No IPv6 server route to set"
+fi
+
+yunohost app setting vpnclient server_ip6 --value "${new_server_ip6}"
+yunohost app setting vpnclient ip6_gw --value "${new_ip6_gw}"
+yunohost app setting vpnclient wired_device --value "${new_wired_device}"

+ 25 - 0
conf/scripts/route-up.d/40-vpnclient-set-ipv6

@@ -0,0 +1,25 @@
+#!/bin/bash
+
+is_ip6addr_set() {
+  local ip6_addr=${1}
+  ip address show dev tun0 2> /dev/null | grep -q "${ip6_addr}/"
+}
+
+ip6_addr=$(yunohost app setting "vpnclient" "ip6_addr")
+if [[ -n "${ip6_addr}" ]] && [[ "${ip6_addr}" != none ]]; then
+  if ! is_ip6addr_set "${ip6_addr}"; then
+    ip address add "${ip6_addr}/64" dev tun0
+  fi
+
+  echo "[INFO] IPv6 delegated prefix found"
+  echo "[INFO] IPv6 address computed from the delegated prefix: ${ip6_addr}"
+
+  if is_ip6addr_set "${ip6_addr}"; then
+    echo "[ OK ] IPv6 address correctly set"
+  else
+    echo "[FAIL] No IPv6 address set" >&2
+    exit 1
+  fi
+else
+  echo "[INFO] No IPv6 delegated prefix found"
+fi

+ 5 - 0
conf/scripts/run-parts.sh

@@ -0,0 +1,5 @@
+#!/bin/bash
+
+export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+
+run-parts -v /etc/openvpn/scripts/$1.d/

+ 68 - 374
conf/ynh-vpnclient

@@ -53,146 +53,18 @@ function critical()
 }
 
 ###################################################################################
-# IPv6 and route config stuff                                                     #
+# Cleanup                                                                         #
 ###################################################################################
 
-has_nativeip6() {
-  ip -6 route | grep -q "default via"
-}
-
-has_ip6delegatedprefix() {
-  [ "${ynh_ip6_addr}" != none ] && [ "${ynh_ip6_addr}" != "" ]
-}
-
-is_ip6addr_set() {
-  ip address show dev tun0 2> /dev/null | grep -q "${ynh_ip6_addr}/"
-}
-
-set_ip6addr() {
-  info "Adding IPv6 from VPN configuration"
-  ip address add "${ynh_ip6_addr}/128" dev tun0
-}
-
-unset_ip6addr() {
-  info "Removing IPv6 from VPN configuration"
-  ip address delete "${ynh_ip6_addr}/128" dev tun0
-}
-
-#
-# Server IPv6 route
-#
-
-is_serverip6route_set() {
-  server_ip6s=${1}
-
-  if [[ -z "${server_ip6s}" ]]; then
-    return 0
-  fi
-
-  for server_ip6 in ${server_ip6s}; do
-    if ! ip -6 route | grep -q "^${server_ip6}"; then
-      return 1
-    fi
-  done
-}
-
-set_serverip6route() {
-  server_ip6s=${1}
-  ip6_gw=${2}
-  wired_device=${3}
-
-  info "Adding IPv6 server route"
-    for server_ip6 in ${server_ip6s};
-    do
-        ip route add "${server_ip6}/128" via "${ip6_gw}" dev "${wired_device}"
-    done
-}
-
-
-unset_serverip6route() {
-  server_ip6s=${1}
-  ip6_gw=${2}
-  wired_device=${3}
-
-  info "Removing IPv6 server route"
-    for server_ip6 in ${server_ip6s};
-    do
-        ip route delete "${server_ip6}/128" via "${ip6_gw}" dev "${wired_device}"
-    done
-}
-
-###################################################################################
-# DNS rules                                                                       #
-###################################################################################
-
-is_dns_set() {
-  if [[ "$ynh_dns_method" == "custom" ]]
-  then
-  
-    current_dns=$(grep -o -P '\s*nameserver\s+\K[abcdefabcdef\d.:]+' /etc/resolv.dnsmasq.conf | sort | uniq)
-    wanted_dns=$(echo "${ynh_dns}" | sed 's/,/\n/g'  | sort | uniq)
-    [ -e /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient ]\
-    && [[ "$current_dns" == "$wanted_dns" ]]
-  else
-    true
-  fi
-}
-
-set_dns() {
-  info "Enforcing custom DNS resolvers from vpnclient"
-
-  resolvconf=/etc/resolv.dnsmasq.conf
-
-  cp -fa "${resolvconf}" "${resolvconf}.ynh"
-  if [[ "$ynh_dns_method" == "custom" ]]
-  then
-    cat << EOF > /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient
-echo "${ynh_dns}" | sed 's/,/\n/g' | sort | uniq | sed 's/^/nameserver /g' > ${resolvconf}
-EOF
-    bash /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient
+cleanup() {
+  local last_exit_code="$?"
+  if [[ "${action}" != "stop" && "${last_exit_code}" -ne 0 ]]; then
+    rm -f /tmp/.ynh-vpnclient-started
   fi
-
-}
-
-unset_dns() {
-  resolvconf=/etc/resolv.dnsmasq.conf
-
-  info "Removing custom DNS resolvers from vpnclient"
-  rm -f /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient
-  [ -e "${resolvconf}.ynh" ] && mv "${resolvconf}.ynh" "${resolvconf}"
-
-  # FIXME : this situation happened to a user ...
-  # We could try to force regen the dns conf 
-  # (though for now it's tightly coupled to dnsmasq)
-  grep -q "^nameserver\s" "${resolvconf}" || error "${resolvconf} does not have any nameserver line !?"
-}
-
-###################################################################################
-# Firewall rules management                                                       #
-###################################################################################
-
-is_firewall_set() {
-  wired_device=$(ip route | awk '/default via/ { print $5; }')
-
-  ip6tables -w -nvL OUTPUT | grep vpnclient_out | grep -q "${wired_device}"\
-  && iptables -w -nvL OUTPUT | grep vpnclient_out | grep -q "${wired_device}"
 }
 
-set_firewall() {
-  info "Adding vpnclient custom rules to the firewall"
-
-  cp /etc/yunohost/hooks.d/{90-vpnclient.tpl,post_iptable_rules/90-vpnclient}
-
-  info "Restarting yunohost firewall..."
-  yunohost firewall reload >/dev/null && success "Firewall restarted!"
-}
-
-unset_firewall() {
-  info "Cleaning vpnclient custom rules from the firewall"
-  rm -f /etc/yunohost/hooks.d/post_iptable_rules/90-vpnclient
-  info "Restarting yunohost firewall..."
-  yunohost firewall reload >/dev/null && success "Firewall restarted!"
-}
+# Cleanup before exit
+trap cleanup 0
 
 ###################################################################################
 # Time sync                                                                       #
@@ -207,7 +79,7 @@ sync_time() {
   # Try to get the date with an http request on the internetcube web site
   if [ $? -ne 0 ]; then
     info "ntp synchronization failed, falling back to curl method"
-    http_date=$(curl --max-time 5 -sD - labriqueinter.net | grep '^Date:' | cut -d' ' -f3-6)
+    http_date=$(curl --max-time 5 -sD - yunohost.org | grep -i '^Date:' | cut -d' ' -f2-)
     http_date_seconds=$(date -d "${http_date}" +%s)
     curr_date_seconds=$(date +%s)
 
@@ -221,92 +93,12 @@ sync_time() {
 }
 
 ###################################################################################
-# OpenVPN client start/stop procedures                                            #
-###################################################################################
-
-is_openvpn_running() {
-  systemctl is-active openvpn@client.service &> /dev/null
-}
-
-start_openvpn() {
-
-  # Unset firewall to let DNS and NTP resolution works
-  # Firewall is reset after vpn is mounted (more details on #1016)
-  unset_firewall
-
-  sync_time
-
-  info "Now actually starting OpenVPN client..."
-
-  if systemctl start openvpn@client.service
-  then
-    info "OpenVPN client started ... waiting for tun0 interface to show up"
-  else
-    tail -n 20 /var/log/openvpn-client.log | tee -a $LOGFILE
-	critical "Failed to start OpenVPN :/"
-  fi
-
-  for attempt in $(seq 0 20)
-  do
-    sleep 1
-    if ip link show dev tun0 &> /dev/null
-    then
-       success "tun0 interface is up!"
-       return 0
-    fi
-  done
-  
-  error "Tun0 interface did not show up ... most likely an issue happening in OpenVPN client ... below is an extract of the log that might be relevant to pinpoint the issue"
-  tail -n 20 /var/log/openvpn-client.log | tee -a $LOGFILE
-  stop_openvpn
-  critical "Failed to start OpenVPN client : tun0 interface did not show up"
-}
-
-stop_openvpn() {
-  info "Stopping OpenVPN service"
-  systemctl stop openvpn@client.service
-
-  for attempt in $(seq 0 20)
-  do
-    if ip link show dev tun0 &> /dev/null
-    then
-       info "(Waiting for tun0 to disappear if it was up)"
-       sleep 1
-    fi
-  done
-}
-
-###################################################################################
-# Yunohost settings interface                                                     #
-###################################################################################
-
-ynh_setting_get() {
-  app=${1}
-  setting=${2}
-
-  grep "^${setting}:" "/etc/yunohost/apps/${app}/settings.yml" | sed s/^[^:]\\+:\\s*[\"\']\\?// | sed s/\\s*[\"\']\$//
-  # '"
-}
-
-ynh_setting_set() {
-  app=${1}
-  setting=${2}
-  value=${3}
-
-  yunohost app setting "${app}" "${setting}" -v "${value}"
-}
-
-###################################################################################
 # The actual ynh vpnclient management thing                                       #
 ###################################################################################
 
-is_running() {
-  ((has_nativeip6 && is_serverip6route_set "${new_server_ip6}") || ! has_nativeip6)\
-  && ((has_ip6delegatedprefix && is_ip6addr_set) || ! has_ip6delegatedprefix)\
-  && is_dns_set && is_firewall_set && is_openvpn_running
-}
-
 check_config() {
+  info "Checking if configuration is valid..."
+
   if [[ ! -e /etc/openvpn/keys/ca-server.crt ]]; then
     critical "You need a CA server (you can add it through the web admin)"
   fi
@@ -334,119 +126,92 @@ check_config() {
   fi
 }
 
-if [ "$1" != restart ]; then
-
+action=${1}
+if [[ "$action" != restart ]]; then
   # Variables
 
   info "Retrieving Yunohost settings... "
 
-  ynh_service_enabled=$(ynh_setting_get vpnclient service_enabled)
-  ynh_ip6_addr=$(ynh_setting_get vpnclient ip6_addr)
-  ynh_dns_method=$(ynh_setting_get vpnclient dns_method)
-  ynh_dns=$(ynh_setting_get vpnclient nameservers)
-
-  old_ip6_gw=$(ynh_setting_get vpnclient ip6_gw)
-  old_wired_device=$(ynh_setting_get vpnclient wired_device)
-  old_server_ip6=$(ynh_setting_get vpnclient server_ip6)
-
-  new_ip6_gw=$(ip -6 route | awk '/default via/ { print $3 }')
-  new_wired_device=$(ip route | awk '/default via/ { print $5; }')
-  ynh_server_names=$(grep -o -P '^\s*remote\s+\K([^\s]+)' /etc/openvpn/client.conf | sort | uniq)
-  new_server_ip6=$(dig AAAA +short $ynh_server_names @127.0.0.1 | grep -v '\.$' | grep -v "timed out" | sort | uniq)
-
-  for i in $ynh_server_names; do
-    if [[ "${i}" =~ : ]] && [[ ! "$new_server_ip6" == *"${i}"* ]] ; then
-        new_server_ip6+=" ${i}"
-    fi
-  done
+  ynh_service_enabled=$(yunohost app setting "vpnclient" "service_enabled")
 
   success "Settings retrieved"
-
 fi
 
 ###################################################################################
 # Start / stop / restart / status handling                                        #
 ###################################################################################
 
-case "${1}" in
+case "$action" in
 
   # ########## #
   #  Starting  #
   # ########## #
 
   start)
-
-    if is_running; then
+    info "[vpnclient] Starting..."
+    
+    if [[ -e /tmp/.ynh-vpnclient.started ]] || systemctl -q is-active openvpn@client.service; then
       info "Service is already running"
       exit 0
-    elif [ "${ynh_service_enabled}" -eq 0 ]; then
+    elif [[ "${ynh_service_enabled}" -eq 0 ]]; then
       warn "Service is disabled, not starting it"
       exit 0
     fi
 
-    check_config
-
-    info "[vpnclient] Starting..."
     touch /tmp/.ynh-vpnclient-started
 
-    # Run openvpn
-    if is_openvpn_running; then
-      info "(openvpn is already running)"
-    else
-      start_openvpn
-    fi
-
-    # Check old state of the server ipv6 route
-    if [ ! -z "${old_server_ip6}" -a ! -z "${old_ip6_gw}" -a ! -z "${old_wired_device}"\
-         -a \( "${new_server_ip6}" != "${old_server_ip6}" -o "${new_ip6_gw}" != "${old_ip6_gw}"\
-         -o "${new_wired_device}" != "${old_wired_device}" \) ]\
-       && is_serverip6route_set "${old_server_ip6}"
-    then
-       unset_serverip6route "${old_server_ip6}" "${old_ip6_gw}" "${old_wired_device}"
-    fi
+    sync_time
+    check_config
 
-    # Set the new server ipv6 route
-    if has_nativeip6 && ! is_serverip6route_set "${new_server_ip6}"
-    then
-      set_serverip6route "${new_server_ip6}" "${new_ip6_gw}" "${new_wired_device}"
-    fi
+    info "Now actually starting OpenVPN client..."
 
-    # Set the ipv6 address
-    if has_ip6delegatedprefix && ! is_ip6addr_set
-    then
-      set_ip6addr
+    if systemctl start openvpn@client.service; then
+      info "OpenVPN client started ... waiting for tun0 interface to show up"
+    else
+      tail -n 20 /var/log/openvpn-client.log | tee -a $LOGFILE
+	    critical "Failed to start OpenVPN :/"
     fi
 
-    # Set host DNS resolvers
-    if ! is_dns_set; then
-       set_dns
+    has_errors=true
+    for attempt in $(seq 0 20); do
+      sleep 1
+      if ip link show dev tun0 &> /dev/null; then
+        success "tun0 interface is up!"
+        has_errors=false
+        break
+      fi
+    done
+  
+    if $has_errors; then
+      error "Tun0 interface did not show up ... most likely an issue happening in OpenVPN client ... below is an extract of the log that might be relevant to pinpoint the issue"
+      tail -n 20 /var/log/openvpn-client.log | tee -a $LOGFILE
+      systemctl stop openvpn@client.service
+      critical "Failed to start OpenVPN client : tun0 interface did not show up"
     fi
 
-    # Set ipv6/ipv4 firewall
-    if ! is_firewall_set; then
-      set_firewall
+    info "Waiting for VPN client to be ready..."
+    if ! timeout 180 tail -n 0 -f /var/log/openvpn-client.log | grep -q "Initialization Sequence Completed"; then
+      error "The VPN client didn't complete initiliasation"
+      tail -n 20 /var/log/openvpn-client.log | tee -a $LOGFILE
+      systemctl stop openvpn@client.service
+      critical "Failed to start OpenVPN client"
     fi
 
-    # Update dynamic settings
-    info "Saving settings..."
-    ynh_setting_set vpnclient server_ip6 "${new_server_ip6}"
-    ynh_setting_set vpnclient ip6_gw "${new_ip6_gw}"
-    ynh_setting_set vpnclient wired_device "${new_wired_device}"
+    info "Validating that VPN is up and the server is connected to internet..."
 
-    ipv4=$(ping -w3 -c1 ip.yunohost.org  >/dev/null 2>&1 && curl --max-time 5 https://ip.yunohost.org --silent)
-    ipv6=$(ping -w3 -c1 ip6.yunohost.org >/dev/null 2>&1 && curl --max-time 5 https://ip6.yunohost.org --silent)
+    ipv4=$(timeout 5 ping -w3 -c1 ip.yunohost.org  >/dev/null 2>&1 && curl --max-time 5 https://ip.yunohost.org --silent)
+    ipv6=$(timeout 5 ping -w3 -c1 ip6.yunohost.org >/dev/null 2>&1 && curl --max-time 5 https://ip6.yunohost.org --silent)
 
-    info "Validating that VPN is up and the server is connected to internet..."
     if ip route get 1.2.3.4 | grep -q tun0; then
-        if ping -c1 -w5 debian.org >/dev/null; then
-            success "YunoHost VPN client started!"
-            info "IPv4 address is $ipv4"
-            info "IPv6 address is $ipv6"
-        else
-            critical "The VPN is up but debian.org cannot be reached, indicating that something is probably misconfigured/blocked."
-        fi
+      if timeout 5 ping -c1 -w3 debian.org >/dev/null; then
+        success "YunoHost VPN client started!"
+        info "IPv4 address is $ipv4"
+        info "IPv6 address is $ipv6"
+      else
+        critical "The VPN is up but debian.org cannot be reached, indicating that something is probably misconfigured/blocked."
+      fi
     else
-        critical "IPv4 routes are misconfigured !?"
+      critical "[CRIT] IPv4 routes are misconfigured !?"
     fi
   ;;
 
@@ -458,19 +223,17 @@ case "${1}" in
     info "[vpnclient] Stopping..."
     rm -f /tmp/.ynh-vpnclient-started
 
-    if has_ip6delegatedprefix && is_ip6addr_set; then
-      unset_ip6addr
-    fi
+    if systemctl is-active -q openvpn@client.service; then
+      info "Stopping OpenVPN service"
+      systemctl stop openvpn@client.service
 
-    if is_serverip6route_set "${old_server_ip6}"; then
-      unset_serverip6route "${old_server_ip6}" "${old_ip6_gw}" "${old_wired_device}"
+      for attempt in $(seq 0 20); do
+        if ip link show dev tun0 &> /dev/null; then
+          info "(Waiting for tun0 to disappear if it was up)"
+          sleep 1
+        fi
+      done
     fi
-
-    is_firewall_set && unset_firewall
-
-    is_dns_set && unset_dns
-
-    is_openvpn_running && stop_openvpn
   ;;
 
   # ########## #
@@ -483,80 +246,11 @@ case "${1}" in
   ;;
 
   # ########## #
-  #   Status   #
-  # ########## #
-
-  status)
-    exitcode=0
-
-    if [ "${ynh_service_enabled}" -eq 0 ]; then
-      error "VPN Client Service disabled"
-      exitcode=1
-    fi
-
-    info "Autodetected internet interface: ${new_wired_device} (last start: ${old_wired_device})"
-    info "Autodetected IPv6 address for the VPN server: ${new_server_ip6} (last start: ${old_server_ip6})"
-
-    if has_ip6delegatedprefix; then
-      info "IPv6 delegated prefix found"
-      info "IPv6 address computed from the delegated prefix: ${ynh_ip6_addr}"
-
-      if is_ip6addr_set; then
-        success "IPv6 address correctly set"
-      else
-        error "No IPv6 address set"
-        exitcode=1
-      fi
-    else
-      info "No IPv6 delegated prefix found"
-    fi
-
-    if has_nativeip6; then
-      info "Native IPv6 detected"
-      info "Autodetected native IPv6 gateway: ${new_ip6_gw} (last start: ${old_ip6_gw})"
-
-      if is_serverip6route_set "${new_server_ip6}"; then
-        success "IPv6 server route correctly set"
-      else
-        error "No IPv6 server route set"
-        exitcode=1
-      fi
-    else
-      info "No native IPv6 detected"
-      info "No IPv6 server route to set"
-    fi
-
-    if is_firewall_set; then
-      success "IPv6/IPv4 firewall set"
-    else
-      info "No IPv6/IPv4 firewall set"
-      exitcode=1
-    fi
-
-    if is_dns_set; then
-      success "Host DNS correctly set"
-    else
-      error "No host DNS set"
-      exitcode=1
-    fi
-
-    if is_openvpn_running; then
-      success "Openvpn is running"
-    else
-      error "Openvpn is not running"
-      exitcode=1
-    fi
-
-    exit ${exitcode}
-  ;;
-
-  # ########## #
   #    Halp    #
   # ########## #
 
   *)
-    echo "Usage: $0 {start|stop|restart|status}"
-    exit 1
+    echo "Usage: $0 {start|stop|restart}"
   ;;
 esac
 

+ 6 - 4
conf/ynh-vpnclient-checker.sh

@@ -1,7 +1,9 @@
 #!/bin/bash
 
-if [ ! -e /tmp/.ynh-vpnclient-stopped ] && ! ip route get 1.2.3.4 | grep -q tun0; then
-  systemctl restart ynh-vpnclient &> /dev/null
+if [[ -e /tmp/.ynh-vpnclient-started ]] || ip route get 1.2.3.4 | grep -q tun0; then
+  echo "[INFO] Service is already running"
+  exit 0
+else
+  echo "[INFO] Restarting VPN client service"
+  yunohost service restart ynh-vpnclient &> /dev/null
 fi
-
-exit 0

+ 34 - 13
config_panel.toml

@@ -6,17 +6,17 @@ name = "Auto-configuration"
     [main.vpn]
     name = ""
     optional = false
-        
+
         [main.vpn.status]
         ask = "The status of your VPN is unknown."
         type = "alert"
         style = "info"
-        
+
         [main.vpn.service_enabled]
         ask = "Enable VPN"
         type = "boolean"
         help = "If disabled, the VPN service will not automatically be started at boot."
-        
+
         [main.vpn.doc]
         ask.en = "VPNclient only interfaces with *dedicated, public IP VPNs accepting inbound traffic*, preferably with an associated `.cube` (or `.ovpn/.conf`) configuration file. Checkout the [list of known compatible providers](https://yunohost.org/providers/vpn) for more info."
         ask.fr = "VPNclient est prévu pour fonctionner avec des *VPN dédiés et à IP publique qui acceptent le traffic entrant*, et de préférence avec un fichier de configuration `.cube` (ou `.ovpn/.conf`) associé. Consultez [la liste des fournisseurs connus et compatibles](https://yunohost.org/providers/vpn) pour plus d'infos."
@@ -26,11 +26,32 @@ name = "Auto-configuration"
         [main.vpn.config_file]
         ask = "Configuration file"
         type = "file"
-        accept = ".cube, .ovpn, .conf"
+        accept = [ ".cube", ".ovpn", ".conf" ]
         help = ".cube file recommended, .ovpn file accepted"
         bind = "/etc/openvpn/client.conf"
         redact = true
-        
+
+        [main.vpn.config_template]
+        type = "file"
+        bind = "/etc/openvpn/client.conf.tpl"
+        redact = true
+        optional = true
+        visible = false
+
+        [main.vpn.cube_file]
+        type = "file"
+        bind = "/etc/openvpn/client.cube"
+        redact = true
+        optional = true
+        visible = false
+
+        [main.vpn.ovpn_file]
+        type = "file"
+        bind = "/etc/openvpn/client.ovpn"
+        redact = true
+        optional = true
+        visible = false
+
     [main.auth]
     name = "Authentication"
     optional = true
@@ -41,13 +62,13 @@ name = "Auto-configuration"
         type = "file"
         bind = "/etc/openvpn/keys/ca-server.crt"
         visible = 'config_file && match(config_file,"^\s*ca\s") && ! match(config_file,"^\s*<ca>")'
-        
+
         [main.auth.crt_client]
         ask = "Update Client Certificate"
         type = "file"
         bind = "/etc/openvpn/keys/user.crt"
         visible = 'config_file && match(config_file,"^\s*cert\s") && ! match(config_file,"^\s*<cert>")'
-        
+
         [main.auth.crt_client_key]
         ask = "Update Client Key"
         type = "file"
@@ -55,7 +76,7 @@ name = "Auto-configuration"
         bind = "/etc/openvpn/keys/user.key"
         visible = 'config_file && match(config_file,"^\s*key\s") && ! match(config_file,"^\s*<key>")'
         redact = true
-        
+
         [main.auth.login_user]
         ask = "Username"
         type = "string"
@@ -63,12 +84,12 @@ name = "Auto-configuration"
         pattern.regexp = '^[a-zA-Z0-9_\-\\\.@]+$'
         pattern.error = "OpenVPN accept only alphabetic chars and -_\\.@"
         visible = 'config_file && match(config_file,"^\s*auth-user-pass\s")'
-        
+
         [main.auth.login_passphrase]
         ask = "Password"
         type = "password"
         visible = 'config_file && match(config_file,"^\s*auth-user-pass(\s.*)?$")'
-        
+
         [main.auth.crt_client_ta]
         ask = "TLS Auth shared secret"
         type = "file"
@@ -77,7 +98,7 @@ name = "Auto-configuration"
         bind = "/etc/openvpn/keys/user_ta.key"
         visible = 'config_file && match(config_file,"^\s*tls-auth\s") && ! match(config_file,"^\s*<tls-auth>")'
         redact = true
-        
+
 [advanced]
 name = "DNS & IPv6"
     [advanced.dns]
@@ -96,7 +117,7 @@ name = "DNS & IPv6"
         visible = "dns_method == 'custom'"
         pattern.regexp = "^([0-9.]{7,15}|[0-9a-fA-F:]+)$"
         pattern.error = "Not an ip"
-        
+
     [advanced.ipv6]
     name = "IPv6"
 
@@ -107,7 +128,7 @@ name = "DNS & IPv6"
         example = "2001:db8:42::"
         pattern.regexp = "^[0-9a-fA-F:]+$"
         pattern.error = "Please provide a valid IPv6 Prefix"
-        
+
         [advanced.ipv6.ip6_addr]
         ask = "IPv6"
         type = "string"

+ 1 - 1
doc/DESCRIPTION.md

@@ -1,4 +1,4 @@
-* Install a VPN connection on your self-hosted server.
+Install a VPN connection on your self-hosted server.
 * Useful for hosting your server behind a filtered (and/or non-neutral) internet access.
 * Useful to have static IP addresses (IPv6 and IPv4).
 * Useful to easily move your server anywhere.

+ 1 - 1
doc/DESCRIPTION_fr.md

@@ -1,4 +1,4 @@
-* Installez une connexion VPN sur votre serveur auto-hébergé
+Installez une connexion VPN sur votre serveur auto-hébergé
 * Utile pour héberger votre serveur derrière un accès internet filtré (et/ou non-neutre)
 * Utile pour obtenir une IP statique (v4 et v6)
 * Utile pour pouvoir facilement déplacer votre serveur

+ 0 - 1
doc/DISCLAIMER.md

@@ -1 +0,0 @@
-Please note that this application is designed to interface with **dedicated, public IP VPNs accepting inbound traffic**, preferably with an associated `.cube` (or `.ovpn/.conf`) configuration file. **Do not** expect that any VPN you randomly bought on the Internet can be used! Checkout the [list of known compatible providers](https://yunohost.org/providers/vpn) for more info.

+ 0 - 1
doc/DISCLAIMER_fr.md

@@ -1 +0,0 @@
-Notez que cette application est prévue pour fonctionner avec des **VPN dédiés et à IP publique qui acceptent le traffic entrant**, et de préférence avec un fichier de configuration `.cube` (ou `.ovpn/.conf`) associé. Un VPN acheté au hasard sur Internet ne fonctionnera sans doute pas ! Consultez [la liste des fournisseurs connus et compatibles](https://yunohost.org/providers/vpn) pour plus d'infos.

+ 8 - 0
doc/PRE_INSTALL.md

@@ -0,0 +1,8 @@
+Please note that this application only interfaces with **dedicated, public IP VPNs accepting inbound traffic**, 
+preferably with an associated `.cube` (or `.ovpn/.conf`) configuration file.
+
+**Do not** expect that any VPN you randomly bought on the Internet can be used! 
+
+Checkout the [list of known compatible providers](https://yunohost.org/providers/vpn) for more info.
+    
+After installation, you will be able to configure the application from YunoHost's webadmin in Applications > VPNclient > Configuration

+ 7 - 0
doc/PRE_INSTALL_fr.md

@@ -0,0 +1,7 @@
+Notez que cette application est prévue pour fonctionner avec des **VPN dédiés et à IP publique qui acceptent le traffic entrant**, et de préférence avec un fichier de configuration `.cube` (ou `.ovpn/.conf`) associé. 
+
+Un VPN acheté au hasard sur Internet ne fonctionnera sans doute pas ! 
+
+Consultez [la liste des fournisseurs connus et compatibles](https://yunohost.org/providers/vpn) pour plus d'infos.
+
+Après l'application, vous pourrez configurer l'application depuis la webadmin de YunoHost dans Applications > VPNclient > Configuration.

+ 0 - 43
manifest.json

@@ -1,43 +0,0 @@
-{
-  "name": "VPN Client",
-  "id": "vpnclient",
-  "packaging_format": 1,
-  "description": {
-    "en": "Tunnel the internet traffic through a VPN",
-    "fr": "Fait passer le trafic internet à travers un VPN"
-  },
-  "version": "2.1.2~ynh1",
-  "url": "https://labriqueinter.net",
-  "license": "AGPL-3.0",
-  "maintainer": {
-    "name": "pitchum",
-    "email": "pitchum@users.noreply.github.com"
-  },
-  "multi_instance": false,
-  "requirements": {
-    "yunohost": ">= 4.3.2"
-  },
-  "services": [],
-  "arguments": {
-      "install": [
-          {
-            "name": "disclaimer1",
-            "type": "display_text",
-            "style": "warning",
-            "ask": {
-                "en": "Please note that this application only interfaces with **dedicated, public IP VPNs accepting inbound traffic**, preferably with an associated `.cube` (or `.ovpn/.conf`) configuration file. **Do not** expect that any VPN you randomly bought on the Internet can be used! Checkout the [list of known compatible providers](https://yunohost.org/providers/vpn) for more info.",
-                "fr": "Notez que cette application est prévue pour fonctionner avec des **VPN dédiés et à IP publique qui acceptent le traffic entrant**, et de préférence avec un fichier de configuration `.cube` (ou `.ovpn/.conf`) associé. Un VPN acheté au hasard sur Internet ne fonctionnera sans doute pas ! Consultez [la liste des fournisseurs connus et compatibles](https://yunohost.org/providers/vpn) pour plus d'infos."
-            }
-        },
-        {
-            "name": "disclaimer2",
-            "type": "display_text",
-            "style": "info",
-            "ask": {
-                "en": "After installation, you will be able to configure the application from YunoHost's webadmin in Applications > VPNclient > Configuration.",
-                "fr": "Après l'application, vous pourrez configurer l'application depuis la webadmin de YunoHost dans Applications > VPNclient > Configuration."
-            }
-        }
-    ]
-  }
-}

+ 37 - 0
manifest.toml

@@ -0,0 +1,37 @@
+#:schema https://raw.githubusercontent.com/YunoHost/apps/master/schemas/manifest.v2.schema.json
+
+packaging_format = 2
+
+id = "vpnclient"
+name = "VPN Client"
+description.en = "Tunnel the internet traffic through a VPN"
+description.fr = "Fait passer le trafic internet à travers un VPN"
+
+version = "2.2~ynh1"
+
+maintainers = []
+
+[upstream]
+license = "AGPL-3.0"
+website = "https://labriqueinter.net"
+
+[integration]
+yunohost = ">= 11.2"
+architectures = "all"
+multi_instance = false
+ldap = "not_relevant"
+sso = "not_relevant"
+disk = "50M"
+ram.build = "50M"
+ram.runtime = "50M"
+
+[install]
+
+
+[resources]
+    [resources.system_user]
+
+    [resources.permissions]
+
+    [resources.apt]
+    packages = "sipcalc, dnsutils, openvpn, curl, fake-hwclock"

+ 163 - 11
scripts/_common.sh

@@ -1,9 +1,4 @@
 #!/bin/bash
-#
-# Common variables and helpers
-#
-
-pkg_dependencies="sipcalc dnsutils openvpn curl fake-hwclock"
 
 service_name="ynh-vpnclient"
 service_checker_name=$service_name"-checker"
@@ -12,11 +7,6 @@ service_checker_name=$service_name"-checker"
 # Operations needed by both 'install' and 'upgrade' scripts
 function vpnclient_deploy_files_and_services()
 {
-  # Ensure vpnclient_ynh has its own system user
-  if ! ynh_system_user_exists ${app}
-  then
-    ynh_system_user_create ${app}
-  fi
 
   # Install command-line cube file loader
   install -o root -g root -m 0755 ../conf/$service_name-loadcubefile.sh /usr/local/bin/
@@ -39,7 +29,9 @@ function vpnclient_deploy_files_and_services()
   mkdir -pm 0775 /etc/openvpn/scripts
   mkdir -pm 0775 /etc/openvpn/scripts/route-up.d
   mkdir -pm 0775 /etc/openvpn/scripts/route-down.d
-  install -b -o root -g root -m 0755 ../conf/openvpn_run-parts.sh /etc/openvpn/scripts/run-parts.sh
+  install -b -o root -g root -m 0755 ../conf/scripts/run-parts.sh /etc/openvpn/scripts/run-parts.sh
+  install -b -o root -g root -m 0755 ../conf/scripts/route-up.d/* /etc/openvpn/scripts/route-up.d/
+  install -b -o root -g root -m 0755 ../conf/scripts/route-down.d/* /etc/openvpn/scripts/route-down.d/
 
   #=================================================
 
@@ -61,3 +53,163 @@ function vpnclient_deploy_files_and_services()
 
   ynh_add_systemd_config $service_checker_name "$service_checker_name.service"
 }
+
+function read_cube() {
+  local config_file="$1"
+  local key="$2"
+  local tmp_dir=$(dirname "$config_file")
+
+  setting_value="$(jq --raw-output ".$key" "$config_file")"
+  if [[ "$setting_value" == "null" ]]
+  then
+    setting_value=''
+  # Save file in tmp dir
+  elif [[ "$key" == "crt_"* ]]
+  then
+    if [ -n "${setting_value}" ]
+    then
+      echo "${setting_value}" | sed 's/|/\n/g' > "$tmp_dir/$key"
+      setting_value="$tmp_dir/$key"
+    fi
+  fi
+  echo $setting_value
+}
+
+function convert_cube_file()
+{
+  local config_file="$1"
+  local tmp_dir=$(dirname "$config_file")
+  
+  ynh_print_info --message="Transforming .cube into OVPN file"
+  server_name="$(read_cube $config_file server_name)"
+  server_port="$(read_cube $config_file server_port)"
+  server_proto="$(read_cube $config_file server_proto)"
+  ip6_net="$(read_cube $config_file ip6_net)"
+  ip6_addr="$(read_cube $config_file ip6_addr)"
+  login_user="$(read_cube $config_file login_user)"
+  login_passphrase="$(read_cube $config_file login_passphrase)"
+  dns0="$(read_cube $config_file dns0)"
+  dns1="$(read_cube $config_file dns1)"
+  crt_server_ca="$(read_cube $config_file crt_server_ca)"
+  crt_client="$(read_cube $config_file crt_client)"
+  crt_client_key="$(read_cube $config_file crt_client_key)"
+  crt_client_ta="$(read_cube $config_file crt_client_ta)"
+
+  if [[ -z "$dns0" && -z "$dns1" ]]; then
+    dns_method="yunohost"
+  else
+    dns_method="custom"
+    nameservers="$dns0,$dns1"
+  fi
+  
+  # Build specific OVPN template
+  config_template="$tmp_dir/client.conf.tpl"
+  cp -f /etc/yunohost/apps/vpnclient/conf/openvpn_client.conf.tpl "$config_template"
+  # Remove some lines
+  jq --raw-output '.openvpn_rm[]' "${config_file}" | while read -r rm_regex
+  do
+    if [ ! -z "${rm_regex}" ]; then
+      sed -i "/${rm_regex/\//\\\/}/d" "$config_template"
+    fi
+  done
+
+  # Add some other lines
+  echo "# Custom additions from .cube" >> "$config_template"
+  jq --raw-output ".openvpn_add[]" "${config_file}" >> "$config_template"
+
+  # Temporarily tweak sever_proto for template hydratation
+  if [ "$server_proto" == tcp ]; then
+    server_proto=tcp-client
+  fi
+
+  # Define other needed vars for template hydratation
+  [ -e "$crt_client_key" ] && cert_comment="" || cert_comment="#"
+  [ -e "$crt_client_ta" ] && ta_comment="" || ta_comment="#"
+  [[ "$server_proto" =~ udp ]] && udp_comment="" || udp_comment="#"
+  [ -n "$login_user" ] && login_comment="" || login_comment="#"
+
+  # Actually generate/hydrate the final configuration
+  ynh_add_config --template="$config_template" --destination="$config_file"
+
+  if [ "$server_proto" == tcp-client ]; then
+    server_proto=tcp
+  fi
+}
+
+function convert_ovpn_file()
+{
+  local config_file="$1"
+  local tmp_dir=$(dirname "$config_file")
+
+  ynh_print_info --message="Extracting TLS keys from .ovpn file"
+  if grep -q '^\s*<ca>' ${config_file}
+  then
+    grep -Poz '(?<=<ca>)(.*\n)*.*(?=</ca>)' ${config_file} | sed '/^$/d'  > $tmp_dir/crt_server_ca
+    crt_server_ca=$tmp_dir/crt_server_ca
+    sed -i '/^\s*<ca>/,/\s*<\/ca>/d' ${config_file}
+    sed -i '/^\s*ca\s/d' ${config_file}
+    echo -e "\nca /etc/openvpn/keys/ca-server.crt" >> $config_file
+  fi
+  if grep -q '^\s*<cert>' ${config_file}
+  then
+    grep -Poz '(?<=<cert>)(.*\n)*.*(?=</cert>)' ${config_file} | sed '/^$/d'  > $tmp_dir/crt_client
+    crt_client=$tmp_dir/crt_client
+    sed -i '/^\s*<cert>/,/\s*<\/cert>/d' ${config_file}
+    sed -i '/^\s*cert\s/d' ${config_file}
+    echo -e "\ncert /etc/openvpn/keys/user.crt" >> ${config_file}
+  elif ! grep -q '^\s*cert\s' ${config_file}
+  then
+    crt_client=""
+  fi
+  if grep -q '^\s*<key>' ${config_file}
+  then
+    grep -Poz '(?<=<key>)(.*\n)*.*(?=</key>)' ${config_file} | sed '/^$/d' > $tmp_dir/crt_client_key
+    crt_client_key=$tmp_dir/crt_client_key
+    sed -i '/^\s*<key>/,/\s*<\/key>/d' ${config_file}
+    sed -i '/^\s*key\s/d' ${config_file}
+    echo -e "\nkey /etc/openvpn/keys/user.key" >> ${config_file}
+  elif ! grep -q '^\s*key\s' ${config_file}
+  then
+    crt_client_key=""
+  fi
+  if grep -q '^\s*<tls-auth>' ${config_file}
+  then
+    grep -Poz '(?<=<tls-auth>)(.*\n)*.*(?=</tls-auth>)' ${config_file} | sed '/^$/d' > $tmp_dir/crt_client_ta
+    crt_client_ta=$tmp_dir/crt_client_ta
+    sed -i '/^\s*<tls-auth>/,/\s*<\/tls-auth>/d' ${config_file}
+    sed -i '/^\s*tls-auth\s/d' ${config_file}
+    echo -e "\ntls-auth /etc/openvpn/keys/user_ta.key 1" >> ${config_file}
+  elif ! grep -q '^\s*tls-auth\s' ${config_file}
+  then
+    crt_client_ta=""
+  fi
+  sed -i 's@^\s*ca\s.*$@ca /etc/openvpn/keys/ca-server.crt@g' ${config_file}
+  sed -i 's@^\s*cert\s.*$@cert /etc/openvpn/keys/user.crt@g' ${config_file}
+  sed -i 's@^\s*key\s.*$@key /etc/openvpn/keys/user.key@g' ${config_file}
+  sed -i 's@^\s*tls-auth\s.*$@tls-auth /etc/openvpn/keys/user_ta.key 1@g' ${config_file}
+
+  script_security="script-security 2"
+  if grep -q '^\s*script-security\s.*$' ${config_file}; then
+    sed -i "s@^\s*script-security\s.*\$@$script_security@g" ${config_file}
+  else
+    echo "$script_security" >> ${config_file}
+  fi
+
+  route_up='route-up "/etc/openvpn/scripts/run-parts.sh route-up"'
+  if grep -q '^\s*route-up\s.*$' ${config_file}; then
+    sed -i "s@^\s*route-up\s.*\$@$route_up@g" ${config_file}
+  else
+    echo "$route_up" >> ${config_file}
+  fi
+
+  route_down='down "/etc/openvpn/scripts/run-parts.sh route-down"'
+  if grep -q '^\s*down\s.*$' ${config_file}; then
+    sed -i "s@^\s*down\s.*\$@$route_down@g" ${config_file}
+  else
+    echo "$route_down" >> ${config_file}
+  fi
+
+  # Currently we need root priviledge to create tun0
+  sed -i '/^\s*user\s/d' ${config_file}
+  sed -i '/^\s*group\s/d' ${config_file}
+}

+ 19 - 35
scripts/backup

@@ -1,57 +1,41 @@
 #!/bin/bash
 
-#=================================================
-# GENERIC START
-#=================================================
-# IMPORT GENERIC HELPERS
-#=================================================
-
 source ../settings/scripts/_common.sh
 source /usr/share/yunohost/helpers
 
 #=================================================
-# MANAGE SCRIPT FAILURE
-#=================================================
-
-# Exit if an error occurs during the execution of the script
-ynh_abort_if_errors
-
-#=================================================
-# LOAD SETTINGS
-#=================================================
-ynh_print_info "Loading installation settings..."
-
-app=$YNH_APP_INSTANCE_NAME
-
-#=================================================
-# STANDARD BACKUP STEPS
-#=================================================
 # BACKUP THE APP MAIN DIR
 #=================================================
 ynh_print_info "Backing up the main app directory..."
 
-ynh_backup "/usr/local/bin/$service_name-loadcubefile.sh"
+ynh_backup --src_path="/usr/local/bin/$service_name-loadcubefile.sh"
 
-ynh_backup "/etc/yunohost/hooks.d/90-vpnclient.tpl"
+ynh_backup --src_path="/etc/yunohost/hooks.d/90-vpnclient.tpl"
 
-ynh_backup "/etc/openvpn/client.conf.tpl"
-ynh_backup "/etc/openvpn/keys/"
-ynh_backup "/etc/openvpn/scripts/run-parts.sh"
+ynh_backup --src_path="/etc/openvpn/client.conf.tpl"
+ynh_backup --src_path="/etc/openvpn/client.conf" --not_mandatory
+ynh_backup --src_path="/etc/openvpn/client.cube" --not_mandatory
+ynh_backup --src_path="/etc/openvpn/client.ovpn" --not_mandatory
 
-ynh_backup "/usr/local/bin/$service_name"
-ynh_backup "/usr/local/bin/$service_checker_name.sh"
+for FILE in $(ls /etc/openvpn/scripts/route-up.d/*-vpnclient-* /etc/openvpn/scripts/route-down.d/*-vpnclient-*); do
+    ynh_backup --src_path="$FILE"
+done
+
+ynh_backup --src_path="/etc/openvpn/keys/"
+ynh_backup --src_path="/etc/openvpn/scripts/run-parts.sh"
+
+ynh_backup --src_path="/usr/local/bin/$service_name"
+ynh_backup --src_path="/usr/local/bin/$service_checker_name.sh"
 
-#=================================================
-# SPECIFIC BACKUP
 #=================================================
 # BACKUP SYSTEMD
 #=================================================
 ynh_print_info "Backing up systemd configuration..."
 
-ynh_backup "/etc/systemd/system/$service_name.service"
-ynh_backup "/etc/systemd/system/$service_checker_name.service"
-ynh_backup "/etc/systemd/system/$service_checker_name.timer"
-ynh_backup "/etc/systemd/system/openvpn@.service.d/override.conf"
+ynh_backup --src_path="/etc/systemd/system/$service_name.service"
+ynh_backup --src_path="/etc/systemd/system/$service_checker_name.service"
+ynh_backup --src_path="/etc/systemd/system/$service_checker_name.timer"
+ynh_backup --src_path="/etc/systemd/system/openvpn@.service.d/override.conf"
 
 #=================================================
 # END OF SCRIPT

+ 17 - 125
scripts/config

@@ -195,23 +195,6 @@ set__login_passphrase() {
 #=================================================
 # OVERWRITING VALIDATE STEP
 #=================================================
-read_cube() {
-    tmp_dir=$(dirname "$1")
-    setting_value="$(jq --raw-output ".$2" "$1")"
-    if [[ "$setting_value" == "null" ]]
-    then
-        setting_value=''
-    # Save file in tmp dir
-    elif [[ "$2" == "crt_"* ]]
-    then
-        if [ -n "${setting_value}" ]
-        then
-            echo "${setting_value}" | sed 's/|/\n/g' > $tmp_dir/$2
-            setting_value="$tmp_dir/$2"
-        fi
-    fi
-    echo $setting_value
-}
 ynh_app_config_validate() {
     # At this moment this var is not already set with the old value
     if [ -z ${config_file+x} ]
@@ -224,115 +207,21 @@ ynh_app_config_validate() {
     # (i.e. it starts with { ..)
     elif [ -f "${config_file}" ] && [[ "$(cat ${config_file} | tr -d ' ' | grep -v "^$" | head -c1)" == "{" ]]
     then
-        ynh_print_info --message="Transforming .cube into OVPN file"
-        server_name="$(read_cube $config_file server_name)"
-        server_port="$(read_cube $config_file server_port)"
-        server_proto="$(read_cube $config_file server_proto)"
-        ip6_net="$(read_cube $config_file ip6_net)"
-        ip6_addr="$(read_cube $config_file ip6_addr)"
-        login_user="$(read_cube $config_file login_user)"
-        login_passphrase="$(read_cube $config_file login_passphrase)"
-        dns0="$(read_cube $config_file dns0)"
-        dns1="$(read_cube $config_file dns1)"
-        crt_server_ca="$(read_cube $config_file crt_server_ca)"
-        crt_client="$(read_cube $config_file crt_client)"
-        crt_client_key="$(read_cube $config_file crt_client_key)"
-        crt_client_ta="$(read_cube $config_file crt_client_ta)"
-
-        if [[ -z "$dns0" && -z "$dns1" ]]; then
-          dns_method="yunohost"
-        else
-          dns_method="custom"
-          nameservers="$dns0,$dns1"
-        fi
-        
-        # Build specific OVPN template
-        tmp_dir=$(dirname "${config_file}")
-        cp -f /etc/yunohost/apps/vpnclient/conf/openvpn_client.conf.tpl $tmp_dir/client.conf.tpl
-        # Remove some lines
-        jq --raw-output '.openvpn_rm[]' "${config_file}" | while read -r rm_regex
-        do
-            if [ ! -z "${rm_regex}" ] ; then
-		sed -i "/${rm_regex/\//\\\/}/d" $tmp_dir/client.conf.tpl
-            fi
-        done
-
-        # Add some other lines
-        echo "# Custom additions from .cube" >> $tmp_dir/client.conf.tpl
-        jq --raw-output ".openvpn_add[]" "${config_file}" >> $tmp_dir/client.conf.tpl
-
-        # Temporarily tweak sever_proto for template hydratation
-        [ "$server_proto" == tcp ] && server_proto=tcp-client
-
-        # Define other needed vars for template hydratation
-        [ -e "$crt_client_key" ] && cert_comment="" || cert_comment="#"
-        [ -e "$crt_client_ta" ] && ta_comment="" || ta_comment="#"
-        [[ "$server_proto" =~ udp ]] && udp_comment="" || udp_comment="#"
-        [ -n "$login_user" ] && login_comment="" || login_comment="#"
-
-        # Actually generate/hydrate the final configuration
-        ynh_add_config --template="$tmp_dir/client.conf.tpl" --destination="${config_file}"
-
-        [ "$server_proto" == tcp-client ] && server_proto=tcp
+        local tmp_dir=$(dirname "$config_file")
 
+        cube_file="$tmp_dir/client.cube"
+        cp -f "$config_file" "$cube_file"
 
+        convert_cube_file "$config_file"
     # Othewise, assume that it's a .ovpn / .conf
     elif [ -f "${config_file}" ]
     then
-        tmp_dir=$(dirname "${config_file}")
-        ynh_print_info --message="Extracting TLS keys from .ovpn file"
-        if grep -q '^\s*<ca>' ${config_file}
-        then
-            grep -Poz '(?<=<ca>)(.*\n)*.*(?=</ca>)' ${config_file} | sed '/^$/d'  > $tmp_dir/crt_server_ca
-            crt_server_ca=$tmp_dir/crt_server_ca
-            sed -i '/^\s*<ca>/,/\s*<\/ca>/d' ${config_file}
-            sed -i '/^\s*ca\s/d' ${config_file}
-            echo -e "\nca /etc/openvpn/keys/ca-server.crt" >> ${config_file}
-        fi
-        if grep -q '^\s*<cert>' ${config_file}
-        then
-            grep -Poz '(?<=<cert>)(.*\n)*.*(?=</cert>)' ${config_file} | sed '/^$/d'  > $tmp_dir/crt_client
-            crt_client=$tmp_dir/crt_client
-            sed -i '/^\s*<cert>/,/\s*<\/cert>/d' ${config_file}
-            sed -i '/^\s*cert\s/d' ${config_file}
-            echo -e "\ncert /etc/openvpn/keys/user.crt" >> ${config_file}
-        elif ! grep -q '^\s*cert\s' ${config_file}
-        then
-            crt_client=""
-        fi
-        if grep -q '^\s*<key>' ${config_file}
-        then
-            grep -Poz '(?<=<key>)(.*\n)*.*(?=</key>)' ${config_file} | sed '/^$/d' > $tmp_dir/crt_client_key
-            crt_client_key=$tmp_dir/crt_client_key
-            sed -i '/^\s*<key>/,/\s*<\/key>/d' ${config_file}
-            sed -i '/^\s*key\s/d' ${config_file}
-            echo -e "\nkey /etc/openvpn/keys/user.key" >> ${config_file}
-        elif ! grep -q '^\s*key\s' ${config_file}
-        then
-            crt_client_key=""
-        fi
-        if grep -q '^\s*<tls-auth>' ${config_file}
-        then
-            grep -Poz '(?<=<tls-auth>)(.*\n)*.*(?=</tls-auth>)' ${config_file} | sed '/^$/d' > $tmp_dir/crt_client_ta
-            crt_client_ta=$tmp_dir/crt_client_ta
-            sed -i '/^\s*<tls-auth>/,/\s*<\/tls-auth>/d' ${config_file}
-            sed -i '/^\s*tls-auth\s/d' ${config_file}
-            echo -e "\ntls-auth /etc/openvpn/keys/user_ta.key 1" >> ${config_file}
-        elif ! grep -q '^\s*tls-auth\s' ${config_file}
-        then
-            crt_client_ta=""
-        fi
-        sed -i 's@^\s*ca\s.*$@ca /etc/openvpn/keys/ca-server.crt@g' ${config_file}
-        sed -i 's@^\s*cert\s.*$@cert /etc/openvpn/keys/user.crt@g' ${config_file}
-        sed -i 's@^\s*key\s.*$@key /etc/openvpn/keys/user.key@g' ${config_file}
-        sed -i 's@^\s*tls-auth\s.*$@tls-auth /etc/openvpn/keys/user_ta.key 1@g' ${config_file}
-    fi
+        local tmp_dir=$(dirname "$config_file")
 
-    # Currently we need root priviledge to create tun0
-    if [ -f "${config_file}" ]
-    then
-        sed -i '/^\s*user\s/d' ${config_file}
-        sed -i '/^\s*group\s/d' ${config_file}
+        ovpn_file="$tmp_dir/client.ovpn"
+        cp -f "$config_file" "$ovpn_file"
+
+        convert_ovpn_file "$config_file"
     fi
 
     _ynh_app_config_validate
@@ -345,8 +234,8 @@ ynh_app_config_apply() {
 
     # Stop vpn client
     ynh_print_info --message="Stopping vpnclient in order to edit files"
-    touch /tmp/.ynh-vpnclient-stopped
-    /usr/local/bin/ynh-vpnclient stop
+    ynh_systemd_action --service_name="ynh-vpnclient-checker.timer" --action="stop"
+    ynh_systemd_action --service_name="ynh-vpnclient" --action="stop"
 
     chown $app:$app /etc/openvpn/keys
     chmod go=--- /etc/openvpn/keys
@@ -359,11 +248,14 @@ ynh_app_config_apply() {
     set_permissions /etc/openvpn/keys/user.key
     set_permissions /etc/openvpn/keys/user_ta.key
 
+    # Cleanup previously uploaded config file
+    [[ "$cube_file" == "/etc/openvpn/client.cube" ]] && rm -f "$cube_file"
+    [[ "$ovpn_file" == "/etc/openvpn/client.ovpn" ]] && rm -f "$ovpn_file"
+
     # Start vpn client
     ynh_print_info --message="Starting vpnclient service if needed"
-    /usr/local/bin/ynh-vpnclient start
-    rm -f /tmp/.ynh-vpnclient-stopped
-
+    ynh_systemd_action --service_name="ynh-vpnclient" --action="start"
+    ynh_systemd_action --service_name="ynh-vpnclient-checker.timer" --action="start"
 }
 
 ynh_app_config_run $1

+ 0 - 51
scripts/install

@@ -1,50 +1,8 @@
 #!/bin/bash
 
-# VPN Client app for YunoHost
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/vpnclient_ynh
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-#=================================================
-# GENERIC START
-#=================================================
-# IMPORT GENERIC HELPERS
-#=================================================
-
 source _common.sh
 source /usr/share/yunohost/helpers
 
-#=================================================
-# MANAGE SCRIPT FAILURE
-#=================================================
-
-# Exit if an error occurs during the execution of the script
-ynh_abort_if_errors
-
-#=================================================
-# RETRIEVE ARGUMENTS FROM THE MANIFEST
-#=================================================
-
-# Retrieve arguments
-app=$YNH_APP_INSTANCE_NAME
-
-#=================================================
-# STORE SETTINGS FROM MANIFEST
-#=================================================
-ynh_script_progression "Storing installation settings..."
-
 # Default values for config panel
 ynh_app_setting_set "$app" service_enabled 0
 ynh_app_setting_set "$app" dns_method "yunohost"
@@ -53,15 +11,6 @@ ynh_app_setting_set "$app" ip6_addr ""
 ynh_app_setting_set "$app" ip6_net ""
 
 #=================================================
-# STANDARD MODIFICATIONS
-#=================================================
-# INSTALL DEPENDENCIES
-#=================================================
-ynh_script_progression "Installing dependencies..."
-
-ynh_install_app_dependencies "$pkg_dependencies"
-
-#=================================================
 # DEPLOY FILES FROM PACKAGE
 #=================================================
 ynh_script_progression "Deploy files from package..."

+ 8 - 49
scripts/remove

@@ -1,39 +1,9 @@
 #!/bin/bash
 
-# VPN Client app for YunoHost
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/vpnclient_ynh
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-#=================================================
-# GENERIC STARTING
-#=================================================
-# IMPORT GENERIC HELPERS
-#=================================================
-
 source _common.sh
 source /usr/share/yunohost/helpers
 
 #=================================================
-# LOAD SETTINGS
-#=================================================
-ynh_print_info "Loading installation settings..."
-
-app=$YNH_APP_INSTANCE_NAME
-
-#=================================================
 # STOP AND REMOVE SERVICES
 #=================================================
 ynh_print_info "Stopping and removing services"
@@ -43,15 +13,13 @@ systemctl disable $service_checker_name.timer --quiet
 systemctl stop $service_checker_name
 systemctl disable $service_checker_name --quiet
 
-if ynh_exec_warn_less yunohost service status $service_name >/dev/null
-then
+if ynh_exec_warn_less yunohost service status $service_name >/dev/null; then
     yunohost service stop $service_name
     yunohost service disable $service_name --quiet
     yunohost service remove $service_name
 fi
 
-for FILE in $(ls /etc/systemd/system/$service_name* /usr/local/bin/ynh-vpnclient* /tmp/.ynh-vpnclient-*)
-do
+for FILE in $(ls /etc/systemd/system/$service_name* /usr/local/bin/ynh-vpnclient* /tmp/.ynh-vpnclient-*); do
     ynh_secure_remove "$FILE"
 done
 
@@ -63,10 +31,16 @@ ynh_print_info "Removing openvpn configuration"
 # Remove openvpn configurations
 ynh_secure_remove /etc/openvpn/client.conf
 ynh_secure_remove /etc/openvpn/client.conf.tpl
+ynh_secure_remove /etc/openvpn/client.cube
+ynh_secure_remove /etc/openvpn/client.ovpn
 
 # Remove openvpn script
 ynh_secure_remove /etc/openvpn/scripts/run-parts.sh
 
+for FILE in $(ls /etc/openvpn/scripts/route-up.d/*-vpnclient-* /etc/openvpn/scripts/route-down.d/*-vpnclient-*); do
+    ynh_secure_remove "$FILE"
+done
+
 # Remove YunoHost hook
 ynh_secure_remove /etc/yunohost/hooks.d/90-vpnclient.tpl
 
@@ -84,21 +58,6 @@ ynh_print_info "Reloading firewall"
 yunohost firewall reload
 
 #=================================================
-# REMOVE DEPENDENCIES
-#=================================================
-ynh_print_info "Removing dependencies"
-ynh_remove_app_dependencies
-
-#=================================================
-# REMOVE DEDICATED USER
-#=================================================
-
-ynh_print_info "Removing the dedicated system user"
-
-# Delete a system user
-ynh_system_user_delete ${app}
-
-#=================================================
 # END OF SCRIPT
 #=================================================
 

+ 19 - 59
scripts/restore

@@ -1,86 +1,46 @@
 #!/bin/bash
 
-#=================================================
-# GENERIC START
-#=================================================
-# IMPORT GENERIC HELPERS
-#=================================================
-
 source ../settings/scripts/_common.sh
 source /usr/share/yunohost/helpers
 
 #=================================================
-# MANAGE SCRIPT FAILURE
-#=================================================
-
-# Exit if an error occurs during the execution of the script
-ynh_abort_if_errors
-
-#=================================================
-# LOAD SETTINGS
-#=================================================
-ynh_print_info "Loading settings..."
-
-app=$YNH_APP_INSTANCE_NAME
-
-#=================================================
 # RESTORE THE APP MAIN DIR
 #=================================================
 ynh_print_info "Restoring the app files..."
 
-ynh_restore_file "/usr/local/bin/$service_name-loadcubefile.sh"
-
-ynh_restore_file "/etc/yunohost/hooks.d/90-vpnclient.tpl"
-
-ynh_restore_file "/etc/openvpn/client.conf.tpl"
-ynh_restore_file "/etc/openvpn/keys/"
-ynh_restore_file "/etc/openvpn/scripts/run-parts.sh"
-
-ynh_restore_file "/usr/local/bin/$service_name"
-ynh_restore_file "/usr/local/bin/$service_checker_name.sh"
-
-#=================================================
-# RECREATE THE DEDICATED USER
-#=================================================
-ynh_print_info "Recreating the dedicated system user..."
-
-# Create the dedicated user (if not existing)
-ynh_system_user_create $app
-
-#=================================================
-# SPECIFIC RESTORATION
-#=================================================
-# REINSTALL DEPENDENCIES
-#=================================================
-ynh_print_info "Reinstalling dependencies..."
-
-# Define and install dependencies
-ynh_install_app_dependencies "$pkg_dependencies"
+ynh_restore
 
 #=================================================
 # RESTORE SYSTEMD
 #=================================================
 ynh_print_info "Restoring the systemd configuration..."
 
-ynh_restore_file "/etc/systemd/system/$service_name.service"
-ynh_restore_file "/etc/systemd/system/$service_checker_name.service"
-ynh_restore_file "/etc/systemd/system/$service_checker_name.timer"
-ynh_restore_file "/etc/systemd/system/openvpn@.service.d/override.conf"
 systemctl daemon-reload
-systemctl enable "$service_name.service" --quiet
-systemctl enable "$service_checker_name.service" --quiet
-systemctl enable "openvpn@.service" --quiet
 
-#=================================================
-# ADVERTISE SERVICE IN ADMIN PANEL
-#=================================================
+# Set default inits
+# The boot order of these services are important, so they are disabled by default
+# and the vpnclient service handles them.
+systemctl disable openvpn --quiet
+systemctl stop openvpn
+
+# main service
 
 yunohost service add $service_name --description "Tunnels the internet traffic through a VPN" --need_lock --test_status="systemctl is-active openvpn@client.service" --log "/var/log/ynh-vpnclient.log"
+yunohost service enable "$service_name"
+
+# checker service
+
+systemctl start "$service_checker_name"
+systemctl enable "$service_checker_name" --quiet
+systemctl start "$service_checker_name.timer"
+systemctl enable "$service_checker_name.timer" --quiet
+
 
 #=================================================
-# GENERIC FINALIZATION
+# ADVERTISE SERVICE IN ADMIN PANEL
 #=================================================
 
+
 #=================================================
 # END OF SCRIPT
 #=================================================

+ 37 - 59
scripts/upgrade

@@ -1,31 +1,10 @@
 #!/bin/bash
 
-#=================================================
-# GENERIC STARTING
-#=================================================
-# IMPORT GENERIC HELPERS
-#=================================================
-
 source _common.sh
 source /usr/share/yunohost/helpers
 
-ynh_abort_if_errors
-
-#=================================================
-# LOAD SETTINGS
 #=================================================
-ynh_print_info "Loading installation settings..."
-
-app=$YNH_APP_INSTANCE_NAME
-
-dns_method=$(ynh_app_setting_get $app dns_method)
-nameservers=$(ynh_app_setting_get $app nameservers)
-service_enabled=$(ynh_app_setting_get $app service_enabled)
-ip6_addr=$(ynh_app_setting_get $app ip6_addr)
-ip6_net=$(ynh_app_setting_get $app ip6_net)
-
-#=================================================
-# SPECIAL UPGRADE FOR VERSIONS < 1.2.0
+# SPECIAL UPGRADE FOR VERSIONS < 2.0
 #=================================================
 
 # Removing configuration files with naming that occured in versions < 1.2.0 ("vpnadmin" instead off "$app")
@@ -33,10 +12,6 @@ if [ -d /var/www/vpnadmin ]; then
   ynh_secure_remove /var/www/vpnadmin
 fi
 
-#=================================================
-# SPECIAL UPGRADE FOR VERSIONS < 2.0
-#=================================================
-
 # Old stuff
 
 if [ -f /etc/nginx/conf.d/*.d/$app.conf ]; then
@@ -52,10 +27,10 @@ if [ -d /var/www/$app ]; then
 	ynh_secure_remove /var/www/$app
 fi
 
-[ -z "$(ynh_app_setting_get $app domain)" ] || ynh_app_setting_delete $app domain
-[ -z "$(ynh_app_setting_get $app path)" ] || ynh_app_setting_delete $app path
-[ -z "$(ynh_app_setting_get $app is_public)" ] || ynh_app_setting_delete $app is_public
-[ -z "$(ynh_app_setting_get $app final_path)" ] || ynh_app_setting_delete $app final_path
+[ -z "${domain:-}" ] || ynh_app_setting_delete $app domain
+[ -z "${path:-}" ] || ynh_app_setting_delete $app path
+[ -z "${is_public:-}" ] || ynh_app_setting_delete $app is_public
+[ -z "${install_dir:-}" ] || ynh_app_setting_delete $app install_dir
 
 if [ -e "/etc/sudoers.d/${app}_ynh" ]; then
   ynh_secure_remove "/etc/sudoers.d/${app}_ynh"
@@ -63,20 +38,20 @@ fi
 
 # New stuff
 
-if [ -z "$dns_method" ]; then
+if [ -z "${dns_method:-}" ]; then
     ynh_app_setting_set --app=$app --key=dns_method --value=custom
 fi
-if [ -z "$nameservers" ]; then
+if [ -z "${nameservers:-}" ]; then
     nameservers="$(grep -o -P '\s*nameserver\s+\K[abcdefabcdef\d.:]+' /etc/resolv.dnsmasq.conf | sort | uniq | paste -s -d, -)"
     ynh_app_setting_set --app=$app --key=nameservers --value="$nameservers"
 fi
-if [ -z "$service_enabled" ]; then
+if [ -z "${service_enabled:-}" ]; then
     ynh_app_setting_set --app=$app --key=service_enabled --value=0
 fi
-if [ -z "$ip6_addr" ]; then
+if [ -z "${ip6_addr:-}" ]; then
     ynh_app_setting_set --app=$app --key=ip6_addr --value=""
 fi
-if [ -z "$ip6_net" ]; then
+if [ -z "${ip6_net:-}" ]; then
     ynh_app_setting_set --app=$app --key=ip6_net --value=""
 fi
 
@@ -88,41 +63,48 @@ if [ -e "/etc/systemd/system/openvpn@.service" ]; then
   ynh_secure_remove "/etc/systemd/system/openvpn@.service"
 fi
 
-##=================================================
-## BACKUP BEFORE UPGRADE THEN ACTIVE TRAP
-##=================================================
-
-# Not done because vpnclient backup ain't so relevant I guess ?
-
 #=================================================
-# DO UPGRADE
-#=================================================
-# INSTALL DEPENDENCIES
+# DEPLOY FILES FROM PACKAGE
 #=================================================
-ynh_print_info "Installing dependencies..."
 
-ynh_install_app_dependencies "$pkg_dependencies"
+ynh_print_info --message="Stopping VPN client to apply config changes..."
 
-#=================================================
-# DEPLOY FILES FROM PACKAGE
-#=================================================
+ynh_systemd_action --action="stop" --service_name="$service_checker_name.timer"
+yunohost service stop $service_name
 
 # Keep a copy of existing config files before overwriting them
-tmpdir=$(mktemp -d /tmp/vpnclient-upgrade-XXX)
-cp -r /etc/openvpn/client* ${tmpdir}
+tmp_dir=$(mktemp -d /tmp/vpnclient-upgrade-XXX)
+cp -r /etc/openvpn/client* ${tmp_dir}
 
 # Deploy files from package
 vpnclient_deploy_files_and_services
 
+# Generate config file from the uploaded .cube or .ovpn file, if available
+if [[ -f "$tmp_dir/client.cube" ]]
+then
+    cp -f "$tmp_dir/client.cube" "$tmp_dir/client.conf"
+    convert_cube_file "$tmp_dir/client.conf"
+elif [[ -f "$tmp_dir/client.ovpn" ]]
+then
+    cp -f "$tmp_dir/client.ovpn" "$tmp_dir/client.conf"
+    convert_ovpn_file "$tmp_dir/client.conf"
+# In case we didn't keep the uploaded .ovpn file, we create one from the current config...
+elif [[ -f "$tmp_dir/client.conf" ]]
+then
+    cp -f "$tmp_dir/client.conf" "$tmp_dir/client.ovpn"
+    convert_ovpn_file "$tmp_dir/client.conf"
+fi
+
 # Restore previously existing config files
-cp -r ${tmpdir}/client* /etc/openvpn/
-ynh_secure_remove ${tmpdir}
+cp -r ${tmp_dir}/client* /etc/openvpn/
+ynh_secure_remove ${tmp_dir}
 
 #=================================================
 # SERVICE INTEGRATION IN YUNOHOST
 #=================================================
 
 ### Make sure that the yunohost services have a description and need-lock enabled
+ynh_print_info "Configuring VPN client services..."
 
 # main service
 yunohost service add $service_name --description "Tunnels the internet traffic through a VPN" --need_lock --test_status="systemctl is-active openvpn@client.service" --log "/var/log/ynh-vpnclient.log"
@@ -139,12 +121,8 @@ fi
 ynh_print_info "Restart services..."
 
 # this is meant to propagate the new files and configs
-
-systemctl -q is-active $service_name               && yunohost service restart $service_name
-
-# Not sure if these are really necessary ...
-systemctl -q is-active $service_checker_name       && systemctl restart $service_checker_name
-systemctl -q is-active $service_checker_name.timer && systemctl restart $service_checker_name.timer
+yunohost service start $service_name
+ynh_systemd_action --action="start" --service_name="$service_checker_name.timer"
 
 #=================================================
 # END OF SCRIPT

+ 9 - 0
tests.toml

@@ -0,0 +1,9 @@
+#:schema https://raw.githubusercontent.com/YunoHost/apps/master/schemas/tests.v1.schema.json
+
+test_format = 1.0
+
+[default]
+
+    [default.test_upgrade_from.0d2a6b1d]
+    name = "v1 era"
+    args.domain = "domain.tld"