Creating a VPN Connection


This example shows you how to create a virtual private network (VPN) and associated resources in Amazon Web Services using Fugue.


You’ll need to have the Fugue CLI set up and the Conductor installed before you can run this example. If you haven’t done so yet, it just takes a few quick steps.

What We’ll Do In This Example

We’ll cover how to write Ludwig to build a basic VPN connection with dynamic routing on AWS using Fugue.

What We’ll Have When We’re Done

The VPN connection uses Border Gateway Protocol (BGP) to propagate routes between the two VPCs, instead of using static routes (though static routes are also possible with Fugue). The customer gateway is an EC2 instance running Sophos UTM 9.

Note: This example uses the software Sophos UTM 9, which costs a few cents an hour and is available from the AWS Marketplace. The rate for Sophos UTM 9 is $0.35 per hour on a m3.medium instance, the vendor-recommended size. This is in addition to the normal cost of running an m3.medium instance on AWS, $0.067 per hour in the us-west-2 region. If you’re not concerned about performance, you can use a t1.micro instance instead. Sophos UTM 9 costs $0.10 per hour on a t1.micro, on top of the cost of running the instance itself, $0.02 per hour in us-west-2.

Sophos UTM 9 also has a free trial, allowing you to try one instance of the product for 30 days.

How Long It Will Take

About 30 minutes.


You can download the source code for this example here.

Note: You’ll need to edit the composition as part of this example. If you’re interested in editor plug-ins, you can find them here.

Let’s Go!

Launching an EC2 Instance with VPN Software

First, we need to launch an EC2 instance that has the VPN-enabling software we’re going to use, Sophos UTM 9. This instance will act as the customer gateway for our VPN connection.

Log in to the EC2 Dashboard of the AWS Management Console and make sure you’re in the Oregon region – for this exercise, all of our infrastructure will be located there.

Click on the “Launch Instance” button, then click “AWS Marketplace” in the left sidebar. Search for Sophos UTM 9 and select the “Sophos UTM 9 (PAYG)” option.

Searching for Sophos UTM 9 in the AWS Marketplace.

Searching for Sophos UTM 9 in the AWS Marketplace.

On the “Step 2: Choose an Instance Type” screen, scroll down to m3.medium size and select it.


Our example uses the vendor-recommended instance size, m3.medium. Running this instance costs about $0.41 per hour in combined software and infrastructure fees. If you prefer, you can select the cheaper t1.micro instance, which costs about $0.12 per hour in combined fees. However, note that performance may be limited on the smaller instance type.

At the bottom of the screen, select “Review and Launch.” Scroll down to the “Security Groups” heading and click “Edit Security Groups.” Select “Add Rule” and create a rule with these settings:

  • Type: Custom TCP Rule
  • Protocol: TCP
  • Port Range: 4444
  • Source:

We’ll keep the SSH and HTTP security group rules just as they are. Click “Review and Launch,” and on the next screen, select “Launch.” Select an existing key pair, if you have one, or follow the instructions on the screen to create a new key pair, then click “Launch Instances.” After the Launch Status screen comes up, click “View Instances” and you’ll see your brand-new instance initializing.

We don’t want source/destination checking enabled for our instance, so we’ll need to disable it. As AWS points out, “Each EC2 instance performs source/destination checks by default. This means that the instance must be the source or destination of any traffic it sends or receives.” However, we want our instance to be able to send and receive traffic when it isn’t the source or destination, since we’re using it as a customer gateway to route traffic between our VPCs.

To do this, click the “Actions” drop-down menu and select Networking > Change Source/Dest. AWS will prompt you to confirm that you want to disable source/destination checking for your instance; click “Yes, Disable.”

There’s one little task left before we get to the Ludwig portion of our example: With the instance selected, check out the “Description” tab and look for the “Public IP” field. Copy this IP address – we’ll need it in a moment.

Where to find the public IP address of the Sophos EC2 instance.

Where to find the public IP address of the Sophos EC2 instance.

All right! Now that our instance is up and running, it’s time to start looking at our composition. Let’s get to it!

Boilerplate Ludwig


If you’re in a hurry to run this composition, you must edit the composition in the next step before jumping ahead (though we recommend reading through the entire Ludwig explanation, of course!).

As usual, we’ll want to begin by declaring that our file is a composition (using the composition keyword). We’ll also import the base AWS library, as well as the EC2 library.


import Fugue.AWS as AWS
import Fugue.AWS.EC2 as EC2

