├── .gitignore ├── README.md ├── admin_security_group.tf ├── dcos_gateway.tf ├── dcos_user_data.sh ├── dhcp_options.tf ├── doc └── images │ └── dcos.png ├── host_keys.tf ├── internal_master_load_balancer.tf ├── internet_gateway.tf ├── key_pair.tf ├── lb_security_group.tf ├── master_instance_profile.tf ├── master_launch_configuration.tf ├── master_role.tf ├── master_route_table.tf ├── master_security_group.tf ├── master_server_group.tf ├── master_subnet.tf ├── master_subnet_network_acl_association.tf ├── master_subnet_route_table_association.tf ├── master_user_data.yml ├── multi-master.cloudformation.json ├── nat_instance.tf ├── outputs.tf ├── private_route_table.tf ├── private_subnet.tf ├── private_subnet_network_acl_association.tf ├── private_subnet_route_table_association.tf ├── provider.tf ├── public_route_table.tf ├── public_slave_launch_configuration.tf ├── public_slave_load_balancer.tf ├── public_slave_security_group.tf ├── public_slave_server_group.tf ├── public_slave_user_data.yml ├── public_subnet.tf ├── public_subnet_network_acl_association.tf ├── public_subnet_route_table_association.tf ├── s3_bucket.tf ├── single-master.cloudformation.json ├── slave_launch_configuration.tf ├── slave_security_group.tf ├── slave_server_group.tf ├── slave_user_data.yml ├── smack ├── enter_cassandra.sh ├── killrweather │ ├── app │ │ ├── Dockerfile │ │ ├── app.sh │ │ ├── build.sh │ │ ├── client_app.sh │ │ └── ingest.sh │ └── data │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── import_data.sh ├── mesosphere │ └── cassandra │ │ ├── Dockerfile │ │ └── build.sh ├── run_app.sh ├── run_client_app.sh ├── run_ingest.sh └── show_kafka_topic.sh ├── terraform.tfvars.template ├── variables.tf ├── vpc.tf ├── vpn_gateway.tf ├── vpn_load_balancer.tf ├── vpn_security_group.tf ├── vpn_user_data.sh └── vpn_user_data.yml /.gitignore: -------------------------------------------------------------------------------- 1 | dcos/ 2 | .idea/ 3 | .terraform/ 4 | *.tfstate 5 | *.tfstate.backup 6 | *.plan 7 | *.tfvars 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DCOS Multi Master Terraform Module 2 | 3 | Using this [Terraform][] [module][], you can launch your own [DCOS][] cluster. 4 | 5 | The Mesosphere Datacenter Operating System (DCOS) spans all of the machines in your datacenter or cloud and treats 6 | them as a single, shared set of resources. DCOS provides a highly elastic and highly scalable way to build, deploy and 7 | manage modern applications using containers, microservices and big data systems.git 8 | 9 | ![DCOS](/doc/images/dcos.png) 10 | 11 | ## Configurables 12 | 13 | See [`variables.tf`](variables.tf) for a list of configurable parameters. 14 | 15 | [Terraform]: https://www.terraform.io 16 | [module]: https://www.terraform.io/docs/modules/index.html 17 | [DCOS]: https://mesosphere.com/learn/ 18 | 19 | ## Module Instructions 20 | 21 | To include this module in your Terraform code-base, use the following snippet: 22 | 23 | ```hcl 24 | module "dcos" { 25 | source = "github.com/zutherb/terraform-dcos" 26 | 27 | aws_access_key = "..." 28 | aws_secret_key = "..." 29 | aws_region = "eu-central-1" 30 | ssh_public_key = "ssh-rsa ..." 31 | 32 | ... 33 | } 34 | ``` 35 | 36 | Then run `terraform get` to retrieve this module. 37 | 38 | ## Stand-Alone Instructions 39 | 40 | Any Terraform module can also be used on its own. To do so, follow these 41 | instructions: 42 | 43 | * clone the repository 44 | * create a `terraform.tfvars` file with all the (required) variables 45 | ```vim 46 | aws_access_key="*****" 47 | aws_secret_key="*****" 48 | aws_region="eu-west-1" 49 | ssh_public_key="ssh-rsa ***** bernd.zuther@codecentric.de" 50 | 51 | openvpn_admin_user="openvpn" 52 | openvpn_admin_pw="******" 53 | ``` 54 | * *optionally* run `terraform plan -out terraform.plan` 55 | * run `terraform apply [terraform.plan]` 56 | 57 | ```bash 58 | ``` 59 | 60 | ## Architecture 61 | 62 | DCOS is based on [Mesos](http://mesos.apache.org/) and includes a distributed systems kernel. It also includes a set 63 | of core system services, such as a native [Marathon](https://mesosphere.github.io/marathon/) instance to manage processes 64 | and installable services, and [Mesos-DNS](https://github.com/mesosphere/mesos-dns) for service discovery. 65 | 66 | ### Components 67 | 68 | DCOS is comprised of Mesos master and agent nodes, a native DCOS Marathon instance, Mesos-DNS for service 69 | discovery, Admin Router for central authentication and proxy to DCOS services, and Zookeeper to coordinate and manage 70 | the installed DCOS services. 71 | 72 | ![DCOS](https://docs.mesosphere.com/wp-content/uploads/2015/12/Enterprise-Architecture-Diagram.png) 73 | 74 | [Read more](https://docs.mesosphere.com/administration/dcosarchitecture/components/) 75 | 76 | ### Network Security 77 | 78 | DCOS provides the admin, private, and public security zones. The admin zone is accessible via HTTP/HTTPS and SSH 79 | connections, and provides access to your master nodes. The private zone is a non-routable network that is only 80 | accessible from the admin zone or through the edgerouter from the public zone. The optional public zone is where 81 | publicly accessible applications are run. 82 | 83 | ![DCOS](https://docs.mesosphere.com/wp-content/uploads/2015/12/security-zones-ce.jpg) 84 | 85 | [Read more](https://docs.mesosphere.com/administration/dcosarchitecture/security/) 86 | 87 | ## Limitations 88 | 89 | - The DCOS Community Edition does not provide authentication. Authentication is available in the DCOS Enterprise Edition. 90 | - The DCOS CLI and web interface do not currently use an encrypted channel for communication. However, you can upload 91 | your own SSL certificate to the masters and change your CLI and web interface configuration to use HTTPS instead of HTTP. 92 | - You must secure your cluster by using security rules. It is strongly recommended that you only allow internal traffic. 93 | - If there is sensitive data in your cluster, follow standard cloud policies for accessing that data. Either set up a 94 | point to point VPN between your secure networks or run a VPN server inside your DCOS cluster. 95 | 96 | ## OpenVPN 97 | 98 | OpenVPN Access Server is a full featured secure network tunneling VPN software solution that integrates OpenVPN server 99 | capabilities, enterprise management capabilities, simplified OpenVPN Connect UI, and OpenVPN Client software packages 100 | that accommodate Windows, MAC, Linux, Android, and iOS environments. OpenVPN Access Server supports a wide range of 101 | configurations, including secure and granular remote access to internal network and/ or private cloud network resources 102 | and applications with fine-grained access control. -------------------------------------------------------------------------------- /admin_security_group.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "admin" { 2 | name = "admin" 3 | description = "Enable admin access to servers" 4 | 5 | vpc_id = "${aws_vpc.dcos.id}" 6 | } 7 | 8 | resource "aws_security_group_rule" "admin_ingress_all" { 9 | security_group_id = "${aws_security_group.admin.id}" 10 | 11 | type = "ingress" 12 | from_port = 0 13 | to_port = 65535 14 | protocol = "-1" 15 | cidr_blocks = ["${var.admin_location}"] 16 | } 17 | 18 | resource "aws_security_group_rule" "admin_egress_all" { 19 | security_group_id = "${aws_security_group.admin.id}" 20 | 21 | type = "egress" 22 | from_port = 0 23 | to_port = 65535 24 | protocol = "-1" 25 | cidr_blocks = ["0.0.0.0/0"] 26 | } 27 | -------------------------------------------------------------------------------- /dcos_gateway.tf: -------------------------------------------------------------------------------- 1 | resource "aws_instance" "dcos" { 2 | vpc_security_group_ids = [ 3 | "${aws_security_group.master.id}", 4 | "${aws_security_group.admin.id}" 5 | ] 6 | 7 | subnet_id = "${aws_subnet.master.id}" 8 | 9 | ami = "${lookup(var.ubuntu_amis, var.aws_region)}" 10 | instance_type = "${var.dcos_gateway_instance_type}" 11 | key_name = "${aws_key_pair.dcos.key_name}" 12 | user_data = "${data.template_file.dcos_user_data.rendered}" 13 | associate_public_ip_address = false 14 | 15 | tags { 16 | Application = "${var.stack_name}" 17 | Role = "dcos" 18 | } 19 | 20 | lifecycle { 21 | create_before_destroy = false 22 | } 23 | } 24 | 25 | data "template_file" "dcos_user_data" { 26 | template = "${file("${path.module}/dcos_user_data.sh")}" 27 | 28 | vars { 29 | internal_master_lb_dns_name = "${aws_elb.internal_master.dns_name}" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /dcos_user_data.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | function init { 3 | export LC_ALL=C.UTF-8 4 | export LANG=C.UTF-8 5 | 6 | echo "export LC_ALL=C.UTF-8" >> ~/.bashrc 7 | echo "export LANG=C.UTF-8" >> ~/.bashrc 8 | 9 | apt-get install -y language-pack-UTF-8 language-pack-en python3 10 | ln -s /usr/bin/python3 /usr/bin/python 11 | 12 | curl "https://bootstrap.pypa.io/get-pip.py" -o "/tmp/get-pip.py" 13 | python /tmp/get-pip.py 14 | 15 | mkdir -p /opt/mesosphere/dcos-cli/bin/ 16 | mkdir -p /opt/smack/state 17 | mkdir -p /opt/smack/conf 18 | mkdir -p /opt/vamp/conf/ 19 | } 20 | 21 | function install_dcos_cli { 22 | curl -s --output /tmp/get-pip.py https://bootstrap.pypa.io/get-pip.py 23 | python /tmp/get-pip.py 24 | pip install virtualenv 25 | wget https://downloads.dcos.io/binaries/cli/linux/x86-64/dcos-1.8/dcos -O /opt/mesosphere/dcos-cli/bin/dcos 26 | chmod +x /opt/mesosphere/dcos-cli/bin/dcos 27 | ln -s /opt/mesosphere/dcos-cli/bin/dcos /usr/sbin/dcos 28 | dcos config set core.dcos_url http://leader.mesos 29 | dcos config set core.email johndoe@mesosphere.com 30 | dcos config set core.dcos_acs_token abc 31 | } 32 | 33 | function install_oracle_java { 34 | echo "install java" 35 | wget --no-cookies \ 36 | --no-check-certificate \ 37 | --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" \ 38 | "http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz" \ 39 | -O /tmp/jdk-8u131-linux-x64.tar.gz 40 | tar xzf /tmp/jdk-8u131-linux-x64.tar.gz --directory=/usr/local/ 41 | update-alternatives --install "/usr/bin/java" "java" "/usr/local/jdk1.8.0_131/bin/java" 1 42 | update-alternatives --install "/usr/bin/javac" "javac" "/usr/local/jdk1.8.0_131/bin/javac" 1 43 | update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/local/jdk1.8.0_131/bin/javaws" 1 44 | update-alternatives --set "java" "/usr/local/jdk1.8.0_131/bin/java" 45 | update-alternatives --set "javac" "/usr/local/jdk1.8.0_131/bin/javac" 46 | update-alternatives --set "javaws" "/usr/local/jdk1.8.0_131/bin/javaws" 47 | export JAVA_HOME=/usr/local/jdk1.8.0_131/ 48 | echo "export JAVA_HOME=$JAVA_HOME" >> ~/.bashrc 49 | } 50 | 51 | function update_dns_nameserver { 52 | apt-get install -y jq 53 | echo nameserver $(curl -s http://${internal_master_lb_dns_name}:8080/v2/info | jq '.leader' | \ 54 | sed 's/\"//' | sed 's/\:8080"//') &> /etc/resolvconf/resolv.conf.d/head 55 | resolvconf -u 56 | } 57 | 58 | function waited_until_marathon_is_running { 59 | until $(curl --output /dev/null --silent --head --fail http://${internal_master_lb_dns_name}:8080/v2/info); do 60 | echo "waiting for marathon" 61 | sleep 5 62 | done 63 | } 64 | 65 | function waited_until_dns_is_ready { 66 | until $(curl --output /dev/null --silent --head --fail http://master.mesos); do 67 | echo "waiting for dns" 68 | sleep 5 69 | update_dns_nameserver 70 | done 71 | } 72 | 73 | function waited_until_kafka_is_running { 74 | until [ -n "$KAFKA_HOST" ] && [ -n "$KAFKA_PORT" ] ; do 75 | sleep 5 76 | echo "Kafka is not yet healthy" 77 | export_kafka_connection 78 | done 79 | } 80 | 81 | function export_kafka_connection { 82 | export KAFKA_CONNECTION=($(dcos kafka connection | jq .dns[0] | sed -r 's/[\"]+//g' | tr ":" " ")) 83 | export KAFKA_HOST=$${KAFKA_CONNECTION[0]} 84 | echo "KAFKA_HOST: $KAFKA_HOST" 85 | export KAFKA_PORT=$${KAFKA_CONNECTION[1]} 86 | echo "KAFKA_PORT: $KAFKA_PORT" 87 | } 88 | 89 | function waited_until_cassandra_is_running { 90 | until [ -n "$CASSANDRA_HOST" ] && [ -n "$CASSANDRA_PORT" ] ; do 91 | sleep 5 92 | echo "Cassandra is not yet healthy" 93 | export_cassandra_connection 94 | done 95 | } 96 | 97 | function export_cassandra_connection { 98 | export CASSANDRA_CONNECTION=($(dcos cassandra connection | jq .dns[0] | sed -r 's/[\"]+//g' | tr ":" " ")) 99 | export CASSANDRA_HOST=$${CASSANDRA_CONNECTION[0]} 100 | echo "CASSANDRA_HOST: $CASSANDRA_HOST" 101 | export CASSANDRA_PORT=$${CASSANDRA_CONNECTION[1]} 102 | echo "CASSANDRA_PORT: $CASSANDRA_PORT" 103 | } 104 | 105 | function init_cassandra_schema { 106 | cat &> /opt/smack/conf/init_cassandra_schema_job.json << EOF 107 | { 108 | "id": "init-cassandra-schema-job", 109 | "description": "Initialize cassandra database", 110 | "run": { 111 | "cmd": "/opt/bus-demo/import_data.sh $CASSANDRA_HOST", 112 | "cpus": 0.1, 113 | "mem": 256, 114 | "disk": 0, 115 | "docker": { 116 | "image": "codecentric/bus-demo-schema:3.0.7" 117 | } 118 | } 119 | } 120 | EOF 121 | dcos job add /opt/smack/conf/init_cassandra_schema_job.json 122 | dcos job run init-cassandra-schema-job 123 | } 124 | 125 | function init_ingest_app { 126 | cat &> /opt/smack/conf/ingest.json << EOF 127 | { 128 | "id": "/bus-demo/ingest", 129 | "cpus": 0.1, 130 | "mem": 2048, 131 | "disk": 0, 132 | "instances": 1, 133 | "container": { 134 | "type": "DOCKER", 135 | "volumes": [], 136 | "docker": { 137 | "image": "codecentric/bus-demo-ingest:0.2.0", 138 | "network": "HOST", 139 | "privileged": false, 140 | "parameters": [], 141 | "forcePullImage": true 142 | } 143 | }, 144 | "env": { 145 | "CASSANDRA_HOST": "$CASSANDRA_HOST", 146 | "CASSANDRA_PORT": "$CASSANDRA_PORT", 147 | "KAFKA_HOST": "$KAFKA_HOST", 148 | "KAFKA_PORT": "$KAFKA_PORT" 149 | }, 150 | "upgradeStrategy": { 151 | "minimumHealthCapacity": 0 152 | } 153 | } 154 | EOF 155 | dcos marathon app add /opt/smack/conf/ingest.json 156 | } 157 | 158 | function waited_until_spark_is_running { 159 | until dcos service | grep spark | awk '{print $3};' | grep True; do 160 | echo "waiting for spark" 161 | sleep 5 162 | done 163 | update_dns_nameserver 164 | sleep 10 165 | } 166 | 167 | 168 | function init_spark_jobs { 169 | cat &> /usr/sbin/run-pi << EOF 170 | dcos spark run --submit-args='--driver-cores 0.1 --driver-memory 1024M --class org.apache.spark.examples.SparkPi https://downloads.mesosphere.com/spark/assets/spark-examples_2.10-1.4.0-SNAPSHOT.jar 10000000' 171 | EOF 172 | cat &> /usr/sbin/run-digest << EOF 173 | dcos spark run --submit-args='--driver-cores 0.1 --driver-memory 1024M --class de.nierbeck.floating.data.stream.spark.KafkaToCassandraSparkApp https://s3.eu-central-1.amazonaws.com/big-data-muc/bus-demo-digest-assembly-0.2.0.jar METRO-Vehicles $CASSANDRA_HOST $CASSANDRA_PORT $KAFKA_HOST $KAFKA_PORT' 174 | EOF 175 | cat &> /usr/sbin/run-digest-hotspot << EOF 176 | dcos spark run --submit-args='--driver-cores 0.1 --driver-memory 1024M --class de.nierbeck.floating.data.stream.spark.CalcClusterSparkApp https://s3.eu-central-1.amazonaws.com/big-data-muc/bus-demo-digest-assembly-0.2.0.jar METRO-Vehicles $CASSANDRA_HOST $CASSANDRA_PORT $KAFKA_HOST $KAFKA_PORT @$' 177 | EOF 178 | chmod 744 /usr/sbin/run-pi /usr/sbin/run-digest /usr/sbin/run-digest-hotspot 179 | /usr/sbin/run-digest 180 | } 181 | 182 | function init_dasboard { 183 | cat &> /opt/smack/conf/dashboard.json << EOF 184 | { 185 | "id": "/bus-demo/dashboard", 186 | "container": { 187 | "type": "DOCKER", 188 | "docker": { 189 | "image": "codecentric/bus-demo-dashboard:0.2.0", 190 | "network": "HOST", 191 | "forcePullImage": true 192 | } 193 | }, 194 | "acceptedResourceRoles": [ 195 | "slave_public" 196 | ], 197 | "env": { 198 | "CASSANDRA_HOST": "$CASSANDRA_HOST", 199 | "CASSANDRA_PORT": "$CASSANDRA_PORT", 200 | "KAFKA_HOST": "$KAFKA_HOST", 201 | "KAFKA_PORT": "$KAFKA_PORT" 202 | }, 203 | "upgradeStrategy": { 204 | "minimumHealthCapacity": 0 205 | }, 206 | "dependencies": ["/bus-demo/ingest"], 207 | "healthChecks": [ 208 | { 209 | "path": "/", 210 | "protocol": "HTTP", 211 | "gracePeriodSeconds": 300, 212 | "intervalSeconds": 60, 213 | "timeoutSeconds": 20, 214 | "maxConsecutiveFailures": 3, 215 | "ignoreHttp1xx": false, 216 | "port": 8000 217 | } 218 | ], 219 | "cpus": 0.1, 220 | "mem": 2048.0 221 | } 222 | EOF 223 | dcos marathon app add /opt/smack/conf/dashboard.json 224 | } 225 | 226 | function install_smack { 227 | dcos package install --yes cassandra --package-version=1.0.16-3.0.8 228 | dcos package install --cli cassandra 229 | dcos package install --yes kafka --package-version=1.1.9-0.10.0.0 230 | dcos package install --cli kafka 231 | dcos package install --yes spark --package-version=1.0.2-2.0.0 232 | dcos package install --cli spark 233 | dcos package install --yes zeppelin --package-version=0.6.0 234 | } 235 | 236 | init 237 | install_oracle_java #need for same commandline extension like kafka 238 | waited_until_marathon_is_running 239 | waited_until_dns_is_ready 240 | install_dcos_cli 241 | install_smack 242 | waited_until_kafka_is_running 243 | export_kafka_connection 244 | waited_until_cassandra_is_running 245 | export_cassandra_connection 246 | init_cassandra_schema 247 | init_ingest_app 248 | waited_until_spark_is_running 249 | init_spark_jobs 250 | init_dasboard 251 | 252 | -------------------------------------------------------------------------------- /dhcp_options.tf: -------------------------------------------------------------------------------- 1 | resource "aws_vpc_dhcp_options" "dcos" { 2 | domain_name = "${var.aws_region}.${lookup(var.dns_domainnames, var.aws_region)}" 3 | domain_name_servers = ["AmazonProvidedDNS"] 4 | } 5 | 6 | resource "aws_vpc_dhcp_options_association" "dcos" { 7 | vpc_id = "${aws_vpc.dcos.id}" 8 | dhcp_options_id = "${aws_vpc_dhcp_options.dcos.id}" 9 | } 10 | -------------------------------------------------------------------------------- /doc/images/dcos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zutherb/terraform-dcos/68c554db01d44c5cd066bcde70299d8ca978e8e1/doc/images/dcos.png -------------------------------------------------------------------------------- /host_keys.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_access_key" "host_keys" { 2 | user = "${aws_iam_user.dcos.name}" 3 | } 4 | 5 | resource "aws_iam_user" "dcos" { 6 | name = "dcos-${var.stack_name}" 7 | } 8 | 9 | resource "aws_iam_user_policy" "dcos" { 10 | name = "dcos" 11 | user = "${aws_iam_user.dcos.name}" 12 | policy = <> ~/.bashrc 8 | echo "export LANG=C.UTF-8" >> ~/.bashrc 9 | 10 | apt-get install -y language-pack-UTF-8 11 | } 12 | 13 | function install_oracle_java { 14 | echo "Installing Oracle Java..." 15 | echo "Fetching Oracle Java..." 16 | wget --no-cookies \ 17 | --no-check-certificate \ 18 | --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" \ 19 | "http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz" \ 20 | -O /tmp/jdk-8u131-linux-x64.tar.gz 21 | 22 | if [[ $? != 0 ]]; then 23 | echo "Failed during Oracle Java download." 24 | exit 1 25 | fi 26 | 27 | echo "Extracting Oracle Java..." 28 | tar xzf /tmp/jdk-8u131-linux-x64.tar.gz --directory=/usr/local/ 29 | if [[ $? != 0 ]]; then 30 | echo "Failed during Oracle Java extraction." 31 | exit 1 32 | fi 33 | 34 | echo "Updating alternatives..." 35 | update-alternatives --install "/usr/bin/java" "java" "/usr/local/jdk1.8.0_131/bin/java" 1 36 | update-alternatives --install "/usr/bin/javac" "javac" "/usr/local/jdk1.8.0_131/bin/javac" 1 37 | update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/local/jdk1.8.0_131/bin/javaws" 1 38 | update-alternatives --set "java" "/usr/local/jdk1.8.0_131/bin/java" 39 | update-alternatives --set "javac" "/usr/local/jdk1.8.0_131/bin/javac" 40 | update-alternatives --set "javaws" "/usr/local/jdk1.8.0_131/bin/javaws" 41 | 42 | echo "Exporting JAVA_HOME..." 43 | export JAVA_HOME=/usr/local/jdk1.8.0_131/ 44 | echo "export JAVA_HOME=$JAVA_HOME" >> ~/.bashrc 45 | } 46 | 47 | function install_openvpnas { 48 | echo "Installing OpenVPN Access Server..." 49 | 50 | wget -O /tmp/openvpn-as-2.0.25-Ubuntu14.amd_64.deb http://swupdate.openvpn.org/as/openvpn-as-2.0.25-Ubuntu14.amd_64.deb 51 | if [[ $? != 0 ]]; then 52 | echo "Failed during OpenVPN download." 53 | exit 1 54 | fi 55 | 56 | dpkg -i /tmp/openvpn-as-2.0.25-Ubuntu14.amd_64.deb 57 | if [[ $? != 0 ]]; then 58 | echo "Failed during OpenVPN installation." 59 | exit 1 60 | fi 61 | 62 | rm -f /tmp/openvpn-as-2.0.25-Ubuntu14.amd_64.deb 63 | 64 | echo "Restarting OpenVPN...." 65 | systemctl daemon-reload 66 | systemctl restart openvpnas 67 | } 68 | 69 | function wait_until_marathon_is_running { 70 | until $(curl --output /dev/null --silent --head --fail http://${internal_master_lb_dns_name}:8080/v2/info); do 71 | echo "waiting for marathon" 72 | sleep 5 73 | done 74 | } 75 | 76 | function export_public_ip { 77 | echo "resolve public ip" 78 | export PUBLIC_IP=$(curl -s http://169.254.169.254/latest/meta-data/public-hostname) 79 | echo "Public IP is: $PUBLIC_IP" 80 | } 81 | 82 | function export_dns_nameserver { 83 | echo "resolve dns server" 84 | apt-get install -y jq 85 | 86 | until [ -n "$DNS_NAMESERVER" ]; do 87 | sleep 5 88 | echo "waiting until name server is ready" 89 | export DNS_NAMESERVER=$(curl -s http://${internal_master_lb_dns_name}:8080/v2/info | jq '.leader' | sed 's/\"//' | sed 's/\:8080"//') 90 | done 91 | 92 | echo "Nameserver is: $DNS_NAMESERVER" 93 | } 94 | 95 | function install_openvpnas { 96 | echo "Install openvpnas" 97 | wget -O /tmp/openvpn-as-2.0.25-Ubuntu14.amd_64.deb http://swupdate.openvpn.org/as/openvpn-as-2.0.25-Ubuntu14.amd_64.deb 98 | dpkg -i /tmp/openvpn-as-2.0.25-Ubuntu14.amd_64.deb 99 | rm -f /tmp/openvpn-as-2.0.25-Ubuntu14.amd_64.deb 100 | 101 | service openvpnas restart 102 | } 103 | 104 | 105 | function setup_openvpnas { 106 | echo "Setup openvpnas" 107 | echo "Add openvpn admin ${admin_user}" 108 | useradd ${admin_user} 109 | echo "${admin_user}:${admin_pw}" | chpasswd 110 | /usr/local/openvpn_as/scripts/sacli -u ${admin_user} -k prop_superuser -v true UserPropPut 111 | 112 | /usr/local/openvpn_as/scripts/sacli -u openvpn UserPropDelAll 113 | 114 | /usr/local/openvpn_as/scripts/sacli -k vpn.client.routing.reroute_dns -v custom ConfigPut 115 | /usr/local/openvpn_as/scripts/sacli -k vpn.general.osi_layer -v 3 ConfigPut 116 | /usr/local/openvpn_as/scripts/sacli -k vpn.server.routing.gateway_access -v true ConfigPut 117 | /usr/local/openvpn_as/scripts/sacli -k vpn.client.routing.reroute_gw -v false ConfigPut 118 | /usr/local/openvpn_as/scripts/sacli -k vpn.server.routing.private_network.0 -v ${vpc_subnet_range} ConfigPut 119 | 120 | waited_until_marathon_is_running 121 | export_dns_nameserver 122 | /usr/local/openvpn_as/scripts/sacli -k vpn.server.dhcp_option.dns.0 -v $DNS_NAMESERVER ConfigPut 123 | 124 | export_public_ip 125 | /usr/local/openvpn_as/scripts/sacli -k host.name -v $PUBLIC_IP ConfigPut 126 | 127 | service openvpnas restart 128 | } 129 | 130 | init 131 | install_oracle_java 132 | install_openvpnas 133 | setup_openvpnas 134 | -------------------------------------------------------------------------------- /vpn_user_data.yml: -------------------------------------------------------------------------------- 1 | admin_user=${admin_user} 2 | admin_pw=${admin_pw} --------------------------------------------------------------------------------