add the install script to support cloud-init and local one-shot deployments

This commit is contained in:
Jack Ivanov 2019-03-20 15:24:58 +01:00
parent 13c4628b5d
commit e8f733a8b8
2 changed files with 163 additions and 0 deletions

View file

@ -0,0 +1,55 @@
# Deploy from script or cloud-init
You can use `install.sh` to prepare the environment and deploy AlgoVPN on the local Ubuntu server in one shot using cloud-init or run the script directly on the server.
## Cloud init deployment
You can copy-paste the snippet bellow to the user data (cloud-init or startup script) field when you creating a new server. For now it is only possible for [DigitalOcean](https://www.digitalocean.com/docs/droplets/resources/metadata/), Amazon [EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html) and [Lightsail](https://lightsail.aws.amazon.com/ls/docs/en/articles/lightsail-how-to-configure-server-additional-data-shell-script), [Google Cloud](https://cloud.google.com/compute/docs/startupscript) and [Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/using-cloud-init).
```
#!/bin/bash
curl -s https://raw.githubusercontent.com/trailofbits/algo/master/install.sh | sudo bash -x
```
The command will prepare the environment and install AlgoVPN with default parameters. If you want to modify the behaviour you may define additional variables.
## Variables
`METHOD` - which method of the deployment to use. Possible values are local and cloud. Default: cloud. The cloud method is intended to use in cloud-init deployments only. If you are not using cloud-init to deploy the server you have to use the local method
`ONDEMAND_CELLULAR` - "Connect On Demand" when connected to cellular networks. Bollean. Default: false
`ONDEMAND_WIFI` - "Connect On Demand" when connected to Wi-Fi. Default: false
`ONDEMAND_WIFI_EXCLUDE` - List the names of any trusted Wi-Fi networks where macOS/iOS IPsec clients should not use "Connect On Demand". Comma-separated list.
`WINDOWS` - To support Windows 10 or Linux Desktop clients. Default: false
`STORE_CAKEY` - To retain the CA key. (required to add users in the future, but less secure). Default: false
`LOCAL_DNS` - To install an ad blocking DNS resolver. Default: false
`SSH_TUNNELING` - Enable SSH tunneling for each user. Default: false
`ENDPOINT` - The public IP address or domain name of your server: (IMPORTANT! This is used to verify the certificate). It will be gathered automatically for DigitalOcean, AWS, GCE or Azure if the `METHOD` is cloud. Otherwise you need to define this variable according to your public IP address.
`USERS` - list of VPN users. Comma-separated list.
## Examples
##### How to customise a cloud-init deployment by variables
```
#!/bin/bash
export ONDEMAND_CELLULAR=true
export WINDOWS=true
export SSH_TUNNELING=true
curl -s https://raw.githubusercontent.com/trailofbits/algo/master/install.sh | sudo bash -x
```
##### How to deploy locally without using cloud-init
```
export METHOD=local
export ONDEMAND_CELLULAR=true
curl -s https://raw.githubusercontent.com/trailofbits/algo/master/install.sh | sudo bash -x
```
##### How to deploy a server using arguments
The arguments order as per [variables](#variables) above
```
curl -s https://raw.githubusercontent.com/trailofbits/algo/master/install.sh | sudo bash -x -s local true false _null true true true true myvpnserver.com
```

108
install.sh Normal file
View file

@ -0,0 +1,108 @@
#!/usr/bin/env sh
set -ex
METHOD="${1:-${METHOD:-cloud}}"
ONDEMAND_CELLULAR="${2:-${ONDEMAND_CELLULAR:-false}}"
ONDEMAND_WIFI="${3:-${ONDEMAND_WIFI:-false}}"
ONDEMAND_WIFI_EXCLUDE="${4:-${ONDEMAND_WIFI_EXCLUDE:-_null}}"
WINDOWS="${5:-${WINDOWS:-false}}"
STORE_CAKEY="${6:-${STORE_CAKEY:-false}}"
LOCAL_DNS="${7:-${LOCAL_DNS:-false}}"
SSH_TUNNELING="${8:-${SSH_TUNNELING:-false}}"
ENDPOINT="${9:-${ENDPOINT:-localhost}}"
USERS="${10:-${USERS:-user1}}"
cd /opt/
installRequirements() {
apt-get update
apt-get install \
software-properties-common \
git \
build-essential \
libssl-dev \
libffi-dev \
python-dev \
python-pip \
python-setuptools \
python-virtualenv \
bind9-host \
jq -y
}
getAlgo() {
[ ! -d "algo" ] && git clone https://github.com/trailofbits/algo algo
cd algo
python -m virtualenv --python=`which python2` .venv
. .venv/bin/activate
python -m pip install -U pip virtualenv
python -m pip install -r requirements.txt
}
publicIpFromInterface() {
echo "Couldn't find a valid ipv4 address, using the first IP found on the interfaces as the endpoint."
DEFAULT_INTERFACE="$(ip -4 route list match default | grep -Eo "dev .*" | awk '{print $2}')"
ENDPOINT=$(ip -4 addr sh dev eth0 | grep -w inet | head -n1 | awk '{print $2}' | grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b')
export ENDPOINT=$ENDPOINT
echo "Using ${ENDPOINT} as the endpoint"
}
publicIpFromMetadata() {
if curl -s http://169.254.169.254/metadata/v1/vendor-data | grep DigitalOcean >/dev/null; then
PROVIDER="digitalocean"
ENDPOINT="$(curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address)"
elif test "$(curl -s http://169.254.169.254/latest/meta-data/services/domain)" = "amazonaws.com"; then
PROVIDER="amazon"
ENDPOINT="$(curl -s http://169.254.169.254/latest/meta-data/public-ipv4)"
elif host -t A -W 10 metadata.google.internal 127.0.0.53 >/dev/null; then
PROVIDER="gce"
ENDPOINT="$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip")"
elif test "$(curl -s -H Metadata:true 'http://169.254.169.254/metadata/instance/compute/publisher/?api-version=2017-04-02&format=text')" = "Canonical"; then
PROVIDER="azure"
ENDPOINT="$(curl -H Metadata:true 'http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text')"
fi
if echo ${ENDPOINT} | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"; then
export ENDPOINT=$ENDPOINT
echo "Using ${ENDPOINT} as the endpoint"
else
publicIpFromInterface
fi
}
deployAlgo() {
getAlgo
cd /opt/algo
. .venv/bin/activate
export HOME=/root
export ANSIBLE_LOCAL_TEMP=/root/.ansible/tmp
export ANSIBLE_REMOTE_TEMP=/root/.ansible/tmp
ansible-playbook main.yml \
-e provider=local \
-e ondemand_cellular=${ONDEMAND_CELLULAR} \
-e ondemand_wifi=${ONDEMAND_WIFI} \
-e ondemand_wifi_exclude=${ONDEMAND_WIFI_EXCLUDE} \
-e windows=${WINDOWS} \
-e store_cakey=${STORE_CAKEY} \
-e local_dns=${LOCAL_DNS} \
-e ssh_tunneling=${SSH_TUNNELING} \
-e endpoint=$ENDPOINT \
-e users=$(echo "$USERS" | jq -Rc 'split(",")') \
-e server=localhost \
-e ssh_user=root \
--skip-tags debug |
tee /var/log/algo.log
}
if test $METHOD = "cloud"; then
publicIpFromMetadata
fi
installRequirements
deployAlgo