<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kostis</title>
    <description>The latest articles on DEV Community by Kostis (@ktsaprailis).</description>
    <link>https://dev.to/ktsaprailis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F35339%2F2156056f-18e5-4cb9-87e7-f4e1423d3b6f.jpg</url>
      <title>DEV Community: Kostis</title>
      <link>https://dev.to/ktsaprailis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ktsaprailis"/>
    <language>en</language>
    <item>
      <title>How to manage procrastination with the Pomodoro Technique</title>
      <dc:creator>Kostis</dc:creator>
      <pubDate>Tue, 03 Oct 2017 15:16:01 +0000</pubDate>
      <link>https://dev.to/ktsaprailis/how-to-manage-procrastination-with-the-pomodoro-technique-9l</link>
      <guid>https://dev.to/ktsaprailis/how-to-manage-procrastination-with-the-pomodoro-technique-9l</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally posted on my &lt;a href="https://tsaprailis.com/2017/09/21/How-to-beat-procrastination-with-the-Pomodoro-technique/"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These are my thoughts and some tips that I have gathered using the Pomodoro Technique, both at work and when studying. This came out of my own search for a way to get more focused when working on something because I would tend to procrastinate on anything imaginable.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the Pomodoro Technique?
&lt;/h3&gt;

&lt;p&gt;Let's ask wikipedia:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Pomodoro Technique is a time management method developed by Francesco Cirillo in the late 1980s. The technique uses a timer to break down work into intervals, traditionally 25 minutes in length, separated by short breaks. These intervals are named pomodoros, the plural in English of the Italian word pomodoro (tomato), after the tomato-shaped kitchen timer that Cirillo used as a university student.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So yeah, it's a time management technique, what else? Further down the article points out how it works in steps:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There are six steps in the technique:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Decide on the task to be done.&lt;/li&gt;
&lt;li&gt;Set the pomodoro timer (traditionally to 25 minutes).&lt;/li&gt;
&lt;li&gt;Work on the task until the timer rings.&lt;/li&gt;
&lt;li&gt;After the timer rings put a checkmark on a piece of paper.&lt;/li&gt;
&lt;li&gt;If you have fewer than four checkmarks, take a short break (3–5 minutes), then go to step 2.&lt;/li&gt;
&lt;li&gt;After four pomodoros, take a longer break (15–30 minutes), reset your checkmark count to zero, then go to step 1.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;The premise here is that instead of trying to focus for hours on end, you should instead try to focus for a small period of time, then give your mind some time to rest and start over. I was skeptical at first (especially regarding trying to focus for 25 minutes at a time) but decided to give it a try. I have found that it helped me get a hold of my brain's urges to shift focus to random stuff.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use whatever timer suits you
&lt;/h3&gt;

&lt;p&gt;It can either be an old school analog time, an app on your phone (which is not suggested because looking at your phone can break your focus because of notifications), an online time, a cli program. Find what works best for you and stick to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start small
&lt;/h3&gt;

&lt;p&gt;As mentioned above the typical way to use the Pomodoro technique is in intervals of 20-25 minutes of work and 3-5 minutes of break. That might sound like a long period of time when you first try it. Instead try smaller intervals of as low as 10 or even 5 minutes and work your way up to the 20-25 minute mark. The same is true for the breaks. If 3 minutes sound too little start with 5 or 7 or even 10 and work your way down. Check which combination works best for you and then try to improve it slowly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time your breaks too
&lt;/h3&gt;

&lt;p&gt;You can easily get carried away when you don't time your breaks. That's why it's equally important to time them. As mentioned if at first you think that 3-5 minutes are not enough, try to increase the time period to 7 or 10 but a) it should be a fixed period and b) it should be on the timer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep a paper and a pen close by
&lt;/h3&gt;

&lt;p&gt;I have found this to be VERY important, almost as important as the timer. Why? Well the typical way I and anyone else procrastinates, is that you start working and then all of sudden a random thought pops up, that you need the answer right away, right? By noting it down on a piece of paper you a) acknowledge the thought and b) are sure you won't forget about it, so it's ok to not find the answer right away.&lt;/p&gt;

&lt;p&gt;Another thing that the paper helps with is with the brain's knee-jerk reaction to open a random site. I have caught myself without even thinking about it, I open a new tab and start to type a procrastinating site like Twitter/Facebook/Whatever. When you get that urge just acknowledge it and set a mark on the paper. In my mind it doesn't matter that you won't go on that site, that was probably not the point, but I think that this is just the brain's way of trying to get a small break. With time I think these knee-jerk reactions can be reduced to a minimum.&lt;/p&gt;