Setting Configuration Variables

Action required! Remember that instance IP address we copied from the AWS Console a moment ago? In your downloaded copy of the composition, paste that IP address next to sophosInstanceIp to replace (Don’t forget to keep the double quotes!)

We’ve also created a top-level binding, region, for convenience. This saves us from having to write out AWS.Us-west-2 whenever we refer to a resource’s region, since we’re deploying all of the resources in the same place.

# Enter the public IP address of the Sophos UTM 9 instance here:
sophosInstanceIp: ""
region: AWS.Us-west-2

Making a VPC

First, we need to create a VPC to form the basis of our network. We’ll assign it a CIDR block of and put it in the Oregon region. The default instance tenancy (shared hardware) is fine for our purposes.

my-vpc: {
  cidrBlock: "",
  instanceTenancy: EC2.DefaultTenancy,
  region: region

Making a Subnet

Now we need to create a subnet to go along with the my-vpc VPC. We’ll just make one /24 subnet and put it in Availability Zone B. We’ve set mapPublicIpOnLaunch: False because we want this to be a private network, which can’t be reached from the Internet at large.

subnet-b: {
  vpc: my-vpc,
  cidrBlock: '',
  availabilityZone: AWS.B,
  mapPublicIpOnLaunch: False

Adding a Route Table

We’ll need a route table associated with our subnet, subnet-b. Since our VPN gateway will handle dynamic routing for us, instead of defining static routes ourselves, we just need to point our route table to the route-propagating gateway (which we’ll create shortly).

rt: {
  vpc: my-vpc,
  associations: [subnet-b],
  routePropagatingVpnGateways: [vpngw]

Adding a Security Group

We may optionally add a security group that opens all VPN ports on my-vpc. We can do this by creating the sg security group, and giving it an ingress rule, all-tcp, that allows incoming traffic on TCP ports 1 through 65535 from all addresses. This is handy if we want to launch other instances into our VPC later.

sg: {
  description: 'Open VPN ports',
  ipPermissions: [all-tcp],
  vpc: my-vpc

all-tcp: {
  ipProtocol: "tcp",
  fromPort: 1,
  toPort: 65535,
  target: EC2.IpPermission.Target.ipRanges([""])

Adding a Virtual Private Gateway

Next, we’ll need a virtual private gateway (also called a VPN gateway). We’ll set vpnType to EC2.Ipsec_1 in order to use an IPsec connection.

vpngw: {
  vpnType: EC2.Ipsec_1,
  vpcAttachment: my-vpc,
  region: region

Adding a Customer Gateway

We’ll also need to tell Fugue where our customer gateway is, so this snippet references the sophosInstanceIp binding we declared earlier on. As with the VPN gateway, we’ll set vpnType to EC2.Ipsec_1. We also need to set the BGP autonomous system number to 65000, which is a value in the private range.

customergw: {
  vpnType: EC2.Ipsec_1,
  ipAddress: sophosInstanceIp,
  bgpAsn: 65000,
  region: region

Adding the VPN Connection

Finally, it’s time to declare the VPN connection itself. As with the VPN gateway and the customer gateway, the vpnType of our VPN connection will be EC2.Ipsec_1. We’ll point to the customer gateway, customergw, and to the VPN gateway, vpngw. Because we’re using BGP rather than static routes, we’ve set staticRoutesOnly to False.

vpnConnection: {
  vpnType: EC2.Ipsec_1,
  customerGateway: customergw,
  vpnGateway: vpngw,
  staticRoutesOnly: False

Starting the Fugue process

We’re finally ready to run this composition! Let’s start up a Fugue process:

$ fugue run VPN.lw -a vpn

You’ll see output like this:

[ fugue run ] Running VPN.lw

Run Details:
    Alias: vpn

Compiling Ludwig file /Users/user/projects/VPN.lw
[ OK ] Successfully compiled. No errors.

Uploading compiled Ludwig composition to S3...
[ OK ] Successfully uploaded.

Requesting the Conductor to create and run process based on composition ...
[ DONE ] Process created and running.

State    Updated    Created    Account              FID                                   Alias          Flags    Last Message    Next Command
-------  ---------  ---------  -------------------  ------------------------------------  -------------  -------  --------------  --------------
Running  2:57pm     2:57pm     fugue-1505320402664  db291128-a1df-4a20-98d4-1192b95a0ce4  vpn            -e                       run
[ HELP ] Run the "fugue status" command to view details and status for all Fugue processes.

After a couple minutes, run fugue status to confirm that the process has been successfully created.

Fugue Status Report for user/xxxxxxxxxxxx - Fri Dec 2 2016 2:58pm
State    Updated    Created    Account     FID/Alias     Flags    Last Message
-------  ---------  ---------  ----------  -----------   -------  --------------
Running  2:57pm     2:57pm     fugue       vpn           -e       SUCCEEDED

Looks good! Now that our process is running, we need to do a few more steps before the VPN connection is ready.

Configuring the Sophos Instance

Now, head to the VPC Dashboard in the AWS Console. As before, make sure you’re still in the Oregon region.

Click on “VPN Connections” in the left sidebar, then select your vpnConnection resource and click the “Download Configuration” button.

Fill in the following fields:

  • Vendor: Sophos
  • Platform: UTM
  • Software: V9

Then click “Yes, Download.” Save it somewhere convenient – we’ll need this when we set up the site-to-site VPN inside the Sophos WebAdmin console.

To access the Sophos WebAdmin console, point your browser to https://<instance ip address or hostname>:4444, using the public IP address you copied earlier.

You’ll likely see a warning in your browser that your connection is not private. Follow the instructions in to your browser to continue. In Firefox, that requires clicking “Advanced, then “Add Exception...,” and then “Confirm Security Exception.” In Chrome, click “Advanced,” then “Proceed to <IP address> (unsafe).”


The reason we see this warning is because the Sophos instance has a self-signed certificate that the browser doesn’t recognize. For the purposes of this example (and the limited amount of time our instance will be running), this is fine.

You should see the Sophos WebAdmin console now.

The Sophos WebAdmin console.

The Sophos WebAdmin console.

Fill out the entire form, and for the “AWS Instance ID” field, copy the resource ID from the AWS Console. It’ll look something like this: i-eb38e745. Accept the terms of the license agreement, then click “Perform basic system setup.” You’ll see a small message at the bottom of the screen saying “Please wait, this will take 40 seconds...”

You should see another warning about your connection not being private. Follow the same steps before to proceed. Then, on the login screen, enter admin as the username, enter the password you created, and log in.

Now, we are going to enable Sophos to dynamically route traffic through your VPN connection. But first, Sophos needs that VPN configuration file we downloaded from earlier.

In the left sidebar, click “Site-to-site VPN,” then “Amazon VPC.” Click on the “Setup” tab, and under “Import Via Amazon VPC Configuration,” upload the VPN configuration file you downloaded, then click “Apply.”

Importing the Amazon VPC configuration in the Sophos WebAdmin console.

Importing the Amazon VPC configuration in the Sophos WebAdmin console.

Two successful VPC tunnels in the Sophos WebAdmin console status page.

Two successful VPC tunnels in the Sophos WebAdmin console status page.

We’re almost done!

Meanwhile, Back in the AWS Console...

Return to the VPC Dashboard in the AWS Console and click on “VPN Connections” in the left sidebar, then select the “Tunnel Details” tab. In a moment, the “Status” field should change to UP and the “Details” field should change to 1 BGP ROUTES for each of your two VPN tunnels.

The successful VPN connection.

The successful VPN connection.

Congratulations! You’re now the proud owner of a working VPN connection that dynamically routes traffic between your default VPC and my-vpc, a VPC (and associated resources) you created in a Ludwig composition. Pat yourself on the back!

Killing The Fugue Process

Once you’re done admiring your new infrastructure, you can clean it up by killing the process. It’s very easy to do:

$ fugue kill -y vpn

You’ll see output like this:

[ fugue kill ] Killing running process with Alias: vpn

Requesting the Conductor to kill running composition with Alias: vpn...
[ Done ] The conductor is killing the process with Alias: vpn

This destroys all of the Fugue-managed infrastructure created for this process.

One more thing: Because you manually launched the Sophos instance, you’ll need to manually terminate it. You can do that by going back to the EC2 Dashboard in the AWS Console, clicking “Instances” in the left sidebar, then selecting the “Actions” drop-down menu and Instance State > Terminate. Otherwise, the instance will remain up and running, potentially costing you money.

Next Steps

Want to try something a little different? How about learning to use encrypted passwords with RDS and Vars? Or, dive into Ludwig by perusing the Fugue Standard Library Reference. You can also check out our service-specific examples in the Fugue Fake Book. And as always, feel free to reach out to with any questions.