Merge branch 'stable-3.1'

* stable-3.1:
  Don't wait for the slave to be ready to create master
  Reindex when spinning up second master
  Set Gerrit to 3.1.5
  Add Gerrit slave to dual-master recipe
  Fixed init phase in entrypoint script
  Publish images when creating whole stack
  Only define cookiedomain if defined

Change-Id: I5b327f53914280c42ec32850e9f4bd5ad3c4dd6f
diff --git a/dual-master/Makefile b/dual-master/Makefile
index 038eb70..6c0280a 100644
--- a/dual-master/Makefile
+++ b/dual-master/Makefile
@@ -3,19 +3,22 @@
 
 CLUSTER_TEMPLATE:=cf-cluster.yml
 SERVICE_MASTER_TEMPLATE:=cf-service-master.yml
+SERVICE_SLAVE_TEMPLATE:=cf-service-slave.yml
 DNS_ROUTING_TEMPLATE:=cf-dns-route.yml
 LOAD_BALANCER_TEMPLATE:=cf-service-lb.yml
 AWS_FC_COMMAND=export AWS_PAGER=;aws cloudformation
 
 .PHONY: create-all delete-all \
-				cluster cluster-keys service-master-1 dns-routing \
-				wait-for-cluster-creation wait-for-service-master-1-creation wait-for-service-master-2-creation wait-for-dns-routing-creation \
-				wait-for-cluster-deletion wait-for-service-master-1-deletion wait-for-service-master-2-deletion wait-for-dns-routing-deletion \
+				cluster cluster-keys service-master-1 service-master-2 service-slave dns-routing \
+				wait-for-cluster-creation wait-for-service-master-1-creation wait-for-service-master-2-creation wait-for-service-slave-creation wait-for-dns-routing-creation \
+				wait-for-cluster-deletion wait-for-service-master-1-deletion wait-for-service-master-2-deletion wait-for-service-slave-deletion wait-for-dns-routing-deletion \
 				service-lb wait-for-service-lb-deletion wait-for-service-lb-creation \
 				gerrit-build gerrit-publish haproxy-publish syslog-sidecar-publish
 
-create-all: cluster wait-for-cluster-creation \
-						service-master-1 wait-for-service-master-1-creation \
+create-all: gerrit-publish haproxy-publish syslog-sidecar-publish \
+						cluster wait-for-cluster-creation \
+						service-slave service-master-1 \
+						wait-for-service-master-1-creation wait-for-service-slave-creation \
 						service-master-2 wait-for-service-master-2-creation \
 						service-lb wait-for-service-lb-creation \
 						dns-routing wait-for-dns-routing-creation
@@ -28,7 +31,8 @@
 		--region $(AWS_REGION) \
 		--parameters \
 		ParameterKey=DesiredCapacity,ParameterValue=$(CLUSTER_DESIRED_CAPACITY) \
-		ParameterKey=ECSKeyName,ParameterValue=$(CLUSTER_KEYS)
+		ParameterKey=ECSKeyName,ParameterValue=$(CLUSTER_KEYS) \
+		ParameterKey=InstanceType,ParameterValue=$(CLUSTER_INSTANCE_TYPE)
 
 service-master-1:
 	$(AWS_FC_COMMAND) create-stack \
@@ -52,7 +56,9 @@
 		ParameterKey=GerritDbVolume,ParameterValue=gerrit-db-master-1 \
 		ParameterKey=GerritLogsVolume,ParameterValue=gerrit-logs-master1 \
 		ParameterKey=PeerSubdomain,ParameterValue=$(MASTER2_SUBDOMAIN) \
-		ParameterKey=LBSubdomain,ParameterValue=$(LB_SUBDOMAIN)
+		ParameterKey=LBSubdomain,ParameterValue=$(LB_SUBDOMAIN) \
+		ParameterKey=SlaveServiceStackName,ParameterValue=$(SERVICE_SLAVE_STACK_NAME)
+
 
 service-master-2:
 	$(AWS_FC_COMMAND) create-stack \
@@ -76,7 +82,24 @@
 		ParameterKey=GerritDbVolume,ParameterValue=gerrit-db-master-2 \
 		ParameterKey=GerritLogsVolume,ParameterValue=gerrit-logs-master-2 \
 		ParameterKey=PeerSubdomain,ParameterValue=$(MASTER1_SUBDOMAIN) \
