こんにちは、広野です。
社内研修開催のため、研修期間の数日だけ受講者とのコミュニケーションに使用する使い捨てチャットサーバを Rocket.Chat を使って構築しました。AWS CloudFormation テンプレート化してあるので、前日にサクッと作って、終わったらサクッと捨てる、そんな用途に最適です。
Rocket.Chat 公式インストール手順
Rocket.Chat インストール手順は Ubuntu であれば簡単すぎて衝撃でした。EC2 の userdata に仕込んでいます。
前提とか
- VPC や マルチ AZ のパブリックサブネット、プライベートサブネット、インターネットゲートウェイは構築済み
- 独自ドメインが Route 53 ホストゾーンに登録済み
- SSL 証明書は構築するリージョンの AWS Certificate Manager で作成済み
- OS は Ubuntu 22.04 とする( Rocket.Chat は snap install でインストールする)
- EC2 への SSH アクセスは SSM とするため、セキュリティグループには 22 ポートを開けていない。が、一応キーペアも関連付けておく(キーペア作成済みであること)
- SSM セッションマネージャでの操作ログを Amazon S3 バケットに吐き出す場合、EC2 の IAM ロールに吐き出し先バケットへの put 権限を追加すること
- 完成すると、AWS CloudFormation テンプレートのパラメータで指定したドメイン名の URL で、Rocket.Chat サーバが起動した状態で立ち上がる(初期画面で、管理者ユーザの登録画面が表示されている状態)
- IPv6 非対応
アーキテクチャ