&lt;h3&gt;
  
  
  Close all distractions
&lt;/h3&gt;

&lt;p&gt;We all know it our brains don't multitask well. You can't focus on a task and have a podcast playing on the background, or trying to find the solution to a problem and having Facebook/Twitter/Hacker News/Reddit/Whatever open.&lt;/p&gt;

&lt;p&gt;To start off try to install an extension like &lt;a href="https://chrome.google.com/webstore/detail/stayfocusd/laankejkbhbdhmipfmgcngdelahlfoji?hl=en"&gt;stayfocusd&lt;/a&gt; with which you can block the usual time-wasting site. That way even if you try to load the site, you will get a message urging you back to work.&lt;/p&gt;

&lt;p&gt;What I have found works best for me is having some sort of calming music playing on the background like &lt;a href="https://www.youtube.com/watch?v=sYoqCJNPxv4"&gt;Weightless by Marconi Union&lt;/a&gt; which has been declared &lt;a href="https://curiosity.com/topics/neuroscientists-found-the-most-relaxing-song-curiosity/"&gt;the most relaxing song&lt;/a&gt; and there's even a 10 hour &lt;a href="https://www.youtube.com/watch?v=qYnA9wWFHLI"&gt;version&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>pomodoro</category>
      <category>procrastination</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to automate creating high end virtual machines on AWS for data science projects</title>
      <dc:creator>Kostis</dc:creator>
      <pubDate>Mon, 02 Oct 2017 14:42:28 +0000</pubDate>
      <link>https://dev.to/ktsaprailis/how-to-automate-creating-high-end-virtual-machines-on-aws-for-data-science-projects-di1</link>
      <guid>https://dev.to/ktsaprailis/how-to-automate-creating-high-end-virtual-machines-on-aws-for-data-science-projects-di1</guid>
      <description>&lt;p&gt;This article originally appeared on my &lt;a href="https://tsaprailis.com/2017/09/11/How-to-automate-creating-a-virtual-machine-for-data-science/" rel="noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is a log of my findings while trying to automate the creation of Virtual Machines on Amazon Web Services.&lt;/p&gt;

&lt;p&gt;Last year I started my MSc in Data Science. Anyone who has been on a similar position knows that running Machine Learning algorithms is very resource intensive. You can either spend hours waiting for an algorithm to finish on a regular PC/laptop, spend about $1000 on buying a high-end PC or get a VM on the cloud providers.&lt;/p&gt;

&lt;p&gt;Both of the latter two options have their pros and cons that may suit one's needs. I will only focus on the last option here i.e. deploying high end VM on AWS.&lt;/p&gt;

&lt;p&gt;The simple way of creating a virtual machine is by using the provider website. AWS has a web console interface for creating resources but it can get time consuming and repetitive to use the interface for one time machines. Furthermore there's a hassle with installing the required software packages everytime (a process called configuration), getting the machine details (public DNS name, public IP etc)&lt;/p&gt;

&lt;p&gt;I'll be using the &lt;a href="https://www.terraform.io/" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt; orchestration tool to quickly set up and configure the required Virtual Machine server as fast as possible to minimize time lost on the trivial activities and maximize the value for the money paid for the server. Finally once I'll be finished with the project I can destroy the Virtual Machine as to stop getting charged for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;p&gt;What will be required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://www.terraform.io/" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt; tool. As mentioned this is the basic tool that will be used for provisioning the Virtual Machines.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://en.wikipedia.org/wiki/Unix_shell" rel="noopener noreferrer"&gt;Unix shell&lt;/a&gt;. This guide can probably work with the &lt;a href="https://msdn.microsoft.com/en-us/commandline/wsl/about" rel="noopener noreferrer"&gt;Windows bash&lt;/a&gt; but I haven't tested it.&lt;/li&gt;
&lt;li&gt;An &lt;a href="https://aws.amazon.com/" rel="noopener noreferrer"&gt;Amazon Web Services&lt;/a&gt; account.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What is Infrastructure As Code and what is Terraform?
&lt;/h3&gt;