-		ParameterKey=LBSubdomain,ParameterValue=$(LB_SUBDOMAIN)
+		ParameterKey=LBSubdomain,ParameterValue=$(LB_SUBDOMAIN) \
+		ParameterKey=SlaveServiceStackName,ParameterValue=$(SERVICE_SLAVE_STACK_NAME) \
+		ParameterKey=ReindexAtSartup,ParameterValue=true
+
+service-slave:
+	$(AWS_FC_COMMAND) create-stack \
+		--stack-name $(SERVICE_SLAVE_STACK_NAME) \
+		--capabilities CAPABILITY_IAM  \
+		--template-body file://`pwd`/$(SERVICE_SLAVE_TEMPLATE) \
+		--region $(AWS_REGION) \
+		--parameters \
+		ParameterKey=ClusterStackName,ParameterValue=$(CLUSTER_STACK_NAME) \
+		ParameterKey=HostedZoneName,ParameterValue=$(HOSTED_ZONE_NAME) \
+		ParameterKey=Subdomain,ParameterValue=$(SLAVE_SUBDOMAIN) \
+		ParameterKey=DockerRegistryUrl,ParameterValue=$(DOCKER_REGISTRY_URI) \
+		ParameterKey=CertificateArn,ParameterValue=$(SSL_CERTIFICATE_ARN) \
+		ParameterKey=GerritKeyPrefix,ParameterValue=$(GERRIT_KEY_PREFIX)\
+		ParameterKey=GerritDockerImage,ParameterValue=aws-gerrit/gerrit:$(IMAGE_TAG)
 
 service-lb:
 	$(AWS_FC_COMMAND) create-stack \
@@ -128,6 +151,13 @@
 	--region $(AWS_REGION)
 	@echo "*** Service stack '$(SERVICE_MASTER2_STACK_NAME)' created"
 
+wait-for-service-slave-creation:
+	@echo "*** Wait for service slave stack '$(SERVICE_SLAVE_STACK_NAME)' creation"
+	$(AWS_FC_COMMAND) wait stack-create-complete \
+	--stack-name $(SERVICE_SLAVE_STACK_NAME) \
+	--region $(AWS_REGION)
+	@echo "*** Service stack '$(SERVICE_SLAVE_STACK_NAME)' created"
+
 wait-for-service-lb-creation:
 	@echo "*** Wait for service lb stack '$(LOAD_BALANCER_STACK_NAME)' creation"
 	$(AWS_FC_COMMAND) wait stack-create-complete \
@@ -163,6 +193,13 @@
 	--region $(AWS_REGION)
 	@echo "*** Service stack master '$(SERVICE_MASTER2_STACK_NAME)' deleted"
 
+wait-for-service-slave-deletion:
+	@echo "*** Wait for service slave stack '$(SERVICE_SLAVE_STACK_NAME)' deletion"
+	$(AWS_FC_COMMAND) wait stack-delete-complete \
+	--stack-name $(SERVICE_SLAVE_STACK_NAME) \
+	--region $(AWS_REGION)
+	@echo "*** Service stack slave '$(SERVICE_SLAVE_STACK_NAME)' deleted"
+
 wait-for-service-lb-deletion:
 	@echo "*** Wait for service lb stack '$(LOAD_BALANCER_STACK_NAME)' deletion"
 	$(AWS_FC_COMMAND) wait stack-delete-complete \
@@ -192,6 +229,11 @@
 	--stack-name $(SERVICE_MASTER2_STACK_NAME) \
 	--region $(AWS_REGION)
 
+delete-service-slave:
+	$(AWS_FC_COMMAND) delete-stack \
+	--stack-name $(SERVICE_SLAVE_STACK_NAME) \
+	--region $(AWS_REGION)
+
 delete-service-lb:
 	$(AWS_FC_COMMAND) delete-stack \
 	--stack-name $(LOAD_BALANCER_STACK_NAME) \
@@ -204,8 +246,8 @@
 
 delete-all: delete-dns-routing wait-for-dns-routing-deletion \
 						delete-service-lb wait-for-service-lb-deletion \
-						delete-service-master-1 wait-for-service-master-1-deletion \
-						delete-service-master-2 wait-for-service-master-2-deletion \
+						delete-service-master-1 delete-service-master-2 delete-service-slave \
+						wait-for-service-master-1-deletion wait-for-service-master-2-deletion wait-for-service-slave-deletion \
 						delete-cluster wait-for-cluster-deletion
 
 gerrit-publish:
