├── .gitignore ├── LICENSE ├── README.md ├── main.tf ├── provider.tf └── terraform.tfvars /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.tfstate 3 | *.tfstate.backup 4 | 5 | # Module directory 6 | .terraform/ 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Luciano Mammino 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terraform-openvpn 2 | A sample terraform setup for OpenVPN using Let's Encrypt and Certbot to generate certificates 3 | 4 | This repository contains the code used in the tutorial: [Using Let’s Encrypt and Certbot to automate the creation of certificates for OpenVPN](http://loige.co/using-lets-encrypt-and-certbot-to-automate-the-creation-of-certificates-for-openvpn/). 5 | 6 | Read the article for details and instructions on how to use it. 7 | 8 | ## License 9 | 10 | Licensed under [MIT License](LICENSE). © Luciano Mammino. 11 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | variable "vpc_cidr_block" { 2 | default = "10.0.0.0/16" 3 | } 4 | 5 | variable "subnet_cidr_block" { 6 | default = "10.0.0.0/16" 7 | } 8 | 9 | resource "aws_vpc" "main" { 10 | cidr_block = "${var.vpc_cidr_block}" 11 | 12 | tags { 13 | Name = "openvpn" 14 | } 15 | } 16 | 17 | resource "aws_subnet" "vpn_subnet" { 18 | vpc_id = "${aws_vpc.main.id}" 19 | map_public_ip_on_launch = true 20 | cidr_block = "${var.subnet_cidr_block}" 21 | } 22 | 23 | resource "aws_internet_gateway" "gw" { 24 | vpc_id = "${aws_vpc.main.id}" 25 | 26 | tags { 27 | Name = "Internet Gateway for openvpn" 28 | } 29 | } 30 | 31 | resource "aws_eip" "openvpn_eip" { 32 | vpc = true 33 | depends_on = ["aws_internet_gateway.gw"] 34 | } 35 | 36 | resource "aws_route" "internet_access_openvpn" { 37 | route_table_id = "${aws_vpc.main.main_route_table_id}" 38 | destination_cidr_block = "0.0.0.0/0" 39 | gateway_id = "${aws_internet_gateway.gw.id}" 40 | } 41 | 42 | variable "public_key" {} 43 | 44 | variable "private_key" {} 45 | 46 | resource "aws_key_pair" "openvpn" { 47 | key_name = "openvpn-key" 48 | public_key = "${var.public_key}" 49 | } 50 | 51 | variable "ssh_user" { 52 | default = "openvpnas" 53 | } 54 | 55 | variable "ssh_port" { 56 | default = 22 57 | } 58 | 59 | variable "ssh_cidr" { 60 | default = "0.0.0.0/0" 61 | } 62 | 63 | variable "https_port" { 64 | default = 443 65 | } 66 | 67 | variable "https_cidr" { 68 | default = "0.0.0.0/0" 69 | } 70 | 71 | variable "tcp_port" { 72 | default = 943 73 | } 74 | 75 | variable "tcp_cidr" { 76 | default = "0.0.0.0/0" 77 | } 78 | 79 | variable "udp_port" { 80 | default = 1194 81 | } 82 | 83 | variable "udp_cidr" { 84 | default = "0.0.0.0/0" 85 | } 86 | 87 | resource "aws_security_group" "openvpn" { 88 | name = "openvpn_sg" 89 | description = "Allow traffic needed by openvpn" 90 | vpc_id = "${aws_vpc.main.id}" 91 | 92 | // ssh 93 | ingress { 94 | from_port = "${var.ssh_port}" 95 | to_port = "${var.ssh_port}" 96 | protocol = "tcp" 97 | cidr_blocks = ["${var.ssh_cidr}"] 98 | } 99 | 100 | // https 101 | ingress { 102 | from_port = "${var.https_port}" 103 | to_port = "${var.https_port}" 104 | protocol = "tcp" 105 | cidr_blocks = ["${var.https_cidr}"] 106 | } 107 | 108 | // open vpn tcp 109 | ingress { 110 | from_port = "${var.tcp_port}" 111 | to_port = "${var.tcp_port}" 112 | protocol = "tcp" 113 | cidr_blocks = ["${var.tcp_cidr}"] 114 | } 115 | 116 | // open vpn udp 117 | ingress { 118 | from_port = "${var.udp_port}" 119 | to_port = "${var.udp_port}" 120 | protocol = "udp" 121 | cidr_blocks = ["${var.udp_cidr}"] 122 | } 123 | 124 | // all outbound traffic 125 | egress { 126 | from_port = 0 127 | to_port = 0 128 | protocol = "-1" 129 | cidr_blocks = ["0.0.0.0/0"] 130 | } 131 | } 132 | 133 | variable "route53_zone_name" {} 134 | variable "subdomain_name" {} 135 | 136 | variable "subdomain_ttl" { 137 | default = "60" 138 | } 139 | 140 | data "aws_route53_zone" "main" { 141 | name = "${var.route53_zone_name}" 142 | } 143 | 144 | resource "aws_route53_record" "vpn" { 145 | zone_id = "${data.aws_route53_zone.main.zone_id}" 146 | name = "${var.subdomain_name}" 147 | type = "A" 148 | ttl = "${var.subdomain_ttl}" 149 | records = ["${aws_instance.openvpn.public_ip}"] 150 | } 151 | 152 | variable "ami" { 153 | default = "ami-f53d7386" // ubuntu xenial openvpn ami in eu-west-1 154 | } 155 | 156 | variable "instance_type" { 157 | default = "t2.medium" 158 | } 159 | 160 | variable "admin_user" { 161 | default = "openvpn" 162 | } 163 | 164 | variable "admin_password" { 165 | default = "openvpn" 166 | } 167 | 168 | resource "aws_instance" "openvpn" { 169 | tags { 170 | Name = "openvpn" 171 | } 172 | 173 | ami = "${var.ami}" 174 | instance_type = "${var.instance_type}" 175 | key_name = "${aws_key_pair.openvpn.key_name}" 176 | subnet_id = "${aws_subnet.vpn_subnet.id}" 177 | vpc_security_group_ids = ["${aws_security_group.openvpn.id}"] 178 | associate_public_ip_address = true 179 | 180 | # `admin_user` and `admin_pw` need to be passed in to the appliance through `user_data`, see docs --> 181 | # https://docs.openvpn.net/how-to-tutorialsguides/virtual-platforms/amazon-ec2-appliance-ami-quick-start-guide/ 182 | user_data = <