&lt;p&gt;Infrastructure as code is a new DevOps philosophy where the application infrastructure is no longer created by hand but programmatically. The benefits are numerous including but not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Speed of deployment&lt;/li&gt;
&lt;li&gt;Version Control of Infrastructure&lt;/li&gt;
&lt;li&gt;Engineer agnostic infrastructure (no single point of failure/no single person to bug)&lt;/li&gt;
&lt;li&gt;Better lifetime management (automatic scale up/down, healing)&lt;/li&gt;
&lt;li&gt;Cross-provider deployment with minimal changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terraform is a tool that helps in this direction. It is an open source tool developed by &lt;a href="https://www.hashicorp.com/" rel="noopener noreferrer"&gt;Hashicorp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This tool allows you to write the final state that you wish your infrastructure to have and terraform applies those changes for you.&lt;/p&gt;

&lt;p&gt;You can provision VMs, create subnets, assign security groups and pretty much perform any action that any cloud provider allows.&lt;/p&gt;

&lt;p&gt;Terraform support a wide range of &lt;a href="https://www.terraform.io/docs/providers/index.html" rel="noopener noreferrer"&gt;providers&lt;/a&gt; including the big 3 ones AWS, GCP, Microsoft Azure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing Terraform
&lt;/h3&gt;

&lt;p&gt;Terraform is written in Go and is provided as a binary for the major OSs but can also be compiled from &lt;a href="https://github.com/hashicorp/terraform" rel="noopener noreferrer"&gt;source code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The binary can be downloaded from the Terraform &lt;a href="https://www.terraform.io/downloads.html" rel="noopener noreferrer"&gt;site&lt;/a&gt; and does not require any installation. We just need to set it to the path variable (for Linux/macOS instructionscan be found &lt;a href="https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux" rel="noopener noreferrer"&gt;here&lt;/a&gt; and for Windows &lt;a href="https://stackoverflow.com/questions/1618280/where-can-i-set-path-to-make-exe-on-windows" rel="noopener noreferrer"&gt;here&lt;/a&gt;) so that it is accessible from our system in any path.&lt;/p&gt;

&lt;p&gt;After we have this has finished we can confirm that it is ready to be used by running the terraform command and we should get something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform
Usage: terraform [--version] [--help] &amp;lt;command&amp;gt; [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Environment management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a new or existing Terraform configuration
    output             Read an output from a state file
    plan               Generate and show an execution plan
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can move on the using the tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the AWS account
&lt;/h3&gt;

&lt;p&gt;This is a step that is not specific to this project but rather it's something that needs to be configured whenever a new AWS account is set up.&lt;br&gt;
When we create a new account with Amazon, the default account we are given has root access to any action. Similarly with the linux root user we do not want to be using this account for the day-to-day actions, so we need to create a new user.&lt;/p&gt;

&lt;p&gt;We navigate to the &lt;a href="https://console.aws.amazon.com/iam/home#" rel="noopener noreferrer"&gt;Identity and Access Management (IAM)&lt;/a&gt; page, click on &lt;code&gt;Users&lt;/code&gt;, then the &lt;code&gt;Add user&lt;/code&gt; button. We provide the User name, and click the Programmatic access checkbox so that an access key ID and a secret access key will be generated.&lt;/p&gt;

&lt;p&gt;Clicking next we are asked to provide a Security Group that this User will belong to. Security Groups are the main way to provide permission and restrict access to specific actions required. For this purpose of this project we will give the &lt;code&gt;AdministratorAccess&lt;/code&gt; permission to this user, however when used in a professional setting it is advised to only allow permissions that a user needs (like AmazonEC2FullAccess if a user will only be creating EC2 instances).&lt;/p&gt;

&lt;p&gt;Finishing the review step Amazon will provide the Access key ID and Secret access key. We will provide these to terraform to grant it access to create the resources for us. We need to keep these as they are only provided once and cannot be retrieved (however we can always create a new pair).&lt;/p&gt;

&lt;p&gt;The secure way to store these credentials as recommended by &lt;a href="https://aws.amazon.com/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks/" rel="noopener noreferrer"&gt;Amazon&lt;/a&gt; is keeping them in a hidden folder under a file called &lt;code&gt;credentials&lt;/code&gt;. This file can be accessed by terraform to retrieve them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd
$ mkdir .aws
$ cd .aws
~/.aws$ vim credentials
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We add the following to the credentials file after replacing &lt;code&gt;ACCESS_KEY&lt;/code&gt; and &lt;code&gt;SECRET_KEY&lt;/code&gt; and then save it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[default]
aws_access_key_id = ACCESS_KEY
aws_secret_access_key = SECRET_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also restrict access to this file only to the current user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.aws$ chmod 600 credentials 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Setting up a key pair
&lt;/h4&gt;

&lt;p&gt;The next step is to create a key pair so that terraform can access the newly created VMS. Notice that this is different than the above credentials. The Amazon credentials are for accessing and allowing the AWS service to create the resources required, while this key pair will be used for accessing the newly created Virtual Machines. &lt;/p&gt;

&lt;p&gt;Log into the &lt;a href="https://eu-west-1.console.aws.amazon.com/ec2/v2/home?region=eu-west-1#KeyPairs:sort=keyName" rel="noopener noreferrer"&gt;AWS console&lt;/a&gt; and select &lt;code&gt;Create Key Pair&lt;/code&gt;. Add a name (I name mine mac-ssh) and click &lt;code&gt;Create&lt;/code&gt;. AWS will create a .pem file and download it locally. &lt;/p&gt;

&lt;p&gt;Move this file to the &lt;code&gt;.aws&lt;/code&gt; directory. Notice the name of the file to move will be different based on the name provided while creating the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/Downloads$ cd ~/Downloads &amp;amp;&amp;amp; mv mac-ssh.pem ../.aws/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then restrict the permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ../.aws &amp;amp;&amp;amp; chmod 400 mac-ssh.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we ready to use this key pair either via a direct ssh to our instances, or for terraform to use this to connect to the instances and run some scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Provisioning VMs &amp;amp; Configuring Them
&lt;/h3&gt;

&lt;p&gt;So now that everything is set up, we can move to actually creating the virtual machines.&lt;/p&gt;

&lt;p&gt;Let's create a new folder called &lt;code&gt;terraform&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir terraform
$ cd terraform
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In that folder we will create two files one called &lt;code&gt;main.tf&lt;/code&gt; and the second &lt;code&gt;configure.sh&lt;/code&gt;. The first file is the terraform specific code that handles the creation of the Virtual Machine. The second file is a &lt;a href="https://en.wikipedia.org/wiki/Shell_script" rel="noopener noreferrer"&gt;bash script&lt;/a&gt; that will be run on the created machine to configure it with the software required.&lt;/p&gt;

&lt;p&gt;So this is the &lt;code&gt;main.tf&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
    region = "eu-west-1"
    version = "~&amp;gt; 0.1"
}