@@ -216,3 +258,9 @@
 
 syslog-sidecar-publish:
 	$(MAKE) -C syslog-sidecar syslog-sidecar-publish
+
+git-daemon-publish:
+	$(MAKE) -C ../master-slave/git-daemon git-daemon-publish
+
+git-ssh-publish:
+	$(MAKE) -C ../master-slave/git-ssh git-ssh-publish
diff --git a/dual-master/cf-cluster.yml b/dual-master/cf-cluster.yml
index 4197929..011a2f5 100644
--- a/dual-master/cf-cluster.yml
+++ b/dual-master/cf-cluster.yml
@@ -177,6 +177,11 @@
                 {\"files\":
                   {\"collect_list\":
                     [
+                      {\"file_path\": \"/var/lib/docker/volumes/gerrit-logs-master-2/_data/replication_log\",
+                      \"log_group_name\": \"${AWS::StackName}\",
+                      \"log_stream_name\": \"${EnvironmentName}/{instance_id}/master-2/replication_log\",
+                      \"timezone\": \"UTC\"
+                      },
                       {\"file_path\": \"/var/lib/docker/volumes/gerrit-logs-master-2/_data/httpd_log\",
                       \"log_group_name\": \"${AWS::StackName}\",
                       \"log_stream_name\": \"${EnvironmentName}/{instance_id}/master-2/httpd_log\",
diff --git a/dual-master/cf-service-master.yml b/dual-master/cf-service-master.yml
index 42ea576..2089e8d 100644
--- a/dual-master/cf-service-master.yml
+++ b/dual-master/cf-service-master.yml
@@ -101,6 +101,10 @@
       Description: Gerrit logs volume name
       Type: String
       Default: gerrit-logs-master
+  ReindexAtSartup:
+      Description: Force index reindexing at startup
+      Type: String
+      Default: false
 
 Resources:
     Service:
@@ -141,7 +145,7 @@
                     - Name: AWS_REGION
                       Value: !Ref AWS::Region
                     - Name: SETUP_REPLICATION
-                      Value: false
+                      Value: true
                     - Name: GERRIT_KEY_PREFIX
                       Value: !Ref GerritKeyPrefix
                     - Name: SETUP_HA
@@ -150,6 +154,8 @@
                       Value: !Sub 'http://${PeerSubdomain}.${HostedZoneName}:${HTTPGerritLBPort}'
                     - Name: HOSTED_ZONE_NAME
                       Value: !Ref HostedZoneName
+                    - Name: REINDEX_AT_STARTUP
+                      Value: !Ref ReindexAtSartup
                   MountPoints:
                     - SourceVolume: !Ref GerritGitVolume
                       ContainerPath: /var/gerrit/git
diff --git a/dual-master/cf-service-slave.yml b/dual-master/cf-service-slave.yml
new file mode 100644
index 0000000..7415836
--- /dev/null
+++ b/dual-master/cf-service-slave.yml
@@ -0,0 +1,469 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Description: Deploy a service into an ECS cluster behind a public load balancer.
+Parameters:
+  GerritServiceName:
+      Type: String
+      Default: gerrit-slave
+  GitDaemonServiceName:
+      Type: String
+      Default: gerrit-git-daemon
+  GitSSHServiceName:
+      Type: String
+      Default: gerrit-git-ssh
+  ClusterStackName:
+      Description: Stack name of the ECS cluster to deply the serivces
+      Type: String
+      Default: gerrit-cluster
+  EnvironmentName:
+      Description: An environment name used to build the log stream names
+      Type: String
+      Default: test
+  GerritDockerImage:
+      Description: Gerrit official Docker image
+      Type: String
+      Default: aws-gerrit/gerrit:latest
+  GitDaemonDockerImage:
+      Description: Git daemon Docker image
+      Type: String
+      Default: aws-gerrit/git-daemon:latest
+  GitSSHDockerImage:
+      Description: Git SSH Docker image
+      Type: String
+      Default: aws-gerrit/git-ssh:latest
+  DockerRegistryUrl:
+      Description: Docker registry URL
+      Type: String
+  DesiredCount:
+      Description: How many instances of this task should we run across our cluster?
+      Type: Number
+      Default: 1
+  HTTPHostPort:
+      Description: Gerrit Host HTTP port
+      Type: Number
+      Default: 9080
+  HTTPContainePort:
+      Description: Gerrit Container HTTP port
+      Type: Number
+      Default: 8080
+  HTTPSPort:
+      Description: Gerrit HTTPS port
+      Type: Number
+      Default: 443
+  SSHHostPort:
+      Description: Gerrit SSH port
+      Type: Number
+      Default: 39418
+  SSHContainerPort:
+      Description: Gerrit SSH port
+      Type: Number
+      Default: 29418
+  GitPort:
+      Description: Git daemon port
+      Type: Number
+      Default: 9418
+  GitSSHPort:
+      Description: Git ssh port
+      Type: Number
+      Default: 1022
+  GitSSHContainerPort:
+      Description: Git ssh port
+      Type: Number
+      Default: 22
+  CertificateArn:
+      Description: SSL Certificates ARN
+      Type: String
+  HostedZoneName:
+      Description: The route53 HostedZoneName.
+      Type: String
+  Subdomain:
+      Description: The subdomain of the Gerrit cluster
+      Type: String
+      Default: gerrit-slave-demo
+  GerritGitVolume:
+      Description: Gerrit git volume name
+      Type: String
+      Default: gerrit-git-slave
+  GerritDataVolume:
+      Description: Gerrit data volume name
+      Type: String
+      Default: gerrit-data-slave
+  GerritCacheVolume:
+      Description: Gerrit cache volume name
+      Type: String
+      Default: gerrit-cache-slave
+  GerritDbVolume:
+      Description: Gerrit db volume name
+      Type: String
+      Default: gerrit-db-slave
+  GerritLogsVolume:
+      Description: Gerrit logs volume name
+      Type: String
+      Default: gerrit-logs-slave
+  GerritKeyPrefix:
+      Description: Gerrit credentials keys prefix
+      Type: String
+
+Resources:
+    GerritService:
+        Type: AWS::ECS::Service
+        DependsOn:
+          - HTTPListener
+          - SSHListener
+        Properties:
+            Cluster:
+              Fn::ImportValue:
+                  !Join [':', [!Ref 'ClusterStackName', 'ClusterName']]
+            DesiredCount: !Ref DesiredCount
+            TaskDefinition: !Ref GerritTaskDefinition
+            LoadBalancers:
+                - ContainerName: !Ref GerritServiceName
+                  ContainerPort: !Ref HTTPContainePort
+                  TargetGroupArn: !Ref HTTPTargetGroup
+                - ContainerName: !Ref GerritServiceName
+                  ContainerPort: !Ref SSHContainerPort
+                  TargetGroupArn: !Ref SSHTargetGroup
+
+    GerritReplicationService:
+        Type: AWS::ECS::Service
+        DependsOn:
+          - GitListener
+          - GitSSHListener
+        Properties:
+            Cluster:
+              Fn::ImportValue:
+                  !Join [':', [!Ref 'ClusterStackName', 'ClusterName']]
+            DesiredCount: !Ref DesiredCount
+            TaskDefinition: !Ref GerritReplicationTaskDefinition
+            LoadBalancers:
+                - ContainerName: !Ref GitDaemonServiceName
+                  ContainerPort: !Ref GitPort
+                  TargetGroupArn: !Ref GitTargetGroup
+                - ContainerName: !Ref GitSSHServiceName
+                  ContainerPort: !Ref GitSSHContainerPort
+                  TargetGroupArn: !Ref GitSSHTargetGroup
+
+    GerritTaskDefinition:
+        Type: AWS::ECS::TaskDefinition
+        Properties:
+            Family: !Join ['', [!Ref GerritServiceName, TaskDefinition]]
+            TaskRoleArn: !Ref ECSTaskExecutionRole
+            ExecutionRoleArn: !Ref ECSTaskExecutionRole
+            NetworkMode: bridge
+            ContainerDefinitions:
+                - Name: !Ref GerritServiceName
+                  Essential: true
+                  Image: !Sub '${DockerRegistryUrl}/${GerritDockerImage}'
+                  Environment:
+                    - Name: CANONICAL_WEB_URL
+                      Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+                    - Name: HTTPD_LISTEN_URL
+                      Value: !Sub 'proxy-https://*:${HTTPContainePort}/'
+                    - Name: CONTAINER_SLAVE
+                      Value: true
+                    - Name: GERRIT_KEY_PREFIX
+                      Value: !Ref GerritKeyPrefix
+                    - Name: AWS_REGION
+                      Value: !Ref AWS::Region
+                  MountPoints:
+                    - SourceVolume: !Ref GerritGitVolume
+                      ContainerPath: /var/gerrit/git
+                    - SourceVolume: !Ref GerritDataVolume
+                      ContainerPath: /var/gerrit/data
+                    - SourceVolume: !Ref GerritCacheVolume
+                      ContainerPath: /var/gerrit/cache
+                    - SourceVolume: !Ref GerritDbVolume
+                      ContainerPath: /var/gerrit/db
+                    - SourceVolume: !Ref GerritLogsVolume
+                      ContainerPath: /var/gerrit/logs
+                  Cpu: 1024
+                  Memory: 2048
+                  PortMappings:
+                    - ContainerPort: !Ref HTTPContainePort
+                      HostPort: !Ref HTTPHostPort
+                      Protocol: tcp
+                    - ContainerPort: !Ref SSHContainerPort
+                      HostPort: !Ref SSHHostPort
+                      Protocol: tcp
+                  LogConfiguration:
+                    LogDriver: awslogs
+                    Options:
+                        awslogs-group: !Ref ClusterStackName
+                        awslogs-region: !Ref AWS::Region
+                        awslogs-stream-prefix: !Ref EnvironmentName
+            Volumes:
+              - Name: !Ref 'GerritDbVolume'
+                DockerVolumeConfiguration:
+                  Scope: shared
+                  Autoprovision: true
+                  Driver: local
+                  Labels:
+                    gerrit-db: !Join ['-', [!Ref EnvironmentName, !Ref GerritDbVolume]]
+              - Name: !Ref 'GerritGitVolume'
+                DockerVolumeConfiguration:
+                  Scope: shared
+                  Autoprovision: true
+                  Driver: local
+                  Labels:
+                    gerrit-git: !Join ['-', [!Ref EnvironmentName, !Ref GerritGitVolume]]
+              - Name: !Ref 'GerritDataVolume'
+                DockerVolumeConfiguration:
+                  Scope: shared
+                  Autoprovision: true
+                  Driver: local
+                  Labels:
+                    gerrit-data: !Join ['-', [!Ref EnvironmentName, !Ref GerritDataVolume]]
+              - Name: !Ref 'GerritCacheVolume'
+                DockerVolumeConfiguration:
+                  Scope: shared
+                  Autoprovision: true
+                  Driver: local
+                  Labels:
+                    gerrit-cache: !Join ['-', [!Ref EnvironmentName, !Ref GerritCacheVolume]]
+              - Name: !Ref 'GerritLogsVolume'
+                DockerVolumeConfiguration:
+                  Scope: shared
+                  Autoprovision: true
+                  Driver: local
+                  Labels:
+                    gerrit-logs: !Join ['-', [!Ref EnvironmentName, !Ref GerritLogsVolume]]
+
+    GerritReplicationTaskDefinition:
+        Type: AWS::ECS::TaskDefinition
+        Properties:
+            Family: !Join ['', [!Ref GerritServiceName, TaskDefinition]]
+            TaskRoleArn: !Ref ECSTaskExecutionRole
+            ExecutionRoleArn: !Ref ECSTaskExecutionRole
+            NetworkMode: bridge
+            ContainerDefinitions:
+                - Name: !Ref GitDaemonServiceName
+                  Essential: true
+                  Image: !Sub '${DockerRegistryUrl}/${GitDaemonDockerImage}'
+                  MountPoints:
+                    - SourceVolume: !Ref GerritGitVolume
+                      ContainerPath: /var/gerrit/git
+                  Cpu: 256
+                  Memory: 512
+                  PortMappings:
+                    - ContainerPort: !Ref GitPort
+                      HostPort: !Ref GitPort
+                      Protocol: tcp
+                  LogConfiguration:
+                    LogDriver: awslogs
+                    Options:
+                        awslogs-group: !Ref ClusterStackName
+                        awslogs-region: !Ref AWS::Region
+                        awslogs-stream-prefix: !Ref EnvironmentName
+                - Name: !Ref GitSSHServiceName
+                  Essential: true
+                  Image: !Sub '${DockerRegistryUrl}/${GitSSHDockerImage}'
+                  Environment:
+                    - Name: TZ
+                      Value: US/Pacific
+                    - Name: SSH_USERS
+                      Value: gerrit:1000:1000
+                    - Name: AWS_REGION
+                      Value: !Ref AWS::Region
+                    - Name: GERRIT_KEY_PREFIX
+                      Value: !Ref GerritKeyPrefix
+                  MountPoints:
+                    - SourceVolume: !Ref GerritGitVolume
+                      ContainerPath: /var/gerrit/git
+                  Cpu: 256
+                  Memory: 512
+                  PortMappings:
+                    - ContainerPort: !Ref GitSSHContainerPort
+                      HostPort: !Ref GitSSHPort
+                      Protocol: tcp
+                  LogConfiguration:
+                    LogDriver: awslogs
+                    Options:
+                        awslogs-group: !Ref ClusterStackName
+                        awslogs-region: !Ref AWS::Region
+                        awslogs-stream-prefix: !Ref EnvironmentName
+            Volumes:
+              - Name: !Ref 'GerritGitVolume'
+                DockerVolumeConfiguration:
+                  Scope: shared
+                  Autoprovision: true
+                  Driver: local
+                  Labels:
+                    gerrit-git: !Join ['-', [!Ref EnvironmentName, !Ref GerritGitVolume]]
+
+    LoadBalancer:
+        Type: AWS::ElasticLoadBalancingV2::LoadBalancer
+        Properties:
+            Type: network
+            Scheme: internet-facing
+            Subnets:
+              - Fn::ImportValue:
+                  !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetOne']]
+            Tags:
+                - Key: Name
+                  Value: !Join ['-', [!Ref 'EnvironmentName', !Ref 'GerritServiceName', 'nlb']]
+
+    HTTPTargetGroup:
+        Type: AWS::ElasticLoadBalancingV2::TargetGroup
+        DependsOn: LoadBalancer
+        Properties:
+            VpcId:
+              Fn::ImportValue:
+                  !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+            Port: !Ref HTTPHostPort
+            Protocol: TCP
+            HealthCheckPort: !Ref HTTPContainePort
+
+    HTTPListener:
+        Type: AWS::ElasticLoadBalancingV2::Listener
+        DependsOn: LoadBalancer
+        Properties:
+            Certificates:
+              - CertificateArn: !Ref CertificateArn
+            DefaultActions:
+            - Type: forward
+              TargetGroupArn: !Ref HTTPTargetGroup
+            LoadBalancerArn: !Ref LoadBalancer
+            Port: !Ref HTTPSPort
+            Protocol: TLS
+
+    SSHTargetGroup:
+        Type: AWS::ElasticLoadBalancingV2::TargetGroup
+        DependsOn: LoadBalancer
+        Properties:
+            VpcId:
+              Fn::ImportValue:
+                  !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+            Port: !Ref SSHHostPort
+            Protocol: TCP
+            HealthCheckPort: !Ref SSHContainerPort
+
+    SSHListener:
+        Type: AWS::ElasticLoadBalancingV2::Listener
+        DependsOn: LoadBalancer
+        Properties:
+            DefaultActions:
+            - Type: forward
+              TargetGroupArn: !Ref SSHTargetGroup
+            LoadBalancerArn: !Ref LoadBalancer
+            Port: !Ref SSHHostPort
+            Protocol: TCP
+
+    GitTargetGroup:
+        Type: AWS::ElasticLoadBalancingV2::TargetGroup
+        DependsOn: LoadBalancer
+        Properties:
+            VpcId:
+              Fn::ImportValue:
+                  !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+            Port: !Ref GitPort
+            Protocol: TCP
+
+    GitListener:
+        Type: AWS::ElasticLoadBalancingV2::Listener
+        DependsOn: LoadBalancer
+        Properties:
+            DefaultActions:
+            - Type: forward
+              TargetGroupArn: !Ref GitTargetGroup
+            LoadBalancerArn: !Ref LoadBalancer
+            Port: !Ref GitPort
+            Protocol: TCP
+
+    GitSSHTargetGroup:
+        Type: AWS::ElasticLoadBalancingV2::TargetGroup
+        DependsOn: LoadBalancer
+        Properties:
+            VpcId:
+              Fn::ImportValue:
+                  !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+            Port: !Ref GitSSHPort
+            Protocol: TCP
+
+    GitSSHListener:
+        Type: AWS::ElasticLoadBalancingV2::Listener
+        DependsOn: LoadBalancer
+        Properties:
+            DefaultActions:
+            - Type: forward
+              TargetGroupArn: !Ref GitSSHTargetGroup
+            LoadBalancerArn: !Ref LoadBalancer
+            Port: !Ref GitSSHPort
+            Protocol: TCP
+
+    SlaveDnsRecord:
+        Type: AWS::Route53::RecordSet
+        Properties:
+          Name: !Sub '${Subdomain}.${HostedZoneName}'
+          HostedZoneName: !Sub '${HostedZoneName}.'
+          Comment: DNS name for Gerrit Slave.
+          Type: A
+          AliasTarget:
+            DNSName: !GetAtt 'LoadBalancer.DNSName'
+            HostedZoneId: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
+            EvaluateTargetHealth: False
+
+    # This is a role which is used by the ECS tasks themselves.
+    ECSTaskExecutionRole:
+      Type: AWS::IAM::Role
+      Properties:
+        AssumeRolePolicyDocument:
+          Statement:
+          - Effect: Allow
+            Principal:
+              Service: [ecs-tasks.amazonaws.com]
+            Action: ['sts:AssumeRole']
+        Path: /
+        Policies:
+          - PolicyName: AmazonECSTaskExecutionRolePolicy
+            PolicyDocument:
+              Statement:
+              - Effect: Allow
+                Action:
+                  # Allow the ECS Tasks to download images from ECR
+                  - 'ecr:GetAuthorizationToken'
+                  - 'ecr:BatchCheckLayerAvailability'
+                  - 'ecr:GetDownloadUrlForLayer'
+                  - 'ecr:BatchGetImage'
+                  # Allow the ECS tasks to upload logs to CloudWatch
+                  - 'logs:CreateLogStream'
+                  - 'logs:PutLogEvents'
+                Resource: '*'
+          - PolicyName: AmazonECSTaskSecretManagerRolePolicy
+            PolicyDocument:
+              Statement:
+              - Effect: Allow
+                Action:
+                  # Allow the ECS Tasks to get SSH Keys
+                  - 'secretsmanager:GetSecretValue'
+                  - 'kms:Decrypt'
+                Resource: '*'
+Outputs:
+  PublicLoadBalancerDNSName:
+    Description: The DNS name of the external load balancer
+    Value: !GetAtt 'LoadBalancer.DNSName'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerDNSName' ] ]
+  CanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID
+    Value: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalHostedZoneID' ] ]
+  PublicLoadBalancerUrl:
+    Description: The url of the external load balancer
+    Value: !Join ['', ['http://', !GetAtt 'LoadBalancer.DNSName']]
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerUrl' ] ]
+  HostedZoneName:
+    Description: Route53 Hosted Zone name
+    Value: !Ref HostedZoneName
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HostedZoneName' ] ]
+  Subdomain:
+    Description: Service DNS subdomain
+    Value: !Ref Subdomain
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'Subdomain' ] ]
+  CanonicalWebUrl:
+    Description: Canonical Web URL
+    Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalWebUrl' ] ]
diff --git a/dual-master/setup.env.template b/dual-master/setup.env.template
index 6858912..b299707 100644
--- a/dual-master/setup.env.template
+++ b/dual-master/setup.env.template
@@ -1,7 +1,9 @@
 CLUSTER_STACK_NAME:=$(AWS_PREFIX)-cluster
-CLUSTER_DESIRED_CAPACITY:=1
+CLUSTER_DESIRED_CAPACITY:=3
+CLUSTER_INSTANCE_TYPE:=m4.2xlarge
 SERVICE_MASTER1_STACK_NAME:=$(AWS_PREFIX)-service-master-1
 SERVICE_MASTER2_STACK_NAME:=$(AWS_PREFIX)-service-master-2
+SERVICE_SLAVE_STACK_NAME:=$(AWS_PREFIX)-service-slave
 HTTP_HOST_PORT_MASTER2:=8081
 SSH_HOST_PORT_MASTER2:=29419
 HTTP_HOST_PORT_MASTER1:=8080
@@ -10,6 +12,7 @@
 HOSTED_ZONE_NAME:=yourcompany.com
 MASTER1_SUBDOMAIN:=$(AWS_PREFIX)-master-1.gerrit-demo
 MASTER2_SUBDOMAIN:=$(AWS_PREFIX)-master-2.gerrit-demo
+SLAVE_SUBDOMAIN:=$(AWS_PREFIX)-slave.gerrit-demo
 LB_SUBDOMAIN=$(AWS_PREFIX)-lb.gerrit-demo
 DOCKER_REGISTRY_URI:=<yourAccountId>.dkr.ecr.us-east-1.amazonaws.com
 SSL_CERTIFICATE_ARN=arn:aws:acm:us-east-1:<yourAccountId>:certificate/33e2c235-a4d1-42b7-b866-18d8d744975c
diff --git a/gerrit/entrypoint.sh b/gerrit/entrypoint.sh
index 5b76d4f..78f0b84 100755
--- a/gerrit/entrypoint.sh
+++ b/gerrit/entrypoint.sh
@@ -6,13 +6,16 @@
 git config -f /var/gerrit/etc/gerrit.config container.slave "${CONTAINER_SLAVE:-false}"
 
 if [ $CONTAINER_SLAVE ]; then
+  echo "Slave mode..."
   rm -fr /var/gerrit/plugins/replication.jar
   java -jar /var/gerrit/bin/gerrit.war reindex --index groups
-elif [ ! -f /var/gerrit/index/gerrit_index.config ]; then
-  java -jar /var/gerrit/bin/gerrit.war reindex -d /var/gerrit
 else
+  echo "Master mode (init phase)..."
   java -jar /var/gerrit/bin/gerrit.war init --no-auto-start --batch --install-all-plugins -d /var/gerrit
-  java -jar /var/gerrit/bin/gerrit.war reindex --index projects -d /var/gerrit
+  if [ $REINDEX_AT_STARTUP == "true" ]; then
+    echo "Master mode (reindex phase)..."
+    java -jar /var/gerrit/bin/gerrit.war reindex -d /var/gerrit
+  fi
 fi
 
 echo "Running Gerrit ..."
diff --git a/gerrit/etc/gerrit.config.template b/gerrit/etc/gerrit.config.template
index dc11036..bc9fdcc 100644
--- a/gerrit/etc/gerrit.config.template
+++ b/gerrit/etc/gerrit.config.template
@@ -10,7 +10,10 @@
 [auth]
   type = ldap
   gitBasicAuth = true
-  cookiedomain = .{{ COOKIE_DOMAIN }}
+  {% if COOKIE_DOMAIN is defined %}
+    cookiedomain = .{{ COOKIE_DOMAIN }}
+  {% endif %}
+
 [ldap]
   server = {{ LDAP_SERVER }}
   username = {{ LDAP_USERNAME }}
diff --git a/gerrit/setup_gerrit.py b/gerrit/setup_gerrit.py
index d1b10b9..2e1abc3 100755
--- a/gerrit/setup_gerrit.py
+++ b/gerrit/setup_gerrit.py
@@ -136,6 +136,8 @@
     else:
         raise e
 
+if 'HOSTED_ZONE_NAME' in os.environ:
+    config_for_template['COOKIE_DOMAIN'] = os.getenv('HOSTED_ZONE_NAME')
 with open(GERRIT_CONFIG_DIRECTORY + "gerrit.config", 'w',
           encoding='utf-8') as f:
     config_for_template.update({
@@ -145,8 +147,7 @@
         'LDAP_GROUP_BASE': config['ldap']['groupBase'],
         'SMTP_SERVER': config['smtp']["server"],
         'SMTP_USER': config['smtp']["user"],
-        'SMTP_DOMAIN': config['smtp']["domain"],
-        'COOKIE_DOMAIN': os.getenv('HOSTED_ZONE_NAME'),
+        'SMTP_DOMAIN': config['smtp']["domain"]
     })
     f.write(template.render(config_for_template))
 
diff --git a/master-slave/Makefile b/master-slave/Makefile
index 6431c3d..77ee882 100644
--- a/master-slave/Makefile
+++ b/master-slave/Makefile
@@ -14,7 +14,8 @@
 				wait-for-cluster-deletion wait-for-service-master-deletion wait-for-dns-routing-deletion \
 				gerrit-build gerrit-publish
 
-create-all: cluster wait-for-cluster-creation \
+create-all: gerrit-publish git-daemon-publish git-ssh-publish \
+						cluster wait-for-cluster-creation \
 						service-slave wait-for-service-slave-creation \
 						service-master wait-for-service-master-creation \
 						dns-routing wait-for-dns-routing-creation
diff --git a/single-master/Makefile b/single-master/Makefile
index 48ad8d6..b053f53 100644
--- a/single-master/Makefile
+++ b/single-master/Makefile
@@ -12,7 +12,8 @@
 				wait-for-cluster-deletion wait-for-service-deletion wait-for-dns-routing-deletion \
 				gerrit-build gerrit-publish
 
-create-all: cluster wait-for-cluster-creation \
+create-all: gerrit-publish \
+						cluster wait-for-cluster-creation \
 						service wait-for-service-creation \
 						dns-routing wait-for-dns-routing-creation