- EC2 インスタンスはプライベートサブネットに配置。シングル構成。
- ALB は SSL アクセラレータとしての意味しかない。
- Rocket.Chat は HTTP 3000 番ポートでリッスンしているので、ALB からはそこにアクセスするよう設定する。
- 図には書いていないが、Route 53 で ALB をエイリアスレコードに紐づける。
- 図には書いていないが、ALB に AWS Certificate Manager の SSL 証明書を紐づける。
AWS CloudFormation テンプレート
適宜、IAM ロールやセキュリティーグループなどは要件に応じて変更してください。ドメイン関連も不要であれば削除で。
東京リージョン Ubuntu 22.04 AMI の Image ID をベタにパラメータのデフォルト値に書いているので、適宜変更してください。
AWSTemplateFormatVersion: "2010-09-09"
Description: The CloudFormation template that creates an EC2 instance, an ALB and a DNS record in Route 53 for Rocket.Chat.
# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
Parameters:
SystemName:
Type: String
Description: System name. (e.g. EXAMPLE)
Default: EXAMPLE
MaxLength: 10
MinLength: 1
GroupName:
Type: String
Description: Group name. (e.g. RocketChat)
Default: RocketChat
MaxLength: 30
MinLength: 1
HostName:
Type: String
Description: Host name. (e.g. ROCKETCHAT)
Default: ROCKETCHAT
MaxLength: 30
MinLength: 1
VpcId:
Type: AWS::EC2::VPC::Id
Description: Choose a existing VPC ID you deploy the EC2 instance in.
InstanceSubnet:
Type: AWS::EC2::Subnet::Id
Description: Choose an existing Private Subnet ID you deploy the EC2 instance in.
AlbSubnet1:
Type: AWS::EC2::Subnet::Id
Description: Choose an existing Public Subnet ID you deploy the Application Load Balancer in.
AlbSubnet2:
Type: AWS::EC2::Subnet::Id
Description: Choose an existing Public Subnet ID you deploy the Application Load Balancer in.
ImageID:
Type: String
Description: OS AMI Image ID (Ubuntu)
Default: ami-03f4fa076d2981b45
MaxLength: 100
MinLength: 1
InstanceType:
Type: String
Default: t3.small
KeyPairName:
Type: AWS::EC2::KeyPair::KeyName
Description: Choose a existing key pair you associate with the EC2.
DomainName:
Type: String
Description: Domain name for URL. xxxxx.xxx (e.g. example.com)
Default: example.com
MaxLength: 40
MinLength: 5
SubDomainName:
Type: String
Description: Sub domain name for URL. xxxxx.example.com
Default: chat
MaxLength: 20
MinLength: 1
CertificateArn:
Type: String
Description: ACM certificate ARN.
Default: "arn:aws:acm:ap-northeast-1:xxxxxxxxxx:certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
MaxLength: 128
MinLength: 10
Resources:
# ------------------------------------------------------------#
# EC2
# ------------------------------------------------------------#
Ec2Instance:
Type: AWS::EC2::Instance
Properties:
IamInstanceProfile: !Ref Ec2InstanceProfile
ImageId: !Ref ImageID
KeyName: !Ref KeyPairName
InstanceType: !Ref InstanceType
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeType: gp2
VolumeSize: 40
SecurityGroupIds:
- !Ref Ec2SecurityGroup
SourceDestCheck: false
SubnetId: !Ref InstanceSubnet
Tags:
- Key: Cost
Value: !Ref SystemName
- Key: Name
Value: !Sub ${SystemName}-${HostName}
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
snap install rocketchat-server
systemctl status snap.rocketchat-server.rocketchat-server.service
systemctl status snap.rocketchat-server.rocketchat-mongo.service
DependsOn:
- Ec2SecurityGroup
- Ec2InstanceProfile
# ------------------------------------------------------------#
# EC2 Security Group
# ------------------------------------------------------------#
Ec2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VpcId
GroupDescription: Allow web access via port TCP 3000.
SecurityGroupIngress:
- SourceSecurityGroupId: !GetAtt AlbSecurityGroup.GroupId
FromPort: 3000
IpProtocol: tcp
ToPort: 3000
Tags:
- Key: Cost
Value: !Ref SystemName
- Key: Name
Value: !Sub SG-${SystemName}-${GroupName}
DependsOn:
- AlbSecurityGroup
# ------------------------------------------------------------#
# EC2 Role / Instance Profile (IAM)
# ------------------------------------------------------------#
Ec2Role:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub Ec2Role-${SystemName}-${GroupName}
Description: This role allows EC2 instance to invoke SSM.
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Policies:
- PolicyName: !Sub Ec2S3Policy-${SystemName}-${GroupName}
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- "s3:GetEncryptionConfiguration"
- "kms:Decrypt"
- "kms:GenerateDataKey"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "logs:DescribeLogGroups"
- "logs:DescribeLogStreams"
Resource: "*"
Effect: Allow
Ec2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
InstanceProfileName: !Ref Ec2Role
Path: /
Roles:
- !Ref Ec2Role
DependsOn:
- Ec2Role
# ------------------------------------------------------------#
# ALB
# ------------------------------------------------------------#
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub ${SystemName}-${GroupName}
Type: application
IpAddressType: ipv4
LoadBalancerAttributes:
- Key: deletion_protection.enabled
Value: false
- Key: access_logs.s3.enabled
Value: false
- Key: idle_timeout.timeout_seconds
Value: 60
- Key: routing.http.desync_mitigation_mode
Value: defensive
- Key: routing.http.drop_invalid_header_fields.enabled
Value: true
- Key: routing.http.preserve_host_header.enabled
Value: false
- Key: routing.http.x_amzn_tls_version_and_cipher_suite.enabled
Value: false
- Key: routing.http.xff_client_port.enabled
Value: false
- Key: routing.http.xff_header_processing.mode
Value: append
- Key: routing.http2.enabled
Value: true
- Key: waf.fail_open.enabled
Value: false
Scheme: internet-facing
SecurityGroups:
- !GetAtt AlbSecurityGroup.GroupId
Subnets:
- !Ref AlbSubnet1
- !Ref AlbSubnet2
Tags:
- Key: Cost
Value: !Ref SystemName
- Key: Name
Value: !Sub ${SystemName}-${GroupName}
DependsOn:
- AlbSecurityGroup
AlbListenerHttps:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
Certificates:
- CertificateArn: !Ref CertificateArn
DefaultActions:
- TargetGroupArn: !Ref AlbListenerHttpsTargetgroup
Type: forward
LoadBalancerArn: !Ref ApplicationLoadBalancer
Port: 443
Protocol: HTTPS
SslPolicy: ELBSecurityPolicy-2016-08
DependsOn:
- ApplicationLoadBalancer
AlbListenerHttpsTargetgroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub TG-${SystemName}-${GroupName}
TargetType: instance
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPath: /
HealthCheckPort: traffic-port
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 5
IpAddressType: ipv4
Matcher:
HttpCode: 200
Port: 3000
Protocol: HTTP
ProtocolVersion: HTTP1
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: 300
- Key: stickiness.enabled
Value: false
- Key: load_balancing.algorithm.type
Value: round_robin
- Key: slow_start.duration_seconds
Value: 0
- Key: stickiness.app_cookie.cookie_name
Value: APPCOOKIE
- Key: stickiness.app_cookie.duration_seconds
Value: 86400
- Key: stickiness.lb_cookie.duration_seconds
Value: 86400
Targets:
- Id: !Ref Ec2Instance
Port: 3000
UnhealthyThresholdCount: 2
VpcId: !Ref VpcId
Tags:
- Key: Cost
Value: !Ref SystemName
DependsOn:
- Ec2Instance
# ------------------------------------------------------------#
# ALB Security Group
# ------------------------------------------------------------#
AlbSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VpcId
GroupDescription: Allow access via HTTPS.
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
FromPort: 443
IpProtocol: tcp
ToPort: 443
Tags:
- Key: Cost
Value: !Ref SystemName
- Key: Name
Value: !Sub SG-${SystemName}-${GroupName}-ALB
# ------------------------------------------------------------#
# Route 53
# ------------------------------------------------------------#
Route53RecordA:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneName: !Sub ${DomainName}.
Name: !Sub ${SubDomainName}.${DomainName}.
Type: A
AliasTarget:
HostedZoneId: !GetAtt ApplicationLoadBalancer.CanonicalHostedZoneID
DNSName: !GetAtt ApplicationLoadBalancer.DNSName
DependsOn: ApplicationLoadBalancer
# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
# Server URL
RocketChatUrl:
Value: !Sub https://${SubDomainName}.${DomainName}
Rocket.Chat バージョン 4 をインストールするには
上記テンプレート内、UserData の部分を修正します。
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
snap install rocketchat-server --channel=4.x/stable
systemctl status snap.rocketchat-server.rocketchat-server.service
systemctl status snap.rocketchat-server.rocketchat-mongo.service
snap install のコマンドに、メジャーバージョンを指定してインストールします。
まとめ
いかがでしたでしょうか?
研修用途、一時利用の環境なので構成がかなりテキトーですが、起動した状態にまでサクっと作れるのが売りです。CloudFormation での ALB の記述方法の参考にもなるかもです。
本記事が皆様のお役に立てれば幸いです。