resource "aws_security_group" "jupyter_notebook_sg" {
    name = "jupyter_notebook_sg"
    # Open up incoming ssh port
    ingress {
        from_port = 22
        to_port = 22
        protocol = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
    }

    # Open up incoming traffic to port 8888 used by Jupyter Notebook
    ingress {
        from_port   = 8888
        to_port     = 8888
        protocol    = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
    }

    # Open up outbound internet access
    egress {
        from_port   = 0
        to_port     = 0
        protocol    = "-1"
        cidr_blocks = ["0.0.0.0/0"]
    }
}

resource "aws_instance" "Node" {
    count = 1
    ami = "ami-a8d2d7ce"
    instance_type = "m4.xlarge"
    key_name = "mac-ssh"
    tags {
        Name = "Jupyter Notebook Meganode"
    }
    vpc_security_group_ids = ["${aws_security_group.jupyter_notebook_sg.id}"]

    provisioner "file" {
        source      = "configure.sh"
        destination = "/tmp/configure.sh"

        connection {
            type     = "ssh"
            user     = "ubuntu"
            private_key = "${file("~/.aws/mac-ssh.pem")}"
        }
    }

    provisioner "remote-exec" {
        inline = [
            "chmod +x /tmp/configure.sh",
            "/tmp/configure.sh",
        ]
        connection {
            type     = "ssh"
            user     = "ubuntu"
            private_key = "${file("~/.aws/mac-ssh.pem")}"
        }

    }

}

