Skip to content

Commit

Permalink
AWS: initial CloudFormation template based on Rails example
Browse files Browse the repository at this point in the history
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/sample-templates-appframeworks-us-west-2.html
Ruby on Rails basic

Changes:
* description
* add git and clone Matreon
  * workaround: use custom branch with MySQL for production
* reduced supported instance types to t2.micro, t2.small and t2.medium
* reduced supported locations to Frankfurt
* simplified AWSRegionArch2AMI table
* hardcoded database name and user
  • Loading branch information
Sjors committed May 3, 2018
1 parent bb68b28 commit 2dfff1a
Show file tree
Hide file tree
Showing 3 changed files with 332 additions and 5 deletions.
3 changes: 2 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ group :development do
end

group :production do
gem 'pg'
# gem 'pg'
gem 'mysql'

# Send emails via Sendgrid
gem 'sendgrid-ruby'
Expand Down
8 changes: 4 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ GEM
minitest (5.11.3)
multi_json (1.13.1)
mustermann (1.0.2)
mysql (2.9.1)
mysql (2.9.1-x86-mingw32)
mysql (2.9.1-x86-mswin32-60)
nenv (0.3.0)
netrc (0.11.0)
nio4r (2.3.0)
Expand All @@ -154,9 +157,6 @@ GEM
nenv (~> 0.1)
shellany (~> 0.0)
orm_adapter (0.5.0)
pg (1.0.0)
pg (1.0.0-x64-mingw32)
pg (1.0.0-x86-mingw32)
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
Expand Down Expand Up @@ -370,7 +370,7 @@ DEPENDENCIES
jbuilder (~> 2.5)
listen (>= 3.0.5, < 3.2)
mini_racer
pg
mysql
puma (~> 3.11)
rack-timeout
rails (~> 5.1.6)
Expand Down
326 changes: 326 additions & 0 deletions Matreon.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,326 @@
{
"AWSTemplateFormatVersion" : "2010-09-09",

"Description" : "Creates a single EC2 instance with a pruned Bitcoin Core node, C-Lightning, Lightning Charge, MySQL, Ruby on Rails and Matreon.",

"Parameters" : {

"KeyName": {
"Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances",
"Type": "AWS::EC2::KeyPair::KeyName",
"ConstraintDescription" : "must be the name of an existing EC2 KeyPair."
},

"DBPassword": {
"NoEcho": "true",
"Description" : "Password MySQL database access",
"Type": "String",
"MinLength": "1",
"MaxLength": "41",
"AllowedPattern" : "[a-zA-Z0-9]*",
"ConstraintDescription" : "must contain only alphanumeric characters."
},

"DBRootPassword": {
"NoEcho": "true",
"Description" : "Root password for MySQL",
"Type": "String",
"MinLength": "1",
"MaxLength": "41",
"AllowedPattern" : "[a-zA-Z0-9]*",
"ConstraintDescription" : "must contain only alphanumeric characters."
},

"InstanceType" : {
"Description" : "WebServer EC2 instance type",
"Type" : "String",
"Default" : "t2.small",
"AllowedValues" : [ "t2.micro", "t2.small", "t2.medium"],
"ConstraintDescription" : "must be a valid EC2 instance type."
},

"SSHLocation" : {
"Description" : "The IP address range that can be used to SSH to the EC2 instances",
"Type": "String",
"MinLength": "9",
"MaxLength": "18",
"Default": "0.0.0.0/0",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
}
},

"Mappings" : {
"AWSInstanceType2Arch" : {
"t2.micro" : { "Arch" : "HVM64" },
"t2.small" : { "Arch" : "HVM64" },
"t2.medium" : { "Arch" : "HVM64" },
},

"AWSInstanceType2NATArch" : {
"t2.micro" : { "Arch" : "NATHVM64" },
"t2.small" : { "Arch" : "NATHVM64" },
"t2.medium" : { "Arch" : "NATHVM64" },

},

"AWSRegionArch2AMI" : {
"eu-central-1" : {"HVM64" : "ami-5652ce39"}
}

},

"Resources" : {

"WebServer": {
"Type": "AWS::EC2::Instance",
"Metadata" : {
"AWS::CloudFormation::Init" : {
"configSets" : {
"full_install" : [ "install_cfn", "install_ruby_2_5_1", "install_mysql", "configure_mysql", "install_application" ]
},

"install_cfn" : {
"files" : {
"/etc/cfn/cfn-hup.conf" : {
"content" : { "Fn::Join" : ["", [
"[main]\n",
"stack=", { "Ref" : "AWS::StackId" }, "\n",
"region=", { "Ref" : "AWS::Region" }, "\n"
]]},
"mode" : "000400",
"owner" : "root",
"group" : "root"
},

"/etc/cfn/hooks.d/cfn-auto-reloader.conf" : {
"content": { "Fn::Join" : ["", [
"[cfn-auto-reloader-hook]\n",
"triggers=post.update\n",
"path=Resources.WebServer.Metadata.AWS::CloudFormation::Init\n",
"action=/opt/aws/bin/cfn-init -v ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource WebServer ",
" --configsets full_install ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
"runas=root\n"
]]},
"mode" : "000400",
"owner" : "root",
"group" : "root"
}
},

"services" : {
"sysvinit" : {
"cfn-hup" : { "enabled" : "true", "ensureRunning" : "true",
"files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]}
}
}
},

"install_ruby_2_5_1": {
"files": {
"/tmp/install_ruby": {
"content": {
"Fn::Join": [
"\n",
[
"#!/bin/bash",
"curl -sSL https://get.rvm.io | bash",
"source /etc/profile.d/rvm.sh",
"rvm install 2.5.1",
"rvm --default use 2.5.1",
"gem install rails"
]
]
},
"mode": "000500",
"owner": "root",
"group": "root"
}
},
"commands": {
"01_install_ruby": {
"command": "/tmp/install_ruby > /var/log/install_ruby.log"
}
}
},

"install_mysql" : {
"packages" : {
"yum" : {
"mysql" : [],
"mysql-server" : [],
"mysql-devel" : [],
"mysql-libs" : []
}
},

"files" : {
"/tmp/setup.mysql" : {
"content" : { "Fn::Join" : ["", [
"CREATE USER 'matreon'@'localhost' IDENTIFIED BY '", { "Ref" : "DBPassword" }, "';\n",
"GRANT ALL ON matreon.* TO 'matreon'@'localhost';\n",
"FLUSH PRIVILEGES;\n"
]]},
"mode" : "000400",
"owner" : "root",
"group" : "root"
}
},

"services" : {
"sysvinit" : {
"mysqld" : { "enabled" : "true", "ensureRunning" : "true" }
}
}
},

"configure_mysql" : {
"commands" : {
"01_set_mysql_root_password" : {
"command" : { "Fn::Join" : ["", ["mysqladmin -u root password '", { "Ref" : "DBRootPassword" }, "'"]]},
"test" : { "Fn::Join" : ["", ["$(mysql matreon -u root --password='", { "Ref" : "DBRootPassword" }, "' >/dev/null 2>&1 </dev/null); (( $? != 0 ))"]]}
},
"02_create_database" : {
"command" : { "Fn::Join" : ["", ["mysql -u root --password='", { "Ref" : "DBRootPassword" }, "' < /tmp/setup.mysql"]]},
"test" : { "Fn::Join" : ["", ["$(mysql matreon -u root --password='", { "Ref" : "DBRootPassword" }, "' >/dev/null 2>&1 </dev/null); (( $? != 0 ))"]]}
},
"03_cleanup" : {
"command" : "rm /tmp/setup.mysql"
}
}
},

"install_application" : {
"packages" : {
"yum" : {
"git" : []
}
},

"files" : {
"/tmp/database.yml" : {
"content" : { "Fn::Join" : ["", [
"development:\n",
" adapter: mysql2\n",
" encoding: utf8\n",
" reconnect: false\n",
" pool: 5\n",
" database: matreon\n",
" username: matreon\n",
" password: ", { "Ref" : "DBPassword" }, "\n",
" socket: /var/lib/mysql/mysql.sock\n"
]]},
"mode" : "000400",
"owner" : "root",
"group" : "root"
},
"/tmp/install_application" : {
"content" : { "Fn::Join" : ["", [
"#!/bin/bash -e\n",
"source /etc/profile.d/rvm.sh\n",
"rvm use 2.5.1\n",
"export HOME=/home/ec2-user\n",
"export PATH=$PATH:/usr/local/bin\n",
"cd /home/ec2-user\n",

"# Kill the rails server if it is running to allow update\n",
"if pgrep ruby &> /dev/null ; then pkill -TERM ruby ; fi\n",

"git clone https://github.com/Sjors/matreon.git\n",
"cd matreon\n",
"git checkout 2018/05/aws_cloudformation"
"bundle install --without development:test\n",

"# Configure the database connection\n",
"mv /tmp/database.yml config\n",
"rake db:create db:migrate RAILS_ENV=production\n"
]]},
"mode" : "000500",
"owner" : "root",
"group" : "root"
},
"/home/ec2-user/start-application" : {
"content" : { "Fn::Join" : ["", [
"#!/bin/bash -e\n",
"source /etc/profile.d/rvm.sh\n",
"rvm use 2.5.1\n",
"export HOME=/home/ec2-user\n",
"export PATH=$PATH:/usr/local/bin\n",
"cd /home/ec2-user/matreon\n",

"# Startup the application\n",
"rails server --binding 0.0.0.0 -p 80 -d RAILS_ENV=production\n"
]]},
"mode" : "000500",
"owner" : "root",
"group" : "root"
}
},
"commands" : {
"01_install_application" : {
"command" : "/tmp/install_application > /var/log/install_application.log"
},
"02_configure_reboot" : {
"command" : "echo /home/ec2-user/start-application >> /etc/rc.local"
},
"03_start_application" : {
"command" : "/home/ec2-user/start-application"
},
"04_cleanup" : {
"command" : "rm /tmp/install_application"
}
}
}
}
},
"Properties": {
"ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
{ "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
"InstanceType" : { "Ref" : "InstanceType" },
"SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
"KeyName" : { "Ref" : "KeyName" },
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -xe\n",
"yum update -y aws-cfn-bootstrap\n",

"/opt/aws/bin/cfn-init -v ",
" --stack ", { "Ref" : "AWS::StackId" },
" --resource WebServer ",
" --configsets full_install ",
" --region ", { "Ref" : "AWS::Region" }, "\n",

"/opt/aws/bin/cfn-signal -e $? ",
" --stack ", { "Ref" : "AWS::StackId" },
" --resource WebServer ",
" --region ", { "Ref" : "AWS::Region" }, "\n"
]]}}
},
"CreationPolicy" : {
"ResourceSignal" : {
"Timeout" : "PT30M"
}
}
},

"WebServerSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Enable HTTP and SSH access",
"SecurityGroupIngress" : [
{"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"},
{"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}}
]
}
}
},

"Outputs" : {
"WebsiteURL" : {
"Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServer", "PublicDnsName" ]}, "/notes" ]] },
"Description" : "URL for newly created Rails application"
}
}
}

0 comments on commit 2dfff1a

Please sign in to comment.