#!/bin/sh

set -eu

app_base="/var/www/wg-selfserve"

die() {
    echo "$@" >&2
    exit 1
}

print_config() {
    cat <<EOF
[frontend]
site_name = $site_name

[wireguard]
tunnel_id = $tunnel_name
configs_base = $user_configs
dns_server = $dns_server
server_address = $public_ip
server_port = 51820
server_pubkey_file = $server_pubkey
server_privkey_file = $server_privkey
client_network = $client_network
server_extra_config = $server_fragment
client_extra_config = $client_fragment
user_client_limit = $user_max

[security]
required_entitlement =

[oauth]
authorization_url = https://oauth.example/authorize
token_url = https://oauth.example/exchange
introspection_url = https://oauth.example/verify
client_id = some_id_string
client_secret = some_secret_string
EOF
}

if ! [ "$(id -u)" = 0 ]; then
    die "This script must be run as root"
fi

if ! which sudo >/dev/null; then
    die "Sudo must be installed before running this script."
fi

if ! which apache2 >/dev/null; then
    die "Apache must be installed (with a basic configuration including SSL certificate) before running this script."
fi

echo "This script will install wg-selfserve."
echo
if ! [ -e "$app_base/config.ini" ]; then
    echo "First, some general required settings."
    echo

    read -p "Site name as shown in browser: " site_name
    read -p "Server name (FQDN): " server_name
    read -p "Public IP address for tunnel: " public_ip
    read -p "Network for client devices (CIDR): " client_network
    read -p "Wireguard interface name: " tunnel_name
    read -p "DNS Server IP: " dns_server
    read -p "Max number of clients per user: " user_max

    interface_name="$(ip -4 -o addr show \
                         | grep "$public_ip" \
                         | awk '{print $2}')"
    user_configs="$app_base/user-configs"
    server_privkey="$app_base/conf/server-priv.key"
    server_pubkey="$app_base/conf/server-pub.key"
    server_fragment="$app_base/server.conf"
    client_fragment="$app_base/client.conf"

    echo
    echo "This is the configuration that will be written to disk:"
    echo
    echo "--- BEGIN CONFIG ---"
    print_config
    echo "---  END CONFIG  ---"
    echo
    echo "NOTE: you will need to manually set the values in the [oauth] section to something meaningful."
    echo
else
    die "Config file exists, cannot proceed."
fi
echo

read -p "Proceed with installation? [y/n]" proceed
if ! [ "$proceed" = "y" ]; then
    die "Aborting then."
fi
echo

echo "Installing packages..."
apt-get install -qy \
        python3-venv \
        wireguard \
        uwsgi uwsgi-plugin-python3 \
        libapache2-mod-proxy-uwsgi
echo "done."
echo

if ! [ -d "$app_base" ]; then
    echo "Setting up application directory..."

    git clone https://gitea.dsv.su.se/DMC/wg-selfserve.git "$app_base"
    python3 -m venv "$app_base/env"
    . "$app_base/env/bin/activate"
    pip3 install -r "$app_base/requirements.txt"
    deactivate

    print_config > "$app_base/config.ini"

    mkdir "$user_configs"

    chown www-data: "$app_base/work"
    chown www-data: "$user_configs"

    mkdir "$app_base/conf"
    wg genkey | tee "$server_privkey" | wg pubkey > "$server_pubkey"

    cat <<EOF >"$client_fragment"
[Interface]
DNS = $dns_server
EOF

    cat <<EOF >"$server_fragment"
[Interface]
PreDown = iptables -t nat -D POSTROUTING -o $interface_name -j MASQUERADE
PostUp = %i -j ACCEPT; iptables -t nat -A POSTROUTING -o $interface_name -j MASQUERADE
EOF

    echo "done."
else
    echo "Application directory exists."
fi
echo

if ! [ -e /etc/uwsgi/apps-enabled/uwsgi.ini ]; then
    echo "Configuring uwsgi..."

    cp "$app_base/examples/uwsgi.ini" \
       /etc/uwsgi/apps-available/wg-selfserve.ini
    ln -s /etc/uwsgi/apps-available/wg-selfserve.ini /etc/uwsgi/apps-enabled/

    echo "done."
else
    echo "Uwsgi config file exists."
fi
echo

if ! [ -e /etc/apache2/sites-enabled/wg-selfserve.conf ]; then
    echo "Configuring apache vhost..."

    sed "s/wireguard.example.com/$server_name/g" \
        "$app_base/examples/apache.conf" \
        > /etc/apache2/site-available/wg-selfserve.conf

    a2enmod proxy_uwsgi proxy rewrite
    a2ensite wg-selfserve.conf

    echo "done."
else
    echo "Apache vhost exists."
fi
echo

echo "Configuring misc system settings..."
cat <<EOF >/etc/sysctl.d/wg-selfserve.conf
net.ipv4.ip_forward=1
EOF

cat <<EOF >/etc/sudoers.d/wg-selfserve
www-data ALL=(root:root) NOPASSWD: $app_base/commands.sh *
EOF
echo "done."
echo

echo "Restarting services..."
sysctl --system
systemctl restart uwsgi
systemctl restart apache2
echo "done."
echo

if ! [ -e "/etc/wireguard/$tunnel_name.conf" ]; then
    echo "Activating wireguard..."

    ln -s "$app_base/work/$tunnel_name.conf" \
       "/etc/wireguard/$tunnel_name.conf"
    systemctl enable "wg-quick@$tunnel_name.service"
    systemctl start "wg-quick@$tunnel_name.service"

    echo "done."
else
    echo "Wireguard config file exists."
fi
echo

echo "All done."
echo "The application should now be working and available at https://$server_name"
echo