output "node_dns_name" {
    value = "${aws_instance.Node.public_dns}"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this the &lt;code&gt;configure.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!#/bin/bash

sudo apt-get update
sudo apt-get -y install git
sudo apt-get -y install vim
sudo apt-get -y install python3 python3-pip python3-dev
sudo -H pip3 install jupyter

mkdir ~/.jupyter
echo "c.NotebookApp.allow_origin = '*'
c.NotebookApp.ip = '0.0.0.0'" | sudo tee /home/ubuntu/.jupyter/jupyter_notebook_config.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Let's break down the terraform blueprint. We start by defining the provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
    region = "eu-west-1"
    version = "~&amp;gt; 0.1"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform defines these blocks contained within the curly braces. The first word is usually a reserved word that defines something in this case the provider that will be used in this blueprint. The next word again is a reserved word but it's provider specific. Blocks can have a third word which is usually an identifier, like a variable to reference the specific resource whithin another block.&lt;br&gt;
Regarding the first block, the core Terraform software is provider agnostic so each blueprint needs to define the provider on which the resources will be created at. You can find all the supported providers &lt;a href="https://www.terraform.io/docs/providers" rel="noopener noreferrer"&gt;here&lt;/a&gt;. You can find all the AWS specific details &lt;a href="https://www.terraform.io/docs/providers/aws/index.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
The region value is basically the AWS datacenter on which the Virtaul Machine will be created at. You can find all available regions &lt;a href="https://docs.aws.amazon.com/general/latest/gr/rande.html#ec2_region" rel="noopener noreferrer"&gt;here&lt;/a&gt;. It's generally advised to pick the one that is closest to you as to minimize the response time between your PC and the Virtual Machine.&lt;br&gt;
Finally the version value is referring to the version of the AWS plugin that will be used.&lt;/p&gt;

&lt;p&gt;The next block defines the first resource that will be created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_security_group" "jupyter_notebook_sg" {
    name = "jupyter_notebook_sg"
    # Open up incoming ssh port
    ingress {
        from_port = 22
        to_port = 22
        protocol = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
    }

    # Open up incoming traffic to port 8888 used by Jupyter Notebook
    ingress {
        from_port   = 8888
        to_port     = 8888
        protocol    = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
    }

    # Open up outbound internet access
    egress {
        from_port   = 0
        to_port     = 0
        protocol    = "-1"
        cidr_blocks = ["0.0.0.0/0"]
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can be considered like a virtual firewall that allows or restricts incoming and outgoing traffic to VMs. You can assign more than one security groups in a VM. In this can we have created three rules. We have allowed incoming traffic (ingress) to ports 22 and 8888 which are used for ssh access and by jupyter notebook respectively from any IP address. The last rule allows outgoing (egress) traffic from all IPs, to all ports, with any protocol.&lt;br&gt;
Finally note that as mentioned in the previous paragraph, the block declaration starts with the &lt;code&gt;resource&lt;/code&gt; word, followed by the type of resource the block defines (here &lt;code&gt;aws_security_group&lt;/code&gt;), and we give the name &lt;code&gt;jupyter_notebook_sg&lt;/code&gt; to this resource. We will see how we use this in the next block. You can read more about security groups &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The third block is the one that defines the Virtual Machine resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_instance" "Node" {
    count = 1
    ami = "ami-a8d2d7ce"
    instance_type = "m4.xlarge"
    key_name = "mac-ssh"
    tags {
        Name = "Jupyter Notebook Meganode"
    }
    vpc_security_group_ids = ["${aws_security_group.jupyter_notebook_sg.id}"]

    provisioner "file" {
        source      = "configure.sh"
        destination = "/tmp/configure.sh"

        connection {
            type     = "ssh"
            user     = "ubuntu"
            private_key = "${file("~/.aws/mac-ssh.pem")}"
        }
    }

    provisioner "remote-exec" {
        inline = [
            "chmod +x /tmp/configure.sh",
            "/tmp/configure.sh",
        ]
        connection {
            type     = "ssh"
            user     = "ubuntu"
            private_key = "${file("~/.aws/mac-ssh.pem")}"
        }

    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As above, we define the resource type we want to create (&lt;code&gt;aws_instance&lt;/code&gt;) and we give the name &lt;code&gt;Node&lt;/code&gt; to this resource. Notice that this name is only used by Terraform it is not something that is defined in AWS.&lt;/p&gt;

&lt;p&gt;The first value that need defining is the &lt;code&gt;ami&lt;/code&gt; (&lt;code&gt;count&lt;/code&gt; is pretty self explanatory so I skip it). This stands for &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html" rel="noopener noreferrer"&gt;Amazon Machine Image&lt;/a&gt;. Basically it's the image of the Operating System that will be installed on the created VM. The way to find this ami value is described by Amazon &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html#finding-an-ami-console" rel="noopener noreferrer"&gt;here&lt;/a&gt;. There are countless images to choose from with many software packages preinstalled to choose from. However this can get a bit chaotic is you are just looking for a simple generic OS image. I have picked the AMI for the ubuntu 16.04 server image.&lt;br&gt;
I prefer to find the ami from the &lt;a href="https://eu-west-1.console.aws.amazon.com/ec2/v2/home?region=eu-west-1#LaunchInstanceWizard:" rel="noopener noreferrer"&gt;launch EC2 instance wizard&lt;/a&gt; that AWS provides, it's clearer for the base OS images.&lt;/p&gt;

&lt;p&gt;Next we define the &lt;code&gt;instance_type&lt;/code&gt;. This is the type of Virtual Machine that will be created. You can find all the different instance types &lt;a href="https://aws.amazon.com/ec2/instance-types/" rel="noopener noreferrer"&gt;here&lt;/a&gt; along with the &lt;a href="https://aws.amazon.com/ec2/pricing/on-demand/" rel="noopener noreferrer"&gt;pricing&lt;/a&gt;. The one I picked here is the m4.xlarge instance which has 4 virtual CPUs, 16 GB of RAM and costs about $0.2 per hour at the time of writing, however this price is usually variant on the region.&lt;br&gt;
&lt;code&gt;Tags&lt;/code&gt; are AWS specific details, here we provide a &lt;code&gt;Name&lt;/code&gt; for the VM.&lt;/p&gt;

&lt;p&gt;Next we provide a list of &lt;code&gt;vpc_security_group_ids&lt;/code&gt; which are the AWS ids Security Groups, we have only provided one in this case, the one we created.&lt;br&gt;
Finally the last two blocks are using another Terraform block type, the provisioner. &lt;a href="https://www.terraform.io/docs/provisioners/index.html" rel="noopener noreferrer"&gt;Provisioners&lt;/a&gt; are used to execute scripts on a local or remote machine as part of resource creation or destruction. Provisioners can be used to bootstrap a resource, cleanup before destroy, run configuration management, etc.&lt;/p&gt;

&lt;p&gt;The first provisioner is a file provisioner which copies files to the resource (we use it to copy the &lt;code&gt;configure.sh&lt;/code&gt; script we created), while the second one &lt;code&gt;remote-exec&lt;/code&gt; runs a shell command on the VM once it has been created (we make the script executable and then run it). Both provisioner use another block called &lt;code&gt;connection&lt;/code&gt; which defines the connection type and the credentials required to reach the VM.&lt;/p&gt;

&lt;p&gt;Finally Terraform defines a way to extract details from the created resources using the &lt;code&gt;output&lt;/code&gt; block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output "node_dns_name" {
    value = "${aws_instance.Node.public_dns}"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will use this to output the VM public DNS name so that we can access the machine easily.&lt;/p&gt;

&lt;p&gt;This was a pretty rough introduction to the basics of Terraform that were used but I urge you to read the official &lt;a href="https://www.terraform.io/docs/index.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; to learn more about it.&lt;/p&gt;

&lt;p&gt;The configuration script is really basic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!#/bin/bash

sudo apt-get update
sudo apt-get -y install git
sudo apt-get -y install vim
sudo apt-get -y install python3 python3-pip python3-dev
sudo -H pip3 install jupyter

mkdir ~/.jupyter
echo "c.NotebookApp.allow_origin = '*'
c.NotebookApp.ip = '0.0.0.0'" | sudo tee /home/ubuntu/.jupyter/jupyter_notebook_config.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We run a system update, then install git, vim, python3 and python3 pip, and the jupyter notebook. The last 3 lines are of interest as they create the jupyter notebook specific configuration file, and assigns values to &lt;code&gt;allow_origin&lt;/code&gt; and &lt;code&gt;ip&lt;/code&gt; which allow access to the notebook from any server. &lt;br&gt;
Of course you can add any other packages you which your VM to have on this script.&lt;/p&gt;



&lt;p&gt;Now that the blueprint is explained we are ready to run it. The first time we run terraform with any blueprint we to initialize it. We do that by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way Terraform will try to find the relevant provider plugin required for this blueprint and download it.&lt;/p&gt;

&lt;p&gt;And now we are ready to create the VM. Let's start by running &lt;code&gt;terraform plan&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed. Cyan entries are data sources to be read.

Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

  + aws_instance.Node
      ami:                          "ami-785db401"
      associate_public_ip_address:  "&amp;lt;computed&amp;gt;"
      availability_zone:            "&amp;lt;computed&amp;gt;"
      ebs_block_device.#:           "&amp;lt;computed&amp;gt;"
      ephemeral_block_device.#:     "&amp;lt;computed&amp;gt;"
      instance_state:               "&amp;lt;computed&amp;gt;"
      instance_type:                "t2.micro"
      ipv6_address_count:           "&amp;lt;computed&amp;gt;"
      ipv6_addresses.#:             "&amp;lt;computed&amp;gt;"
      key_name:                     "mac-ssh"
      network_interface.#:          "&amp;lt;computed&amp;gt;"
      network_interface_id:         "&amp;lt;computed&amp;gt;"
      placement_group:              "&amp;lt;computed&amp;gt;"
      primary_network_interface_id: "&amp;lt;computed&amp;gt;"
      private_dns:                  "&amp;lt;computed&amp;gt;"
      private_ip:                   "&amp;lt;computed&amp;gt;"
      public_dns:                   "&amp;lt;computed&amp;gt;"
      public_ip:                    "&amp;lt;computed&amp;gt;"
      root_block_device.#:          "&amp;lt;computed&amp;gt;"
      security_groups.#:            "&amp;lt;computed&amp;gt;"
      source_dest_check:            "true"
      subnet_id:                    "&amp;lt;computed&amp;gt;"
      tags.%:                       "1"
      tags.Name:                    "Jupyter Notebook Meganode"
      tenancy:                      "&amp;lt;computed&amp;gt;"
      volume_tags.%:                "&amp;lt;computed&amp;gt;"
      vpc_security_group_ids.#:     "&amp;lt;computed&amp;gt;"

  + aws_security_group.jupyter_notebook_sg
      description:                           "Managed by Terraform"
      egress.#:                              "1"
      egress.482069346.cidr_blocks.#:        "1"
      egress.482069346.cidr_blocks.0:        "0.0.0.0/0"
      egress.482069346.from_port:            "0"
      egress.482069346.ipv6_cidr_blocks.#:   "0"
      egress.482069346.prefix_list_ids.#:    "0"
      egress.482069346.protocol:             "-1"
      egress.482069346.security_groups.#:    "0"
      egress.482069346.self:                 "false"
      egress.482069346.to_port:              "0"
      ingress.#:                             "2"
      ingress.2541437006.cidr_blocks.#:      "1"
      ingress.2541437006.cidr_blocks.0:      "0.0.0.0/0"
      ingress.2541437006.from_port:          "22"
      ingress.2541437006.ipv6_cidr_blocks.#: "0"
      ingress.2541437006.protocol:           "tcp"
      ingress.2541437006.security_groups.#:  "0"
      ingress.2541437006.self:               "false"
      ingress.2541437006.to_port:            "22"
      ingress.433339597.cidr_blocks.#:       "1"
      ingress.433339597.cidr_blocks.0:       "0.0.0.0/0"
      ingress.433339597.from_port:           "8888"
      ingress.433339597.ipv6_cidr_blocks.#:  "0"
      ingress.433339597.protocol:            "tcp"
      ingress.433339597.security_groups.#:   "0"
      ingress.433339597.self:                "false"
      ingress.433339597.to_port:             "8888"
      name:                                  "jupyter_notebook_sg"
      owner_id:                              "&amp;lt;computed&amp;gt;"
      vpc_id:                                "&amp;lt;computed&amp;gt;"


Plan: 2 to add, 0 to change, 0 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform will output what resources will be created so that you can double check that everything is as required. Then we actually run the &lt;code&gt;terraform apply&lt;/code&gt; and the resource creation begins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kostis@kostismbp terraform $ terraform apply
aws_security_group.jupyter_notebook_sg: Creating...
  description:                           "" =&amp;gt; "Managed by Terraform"
  egress.#:                              "" =&amp;gt; "1"
  egress.482069346.cidr_blocks.#:        "" =&amp;gt; "1"
  egress.482069346.cidr_blocks.0:        "" =&amp;gt; "0.0.0.0/0"
  egress.482069346.from_port:            "" =&amp;gt; "0"
  egress.482069346.ipv6_cidr_blocks.#:   "" =&amp;gt; "0"
  egress.482069346.prefix_list_ids.#:    "" =&amp;gt; "0"
  egress.482069346.protocol:             "" =&amp;gt; "-1"
  egress.482069346.security_groups.#:    "" =&amp;gt; "0"
  egress.482069346.self:                 "" =&amp;gt; "false"
  egress.482069346.to_port:              "" =&amp;gt; "0"
  ingress.#:                             "" =&amp;gt; "2"
  ingress.2541437006.cidr_blocks.#:      "" =&amp;gt; "1"
  ingress.2541437006.cidr_blocks.0:      "" =&amp;gt; "0.0.0.0/0"
...
...
...
aws_instance.Node: Creation complete after 1m13s (ID: i-05a88fcd8cafae195)

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

node_dns_name = ec2-34-240-28-230.eu-west-1.compute.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a while the resources have been created, we can see that Terraform has provided the public DNS name as mentioned, and we can ssh to the machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kostis@kostismbp terraform $ ssh -i ~/.aws/mac-ssh.pem ubuntu@ec2-34-240-28-230.eu-west-1.compute.amazonaws.com
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-1022-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

36 packages can be updated.
9 updates are security updates.


Last login: Mon Sep 11 21:08:07 2017 from 141.237.148.33
ubuntu@ip-172-31-45-252:~$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are ready to start the Jupyter Notebook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ubuntu@ip-172-31-45-252:~$ jupyter notebook
[I 21:11:32.984 NotebookApp] Writing notebook server cookie secret to /run/user/1000/jupyter/notebook_cookie_secret
[I 21:11:33.006 NotebookApp] Serving notebooks from local directory: /home/ubuntu
[I 21:11:33.006 NotebookApp] 0 active kernels
[I 21:11:33.007 NotebookApp] The Jupyter Notebook is running at: http://0.0.0.0:8888/?token=5cefea05e76d542e73d440f4f2085b536687ecd92adf5552
[I 21:11:33.007 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[W 21:11:33.007 NotebookApp] No web browser found: could not locate runnable browser.
[C 21:11:33.007 NotebookApp]

    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://0.0.0.0:8888/?token=5cefea05e76d542e73d440f4f2085b536687ecd92adf5552
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once it has started Jupyter provides a URL to access it, however we need to substitute the wildcard 0.0.0.0 IP with the machine DNS name so in this case the URL to access the Notebook will be &lt;code&gt;http://ec2-34-240-28-230.eu-west-1.compute.amazonaws.com:8888/?token=5cefea05e76d542e73d440f4f2085b536687ecd92adf5552&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Going to this URL confirms that everything is up and running!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftsaprailis.com%2Fimg%2FAWS_jupyter.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftsaprailis.com%2Fimg%2FAWS_jupyter.png" alt="jupyter"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Once we are done with our work we can just destroy the VM. Terraform will ask to confirm the destruction of the VM and then proceed to destroy it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kostis@kostismbp terraform $ terraform destroy
aws_security_group.jupyter_notebook_sg: Refreshing state... (ID: sg-a19bc7d9)
aws_instance.Node: Refreshing state... (ID: i-05a88fcd8cafae195)

The Terraform destroy plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning.
Resources shown in red will be destroyed.

  - aws_instance.Node

  - aws_security_group.jupyter_notebook_sg


Do you really want to destroy?
  Terraform will delete all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

aws_instance.Node: Destroying... (ID: i-05a88fcd8cafae195)
aws_instance.Node: Still destroying... (ID: i-05a88fcd8cafae195, 10s elapsed)
aws_instance.Node: Still destroying... (ID: i-05a88fcd8cafae195, 20s elapsed)
aws_instance.Node: Still destroying... (ID: i-05a88fcd8cafae195, 30s elapsed)
aws_instance.Node: Still destroying... (ID: i-05a88fcd8cafae195, 40s elapsed)
aws_instance.Node: Still destroying... (ID: i-05a88fcd8cafae195, 50s elapsed)
aws_instance.Node: Still destroying... (ID: i-05a88fcd8cafae195, 1m0s elapsed)
aws_instance.Node: Destruction complete after 1m3s
aws_security_group.jupyter_notebook_sg: Destroying... (ID: sg-a19bc7d9)
aws_security_group.jupyter_notebook_sg: Destruction complete after 1s

Destroy complete! Resources: 2 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Hope you liked this tutorial. I tried to summarize everything I learned along the way. Terraform is a very helpful tool that is being adopted by many tech companies. After this introduction I would encourage you to read more about it. Creating a single machine is just a very simple case but if you get the hang of you can create multi node architecture with big data systems like Hadoop, Spark etc.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
