基本構成は下記の通り
Route53 + ALB + Cloud Watch logs + S3 + RDS + EC2(nginx + php-fpm + Laravel)
実行環境構築
awsのconfig設定
> aws configure --profile dev-user
AWS Access Key ID [None]: XXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: json
cat ~/.aws/config
# aws-cliを使う際はuserを設定
export AWS_DEFAULT_PROFILE=dev-user
terraformインストール
brew install terraform
> terraform -v
Terraform v0.12.28
Terraformのログを残すように設定
vi ~/.bash_profile
# terraform
export TF_LOG=DEBUG
export TF_LOG_PATH='./terraform.log'
Terraform実行前に
- ドメインを取得しておく。自分はフリーのものを使用した。
- S3等に接続できるWEB用のAWSアカウントを作成する
- route53でドメインを作成する
- example.tfvarsを参考に各環境ごとに「xxx.tfvars」を作成
EC2で使う鍵をterraformのソース内に作成しておく
mkdir .ssh
ssh-keygen -f .ssh/xxxx
ソース
main.tf
terraform {
required_version = ">= 0.12.28"
required_providers {
aws = ">= 2.70.0"
}
}
provider "aws" {
profile = "dev-user"
region = "ap-northeast-1"
}
variable "root_domain" {}
variable "dev_laravel_domain" {}
variable "github_personal_access_token" {}
variable "web_ssh_key_name" {}
variable "web_ssh_public_key" {}
variable "web_server_count" {}
variable "db_name" {}
variable "db_username" {}
variable "db_password" {}
variable "aws_access_key_id" {}
variable "aws_secret_access_key" {}
variable "aws_bucket" {}
############################################################
### ネットワーク
############################################################
### VPC ####################
resource "aws_vpc" "y-oka-vpc" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "y-oka-vpc"
}
}
### サブネット ####################
# パブリックサブネット
resource "aws_subnet" "y-oka-pub-subnet-a" {
vpc_id = aws_vpc.y-oka-vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-northeast-1a"
map_public_ip_on_launch = true
tags = {
Name = "y-oka-pub-subnet-a"
}
}
resource "aws_subnet" "y-oka-pub-subnet-c" {
vpc_id = aws_vpc.y-oka-vpc.id
cidr_block = "10.0.2.0/24"
availability_zone = "ap-northeast-1c"
map_public_ip_on_launch = true
tags = {
Name = "y-oka-pub-subnet-c"
}
}
# プライベートサブネット
resource "aws_subnet" "y-oka-prv-subnet-a" {
vpc_id = aws_vpc.y-oka-vpc.id
cidr_block = "10.0.3.0/24"
availability_zone = "ap-northeast-1a"
map_public_ip_on_launch = false
tags = {
Name = "y-oka-prv-subnet-a"
}
}
resource "aws_subnet" "y-oka-prv-subnet-c" {
vpc_id = aws_vpc.y-oka-vpc.id
cidr_block = "10.0.4.0/24"
availability_zone = "ap-northeast-1c"
map_public_ip_on_launch = false
tags = {
Name = "y-oka-prv-subnet-c"
}
}
# DBプライベートサブネット
resource "aws_subnet" "y-oka-db-prv-subnet-a" {
vpc_id = aws_vpc.y-oka-vpc.id
cidr_block = "10.0.5.0/24"
availability_zone = "ap-northeast-1a"
map_public_ip_on_launch = false
tags = {
Name = "y-oka-db-prv-subnet-a"
}
}
resource "aws_subnet" "y-oka-db-prv-subnet-c" {
vpc_id = aws_vpc.y-oka-vpc.id
cidr_block = "10.0.6.0/24"
availability_zone = "ap-northeast-1c"
map_public_ip_on_launch = false
tags = {
Name = "y-oka-db-prv-subnet-c"
}
}
# DBサブネットグループ
resource "aws_db_subnet_group" "y-oka-db-subnet-group" {
name = "y-oka-db-subnet-group"
subnet_ids = [
aws_subnet.y-oka-db-prv-subnet-a.id,
aws_subnet.y-oka-db-prv-subnet-c.id
]
tags = {
Name = "y-oka-db-subnet-group"
}
}
### ネットワークルーティング ####################
# publicサブネット <- IGW -> 外部インターネット
resource "aws_internet_gateway" "y-oka-igw" {
vpc_id = aws_vpc.y-oka-vpc.id
tags = {
Name = "y-oka-igw"
}
}
resource "aws_route_table" "y-oka-pub-rtb" {
vpc_id = aws_vpc.y-oka-vpc.id
route {
gateway_id = aws_internet_gateway.y-oka-igw.id
cidr_block = "0.0.0.0/0"
}
tags = {
Name = "y-oka-pub-rtb"
}
}
resource "aws_route_table_association" "y-oka-pub-rtb-ass-a" {
subnet_id = aws_subnet.y-oka-pub-subnet-a.id
route_table_id = aws_route_table.y-oka-pub-rtb.id
}
resource "aws_route_table_association" "y-oka-pub-rtb-ass-c" {
subnet_id = aws_subnet.y-oka-pub-subnet-c.id
route_table_id = aws_route_table.y-oka-pub-rtb.id
}
# privateサブネット <- NGW -> publicサブネット
resource "aws_eip" "y-oka-ngw-eip-a" {
tags = {
Name = "y-oka-ngw-eip-a"
}
}
resource "aws_eip" "y-oka-ngw-eip-c" {
tags = {
Name = "y-oka-ngw-eip-c"
}
}
# NATゲートウェイ ルーティング
resource "aws_nat_gateway" "y-oka-ngw-a" {
allocation_id = aws_eip.y-oka-ngw-eip-a.id
subnet_id = aws_subnet.y-oka-pub-subnet-a.id
tags = {
Name = "y-oka-ngw-a"
}
}
resource "aws_nat_gateway" "y-oka-ngw-c" {
allocation_id = aws_eip.y-oka-ngw-eip-c.id
subnet_id = aws_subnet.y-oka-pub-subnet-c.id
tags = {
Name = "y-oka-ngw-c"
}
}
resource "aws_route_table" "y-oka-prv-rtb-a" {
vpc_id = aws_vpc.y-oka-vpc.id
route {
gateway_id = aws_nat_gateway.y-oka-ngw-a.id
cidr_block = "0.0.0.0/0"
}
tags = {
Name = "y-oka-prv-rtb-a"
}
}
resource "aws_route_table" "y-oka-prv-rtb-c" {
vpc_id = aws_vpc.y-oka-vpc.id
route {
gateway_id = aws_nat_gateway.y-oka-ngw-c.id
cidr_block = "0.0.0.0/0"
}
tags = {
Name = "y-oka-prv-rtb-c"
}
}
resource "aws_route_table_association" "y-oka-prv-rtb-ass-a" {
subnet_id = aws_subnet.y-oka-prv-subnet-a.id
route_table_id = aws_route_table.y-oka-prv-rtb-a.id
}
resource "aws_route_table_association" "y-oka-prv-rtb-ass-c" {
subnet_id = aws_subnet.y-oka-prv-subnet-c.id
route_table_id = aws_route_table.y-oka-prv-rtb-c.id
}
############################################################
### セキュリティグループ
############################################################
### publicセキュリティー ####################
resource "aws_security_group" "y-oka-pub-sg" {
name = "y-oka-pub-sg"
vpc_id = aws_vpc.y-oka-vpc.id
tags = {
Name = "y-oka-pub-sg"
}
}
# アウトバウンド(外に出る)ルール
resource "aws_security_group_rule" "y-oka-pub-sg-out-all" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.y-oka-pub-sg.id
}
### privateセキュリティー ####################
resource "aws_security_group" "y-oka-prv-sg" {
name = "y-oka-prv-sg"
vpc_id = aws_vpc.y-oka-vpc.id
tags = {
Name = "y-oka-prv-sg"
}
}
# アウトバウンド(外に出る)ルール
resource "aws_security_group_rule" "y-oka-prv-sg-out-all" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.y-oka-prv-sg.id
}
# インバウンド(受け入れる)ルール
resource "aws_security_group_rule" "y-oka-prv-sg-in-http" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.y-oka-prv-sg.id
}
### DBセキュリティー ####################
resource "aws_security_group" "y-oka-db-sg" {
name = "y-oka-db-sg"
vpc_id = aws_vpc.y-oka-vpc.id
tags = {
Name = "y-oka-db-sg"
}
}
# アウトバウンド(外に出る)ルール
resource "aws_security_group_rule" "y-oka-db-sg-out-all" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.y-oka-db-sg.id
}
# インバウンド(受け入れる)ルール
resource "aws_security_group_rule" "y-oka-db-sg-in-mysql" {
type = "ingress"
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.y-oka-db-sg.id
}
### ALBセキュリティー ####################
resource "aws_security_group" "y-oka-alb-sg" {
name = "y-oka-alb-sg"
vpc_id = aws_vpc.y-oka-vpc.id
tags = {
Name = "y-oka-alb-sg"
}
}
resource "aws_security_group_rule" "y-oka-alb-sg-out-all" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.y-oka-alb-sg.id
}
# インバウンド(受け入れる)ルール
resource "aws_security_group_rule" "y-oka-alb-sg-in-http" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.y-oka-alb-sg.id
}
############################################################
### IAM
############################################################
# EC2のIAM
data "aws_iam_policy_document" "y-oka-ec2-policy" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "y-oka-ec2-role" {
name = "y-oka-ec2-role"
assume_role_policy = data.aws_iam_policy_document.y-oka-ec2-policy.json
}
resource "aws_iam_instance_profile" "y-oka-ec2-profile" {
name = "y-oka-ec2-profile"
role = aws_iam_role.y-oka-ec2-role.name
}
data "aws_iam_policy" "y-oka-ssm-policy" {
arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
data "aws_iam_policy" "y-oka-s3-policy" {
arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
data "aws_iam_policy" "y-oka-cloud-watch-logs-policy" {
arn = "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
}
resource "aws_iam_role_policy_attachment" "y-oka-ec2-role-ssm-policy-attach" {
role = aws_iam_role.y-oka-ec2-role.name
policy_arn = data.aws_iam_policy.y-oka-ssm-policy.arn
}
resource "aws_iam_role_policy_attachment" "y-oka-ec2-role-s3-policy-attach" {
role = aws_iam_role.y-oka-ec2-role.name
policy_arn = data.aws_iam_policy.y-oka-s3-policy.arn
}
resource "aws_iam_role_policy_attachment" "y-oka-ec2-role-cloud-watch-logs-policy-attach" {
role = aws_iam_role.y-oka-ec2-role.name
policy_arn = data.aws_iam_policy.y-oka-cloud-watch-logs-policy.arn
}
# ALBのIAM
data "aws_elb_service_account" "y-oka-elb-service-account" {}
data "aws_iam_policy_document" "y-oka-s3-alb-log-policy" {
statement {
effect = "Allow"
actions = ["s3:PutObject"]
resources = ["arn:aws:s3:::${aws_s3_bucket.y-oka-s3-alb-log.id}/*"]
principals {
type = "AWS"
identifiers = [data.aws_elb_service_account.y-oka-elb-service-account.id]
}
}
}
############################################################
### CloudWatch Logs
############################################################
resource "aws_cloudwatch_log_group" "y-oka-web-ec2-log-message" {
name = "/y-oka/web-ec2/message"
}
resource "aws_cloudwatch_log_group" "y-oka-web-ec2-log-secure" {
name = "/y-oka/web-ec2/secure"
}
resource "aws_cloudwatch_log_group" "y-oka-web-ec2-log-nginx-access" {
name = "/y-oka/web-ec2/nginx/access-log"
}
resource "aws_cloudwatch_log_group" "y-oka-web-ec2-log-nginx-error" {
name = "/y-oka/web-ec2/nginx/error-log"
}
resource "aws_cloudwatch_log_group" "y-oka-web-ec2-log-php-fpm-error" {
name = "/y-oka/web-ec2/php-fpm/error-log"
}
############################################################
### S3
############################################################
resource "aws_s3_bucket" "y-oka-s3-alb-log" {
bucket = "y-oka-s3-alb-log"
force_destroy = true
lifecycle_rule {
enabled = true
expiration {
days = 30
}
}
}
resource "aws_s3_bucket_policy" "y-oka-s3-alb-log-bucket-policy" {
bucket = aws_s3_bucket.y-oka-s3-alb-log.id
policy = data.aws_iam_policy_document.y-oka-s3-alb-log-policy.json
}
resource "aws_s3_bucket" "y-oka-web-s3" {
bucket = var.aws_bucket
force_destroy = true
acl = "private"
}
resource "aws_s3_bucket_public_access_block" "y-oka-web-s3-access" {
bucket = aws_s3_bucket.y-oka-web-s3.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
############################################################
### RDS
############################################################
resource "aws_db_parameter_group" "y-oka-db-param-group" {
name = "y-oka-db-param-group"
family = "aurora-mysql5.7"
}
resource "aws_rds_cluster_parameter_group" "y-oka-db-cluster-param-group" {
name = "y-oka-db-cluster-param-group"
family = "aurora-mysql5.7"
parameter {
name = "character_set_server"
value = "utf8"
}
parameter {
name = "character_set_client"
value = "utf8"
}
parameter {
name = "time_zone"
value = "Asia/Tokyo"
apply_method = "immediate"
}
}
resource "aws_rds_cluster" "y-oka-aurora-cluster" {
cluster_identifier = "y-oka-aurora-cluster"
database_name = var.db_name
master_username = var.db_username
master_password = var.db_password
port = 3306
apply_immediately = false # apply時に再起動するか
skip_final_snapshot = true # インスタンス削除時にスナップショットを取るかどうか
engine = "aurora-mysql"
engine_version = "5.7.mysql_aurora.2.08.1"
vpc_security_group_ids = [aws_security_group.y-oka-db-sg.id]
db_subnet_group_name = aws_db_subnet_group.y-oka-db-subnet-group.name
db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.y-oka-db-cluster-param-group.name
tags = {
Name = "y-oka-aurora-cluster"
}
}
resource "aws_rds_cluster_instance" "y-oka-aurora-cluster-instance" {
count = 2
identifier = "aurora-cluster-${count.index + 1}"
cluster_identifier = aws_rds_cluster.y-oka-aurora-cluster.id
instance_class = "db.t2.small"
apply_immediately = false # apply時に再起動するか
engine = "aurora-mysql"
engine_version = "5.7.mysql_aurora.2.08.1"
db_subnet_group_name = aws_db_subnet_group.y-oka-db-subnet-group.name
db_parameter_group_name = aws_db_parameter_group.y-oka-db-param-group.name
tags = {
Name = "y-oka-aurora-cluster-instance-${count.index + 1}"
}
}
output "db-entpoint" {
value = aws_rds_cluster.y-oka-aurora-cluster.endpoint
}
output "db-reader-entpoint" {
value = aws_rds_cluster.y-oka-aurora-cluster.reader_endpoint
}
############################################################
### EC2
############################################################
resource "aws_key_pair" "y-oka-web-ec2-key-pair" {
key_name = var.web_ssh_key_name
public_key = file("./.ssh/${var.web_ssh_public_key}")
}
data "template_file" "y-oka-web-ec2-user_data" {
count = var.web_server_count
template = file("./user_data.sh.tpl")
vars = {
count_index = count.index + 1
github_personal_access_token = var.github_personal_access_token
web_log_message = aws_cloudwatch_log_group.y-oka-web-ec2-log-message.name
web_log_secure = aws_cloudwatch_log_group.y-oka-web-ec2-log-secure.name
web_log_nginx_access = aws_cloudwatch_log_group.y-oka-web-ec2-log-nginx-access.name
web_log_nginx_error = aws_cloudwatch_log_group.y-oka-web-ec2-log-nginx-error.name
web_log_php_fpm_error = aws_cloudwatch_log_group.y-oka-web-ec2-log-php-fpm-error.name
db_host = aws_rds_cluster.y-oka-aurora-cluster.endpoint
db_name = var.db_name
db_username = var.db_username
db_password = var.db_password
aws_access_key_id = var.aws_access_key_id
aws_secret_access_key = var.aws_secret_access_key
aws_bucket = var.aws_bucket
}
}
# Webサーバー
resource "aws_instance" "y-oka-web-ec2" {
count = var.web_server_count
ami = "ami-06ad9296e6cf1e3cf"
instance_type = "t2.micro"
iam_instance_profile = aws_iam_instance_profile.y-oka-ec2-profile.name
key_name = aws_key_pair.y-oka-web-ec2-key-pair.id
subnet_id = [
aws_subnet.y-oka-prv-subnet-a.id,
aws_subnet.y-oka-prv-subnet-c.id][count.index % 2]
vpc_security_group_ids = [aws_security_group.y-oka-prv-sg.id]
user_data = element(data.template_file.y-oka-web-ec2-user_data.*.rendered, count.index)
tags = {
Name = "y-oka-web-ec2-${count.index + 1}"
}
}
############################################################
### ALB
############################################################
# ALB
resource "aws_lb" "y-oka-alb" {
name = "y-oka-alb"
load_balancer_type = "application"
internal = false
idle_timeout = 60
# enable_deletion_protection = true # 削除保護
subnets = [
aws_subnet.y-oka-pub-subnet-a.id,
aws_subnet.y-oka-pub-subnet-c.id
]
security_groups = [aws_security_group.y-oka-alb-sg.id]
access_logs {
bucket = aws_s3_bucket.y-oka-s3-alb-log.id
enabled = true
}
}
# ターゲットグループ
resource "aws_lb_target_group" "y-oka-alb-target-group-http" {
name = "y-oka-alb-target-group-http"
vpc_id = aws_vpc.y-oka-vpc.id
port = "80"
protocol = "HTTP"
health_check {
path = "/api"
}
}
# リスナー
resource "aws_lb_listener" "y-oka-alb-listener-http" {
load_balancer_arn = aws_lb.y-oka-alb.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.y-oka-alb-target-group-http.arn
}
}
# リスナールール
resource "aws_lb_listener_rule" "y-oka-alb-listener-rule-http" {
listener_arn = aws_lb_listener.y-oka-alb-listener-http.arn
priority = 99
action {
type = "forward"
target_group_arn = aws_lb_target_group.y-oka-alb-target-group-http.arn
}
condition {
path_pattern {
values = ["/*"]
}
}
}
resource "aws_lb_target_group_attachment" "y-oka-alb-target-group-attaches" {
count = var.web_server_count
target_group_arn = aws_lb_target_group.y-oka-alb-target-group-http.arn
target_id = element(aws_instance.y-oka-web-ec2.*.id, count.index)
port = 80
}
############################################################
### Route 53
############################################################
### ドメイン設定 ####################
data "aws_route53_zone" "root-domain" {
name = var.root_domain
}
resource "aws_route53_record" "root-domain-ns" {
allow_overwrite = true
zone_id = data.aws_route53_zone.root-domain.zone_id
name = data.aws_route53_zone.root-domain.name
ttl = 30
type = "NS"
records = [
data.aws_route53_zone.root-domain.name_servers[0],
data.aws_route53_zone.root-domain.name_servers[1],
data.aws_route53_zone.root-domain.name_servers[2],
data.aws_route53_zone.root-domain.name_servers[3],
]
}
output "okdyy75_nameserver" {
value = join(", ", data.aws_route53_zone.root-domain.name_servers)
}
resource "aws_route53_record" "dev-laravel-domain-a" {
zone_id = data.aws_route53_zone.root-domain.zone_id
name = var.dev_laravel_domain
type = "A"
alias {
name = aws_lb.y-oka-alb.dns_name
zone_id = aws_lb.y-oka-alb.zone_id
evaluate_target_health = true
}
}
### 内部ドメイン ####################
resource "aws_route53_record" "dev-laravel-internal-domain-a" {
zone_id = data.aws_route53_zone.root-domain.zone_id
name = "dev-laravel-internal.okdyy75.ga"
type = "A"
ttl = "300"
records = aws_instance.y-oka-web-ec2.*.private_ip
}
user_data.sh.tpl
#!/bin/bash
export HOME="/root"
hostnamectl set-hostname "y-oka-web${count_index}"
yum -y update
yum install -y git
### CloudWatch Logs ##################################################
sudo yum install -y awslogs
cat <<EOT > /etc/awslogs/awscli.conf
[plugins]
cwlogs = cwlogs
[default]
region = ap-northeast-1
EOT
cat <<EOT > /etc/awslogs/awslogs.conf
[general]
state_file = /var/lib/awslogs/agent-state
[${web_log_message}]
file = /var/log/messages
log_group_name = ${web_log_message}
log_stream_name = {instance_id}
datetime_format = %b %d %H:%M:%S
[${web_log_secure}]
file = /var/log/secure
log_group_name = ${web_log_secure}
log_stream_name = {instance_id}
datetime_format = %b %d %H:%M:%S
[${web_log_nginx_access}]
file = /var/log/nginx/access.log
log_group_name = ${web_log_nginx_access}
log_stream_name = {instance_id}
datetime_format = %d/%b/%Y:%H:%M:%S %z
[${web_log_nginx_error}]
file = /var/log/nginx/error.log
log_group_name = ${web_log_nginx_error}
log_stream_name = {instance_id}
datetime_format = %Y/%m/%d %H:%M:%S
[${web_log_php_fpm_error}]
file = /var/log/php-fpm/error.log
log_group_name = ${web_log_php_fpm_error}
log_stream_name = {instance_id}
datetime_format = %d-%b-%Y %H:%M:%S
EOT
systemctl status awslogsd.service
systemctl enable awslogsd.service
### php-fpm ##################################################
amazon-linux-extras install -y php7.4
yum install -y php-mbstring php-xml
systemctl enable php-fpm.service
sed -i "s|user = apache|user = nginx|" /etc/php-fpm.d/www.conf
sed -i "s|group = apache|group = nginx|" /etc/php-fpm.d/www.conf
systemctl start php-fpm.service
systemctl status php-fpm.service
### nginx ##################################################
amazon-linux-extras install -y nginx1.12
systemctl enable nginx.service
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.org
cat <<'EOT' > /etc/nginx/nginx.conf
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name dev-laravel.okdyy75.ga;
root /var/www/dev-laravel/public;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php?$ {
fastcgi_intercept_errors on;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass php-fpm;
}
}
}
EOT
systemctl start nginx.service
systemctl status nginx.service
### mysql ##################################################
yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
yum-config-manager --disable mysql80-community
yum-config-manager --enable mysql57-community
yum install -y mysql-community-client
### app ##################################################
mkdir -p /var/www
cd /var/www
git clone "https://okdyy75:${github_personal_access_token}@github.com/okdyy75/dev-laravel.git"
cd dev-laravel
mkdir -m 777 vendor
chmod -R 777 bootstrap/cache
chmod -R 777 storage
chown -R nginx:nginx storage/logs
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
composer install
composer dump-autoload
cp -p .env.example .env
php artisan key:generate
sed -i "s|DB_HOST=.*|DB_HOST=${db_host}|" .env
sed -i "s|DB_DATABASE=.*|DB_DATABASE=${db_name}|" .env
sed -i "s|DB_USERNAME=.*|DB_USERNAME=${db_username}|" .env
sed -i "s|DB_PASSWORD=.*|DB_PASSWORD=${db_password}|" .env
sed -i "s|AWS_ACCESS_KEY_ID=.*|AWS_ACCESS_KEY_ID=${aws_access_key_id}|" .env
sed -i "s|AWS_SECRET_ACCESS_KEY=.*|AWS_SECRET_ACCESS_KEY=${aws_secret_access_key}|" .env
sed -i "s|AWS_BUCKET=.*|AWS_BUCKET=${aws_bucket}|" .env
### node.js ##################################################
# curl -sL https://rpm.nodesource.com/setup_10.x | bash -
# yum install -y nodejs
# npm install
# npm run dev
Terraform実行
# 一番最初に実行する際はinit
terraform init
# 計画
terraform plan -var-file=dev.tfvars
# デプロイ
terraform apply -var-file=dev.tfvars
# 破棄
terraform destroy -var-file=dev.tfvars
作成したWebサーバーにSSM経由でログインする
macOS に Session Manager plugin をインストール
SSM経由でアクセス
aws ssm start-session --target [EC2のインスタンスID]
sshで簡単にログインできるように下記設定
vi ~/.ssh/config
# SSH over Session Manager
host i-* mi-*
ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
SSM経由でssh
ssh -i .ssh/web_id_rsa ec2-user@[EC2のインスタンスID]
EC2にsshしてWeb、DB、S3と接続できるか確認
# DBのテスト
php artisan migrate
php artisan migrate:rollback
# S3のテスト
echo "テストです!" > storage/test.txt
php artisan test:s3 store test.txt
Terraform TIPs
- resource名はケバブケースで書こう。(resource名とnameを合わせた時にアンダーバーが使えない場合が多々あり)
- 上記に合わせて変数名はスネークケースで書こう。
感想
AWS勉強するのにTerraformはおすすめです
bashでごり押してますがECSにすれば解決ですね
次は下記を導入していきたいです
- デフォルトユーザーを変える(ec2-user)
- httpsでの接続
- ECSで作成
- 秘匿情報をパラメーターストアで管理
- RDSにログの追加
- メールサーバーの設定
- VPNの導入
- 本番運用を想定した記述。tfstateの管理
参考にさせて頂いた資料
ソースは全部GitHubに上げてます
docker
https://github.com/okdyy75/dev-laravel-docker
laravel
https://github.com/okdyy75/dev-laravel
terraform
https://github.com/okdyy75/dev-laravel-terraform
terraformソース内のy-okaになっている部分は適宜自分の名前にしてください