Merge changes Ie131d7c4,I705f37c8,I7b79c0df,I588b776f,I30b55c37, ...

* changes:
  dual-primary: separate HTTP from SSH traffic
  Remove unused ReplicaServiceStackName parameter
  Removed unused LOAD_BALANCER_STACK_NAME variable
  primary-replica: separate HTTP from SSH traffic
  Single-primary: separate HTTP from SSH traffic
  Do not use static naming for TargetGroup and LoadBalancers
diff --git a/dual-primary/Makefile b/dual-primary/Makefile
index 56fdaee..1275bbb 100644
--- a/dual-primary/Makefile
+++ b/dual-primary/Makefile
@@ -130,14 +130,16 @@
 		ParameterKey=ClusterStackName,ParameterValue=$(CLUSTER_STACK_NAME) \
 		ParameterKey=TemplateBucketName,ParameterValue=$(TEMPLATE_BUCKET_NAME) \
 		ParameterKey=HostedZoneName,ParameterValue=$(HOSTED_ZONE_NAME) \
-		ParameterKey=Subdomain,ParameterValue=$(PRIMARY1_SUBDOMAIN) \
-		ParameterKey=ReplicaSubdomain,ParameterValue=$(REPLICA_SUBDOMAIN) \
+		ParameterKey=HttpSubdomain,ParameterValue=$(HTTP_PRIMARY1_SUBDOMAIN) \
+		ParameterKey=SshSubdomain,ParameterValue=$(SSH_PRIMARY1_SUBDOMAIN) \
+		ParameterKey=SshReplicaSubdomain,ParameterValue=$(SSH_REPLICA_SUBDOMAIN) \
 		ParameterKey=DockerRegistryUrl,ParameterValue=$(DOCKER_REGISTRY_URI) \
 		ParameterKey=CertificateArn,ParameterValue=$(SSL_CERTIFICATE_ARN) \
 		ParameterKey=GerritKeyPrefix,ParameterValue=$(GERRIT_KEY_PREFIX)\
 		ParameterKey=DockerImage,ParameterValue=aws-gerrit/gerrit:$(IMAGE_TAG) \
-		ParameterKey=PeerSubdomain,ParameterValue=$(PRIMARY2_SUBDOMAIN) \
-		ParameterKey=PrimariesGerritSubdomain,ParameterValue=$(PRIMARIES_GERRIT_SUBDOMAIN) \
+		ParameterKey=PeerSubdomain,ParameterValue=$(HTTP_PRIMARY2_SUBDOMAIN) \
+		ParameterKey=HttpPrimariesGerritSubdomain,ParameterValue=$(HTTP_PRIMARIES_GERRIT_SUBDOMAIN) \
+		ParameterKey=SshPrimariesGerritSubdomain,ParameterValue=$(SSH_PRIMARIES_GERRIT_SUBDOMAIN) \
 		ParameterKey=GerritRAM,ParameterValue=$(GERRIT_RAM) \
 		ParameterKey=GerritCPU,ParameterValue=$(GERRIT_CPU) \
 		ParameterKey=GerritHeapLimit,ParameterValue=$(GERRIT_HEAP_LIMIT) \
@@ -188,14 +190,16 @@
 		ParameterKey=ClusterStackName,ParameterValue=$(CLUSTER_STACK_NAME) \
 		ParameterKey=TemplateBucketName,ParameterValue=$(TEMPLATE_BUCKET_NAME) \
 		ParameterKey=HostedZoneName,ParameterValue=$(HOSTED_ZONE_NAME) \
-		ParameterKey=Subdomain,ParameterValue=$(PRIMARY2_SUBDOMAIN) \
-		ParameterKey=ReplicaSubdomain,ParameterValue=$(REPLICA_SUBDOMAIN) \
+		ParameterKey=HttpSubdomain,ParameterValue=$(HTTP_PRIMARY2_SUBDOMAIN) \
+		ParameterKey=SshSubdomain,ParameterValue=$(SSH_PRIMARY2_SUBDOMAIN) \
+		ParameterKey=SshReplicaSubdomain,ParameterValue=$(SSH_REPLICA_SUBDOMAIN) \
 		ParameterKey=DockerRegistryUrl,ParameterValue=$(DOCKER_REGISTRY_URI) \
 		ParameterKey=CertificateArn,ParameterValue=$(SSL_CERTIFICATE_ARN) \
 		ParameterKey=GerritKeyPrefix,ParameterValue=$(GERRIT_KEY_PREFIX)\
 		ParameterKey=DockerImage,ParameterValue=aws-gerrit/gerrit:$(IMAGE_TAG) \
-		ParameterKey=PeerSubdomain,ParameterValue=$(PRIMARY1_SUBDOMAIN) \
-		ParameterKey=PrimariesGerritSubdomain,ParameterValue=$(PRIMARIES_GERRIT_SUBDOMAIN) \
+		ParameterKey=PeerSubdomain,ParameterValue=$(HTTP_PRIMARY1_SUBDOMAIN) \
+		ParameterKey=HttpPrimariesGerritSubdomain,ParameterValue=$(HTTP_PRIMARIES_GERRIT_SUBDOMAIN) \
+		ParameterKey=SshPrimariesGerritSubdomain,ParameterValue=$(SSH_PRIMARIES_GERRIT_SUBDOMAIN) \
 		ParameterKey=ReindexAtSartup,ParameterValue=true \
 		ParameterKey=GerritRAM,ParameterValue=$(GERRIT_RAM) \
 		ParameterKey=GerritCPU,ParameterValue=$(GERRIT_CPU) \
@@ -255,7 +259,8 @@
 		ParameterKey=ClusterStackName,ParameterValue=$(CLUSTER_STACK_NAME) \
 		ParameterKey=TemplateBucketName,ParameterValue=$(TEMPLATE_BUCKET_NAME) \
 		ParameterKey=HostedZoneName,ParameterValue=$(HOSTED_ZONE_NAME) \
-		ParameterKey=Subdomain,ParameterValue=$(REPLICA_SUBDOMAIN) \
+		ParameterKey=HttpSubdomain,ParameterValue=$(HTTP_REPLICA_SUBDOMAIN) \
+		ParameterKey=SshSubdomain,ParameterValue=$(SSH_REPLICA_SUBDOMAIN) \
 		ParameterKey=DockerRegistryUrl,ParameterValue=$(DOCKER_REGISTRY_URI) \
 		ParameterKey=CertificateArn,ParameterValue=$(SSL_CERTIFICATE_ARN) \
 		ParameterKey=GerritKeyPrefix,ParameterValue=$(GERRIT_KEY_PREFIX)\
@@ -283,7 +288,8 @@
 		ParameterKey=Primary2ServiceStackName,ParameterValue=$(SERVICE_PRIMARY2_STACK_NAME) \
 		ParameterKey=ClusterStackName,ParameterValue=$(CLUSTER_STACK_NAME) \
 		ParameterKey=PrimariesGerritHostedZoneName,ParameterValue=$(HOSTED_ZONE_NAME) \
-		ParameterKey=PrimariesGerritSubdomain,ParameterValue=$(PRIMARIES_GERRIT_SUBDOMAIN)
+		ParameterKey=HttpPrimariesGerritSubdomain,ParameterValue=$(HTTP_PRIMARIES_GERRIT_SUBDOMAIN) \
+		ParameterKey=SshPrimariesGerritSubdomain,ParameterValue=$(SSH_PRIMARIES_GERRIT_SUBDOMAIN)
 
 dashboard:
 ifeq ($(METRICS_CLOUDWATCH_ENABLED),true)
diff --git a/dual-primary/README.md b/dual-primary/README.md
index 23bc084..3bbb5cc 100644
--- a/dual-primary/README.md
+++ b/dual-primary/README.md
@@ -161,11 +161,16 @@
 * `SERVICE_PRIMARY1_STACK_NAME`: Optional. Name of the primary 1 service stack. `gerrit-service-primary-1` by default.
 * `SERVICE_PRIMARY2_STACK_NAME`: Optional. Name of the primary 2 service stack. `gerrit-service-primary-2` by default.
 * `DASHBOARD_STACK_NAME` : Optional. Name of the dashboard stack. `gerrit-dashboard` by default.
-* `PRIMARY1_SUBDOMAIN`: Optional. Name of the primary 1 sub domain. `gerrit-primary-1-demo` by default.
-* `PRIMARY2_SUBDOMAIN`: Optional. Name of the primary 2 sub domain. `gerrit-primary-2-demo` by default.
-* `REPLICA_SUBDOMAIN`: Mandatory. The subdomain of the Gerrit replica. For example: `<AWS_PREFIX>-replica`
-* `PRIMARIES_GERRIT_SUBDOMAIN`: Mandatory. The subdomain of the lb serving traffic to both primary gerrit instances.
-   For example: `<AWS_PREFIX>-primaries`
+* `HTTP_PRIMARY1_SUBDOMAIN`: Optional. Name of the primary 1 sub domain for HTTP traffic. `gerrit-http-primary-1-demo` by default.
+* `SSH_PRIMARY1_SUBDOMAIN`: Optional. Name of the primary 1 sub domain for SSH traffic. `gerrit-ssh-primary-1-demo` by default.
+* `HTTP_PRIMARY2_SUBDOMAIN`: Optional. Name of the primary 2 sub domain for HTTP traffic. `gerrit-http-primary-2-demo` by default.
+* `SSH_PRIMARY2_SUBDOMAIN`: Optional. Name of the primary 2 sub domain for SSH traffic. `gerrit-ssh-primary-2-demo` by default.
+* `HTTP_REPLICA_SUBDOMAIN`: Mandatory. The subdomain of the Gerrit replica for HTTP traffic. For example: `<AWS_PREFIX>-http-replica`
+* `SSH_REPLICA_SUBDOMAIN`: Mandatory. The subdomain of the Gerrit replica for SSH traffic. For example: `<AWS_PREFIX>-ssh-replica`
+* `HTTP_PRIMARIES_GERRIT_SUBDOMAIN`: Mandatory. The subdomain of the lb serving HTTP traffic to both primary gerrit instances.
+   For example: `<AWS_PREFIX>-http-primaries`
+* `SSH_PRIMARIES_GERRIT_SUBDOMAIN`: Mandatory. The subdomain of the lb serving SSH traffic to both primary gerrit instances.
+  For example: `<AWS_PREFIX>-ssh-primaries`
 * `PRIMARY_FILESYSTEM_THROUGHPUT_MODE`: Optional. The throughput mode for the primary file system to be created.
 default: `bursting`. More info [here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-filesystem.html)
 * `PRIMARY_FILESYSTEM_PROVISIONED_THROUGHPUT_IN_MIBPS`: Optional. Only used when `PRIMARY_FILESYSTEM_THROUGHPUT_MODE` is set to `provisioned`.
diff --git a/dual-primary/cf-cluster.yml b/dual-primary/cf-cluster.yml
index 440c6d7..787d7a5 100644
--- a/dual-primary/cf-cluster.yml
+++ b/dual-primary/cf-cluster.yml
@@ -266,12 +266,42 @@
 
           /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ReplicaECSAutoScalingGroup --region ${AWS::Region}
 
-  PrimariesGerritLoadBalancer:
+  PrimariesHTTPGerritLoadBalancerSG:
+    Type: AWS::EC2::SecurityGroup
+    Properties:
+      VpcId: !If [NetworkStackNeeded, !GetAtt ECSTaskNetworkStack.Outputs.VPCRef, !Ref VPCIdProp]
+      GroupDescription: "Allow public HTTPS traffic to primaries gerrit"
+      GroupName: !Sub '${AWS::StackName}-primaries-http'
+      SecurityGroupIngress:
+        - IpProtocol: 'tcp'
+          FromPort: !FindInMap ['Gerrit', 'Port', 'HTTPS']
+          ToPort: !FindInMap ['Gerrit', 'Port', 'HTTPS']
+          CidrIp: '0.0.0.0/0'
+          Description: "HTTPS connections from everywhere (IPv4)"
+        - IpProtocol: 'tcp'
+          FromPort: !FindInMap ['Gerrit', 'Port', 'HTTPS']
+          ToPort: !FindInMap ['Gerrit', 'Port', 'HTTPS']
+          CidrIpv6: '::/0'
+          Description: "HTTPS connections from everywhere (IPv6)"
+
+  PrimariesHTTPGerritLoadBalancer:
+    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
+    Properties:
+      Name: !Sub '${AWS::StackName}-http-primaries'
+      Type: application
+      Scheme: !Ref PrimariesGerritLoadBalancerScheme
+      SecurityGroups:
+        - !Ref PrimariesHTTPGerritLoadBalancerSG
+      Subnets:
+        - !If [NetworkStackNeeded, !GetAtt ECSTaskNetworkStack.Outputs.PublicSubnetOneRef, !Ref Subnet1IdProp]
+        - !If [NetworkStackNeeded, !GetAtt ECSTaskNetworkStack.Outputs.PublicSubnetTwoRef, !Ref Subnet2IdProp]
+
+  PrimariesSSHGerritLoadBalancer:
     Type: AWS::ElasticLoadBalancingV2::LoadBalancer
     Properties:
       Type: network
       Scheme: !Ref PrimariesGerritLoadBalancerScheme
-      Name: 'primary-gerrit-instances'
+      Name: !Sub '${AWS::StackName}-ssh-primaries'
       LoadBalancerAttributes:
         - Key: 'load_balancing.cross_zone.enabled'
           Value: true
@@ -281,22 +311,20 @@
 
   PrimariesGerritHTTPTargetGroup:
     Type: AWS::ElasticLoadBalancingV2::TargetGroup
-    DependsOn: PrimariesGerritLoadBalancer
+    DependsOn: PrimariesHTTPGerritLoadBalancer
     Properties:
       VpcId: !If [NetworkStackNeeded, !GetAtt ECSTaskNetworkStack.Outputs.VPCRef, !Ref VPCIdProp]
       Port: !FindInMap ['Gerrit', 'Port', 'HTTP']
-      Protocol: TCP
+      Protocol: HTTP
       HealthCheckPort: !FindInMap ['Gerrit', 'Port', 'HTTP']
       HealthCheckProtocol: HTTP
       HealthCheckPath: '/config/server/healthcheck~status'
-      Name: 'primaries-gerrit-http'
+      Name: !Sub '${AWS::StackName}-primaries-http'
       TargetGroupAttributes:
         - Key: 'stickiness.enabled'
           Value: true
-        # NLB only supports source_ip. Move this to `lb_cookie` or `app_cookie`
-        # when this target group is moved behind an ALB
         - Key: 'stickiness.type'
-          Value: 'source_ip'
+          Value: 'lb_cookie'
 
   PrimariesGerritHTTPSListener:
     Type: AWS::ElasticLoadBalancingV2::Listener
@@ -306,13 +334,13 @@
       DefaultActions:
         - Type: forward
           TargetGroupArn: !Ref PrimariesGerritHTTPTargetGroup
-      LoadBalancerArn: !Ref PrimariesGerritLoadBalancer
+      LoadBalancerArn: !Ref PrimariesHTTPGerritLoadBalancer
       Port: !FindInMap ['Gerrit', 'Port', 'HTTPS']
-      Protocol: TLS
+      Protocol: HTTPS
 
   PrimariesGerritSSHTargetGroup:
     Type: AWS::ElasticLoadBalancingV2::TargetGroup
-    DependsOn: PrimariesGerritLoadBalancer
+    DependsOn: PrimariesSSHGerritLoadBalancer
     Properties:
       VpcId: !If [NetworkStackNeeded, !GetAtt ECSTaskNetworkStack.Outputs.VPCRef, !Ref VPCIdProp]
       Port: !FindInMap ['Gerrit', 'Port', 'SSH']
@@ -320,7 +348,7 @@
       HealthCheckPort: !FindInMap ['Gerrit', 'Port', 'HTTP']
       HealthCheckProtocol: HTTP
       HealthCheckPath: '/config/server/healthcheck~status'
-      Name: 'primaries-gerrit-ssh'
+      Name: !Sub '${AWS::StackName}-primaries-ssh'
 
   PrimariesGerritSSHListener:
     Type: AWS::ElasticLoadBalancingV2::Listener
@@ -328,7 +356,7 @@
       DefaultActions:
         - Type: forward
           TargetGroupArn: !Ref PrimariesGerritSSHTargetGroup
-      LoadBalancerArn: !Ref PrimariesGerritLoadBalancer
+      LoadBalancerArn: !Ref PrimariesSSHGerritLoadBalancer
       Port: !FindInMap ['Gerrit', 'Port', 'SSH']
       Protocol: TCP
 
@@ -540,13 +568,23 @@
     Value: !Ref 'PrimariesGerritSSHTargetGroup'
     Export:
       Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PrimariesGerritSSHTargetGroup' ] ]
-  PrimariesGerritLoadBalancerDNSName:
-    Description: The DNS name of the load balancer serving requests to both gerrit1 and gerrit2
-    Value: !GetAtt 'PrimariesGerritLoadBalancer.DNSName'
+  PrimariesHTTPGerritLoadBalancerDNSName:
+    Description: The DNS name of the load balancer serving HTTP requests to both gerrit1 and gerrit2
+    Value: !GetAtt 'PrimariesHTTPGerritLoadBalancer.DNSName'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PrimariesGerritLoadBalancerDNSName' ] ]
-  PrimariesGerritCanonicalHostedZoneID:
-    Description: Canonical Hosted Zone ID of the load balancer serving requests to both gerrit1 and gerrit2
-    Value: !GetAtt 'PrimariesGerritLoadBalancer.CanonicalHostedZoneID'
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PrimariesHTTPGerritLoadBalancerDNSName' ] ]
+  PrimariesSSHGerritLoadBalancerDNSName:
+    Description: The DNS name of the load balancer serving SSH requests to both gerrit1 and gerrit2
+    Value: !GetAtt 'PrimariesSSHGerritLoadBalancer.DNSName'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PrimariesGerritCanonicalHostedZoneID' ] ]
\ No newline at end of file
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PrimariesSSHGerritLoadBalancerDNSName' ] ]
+  PrimariesHTTPGerritCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the load balancer serving HTTP requests to both gerrit1 and gerrit2
+    Value: !GetAtt 'PrimariesHTTPGerritLoadBalancer.CanonicalHostedZoneID'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PrimariesHTTPGerritCanonicalHostedZoneID' ] ]
+  PrimariesSSHGerritCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the load balancer serving SSH requests to both gerrit1 and gerrit2
+    Value: !GetAtt 'PrimariesSSHGerritLoadBalancer.CanonicalHostedZoneID'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PrimariesSSHGerritCanonicalHostedZoneID' ] ]
\ No newline at end of file
diff --git a/dual-primary/cf-dns-route.yml b/dual-primary/cf-dns-route.yml
index 156cbc5..25a87b1 100644
--- a/dual-primary/cf-dns-route.yml
+++ b/dual-primary/cf-dns-route.yml
@@ -13,81 +13,157 @@
       Description: Stack name of the ECS Primary Gerrit service
       Type: String
       Default: gerrit-service-primary-2
-  PrimariesGerritSubdomain:
-    Description: The subdomain of the load balancer serving requests to primary gerrit instances
+  HttpPrimariesGerritSubdomain:
+    Description: The subdomain of the load balancer serving HTTP traffic to both gerrit instances
+    Type: String
+  SshPrimariesGerritSubdomain:
+    Description: The subdomain of the load balancer serving SSH traffic to both gerrit instances
     Type: String
   PrimariesGerritHostedZoneName:
     Description: The zone name of the load balancer serving requests to primary gerrit instances
     Type: String
 
 Resources:
-  Primary1DnsRecord:
+  Primary1HTTPDnsRecord:
       Type: AWS::Route53::RecordSet
       Properties:
         Name:
           !Join
             - '.'
-            - - Fn::ImportValue: !Join [':', [!Ref 'Primary1ServiceStackName', 'Subdomain']]
+            - - Fn::ImportValue: !Join [':', [!Ref 'Primary1ServiceStackName', 'HttpSubdomain']]
               - Fn::ImportValue: !Join [':', [!Ref 'Primary1ServiceStackName', 'HostedZoneName']]
         HostedZoneName:
           !Join
             - ''
             - - Fn::ImportValue: !Join [':', [!Ref 'Primary1ServiceStackName', 'HostedZoneName']]
               - '.'
-        Comment: DNS name for Gerrit Primary.
+        Comment: DNS name for Load Balancer serving HTTP requests to primary gerrit-1
         Type: A
         AliasTarget:
           DNSName:
             Fn::ImportValue:
-              !Join [':', [!Ref 'Primary1ServiceStackName', 'PublicLoadBalancerDNSName']]
+              !Join [':', [!Ref 'Primary1ServiceStackName', 'GerritHTTPLoadBalancerDNSName']]
           HostedZoneId:
             Fn::ImportValue:
-              !Join [':', [!Ref 'Primary1ServiceStackName', 'CanonicalHostedZoneID']]
+              !Join [':', [!Ref 'Primary1ServiceStackName', 'GerritHTTPCanonicalHostedZoneID']]
           EvaluateTargetHealth: False
-  Primary2DnsRecord:
+
+  Primary1SSHDnsRecord:
+    Type: AWS::Route53::RecordSet
+    Properties:
+      Name:
+        !Join
+        - '.'
+        - - Fn::ImportValue: !Join [':', [!Ref 'Primary1ServiceStackName', 'SshSubdomain']]
+          - Fn::ImportValue: !Join [':', [!Ref 'Primary1ServiceStackName', 'HostedZoneName']]
+      HostedZoneName:
+        !Join
+        - ''
+        - - Fn::ImportValue: !Join [':', [!Ref 'Primary1ServiceStackName', 'HostedZoneName']]
+          - '.'
+      Comment: DNS name for Load Balancer serving SSH requests to primary gerrit-1
+      Type: A
+      AliasTarget:
+        DNSName:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'Primary1ServiceStackName', 'GerritSSHLoadBalancerDNSName']]
+        HostedZoneId:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'Primary1ServiceStackName', 'GerritSSHCanonicalHostedZoneID']]
+        EvaluateTargetHealth: False
+
+  Primary2HTTPDnsRecord:
       Type: AWS::Route53::RecordSet
       Properties:
         Name:
           !Join
             - '.'
-            - - Fn::ImportValue: !Join [':', [!Ref 'Primary2ServiceStackName', 'Subdomain']]
+            - - Fn::ImportValue: !Join [':', [!Ref 'Primary2ServiceStackName', 'HttpSubdomain']]
               - Fn::ImportValue: !Join [':', [!Ref 'Primary2ServiceStackName', 'HostedZoneName']]
         HostedZoneName:
           !Join
             - ''
             - - Fn::ImportValue: !Join [':', [!Ref 'Primary2ServiceStackName', 'HostedZoneName']]
               - '.'
-        Comment: DNS name for Gerrit Primary.
+        Comment: DNS name for Load Balancer serving HTTP requests to primary gerrit-2
         Type: A
         AliasTarget:
           DNSName:
             Fn::ImportValue:
-              !Join [':', [!Ref 'Primary2ServiceStackName', 'PublicLoadBalancerDNSName']]
+              !Join [':', [!Ref 'Primary2ServiceStackName', 'GerritHTTPLoadBalancerDNSName']]
           HostedZoneId:
             Fn::ImportValue:
-              !Join [':', [!Ref 'Primary2ServiceStackName', 'CanonicalHostedZoneID']]
+              !Join [':', [!Ref 'Primary2ServiceStackName', 'GerritHTTPCanonicalHostedZoneID']]
           EvaluateTargetHealth: False
 
-  PrimariesGerritDnsRecord:
+  Primary2SSHDnsRecord:
     Type: AWS::Route53::RecordSet
     Properties:
       Name:
         !Join
         - '.'
-        - - !Ref PrimariesGerritSubdomain
+        - - Fn::ImportValue: !Join [':', [!Ref 'Primary2ServiceStackName', 'SshSubdomain']]
+          - Fn::ImportValue: !Join [':', [!Ref 'Primary2ServiceStackName', 'HostedZoneName']]
+      HostedZoneName:
+        !Join
+        - ''
+        - - Fn::ImportValue: !Join [':', [!Ref 'Primary2ServiceStackName', 'HostedZoneName']]
+          - '.'
+      Comment: DNS name for Load Balancer serving SSH requests to primary gerrit-2
+      Type: A
+      AliasTarget:
+        DNSName:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'Primary2ServiceStackName', 'GerritSSHLoadBalancerDNSName']]
+        HostedZoneId:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'Primary2ServiceStackName', 'GerritSSHCanonicalHostedZoneID']]
+        EvaluateTargetHealth: False
+
+  PrimariesHTTPGerritDnsRecord:
+    Type: AWS::Route53::RecordSet
+    Properties:
+      Name:
+        !Join
+        - '.'
+        - - !Ref HttpPrimariesGerritSubdomain
           - !Ref PrimariesGerritHostedZoneName
       HostedZoneName:
         !Join
         - ''
         - - !Ref PrimariesGerritHostedZoneName
           - '.'
-      Comment: DNS name for the load balancer serving requests to primary gerrit instances
+      Comment: DNS name for the load balancer serving HTTP requests to primary gerrit instances
       Type: A
       AliasTarget:
         DNSName:
           Fn::ImportValue:
-            !Join [':', [!Ref 'ClusterStackName', 'PrimariesGerritLoadBalancerDNSName']]
+            !Join [':', [!Ref 'ClusterStackName', 'PrimariesHTTPGerritLoadBalancerDNSName']]
         HostedZoneId:
           Fn::ImportValue:
-            !Join [':', [!Ref 'ClusterStackName', 'PrimariesGerritCanonicalHostedZoneID']]
+            !Join [':', [!Ref 'ClusterStackName', 'PrimariesHTTPGerritCanonicalHostedZoneID']]
+        EvaluateTargetHealth: False
+
+  PrimariesSSHGerritDnsRecord:
+    Type: AWS::Route53::RecordSet
+    Properties:
+      Name:
+        !Join
+        - '.'
+        - - !Ref SshPrimariesGerritSubdomain
+          - !Ref PrimariesGerritHostedZoneName
+      HostedZoneName:
+        !Join
+        - ''
+        - - !Ref PrimariesGerritHostedZoneName
+          - '.'
+      Comment: DNS name for the load balancer serving SSH requests to primary gerrit instances
+      Type: A
+      AliasTarget:
+        DNSName:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'ClusterStackName', 'PrimariesSSHGerritLoadBalancerDNSName']]
+        HostedZoneId:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'ClusterStackName', 'PrimariesSSHGerritCanonicalHostedZoneID']]
         EvaluateTargetHealth: False
\ No newline at end of file
diff --git a/dual-primary/cf-service-primary.yml b/dual-primary/cf-service-primary.yml
index 8c3384d..70b2a50 100644
--- a/dual-primary/cf-service-primary.yml
+++ b/dual-primary/cf-service-primary.yml
@@ -29,16 +29,23 @@
   HostedZoneName:
         Description: The route53 HostedZoneName.
         Type: String
-  Subdomain:
-        Description: The subdomain of the Gerrit cluster
+  HttpSubdomain:
+        Description: The subdomain of the loadbalancer serving HTTP traffic to the primary Gerrit
         Type: String
-        Default: gerrit-primary-demo
-  ReplicaSubdomain:
-        Description: The subdomain of the Gerrit replica
+        Default: gerrit-http-primary-demo
+  SshSubdomain:
+    Description: The subdomain of the loadbalancer serving SSH traffic to the primary Gerrit
+    Type: String
+    Default: gerrit-ssh-primary-demo
+  SshReplicaSubdomain:
+        Description: The subdomain of the loadbalancer serving SSH traffic to the replicas
         Type: String
-  PrimariesGerritSubdomain:
-        Description: The subdomain of the load balancer fronting both gerrit-1 and gerrit-2
+  HttpPrimariesGerritSubdomain:
+        Description: The subdomain of the load balancer serving HTTP traffic to both gerrit-1 and gerrit-2
         Type: String
+  SshPrimariesGerritSubdomain:
+    Description: The subdomain of the load balancer serving SSH traffic to both gerrit-1 and gerrit-2
+    Type: String
   LoadBalancerScheme:
         Description: Load Balancer scheme, the nodes of an internet-facing load balancer have public IP addresses.
         Type: String
@@ -251,7 +258,11 @@
                   Image: !Sub '${DockerRegistryUrl}/${DockerImage}'
                   Environment:
                     - Name: CANONICAL_WEB_URL
-                      Value: !Sub 'https://${PrimariesGerritSubdomain}.${HostedZoneName}'
+                      Value: !Sub 'https://${HttpPrimariesGerritSubdomain}.${HostedZoneName}'
+                    - Name: SSHD_ADVERTISED_ADDRESS
+                      Value: !Sub
+                        - '${SshPrimariesGerritSubdomain}.${HostedZoneName}:${SSHPort}'
+                        - { SSHPort: !FindInMap ['Gerrit', 'Port', 'SSH'] }
                     - Name: HTTPD_LISTEN_URL
                       Value: !Sub
                         - 'proxy-https://*:${HTTPContainerPort}/'
@@ -307,7 +318,7 @@
                     - Name: GIT_SSH_PORT
                       Value: !FindInMap ['Git', 'SSH', 'Port']
                     - Name: REPLICA_SUBDOMAIN
-                      Value: !Ref ReplicaSubdomain
+                      Value: !Ref SshReplicaSubdomain
                     - Name: GERRIT_INSTANCE_ID
                       Value: !Ref InstanceId
                     - Name: METRICS_CLOUDWATCH_ENABLED
@@ -395,9 +406,47 @@
                 Host:
                   SourcePath: !Join ['/', ["/gerrit-mount-point", !FindInMap ['Gerrit', 'Volume', 'Logs']]]
 
-    LoadBalancer:
+    GerritHTTPLoadBalancerSG:
+      Type: AWS::EC2::SecurityGroup
+      Properties:
+        VpcId:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+        GroupDescription: "Allow public HTTP traffic to primary Gerrit"
+        GroupName: !Sub '${ClusterStackName}-primary${GerritInstanceNumber}-http'
+        SecurityGroupIngress:
+          - IpProtocol: 'tcp'
+            FromPort: !FindInMap ['Gerrit', 'Port', 'HTTP']
+            ToPort: !FindInMap ['Gerrit', 'Port', 'HTTP']
+            CidrIp: '0.0.0.0/0'
+            Description: "HTTP connections from everywhere (IPv4)"
+          - IpProtocol: 'tcp'
+            FromPort: !FindInMap ['Gerrit', 'Port', 'HTTP']
+            ToPort: !FindInMap ['Gerrit', 'Port', 'HTTP']
+            CidrIpv6: '::/0'
+            Description: "HTTP connections from everywhere (IPv6)"
+
+    GerritHTTPLoadBalancer:
+      Type: AWS::ElasticLoadBalancingV2::LoadBalancer
+      Properties:
+        Name: !Sub '${ClusterStackName}-primary${GerritInstanceNumber}-http'
+        Type: application
+        Scheme: !Ref 'LoadBalancerScheme'
+        SecurityGroups:
+          - !Ref GerritHTTPLoadBalancerSG
+        Subnets:
+          - Fn::ImportValue:
+              !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetOne']]
+          - Fn::ImportValue:
+              !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetTwo']]
+        Tags:
+          - Key: Name
+            Value: !Join ['-', [!Ref 'EnvironmentName', !FindInMap ['Gerrit', 'Service', 'Name'], 'alb']]
+
+    GerritSSHLoadBalancer:
         Type: AWS::ElasticLoadBalancingV2::LoadBalancer
         Properties:
+            Name: !Sub '${AWS::StackName}-primary${GerritInstanceNumber}-ssh'
             Type: network
             Scheme: !Ref 'LoadBalancerScheme'
             LoadBalancerAttributes:
@@ -414,32 +463,32 @@
 
     HTTPTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: GerritHTTPLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
                   !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
             Port: !FindInMap ['Gerrit', 'Port', 'HTTP']
-            Protocol: TCP
+            Protocol: HTTP
             HealthCheckPort: !FindInMap ['Gerrit', 'Port', 'HTTP']
             HealthCheckProtocol: HTTP
             HealthCheckPath: '/config/server/healthcheck~status'
-            Name: !Sub 'gerrit-${GerritInstanceNumber}-primary-http'
+            Name: !Sub '${AWS::StackName}-primary${GerritInstanceNumber}-http'
 
     HTTPListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
+        DependsOn: GerritHTTPLoadBalancer
         Properties:
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref HTTPTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref GerritHTTPLoadBalancer
             Port: !FindInMap ['Gerrit', 'Port', 'HTTP']
-            Protocol: TCP
+            Protocol: HTTP
 
     SSHTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: GerritSSHLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
@@ -449,16 +498,16 @@
             HealthCheckPort: !FindInMap ['Gerrit', 'Port', 'HTTP']
             HealthCheckProtocol: HTTP
             HealthCheckPath: '/config/server/healthcheck~status'
-            Name: !Sub 'gerrit-${GerritInstanceNumber}-primary-ssh'
+            Name: !Sub '${AWS::StackName}-primary${GerritInstanceNumber}-ssh'
 
     SSHListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
+        DependsOn: GerritSSHLoadBalancer
         Properties:
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref SSHTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref GerritSSHLoadBalancer
             Port: !FindInMap ['Gerrit', 'Port', 'SSH']
             Protocol: TCP
 
@@ -469,33 +518,67 @@
         TimeoutInMinutes: '5'
 
 Outputs:
-  PublicLoadBalancerDNSName:
-    Description: The DNS name of the external load balancer
-    Value: !GetAtt 'LoadBalancer.DNSName'
+  ########
+  # HTTP #
+  ########
+  GerritHTTPLoadBalancerDNSName:
+    Description: The DNS name of the gerrit HTTP load balancer
+    Value: !GetAtt 'GerritHTTPLoadBalancer.DNSName'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerDNSName' ] ]
-  CanonicalHostedZoneID:
-    Description: Canonical Hosted Zone ID
-    Value: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPLoadBalancerDNSName' ] ]
+  GerritHTTPCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the gerrit HTTP load balancer
+    Value: !GetAtt 'GerritHTTPLoadBalancer.CanonicalHostedZoneID'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalHostedZoneID' ] ]
-  PublicLoadBalancerUrl:
-    Description: The url of the external load balancer
-    Value: !Join ['', ['http://', !GetAtt 'LoadBalancer.DNSName']]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPCanonicalHostedZoneID' ] ]
+  GerritHTTPLoadBalancerUrl:
+    Description: The url of the gerrit HTTP load balancer
+    Value: !Join ['', ['http://', !GetAtt 'GerritHTTPLoadBalancer.DNSName']]
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerUrl' ] ]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPLoadBalancerUrl' ] ]
+  #######
+  # SSH #
+  #######
+  GerritSSHLoadBalancerDNSName:
+    Description: The DNS name of the gerrit SSH load balancer
+    Value: !GetAtt 'GerritSSHLoadBalancer.DNSName'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHLoadBalancerDNSName' ] ]
+  GerritSSHCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the gerrit SSH load balancer
+    Value: !GetAtt 'GerritSSHLoadBalancer.CanonicalHostedZoneID'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHCanonicalHostedZoneID' ] ]
+  GerritSSHLoadBalancerUrl:
+    Description: The url of the gerrit SSH load balancer
+    Value: !Join ['', ['http://', !GetAtt 'GerritSSHLoadBalancer.DNSName']]
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHLoadBalancerUrl' ] ]
+  #######
+  # DNS #
+  #######
   HostedZoneName:
     Description: Route53 Hosted Zone name
     Value: !Ref HostedZoneName
     Export:
       Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HostedZoneName' ] ]
-  Subdomain:
-    Description: Service DNS subdomain
-    Value: !Ref Subdomain
+  HttpSubdomain:
+    Description: Service DNS subdomain for gerrit HTTP traffic
+    Value: !Ref HttpSubdomain
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'Subdomain' ] ]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HttpSubdomain' ] ]
+  SshSubdomain:
+    Description: Service DNS subdomain for gerrit SSH traffic
+    Value: !Ref SshSubdomain
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'SshSubdomain' ] ]
   CanonicalWebUrl:
     Description: Canonical Web URL
-    Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+    Value: !Sub 'https://${HttpPrimariesGerritSubdomain}.${HostedZoneName}'
     Export:
       Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalWebUrl' ] ]
+  SshdAvertisedListenerUrl:
+    Description: SSHD avertised listener URL
+    Value: !Sub 'https://${SshPrimariesGerritSubdomain}.${HostedZoneName}'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'SshdAvertisedListenerUrl' ] ]
diff --git a/dual-primary/cf-service-replica.yml b/dual-primary/cf-service-replica.yml
index df360e7..cab9668 100644
--- a/dual-primary/cf-service-replica.yml
+++ b/dual-primary/cf-service-replica.yml
@@ -74,10 +74,14 @@
   HostedZoneName:
       Description: The route53 HostedZoneName.
       Type: String
-  Subdomain:
-      Description: The subdomain of the Gerrit cluster
+  HttpSubdomain:
+      Description: The subdomain of the Gerrit loadbalancer serving HTTP traffic for replicas
       Type: String
-      Default: gerrit-replica-demo
+      Default: gerrit-http-replica-demo
+  SshSubdomain:
+      Description: The subdomain of the Gerrit loadbalancer serving SSH traffic for replicas
+      Type: String
+      Default: gerrit-ssh-replica-demo
   LoadBalancerScheme:
         Description: Load Balancer schema, The nodes of an Internet-facing load balancer have public IP addresses.
         Type: String
@@ -257,7 +261,9 @@
                   Image: !Sub '${DockerRegistryUrl}/${GerritDockerImage}'
                   Environment:
                     - Name: CANONICAL_WEB_URL
-                      Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+                      Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
+                    - Name: SSHD_ADVERTISED_ADDRESS
+                      Value: !Sub '${SshSubdomain}.${HostedZoneName}:${SSHHostPort}'
                     - Name: HTTPD_LISTEN_URL
                       Value: !Sub 'proxy-https://*:${HTTPContainePort}/'
                     - Name: CONTAINER_REPLICA
@@ -428,9 +434,47 @@
               - '/'
               - !GetAtt GerritService.Name
 
-    LoadBalancer:
+    ReplicaHTTPLoadBalancerSG:
+      Type: AWS::EC2::SecurityGroup
+      Properties:
+        VpcId:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+        GroupDescription: "Allow public HTTPS traffic to replicas"
+        GroupName: !Sub '${ClusterStackName}-replica-http'
+        SecurityGroupIngress:
+          - IpProtocol: 'tcp'
+            FromPort: !Ref HTTPSPort
+            ToPort: !Ref HTTPSPort
+            CidrIp: '0.0.0.0/0'
+            Description: "HTTPS connections from everywhere (IPv4)"
+          - IpProtocol: 'tcp'
+            FromPort: !Ref HTTPSPort
+            ToPort: !Ref HTTPSPort
+            CidrIpv6: '::/0'
+            Description: "HTTPS connections from everywhere (IPv6)"
+
+    ReplicaHTTPLoadBalancer:
+      Type: AWS::ElasticLoadBalancingV2::LoadBalancer
+      Properties:
+        Name: !Sub '${ClusterStackName}-replica-http'
+        Type: application
+        Scheme: !Ref 'LoadBalancerScheme'
+        SecurityGroups:
+          - !Ref ReplicaHTTPLoadBalancerSG
+        Subnets:
+          - Fn::ImportValue:
+              !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetOne']]
+          - Fn::ImportValue:
+              !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetTwo']]
+        Tags:
+          - Key: Name
+            Value: !Join ['-', [!Ref 'EnvironmentName', !Ref 'GerritServiceName', 'alb']]
+
+    ReplicaSSHLoadBalancer:
         Type: AWS::ElasticLoadBalancingV2::LoadBalancer
         Properties:
+            Name: !Sub '${ClusterStackName}-replica-ssh'
             Type: network
             Scheme: !Ref 'LoadBalancerScheme'
             LoadBalancerAttributes:
@@ -447,41 +491,38 @@
 
     HTTPTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: ReplicaHTTPLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
                   !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
             Port: !Ref HTTPHostPort
-            Protocol: TCP
+            Protocol: HTTP
             HealthCheckPort: !Ref HTTPHostPort
             HealthCheckProtocol: HTTP
             HealthCheckPath: '/config/server/healthcheck~status'
-            Name: 'gerrit-replica-http'
+            Name: !Sub '${AWS::StackName}-replica-http'
             TargetGroupAttributes:
               - Key: 'stickiness.enabled'
                 Value: true
-              # NLB only supports source_ip. Move this to `lb_cookie` or `app_cookie`
-              # when this target group is moved behind an ALB
               - Key: 'stickiness.type'
-                Value: 'source_ip'
+                Value: 'lb_cookie'
 
     HTTPListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             Certificates:
               - CertificateArn: !Ref CertificateArn
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref HTTPTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref ReplicaHTTPLoadBalancer
             Port: !Ref HTTPSPort
-            Protocol: TLS
+            Protocol: HTTPS
 
     SSHTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: ReplicaSSHLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
@@ -491,74 +532,83 @@
             HealthCheckPort: !Ref HTTPHostPort
             HealthCheckProtocol: HTTP
             HealthCheckPath: '/config/server/healthcheck~status'
-            Name: 'gerrit-replica-ssh'
+            Name: !Sub '${AWS::StackName}-replica-ssh'
 
     SSHListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref SSHTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref ReplicaSSHLoadBalancer
             Port: !Ref SSHHostPort
             Protocol: TCP
 
     GitTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: ReplicaSSHLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
                   !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
             Port: !Ref GitPort
             Protocol: TCP
-            Name: 'gerrit-replica-git'
+            Name: !Sub '${AWS::StackName}-replica-git'
 
     GitListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref GitTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref ReplicaSSHLoadBalancer
             Port: !Ref GitPort
             Protocol: TCP
 
     GitSSHTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: ReplicaSSHLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
                   !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
             Port: !Ref GitSSHPort
             Protocol: TCP
-            Name: 'gerrit-replica-git-ssh'
+            Name: !Sub '${AWS::StackName}-replica-gitssh'
 
     GitSSHListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref GitSSHTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref ReplicaSSHLoadBalancer
             Port: !Ref GitSSHPort
             Protocol: TCP
 
-    ReplicaDnsRecord:
-        Type: AWS::Route53::RecordSet
-        Properties:
-          Name: !Sub '${Subdomain}.${HostedZoneName}'
-          HostedZoneName: !Sub '${HostedZoneName}.'
-          Comment: DNS name for Gerrit Replica.
-          Type: A
-          AliasTarget:
-            DNSName: !GetAtt 'LoadBalancer.DNSName'
-            HostedZoneId: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
-            EvaluateTargetHealth: False
+    ReplicaSSHDnsRecord:
+      Type: AWS::Route53::RecordSet
+      Properties:
+        Name: !Sub '${SshSubdomain}.${HostedZoneName}'
+        HostedZoneName: !Sub '${HostedZoneName}.'
+        Comment: DNS name for Load Balancer serving SSH requests to gerrit replicas
+        Type: A
+        AliasTarget:
+          DNSName: !GetAtt 'ReplicaSSHLoadBalancer.DNSName'
+          HostedZoneId: !GetAtt 'ReplicaSSHLoadBalancer.CanonicalHostedZoneID'
+          EvaluateTargetHealth: False
+
+    ReplicaHTTPDnsRecord:
+      Type: AWS::Route53::RecordSet
+      Properties:
+        Name: !Sub '${HttpSubdomain}.${HostedZoneName}'
+        HostedZoneName: !Sub '${HostedZoneName}.'
+        Comment: DNS name for Load Balancer serving HTTP requests to gerrit replicas
+        Type: A
+        AliasTarget:
+          DNSName: !GetAtt 'ReplicaHTTPLoadBalancer.DNSName'
+          HostedZoneId: !GetAtt 'ReplicaHTTPLoadBalancer.CanonicalHostedZoneID'
+          EvaluateTargetHealth: False
 
     ECSTaskExecutionRoleStack:
       Type: AWS::CloudFormation::Stack
@@ -567,33 +617,62 @@
         TimeoutInMinutes: '5'
 
 Outputs:
-  PublicLoadBalancerDNSName:
-    Description: The DNS name of the external load balancer
-    Value: !GetAtt 'LoadBalancer.DNSName'
+  ########
+  # HTTP #
+  ########
+  ReplicaHTTPLoadBalancerDNSName:
+    Description: The DNS name of the replica HTTP load balancer
+    Value: !GetAtt 'ReplicaHTTPLoadBalancer.DNSName'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerDNSName' ] ]
-  CanonicalHostedZoneID:
-    Description: Canonical Hosted Zone ID
-    Value: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaHTTPLoadBalancerDNSName' ] ]
+  ReplicaHTTPCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the replica HTTP load balancer
+    Value: !GetAtt 'ReplicaHTTPLoadBalancer.CanonicalHostedZoneID'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalHostedZoneID' ] ]
-  PublicLoadBalancerUrl:
-    Description: The url of the external load balancer
-    Value: !Join ['', ['http://', !GetAtt 'LoadBalancer.DNSName']]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaHTTPCanonicalHostedZoneID' ] ]
+  ReplicaHTTPLoadBalancerUrl:
+    Description: The url of the replica HTTP load balancer
+    Value: !Join ['', ['http://', !GetAtt 'ReplicaHTTPLoadBalancer.DNSName']]
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerUrl' ] ]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaHTTPLoadBalancerUrl' ] ]
+  #######
+  # SSH #
+  #######
+  ReplicaSSHLoadBalancerDNSName:
+    Description: The DNS name of the replica SSH load balancer
+    Value: !GetAtt 'ReplicaSSHLoadBalancer.DNSName'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaSSHLoadBalancerDNSName' ] ]
+  ReplicaSSHCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the replica SSH load balancer
+    Value: !GetAtt 'ReplicaSSHLoadBalancer.CanonicalHostedZoneID'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaSSHCanonicalHostedZoneID' ] ]
+  ReplicaSSHLoadBalancerUrl:
+    Description: The url of the replica SSH load balancer
+    Value: !Join ['', ['http://', !GetAtt 'ReplicaSSHLoadBalancer.DNSName']]
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaSSHLoadBalancerUrl' ] ]
+  #######
+  # DNS #
+  #######
   HostedZoneName:
     Description: Route53 Hosted Zone name
     Value: !Ref HostedZoneName
     Export:
       Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HostedZoneName' ] ]
-  Subdomain:
-    Description: Service DNS subdomain
-    Value: !Ref Subdomain
+  HttpSubdomain:
+    Description: Service DNS subdomain for replicas HTTP traffic
+    Value: !Ref HttpSubdomain
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'Subdomain' ] ]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HttpSubdomain' ] ]
+  SshSubdomain:
+    Description: Service DNS subdomain for replicas SSH traffic
+    Value: !Ref SshSubdomain
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'SshSubdomain' ] ]
   CanonicalWebUrl:
     Description: Canonical Web URL
-    Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+    Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
     Export:
       Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalWebUrl' ] ]
diff --git a/dual-primary/setup.env.template b/dual-primary/setup.env.template
index 8f76af9..663e9e1 100644
--- a/dual-primary/setup.env.template
+++ b/dual-primary/setup.env.template
@@ -14,12 +14,20 @@
 SERVICE_REPLICA_STACK_NAME:=$(AWS_PREFIX)-service-replica
 DNS_ROUTING_STACK_NAME:=$(AWS_PREFIX)-dns-routing
 DASHBOARD_STACK_NAME:=$(AWS_PREFIX)-dashboard
-LOAD_BALANCER_STACK_NAME:=$(AWS_PREFIX)-load-balancer
 HOSTED_ZONE_NAME:=yourcompany.com
-PRIMARY1_SUBDOMAIN:=$(AWS_PREFIX)-primary-1.gerrit-demo
-PRIMARY2_SUBDOMAIN:=$(AWS_PREFIX)-primary-2.gerrit-demo
-REPLICA_SUBDOMAIN:=$(AWS_PREFIX)-replica.gerrit-demo
-PRIMARIES_GERRIT_SUBDOMAIN=$(AWS_PREFIX)-primaries.gerrit-demo
+
+HTTP_PRIMARY1_SUBDOMAIN:=$(AWS_PREFIX)-http-primary-1.gerrit-demo
+SSH_PRIMARY1_SUBDOMAIN:=$(AWS_PREFIX)-ssh-primary-1.gerrit-demo
+
+HTTP_PRIMARY2_SUBDOMAIN:=$(AWS_PREFIX)-http-primary-2.gerrit-demo
+SSH_PRIMARY2_SUBDOMAIN:=$(AWS_PREFIX)-ssh-primary-2.gerrit-demo
+
+HTTP_REPLICA_SUBDOMAIN:=$(AWS_PREFIX)-http-replica.gerrit-demo
+SSH_REPLICA_SUBDOMAIN:=$(AWS_PREFIX)-ssh-replica.gerrit-demo
+
+HTTP_PRIMARIES_GERRIT_SUBDOMAIN=$(AWS_PREFIX)-http-primaries.gerrit-demo
+SSH_PRIMARIES_GERRIT_SUBDOMAIN=$(AWS_PREFIX)-ssh-primaries.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
 GERRIT_RAM=6000
diff --git a/gerrit/etc/gerrit.config.template b/gerrit/etc/gerrit.config.template
index 7488c31..0656386 100644
--- a/gerrit/etc/gerrit.config.template
+++ b/gerrit/etc/gerrit.config.template
@@ -51,6 +51,9 @@
 
 [sshd]
 	listenAddress = *:29418
+{% if SSHD_ADVERTISED_ADDRESS %}
+    advertisedAddress = {{ SSHD_ADVERTISED_ADDRESS }}
+{% endif %}
 [httpd]
 	listenUrl = http://*:8080/
 	requestLog = true
diff --git a/gerrit/setup_gerrit.py b/gerrit/setup_gerrit.py
index 74ecdba..d18d95d 100755
--- a/gerrit/setup_gerrit.py
+++ b/gerrit/setup_gerrit.py
@@ -173,6 +173,7 @@
         'REFS_DB_ENABLED': os.getenv('REFS_DB_ENABLED'),
         'DYNAMODB_LOCKS_TABLE_NAME': os.getenv('DYNAMODB_LOCKS_TABLE_NAME'),
         'DYNAMODB_REFS_TABLE_NAME': os.getenv('DYNAMODB_REFS_TABLE_NAME'),
+        'SSHD_ADVERTISED_ADDRESS': os.getenv('SSHD_ADVERTISED_ADDRESS'),
     })
     f.write(template.render(config_for_template))
 
diff --git a/primary-replica/Makefile b/primary-replica/Makefile
index 0afea75..fce2cb8 100644
--- a/primary-replica/Makefile
+++ b/primary-replica/Makefile
@@ -82,8 +82,9 @@
 		ParameterKey=ClusterStackName,ParameterValue=$(CLUSTER_STACK_NAME) \
 		ParameterKey=TemplateBucketName,ParameterValue=$(TEMPLATE_BUCKET_NAME) \
 		ParameterKey=HostedZoneName,ParameterValue=$(HOSTED_ZONE_NAME) \
-		ParameterKey=Subdomain,ParameterValue=$(PRIMARY_SUBDOMAIN) \
-		ParameterKey=ReplicaSubdomain,ParameterValue=$(REPLICA_SUBDOMAIN) \
+		ParameterKey=HttpSubdomain,ParameterValue=$(HTTP_PRIMARY_SUBDOMAIN) \
+		ParameterKey=SshSubdomain,ParameterValue=$(SSH_PRIMARY_SUBDOMAIN) \
+		ParameterKey=SshReplicaSubdomain,ParameterValue=$(SSH_REPLICA_SUBDOMAIN) \
 		ParameterKey=DockerRegistryUrl,ParameterValue=$(DOCKER_REGISTRY_URI) \
 		ParameterKey=CertificateArn,ParameterValue=$(SSL_CERTIFICATE_ARN) \
 		ParameterKey=ReplicaServiceStackName,ParameterValue=$(SERVICE_REPLICA_STACK_NAME) \
@@ -127,7 +128,8 @@
 		ParameterKey=ClusterStackName,ParameterValue=$(CLUSTER_STACK_NAME) \
 		ParameterKey=TemplateBucketName,ParameterValue=$(TEMPLATE_BUCKET_NAME) \
 		ParameterKey=HostedZoneName,ParameterValue=$(HOSTED_ZONE_NAME) \
-		ParameterKey=Subdomain,ParameterValue=$(REPLICA_SUBDOMAIN) \
+		ParameterKey=HttpSubdomain,ParameterValue=$(HTTP_REPLICA_SUBDOMAIN) \
+		ParameterKey=SshSubdomain,ParameterValue=$(SSH_REPLICA_SUBDOMAIN) \
 		ParameterKey=DockerRegistryUrl,ParameterValue=$(DOCKER_REGISTRY_URI) \
 		ParameterKey=CertificateArn,ParameterValue=$(SSL_CERTIFICATE_ARN) \
 		ParameterKey=GerritKeyPrefix,ParameterValue=$(GERRIT_KEY_PREFIX)\
@@ -151,8 +153,7 @@
 		--template-body file://`pwd`/$(DNS_ROUTING_TEMPLATE) \
 		--region $(AWS_REGION) \
 		--parameters \
-		ParameterKey=PrimaryServiceStackName,ParameterValue=$(SERVICE_PRIMARY_STACK_NAME) \
-		ParameterKey=ReplicaServiceStackName,ParameterValue=$(SERVICE_REPLICA_STACK_NAME)
+		ParameterKey=PrimaryServiceStackName,ParameterValue=$(SERVICE_PRIMARY_STACK_NAME)
 
 dashboard:
 ifeq ($(METRICS_CLOUDWATCH_ENABLED),true)
diff --git a/primary-replica/README.md b/primary-replica/README.md
index d710050..9cff49c 100644
--- a/primary-replica/README.md
+++ b/primary-replica/README.md
@@ -56,8 +56,10 @@
 * `SERVICE_PRIMARY_STACK_NAME`: Optional. Name of the primary service stack. `gerrit-service-primary` by default.
 * `SERVICE_REPLICA_STACK_NAME`: Optional. Name of the replica service stack. `gerrit-service-replica` by default.
 * `DASHBOARD_STACK_NAME` : Optional. Name of the dashboard stack. `gerrit-dashboard` by default.
-* `PRIMARY_SUBDOMAIN`: Optional. Name of the primary sub domain. `gerrit-primary-demo` by default.
-* `REPLICA_SUBDOMAIN`: Optional. Name of the replica sub domain. `gerrit-replica-demo` by default.
+* `HTTP_PRIMARY_SUBDOMAIN`: Optional. Name of the primary sub domain for HTTP traffic. `gerrit-http-primary-demo` by default.
+* `SSH_PRIMARY_SUBDOMAIN`: Optional. Name of the primary sub domain for SSH traffic. `gerrit-ssh-primary-demo` by default.
+* `HTTP_REPLICA_SUBDOMAIN`: Optional. Name of the replica sub domain for HTTP traffic. `gerrit-http-replica-demo` by default.
+* `SSH_REPLICA_SUBDOMAIN`: Optional. Name of the replica sub domain for SSH traffic. `gerrit-ssh-replica-demo` by default.
 * `GERRIT_PRIMARY_INSTANCE_ID`: Optional. Identifier for the Gerrit primary instance.
 "gerrit-primary-replica-PRIMARY" by default.
 * `GERRIT_REPLICA_INSTANCE_ID`: Optional. Identifier for the Gerrit replica instance.
diff --git a/primary-replica/cf-dns-route.yml b/primary-replica/cf-dns-route.yml
index ec9b369..eb19872 100644
--- a/primary-replica/cf-dns-route.yml
+++ b/primary-replica/cf-dns-route.yml
@@ -5,32 +5,52 @@
       Description: Stack name of the ECS Primary Gerrit service
       Type: String
       Default: gerrit-service-primary
-  ReplicaServiceStackName:
-      Description: Stack name of the ECS Replica Gerrit service
-      Type: String
-      Default: gerrit-service-replica
 
 Resources:
-  PrimaryDnsRecord:
+  PrimaryHTTPDnsRecord:
       Type: AWS::Route53::RecordSet
       Properties:
         Name:
           !Join
             - '.'
-            - - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'Subdomain']]
+            - - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'HttpSubdomain']]
               - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'HostedZoneName']]
         HostedZoneName:
           !Join
             - ''
             - - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'HostedZoneName']]
               - '.'
-        Comment: DNS name for Gerrit Primary.
+        Comment: DNS name for Load Balancer serving HTTP requests to primary gerrit
         Type: A
         AliasTarget:
           DNSName:
             Fn::ImportValue:
-              !Join [':', [!Ref 'PrimaryServiceStackName', 'PublicLoadBalancerDNSName']]
+              !Join [':', [!Ref 'PrimaryServiceStackName', 'GerritHTTPLoadBalancerDNSName']]
           HostedZoneId:
             Fn::ImportValue:
-              !Join [':', [!Ref 'PrimaryServiceStackName', 'CanonicalHostedZoneID']]
+              !Join [':', [!Ref 'PrimaryServiceStackName', 'GerritHTTPCanonicalHostedZoneID']]
           EvaluateTargetHealth: False
+
+  PrimarySSHDnsRecord:
+    Type: AWS::Route53::RecordSet
+    Properties:
+      Name:
+        !Join
+        - '.'
+        - - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'SshSubdomain']]
+          - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'HostedZoneName']]
+      HostedZoneName:
+        !Join
+        - ''
+        - - Fn::ImportValue: !Join [':', [!Ref 'PrimaryServiceStackName', 'HostedZoneName']]
+          - '.'
+      Comment: DNS name for Load Balancer serving SSH requests to primary gerrit
+      Type: A
+      AliasTarget:
+        DNSName:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'PrimaryServiceStackName', 'GerritSSHLoadBalancerDNSName']]
+        HostedZoneId:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'PrimaryServiceStackName', 'GerritSSHCanonicalHostedZoneID']]
+        EvaluateTargetHealth: False
\ No newline at end of file
diff --git a/primary-replica/cf-service-primary.yml b/primary-replica/cf-service-primary.yml
index aed8067..10a0642 100644
--- a/primary-replica/cf-service-primary.yml
+++ b/primary-replica/cf-service-primary.yml
@@ -55,18 +55,22 @@
   HostedZoneName:
         Description: The route53 HostedZoneName.
         Type: String
-  Subdomain:
-        Description: The subdomain of the Gerrit cluster
+  HttpSubdomain:
+        Description: The subdomain of the loadbalancer serving HTTP traffic for the primary Gerrit
         Type: String
-        Default: gerrit-primary-demo
+        Default: gerrit-primary-http-demo
+  SshSubdomain:
+    Description: The subdomain of the loadbalancer serving SSH traffic for the primary Gerrit
+    Type: String
+    Default: gerrit-primary-ssh-demo
   LoadBalancerScheme:
         Description: Load Balancer schema, The nodes of an Internet-facing load balancer have public IP addresses.
         Type: String
         Default: internet-facing
         AllowedValues: [internal, internet-facing]
-  ReplicaSubdomain:
-        Description: The subdomain of the Gerrit replica
-        Type: String
+  SshReplicaSubdomain:
+    Description: The subdomain of the loadbalancer serving SSH traffic for the replicas
+    Type: String
   GerritKeyPrefix:
         Description: Gerrit credentials keys prefix
         Type: String
@@ -219,7 +223,9 @@
                   Image: !Sub '${DockerRegistryUrl}/${DockerImage}'
                   Environment:
                     - Name: CANONICAL_WEB_URL
-                      Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+                      Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
+                    - Name: SSHD_ADVERTISED_ADDRESS
+                      Value: !Sub '${SshSubdomain}.${HostedZoneName}:${SSHPort}'
                     - Name: HTTPD_LISTEN_URL
                       Value: !Sub 'proxy-https://*:${HTTPPort}/'
                     - Name: AWS_REGION
@@ -263,7 +269,7 @@
                     - Name: GIT_SSH_PORT
                       Value: !Ref GitSSHPort
                     - Name: REPLICA_SUBDOMAIN
-                      Value: !Ref ReplicaSubdomain
+                      Value: !Ref SshReplicaSubdomain
                     - Name: HOSTED_ZONE_NAME
                       Value: !Ref HostedZoneName
                     - Name: REINDEX_AT_STARTUP
@@ -334,9 +340,47 @@
                 Host:
                   SourcePath: !Join ['/', ["/gerrit-mount-point", !FindInMap ['Gerrit', 'Volume', 'Logs']]]
 
-    LoadBalancer:
+    GerritHTTPLoadBalancerSG:
+      Type: AWS::EC2::SecurityGroup
+      Properties:
+        VpcId:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+        GroupDescription: "Allow public HTTPS traffic to primary Gerrit"
+        GroupName: !Sub '${ClusterStackName}-gerrit-http-sg'
+        SecurityGroupIngress:
+          - IpProtocol: 'tcp'
+            FromPort: !Ref HTTPSPort
+            ToPort: !Ref HTTPSPort
+            CidrIp: '0.0.0.0/0'
+            Description: "HTTPS connections from everywhere (IPv4)"
+          - IpProtocol: 'tcp'
+            FromPort: !Ref HTTPSPort
+            ToPort: !Ref HTTPSPort
+            CidrIpv6: '::/0'
+            Description: "HTTPS connections from everywhere (IPv6)"
+
+    GerritHTTPLoadBalancer:
+      Type: AWS::ElasticLoadBalancingV2::LoadBalancer
+      Properties:
+        Name: !Sub '${ClusterStackName}-primary-http'
+        Type: application
+        Scheme: !Ref 'LoadBalancerScheme'
+        SecurityGroups:
+          - !Ref GerritHTTPLoadBalancerSG
+        Subnets:
+          - Fn::ImportValue:
+              !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetOne']]
+          - Fn::ImportValue:
+              !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetTwo']]
+        Tags:
+          - Key: Name
+            Value: !Join ['-', [!Ref 'EnvironmentName', !Ref 'GerritServiceName', 'alb']]
+
+    GerritSSHLoadBalancer:
         Type: AWS::ElasticLoadBalancingV2::LoadBalancer
         Properties:
+            Name: !Sub '${ClusterStackName}-primary-ssh'
             Type: network
             Scheme: !Ref 'LoadBalancerScheme'
             LoadBalancerAttributes:
@@ -353,34 +397,33 @@
 
     HTTPTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: GerritHTTPLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
                   !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
             Port: !Ref HTTPPort
-            Protocol: TCP
+            Protocol: HTTP
             HealthCheckProtocol: HTTP
             HealthCheckPort: !Ref HTTPPort
             HealthCheckPath: '/config/server/healthcheck~status'
-            Name: 'gerrit-primary-http'
+            Name: !Sub '${ClusterStackName}-primary-http'
 
     HTTPListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             Certificates:
               - CertificateArn: !Ref CertificateArn
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref HTTPTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref GerritHTTPLoadBalancer
             Port: !Ref HTTPSPort
-            Protocol: TLS
+            Protocol: HTTPS
 
     SSHTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: GerritSSHLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
@@ -390,16 +433,15 @@
             HealthCheckProtocol: HTTP
             HealthCheckPort: !Ref HTTPPort
             HealthCheckPath: '/config/server/healthcheck~status'
-            Name: 'gerrit-primary-ssh'
+            Name: !Sub '${ClusterStackName}-primary-ssh'
 
     SSHListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref SSHTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref GerritSSHLoadBalancer
             Port: !Ref SSHPort
             Protocol: TCP
 
@@ -410,33 +452,62 @@
         TimeoutInMinutes: '5'
 
 Outputs:
-  PublicLoadBalancerDNSName:
-    Description: The DNS name of the external load balancer
-    Value: !GetAtt 'LoadBalancer.DNSName'
+  ########
+  # HTTP #
+  ########
+  GerritHTTPLoadBalancerDNSName:
+    Description: The DNS name of the gerrit HTTP load balancer
+    Value: !GetAtt 'GerritHTTPLoadBalancer.DNSName'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerDNSName' ] ]
-  CanonicalHostedZoneID:
-    Description: Canonical Hosted Zone ID
-    Value: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPLoadBalancerDNSName' ] ]
+  GerritHTTPCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the gerrit HTTP load balancer
+    Value: !GetAtt 'GerritHTTPLoadBalancer.CanonicalHostedZoneID'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalHostedZoneID' ] ]
-  PublicLoadBalancerUrl:
-    Description: The url of the external load balancer
-    Value: !Join ['', ['http://', !GetAtt 'LoadBalancer.DNSName']]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPCanonicalHostedZoneID' ] ]
+  GerritHTTPLoadBalancerUrl:
+    Description: The url of the gerrit HTTP load balancer
+    Value: !Join ['', ['http://', !GetAtt 'GerritHTTPLoadBalancer.DNSName']]
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerUrl' ] ]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPLoadBalancerUrl' ] ]
+  #######
+  # SSH #
+  #######
+  GerritSSHLoadBalancerDNSName:
+    Description: The DNS name of the gerrit SSH load balancer
+    Value: !GetAtt 'GerritSSHLoadBalancer.DNSName'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHLoadBalancerDNSName' ] ]
+  GerritSSHCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the gerrit SSH load balancer
+    Value: !GetAtt 'GerritSSHLoadBalancer.CanonicalHostedZoneID'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHCanonicalHostedZoneID' ] ]
+  GerritSSHLoadBalancerUrl:
+    Description: The url of the gerrit SSH load balancer
+    Value: !Join ['', ['http://', !GetAtt 'GerritSSHLoadBalancer.DNSName']]
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHLoadBalancerUrl' ] ]
+  #######
+  # DNS #
+  #######
   HostedZoneName:
     Description: Route53 Hosted Zone name
     Value: !Ref HostedZoneName
     Export:
       Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HostedZoneName' ] ]
-  Subdomain:
-    Description: Service DNS subdomain
-    Value: !Ref Subdomain
+  HttpSubdomain:
+    Description: Service DNS subdomain for gerrit HTTP traffic
+    Value: !Ref HttpSubdomain
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'Subdomain' ] ]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HttpSubdomain' ] ]
+  SshSubdomain:
+    Description: Service DNS subdomain for gerrit SSH traffic
+    Value: !Ref SshSubdomain
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'SshSubdomain' ] ]
   CanonicalWebUrl:
     Description: Canonical Web URL
-    Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+    Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
     Export:
       Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalWebUrl' ] ]
diff --git a/primary-replica/cf-service-replica.yml b/primary-replica/cf-service-replica.yml
index bf8be87..e7a75df 100644
--- a/primary-replica/cf-service-replica.yml
+++ b/primary-replica/cf-service-replica.yml
@@ -74,10 +74,14 @@
   HostedZoneName:
       Description: The route53 HostedZoneName.
       Type: String
-  Subdomain:
-      Description: The subdomain of the Gerrit cluster
+  HttpSubdomain:
+      Description: The subdomain of the Gerrit loadbalancer serving HTTP traffic for replicas
       Type: String
-      Default: gerrit-replica-demo
+      Default: gerrit-http-replica-demo
+  SshSubdomain:
+    Description: The subdomain of the Gerrit loadbalancer serving SSH traffic for replicas
+    Type: String
+    Default: gerrit-ssh-replica-demo
   LoadBalancerScheme:
       Description: Load Balancer schema, The nodes of an Internet-facing load balancer have public IP addresses.
       Type: String
@@ -257,7 +261,9 @@
                   Image: !Sub '${DockerRegistryUrl}/${GerritDockerImage}'
                   Environment:
                     - Name: CANONICAL_WEB_URL
-                      Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+                      Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
+                    - Name: SSHD_ADVERTISED_ADDRESS
+                      Value: !Sub '${SshSubdomain}.${HostedZoneName}:${SSHHostPort}'
                     - Name: HTTPD_LISTEN_URL
                       Value: !Sub 'proxy-https://*:${HTTPContainePort}/'
                     - Name: CONTAINER_REPLICA
@@ -428,9 +434,47 @@
               - '/'
               - !GetAtt GerritService.Name
 
-    LoadBalancer:
+    ReplicaHTTPLoadBalancerSG:
+      Type: AWS::EC2::SecurityGroup
+      Properties:
+        VpcId:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+        GroupDescription: "Allow public HTTPS traffic to replicas"
+        GroupName: !Sub '${ClusterStackName}-replica-http-sg'
+        SecurityGroupIngress:
+          - IpProtocol: 'tcp'
+            FromPort: !Ref HTTPSPort
+            ToPort: !Ref HTTPSPort
+            CidrIp: '0.0.0.0/0'
+            Description: "HTTPS connections from everywhere (IPv4)"
+          - IpProtocol: 'tcp'
+            FromPort: !Ref HTTPSPort
+            ToPort: !Ref HTTPSPort
+            CidrIpv6: '::/0'
+            Description: "HTTPS connections from everywhere (IPv6)"
+
+    ReplicaHTTPLoadBalancer:
+      Type: AWS::ElasticLoadBalancingV2::LoadBalancer
+      Properties:
+        Name: !Sub '${ClusterStackName}-replica-http'
+        Type: application
+        Scheme: !Ref 'LoadBalancerScheme'
+        SecurityGroups:
+          - !Ref ReplicaHTTPLoadBalancerSG
+        Subnets:
+          - Fn::ImportValue:
+              !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetOne']]
+          - Fn::ImportValue:
+              !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetTwo']]
+        Tags:
+          - Key: Name
+            Value: !Join ['-', [!Ref 'EnvironmentName', !Ref 'GerritServiceName', 'alb']]
+
+    ReplicaSSHLoadBalancer:
         Type: AWS::ElasticLoadBalancingV2::LoadBalancer
         Properties:
+            Name: !Sub '${ClusterStackName}-replica-ssh'
             Type: network
             Scheme: !Ref 'LoadBalancerScheme'
             LoadBalancerAttributes:
@@ -447,41 +491,38 @@
 
     HTTPTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: ReplicaHTTPLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
                   !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
             Port: !Ref HTTPHostPort
-            Protocol: TCP
+            Protocol: HTTP
             HealthCheckPort: !Ref HTTPHostPort
             HealthCheckProtocol: HTTP
             HealthCheckPath: '/config/server/healthcheck~status'
-            Name: 'gerrit-replica-http'
+            Name: !Sub '${ClusterStackName}-replica-http'
             TargetGroupAttributes:
               - Key: 'stickiness.enabled'
                 Value: true
-              # NLB only supports source_ip. Move this to `lb_cookie` or `app_cookie`
-              # when this target group is moved behind an ALB
               - Key: 'stickiness.type'
-                Value: 'source_ip'
+                Value: 'lb_cookie'
 
     HTTPListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             Certificates:
               - CertificateArn: !Ref CertificateArn
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref HTTPTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref ReplicaHTTPLoadBalancer
             Port: !Ref HTTPSPort
-            Protocol: TLS
+            Protocol: HTTPS
 
     SSHTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: ReplicaSSHLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
@@ -491,22 +532,21 @@
             HealthCheckPort: !Ref HTTPHostPort
             HealthCheckProtocol: HTTP
             HealthCheckPath: '/config/server/healthcheck~status'
-            Name: 'gerrit-replica-ssh'
+            Name: !Sub '${ClusterStackName}-replica-ssh'
 
     SSHListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref SSHTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref ReplicaSSHLoadBalancer
             Port: !Ref SSHHostPort
             Protocol: TCP
 
     GitTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: ReplicaSSHLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
@@ -516,18 +556,17 @@
 
     GitListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref GitTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref ReplicaSSHLoadBalancer
             Port: !Ref GitPort
             Protocol: TCP
 
     GitSSHTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: ReplicaSSHLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
@@ -537,27 +576,38 @@
 
     GitSSHListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref GitSSHTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref ReplicaSSHLoadBalancer
             Port: !Ref GitSSHPort
             Protocol: TCP
 
-    ReplicaDnsRecord:
+    ReplicaSSHDnsRecord:
         Type: AWS::Route53::RecordSet
         Properties:
-          Name: !Sub '${Subdomain}.${HostedZoneName}'
+          Name: !Sub '${SshSubdomain}.${HostedZoneName}'
           HostedZoneName: !Sub '${HostedZoneName}.'
-          Comment: DNS name for Gerrit Replica.
+          Comment: DNS name for Load Balancer serving SSH requests to gerrit replicas
           Type: A
           AliasTarget:
-            DNSName: !GetAtt 'LoadBalancer.DNSName'
-            HostedZoneId: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
+            DNSName: !GetAtt 'ReplicaSSHLoadBalancer.DNSName'
+            HostedZoneId: !GetAtt 'ReplicaSSHLoadBalancer.CanonicalHostedZoneID'
             EvaluateTargetHealth: False
 
+    ReplicaHTTPDnsRecord:
+      Type: AWS::Route53::RecordSet
+      Properties:
+        Name: !Sub '${HttpSubdomain}.${HostedZoneName}'
+        HostedZoneName: !Sub '${HostedZoneName}.'
+        Comment: DNS name for Load Balancer serving HTTP requests to gerrit replicas
+        Type: A
+        AliasTarget:
+          DNSName: !GetAtt 'ReplicaHTTPLoadBalancer.DNSName'
+          HostedZoneId: !GetAtt 'ReplicaHTTPLoadBalancer.CanonicalHostedZoneID'
+          EvaluateTargetHealth: False
+
     ECSTaskExecutionRoleStack:
       Type: AWS::CloudFormation::Stack
       Properties:
@@ -565,33 +615,62 @@
         TimeoutInMinutes: '5'
 
 Outputs:
-  PublicLoadBalancerDNSName:
-    Description: The DNS name of the external load balancer
-    Value: !GetAtt 'LoadBalancer.DNSName'
+  ########
+  # HTTP #
+  ########
+  ReplicaHTTPLoadBalancerDNSName:
+    Description: The DNS name of the replica HTTP load balancer
+    Value: !GetAtt 'ReplicaHTTPLoadBalancer.DNSName'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerDNSName' ] ]
-  CanonicalHostedZoneID:
-    Description: Canonical Hosted Zone ID
-    Value: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaHTTPLoadBalancerDNSName' ] ]
+  ReplicaHTTPCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the replica HTTP load balancer
+    Value: !GetAtt 'ReplicaHTTPLoadBalancer.CanonicalHostedZoneID'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalHostedZoneID' ] ]
-  PublicLoadBalancerUrl:
-    Description: The url of the external load balancer
-    Value: !Join ['', ['http://', !GetAtt 'LoadBalancer.DNSName']]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaHTTPCanonicalHostedZoneID' ] ]
+  ReplicaHTTPLoadBalancerUrl:
+    Description: The url of the replica HTTP load balancer
+    Value: !Join ['', ['http://', !GetAtt 'ReplicaHTTPLoadBalancer.DNSName']]
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerUrl' ] ]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaHTTPLoadBalancerUrl' ] ]
+  #######
+  # SSH #
+  #######
+  ReplicaSSHLoadBalancerDNSName:
+    Description: The DNS name of the replica SSH load balancer
+    Value: !GetAtt 'ReplicaSSHLoadBalancer.DNSName'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaSSHLoadBalancerDNSName' ] ]
+  ReplicaSSHCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the replica SSH load balancer
+    Value: !GetAtt 'ReplicaSSHLoadBalancer.CanonicalHostedZoneID'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaSSHCanonicalHostedZoneID' ] ]
+  ReplicaSSHLoadBalancerUrl:
+    Description: The url of the replica SSH load balancer
+    Value: !Join ['', ['http://', !GetAtt 'ReplicaSSHLoadBalancer.DNSName']]
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ReplicaSSHLoadBalancerUrl' ] ]
+  #######
+  # DNS #
+  #######
   HostedZoneName:
     Description: Route53 Hosted Zone name
     Value: !Ref HostedZoneName
     Export:
       Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HostedZoneName' ] ]
-  Subdomain:
-    Description: Service DNS subdomain
-    Value: !Ref Subdomain
+  HttpSubdomain:
+    Description: Service DNS subdomain for replicas HTTP traffic
+    Value: !Ref HttpSubdomain
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'Subdomain' ] ]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HttpSubdomain' ] ]
+  SshSubdomain:
+    Description: Service DNS subdomain for replicas SSH traffic
+    Value: !Ref SshSubdomain
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'SshSubdomain' ] ]
   CanonicalWebUrl:
     Description: Canonical Web URL
-    Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+    Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
     Export:
       Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalWebUrl' ] ]
diff --git a/primary-replica/setup.env.template b/primary-replica/setup.env.template
index 8186090..4aade05 100644
--- a/primary-replica/setup.env.template
+++ b/primary-replica/setup.env.template
@@ -8,8 +8,10 @@
 DNS_ROUTING_MONITORING_STACK_NAME:=$(AWS_PREFIX)-monitoring-dns-routing
 DASHBOARD_STACK_NAME:=$(AWS_PREFIX)-dashboard
 HOSTED_ZONE_NAME:=yourcompany.com
-PRIMARY_SUBDOMAIN:=$(AWS_PREFIX)-primary.gerrit-demo
-REPLICA_SUBDOMAIN:=$(AWS_PREFIX)-replica.gerrit-demo
+HTTP_PRIMARY_SUBDOMAIN:=$(AWS_PREFIX)-http-primary.gerrit-demo
+SSH_PRIMARY_SUBDOMAIN:=$(AWS_PREFIX)-ssh-primary.gerrit-demo
+HTTP_REPLICA_SUBDOMAIN:=$(AWS_PREFIX)-http-replica.gerrit-demo
+SSH_REPLICA_SUBDOMAIN:=$(AWS_PREFIX)-ssh-replica.gerrit-demo
 PROMETHEUS_SUBDOMAIN:=$(AWS_PREFIX)-prometheus.gerrit-demo
 GRAFANA_SUBDOMAIN:=$(AWS_PREFIX)-grafana.gerrit-demo
 DOCKER_REGISTRY_URI:=<yourAccountId>.dkr.ecr.us-east-1.amazonaws.com
diff --git a/single-primary/Makefile b/single-primary/Makefile
index 067c9e8..4c62493 100644
--- a/single-primary/Makefile
+++ b/single-primary/Makefile
@@ -63,7 +63,8 @@
 		ParameterKey=ClusterStackName,ParameterValue=$(CLUSTER_STACK_NAME) \
 		ParameterKey=TemplateBucketName,ParameterValue=$(TEMPLATE_BUCKET_NAME) \
 		ParameterKey=HostedZoneName,ParameterValue=$(HOSTED_ZONE_NAME) \
-		ParameterKey=Subdomain,ParameterValue=$(SUBDOMAIN) \
+		ParameterKey=HttpSubdomain,ParameterValue=$(HTTP_SUBDOMAIN) \
+		ParameterKey=SshSubdomain,ParameterValue=$(SSH_SUBDOMAIN) \
 		ParameterKey=DockerRegistryUrl,ParameterValue=$(DOCKER_REGISTRY_URI) \
 		ParameterKey=CertificateArn,ParameterValue=$(SSL_CERTIFICATE_ARN) \
 		ParameterKey=GerritKeyPrefix,ParameterValue=$(GERRIT_KEY_PREFIX) \
diff --git a/single-primary/README.md b/single-primary/README.md
index 05bf3db..2aaa012 100644
--- a/single-primary/README.md
+++ b/single-primary/README.md
@@ -103,9 +103,11 @@
 
 ### Access your Gerrit
 
-You Gerrit instance will be available at this URL: `http://<HOSTED_ZONE_NAME>.<SUBDOMAIN>`.
+The Gerrit instance will be available at two different URLs, to handle HTTP and
+SSH traffic respectively:
 
-The available ports are `8080` for HTTP and `29418` for SSH.
+* HTTP traffic: `https://<HTTP_SUBDOMAIN>.<HOSTED_ZONE_NAME>:443`
+* SSH traffic: `ssh://<SSH_SUBDOMAIN>.<HOSTED_ZONE_NAME>:29418`
 
 ### External Services
 
diff --git a/single-primary/cf-dns-route.yml b/single-primary/cf-dns-route.yml
index bf0d474..9a25016 100644
--- a/single-primary/cf-dns-route.yml
+++ b/single-primary/cf-dns-route.yml
@@ -7,26 +7,50 @@
       Default: gerrit-service
 
 Resources:
-  DnsRecord:
+  GerritSSHDnsRecord:
       Type: AWS::Route53::RecordSet
       Properties:
         Name:
           !Join
             - '.'
-            - - Fn::ImportValue: !Join [':', [!Ref 'ServiceStackName', 'Subdomain']]
+            - - Fn::ImportValue: !Join [':', [!Ref 'ServiceStackName', 'SshSubdomain']]
               - Fn::ImportValue: !Join [':', [!Ref 'ServiceStackName', 'HostedZoneName']]
         HostedZoneName:
           !Join
             - ''
             - - Fn::ImportValue: !Join [':', [!Ref 'ServiceStackName', 'HostedZoneName']]
               - '.'
-        Comment: DNS name for Gerrit Primary.
+        Comment: DNS name for Load Balancer serving SSH requests to primary gerrit
         Type: A
         AliasTarget:
           DNSName:
             Fn::ImportValue:
-              !Join [':', [!Ref 'ServiceStackName', 'PublicLoadBalancerDNSName']]
+              !Join [':', [!Ref 'ServiceStackName', 'GerritSSHLoadBalancerDNSName']]
           HostedZoneId:
             Fn::ImportValue:
-              !Join [':', [!Ref 'ServiceStackName', 'CanonicalHostedZoneID']]
+              !Join [':', [!Ref 'ServiceStackName', 'GerritSSHCanonicalHostedZoneID']]
           EvaluateTargetHealth: False
+
+  GerritHTTPDnsRecord:
+    Type: AWS::Route53::RecordSet
+    Properties:
+      Name:
+        !Join
+          - '.'
+          - - Fn::ImportValue: !Join [':', [!Ref 'ServiceStackName', 'HttpSubdomain']]
+            - Fn::ImportValue: !Join [':', [!Ref 'ServiceStackName', 'HostedZoneName']]
+      HostedZoneName:
+        !Join
+        - ''
+        - - Fn::ImportValue: !Join [':', [!Ref 'ServiceStackName', 'HostedZoneName']]
+          - '.'
+      Comment: DNS name for Load Balancer serving HTTP requests to primary gerrit
+      Type: A
+      AliasTarget:
+        DNSName:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'ServiceStackName', 'GerritHTTPLoadBalancerDNSName']]
+        HostedZoneId:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'ServiceStackName', 'GerritHTTPCanonicalHostedZoneID']]
+        EvaluateTargetHealth: False
\ No newline at end of file
diff --git a/single-primary/cf-service.yml b/single-primary/cf-service.yml
index 1bebd2f..7b9fb06 100644
--- a/single-primary/cf-service.yml
+++ b/single-primary/cf-service.yml
@@ -44,10 +44,14 @@
   HostedZoneName:
         Description: The route53 HostedZoneName.
         Type: String
-  Subdomain:
-        Description: The subdomain of the Gerrit cluster
+  HttpSubdomain:
+        Description: The HTTP subdomain of the Gerrit cluster
         Type: String
-        Default: gerrit-primary-demo
+        Default: gerrit-http-primary-demo
+  SshSubdomain:
+    Description: The SSH subdomain of the Gerrit cluster
+    Type: String
+    Default: gerrit-ssh-primary-demo
   LoadBalancerScheme:
         Description: Load Balancer schema, The nodes of an Internet-facing load balancer have public IP addresses.
         Type: String
@@ -207,7 +211,9 @@
                   Image: !Sub '${DockerRegistryUrl}/${DockerImage}'
                   Environment:
                     - Name: CANONICAL_WEB_URL
-                      Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+                      Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
+                    - Name: SSHD_ADVERTISED_ADDRESS
+                      Value: !Sub '${SshSubdomain}.${HostedZoneName}:${SSHPort}'
                     - Name: HTTPD_LISTEN_URL
                       Value: !Sub 'proxy-https://*:${HTTPPort}/'
                     - Name: AWS_REGION
@@ -312,9 +318,48 @@
                 Host:
                   SourcePath: !Join ['/', ["/gerrit-mount-point", !FindInMap ['Gerrit', 'Volume', 'Logs']]]
 
-    LoadBalancer:
+    GerritHTTPLoadBalancerSG:
+      Type: AWS::EC2::SecurityGroup
+      Properties:
+        VpcId:
+          Fn::ImportValue:
+            !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+        GroupDescription: "Allow public HTTPS traffic"
+        GroupName: !Sub '${ClusterStackName}-primary-http'
+        SecurityGroupIngress:
+          - IpProtocol: 'tcp'
+            FromPort: !Ref HTTPSPort
+            ToPort: !Ref HTTPSPort
+            CidrIp: '0.0.0.0/0'
+            Description: "HTTPS connections from everywhere (IPv4)"
+          - IpProtocol: 'tcp'
+            FromPort: !Ref HTTPSPort
+            ToPort: !Ref HTTPSPort
+            CidrIpv6: '::/0'
+            Description: "HTTPS connections from everywhere (IPv6)"
+
+
+    GerritHTTPLoadBalancer:
+      Type: AWS::ElasticLoadBalancingV2::LoadBalancer
+      Properties:
+        Name: !Sub '${ClusterStackName}-primary-http'
+        Type: application
+        Scheme: !Ref 'LoadBalancerScheme'
+        SecurityGroups:
+          - !Ref GerritHTTPLoadBalancerSG
+        Subnets:
+          - Fn::ImportValue:
+              !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetOne']]
+          - Fn::ImportValue:
+              !Join [':', [!Ref 'ClusterStackName', 'PublicSubnetTwo']]
+        Tags:
+          - Key: Name
+            Value: !Join ['-', [!Ref 'EnvironmentName', !Ref 'GerritServiceName', 'alb']]
+
+    GerritSSHLoadBalancer:
         Type: AWS::ElasticLoadBalancingV2::LoadBalancer
         Properties:
+            Name: !Sub '${ClusterStackName}-primary-ssh'
             Type: network
             Scheme: !Ref 'LoadBalancerScheme'
             LoadBalancerAttributes:
@@ -331,34 +376,33 @@
 
     HTTPTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: GerritHTTPLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
-                  !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
+                !Join [':', [!Ref 'ClusterStackName', 'VPCId']]
             Port: !Ref HTTPPort
-            Protocol: TCP
+            Protocol: HTTP
             HealthCheckProtocol: HTTP
             HealthCheckPort: !Ref HTTPPort
             HealthCheckPath: '/config/server/healthcheck~status'
-            Name: 'gerrit-primary-http'
+            Name: !Sub '${ClusterStackName}-primary-http'
 
     HTTPListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             Certificates:
               - CertificateArn: !Ref CertificateArn
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref HTTPTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref GerritHTTPLoadBalancer
             Port: !Ref HTTPSPort
-            Protocol: TLS
+            Protocol: HTTPS
 
     SSHTargetGroup:
         Type: AWS::ElasticLoadBalancingV2::TargetGroup
-        DependsOn: LoadBalancer
+        DependsOn: GerritSSHLoadBalancer
         Properties:
             VpcId:
               Fn::ImportValue:
@@ -368,16 +412,15 @@
             HealthCheckProtocol: HTTP
             HealthCheckPort: !Ref HTTPPort
             HealthCheckPath: '/config/server/healthcheck~status'
-            Name: 'gerrit-primary-ssh'
+            Name: !Sub '${ClusterStackName}-primary-ssh'
 
     SSHListener:
         Type: AWS::ElasticLoadBalancingV2::Listener
-        DependsOn: LoadBalancer
         Properties:
             DefaultActions:
             - Type: forward
               TargetGroupArn: !Ref SSHTargetGroup
-            LoadBalancerArn: !Ref LoadBalancer
+            LoadBalancerArn: !Ref GerritSSHLoadBalancer
             Port: !Ref SSHPort
             Protocol: TCP
 
@@ -757,33 +800,62 @@
                 }
 
 Outputs:
-  PublicLoadBalancerDNSName:
-    Description: The DNS name of the external load balancer
-    Value: !GetAtt 'LoadBalancer.DNSName'
+  ########
+  # HTTP #
+  ########
+  GerritHTTPLoadBalancerDNSName:
+    Description: The DNS name of the Gerrit HTTP load balancer
+    Value: !GetAtt 'GerritHTTPLoadBalancer.DNSName'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerDNSName' ] ]
-  CanonicalHostedZoneID:
-    Description: Canonical Hosted Zone ID
-    Value: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPLoadBalancerDNSName' ] ]
+  GerritHTTPCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the Gerrit HTTP load balancer
+    Value: !GetAtt 'GerritHTTPLoadBalancer.CanonicalHostedZoneID'
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalHostedZoneID' ] ]
-  PublicLoadBalancerUrl:
-    Description: The url of the external load balancer
-    Value: !Join ['', ['http://', !GetAtt 'LoadBalancer.DNSName']]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPCanonicalHostedZoneID' ] ]
+  GerritHTTPLoadBalancerUrl:
+    Description: The url of the Gerrit HTTP load balancer
+    Value: !Join ['', ['http://', !GetAtt 'GerritHTTPLoadBalancer.DNSName']]
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicLoadBalancerUrl' ] ]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritHTTPLoadBalancerUrl' ] ]
+  #######
+  # SSH #
+  #######
+  GerritSSHLoadBalancerDNSName:
+    Description: The DNS name of the Gerrit SSH load balancer
+    Value: !GetAtt 'GerritSSHLoadBalancer.DNSName'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHLoadBalancerDNSName' ] ]
+  GerritSSHCanonicalHostedZoneID:
+    Description: Canonical Hosted Zone ID of the Gerrit SSH load balancer
+    Value: !GetAtt 'GerritSSHLoadBalancer.CanonicalHostedZoneID'
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHCanonicalHostedZoneID' ] ]
+  GerritSSHLoadBalancerUrl:
+    Description: The url of the Gerrit SSH load balancer
+    Value: !Join ['', ['http://', !GetAtt 'GerritSSHLoadBalancer.DNSName']]
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'GerritSSHLoadBalancerUrl' ] ]
+  #######
+  # DNS #
+  #######
   HostedZoneName:
     Description: Route53 Hosted Zone name
     Value: !Ref HostedZoneName
     Export:
       Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HostedZoneName' ] ]
-  Subdomain:
-    Description: Service DNS subdomain
-    Value: !Ref Subdomain
+  HttpSubdomain:
+    Description: Service DNS subdomain for HTTP traffic
+    Value: !Ref HttpSubdomain
     Export:
-      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'Subdomain' ] ]
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'HttpSubdomain' ] ]
+  SshSubdomain:
+    Description: Service DNS subdomain for SSH traffic
+    Value: !Ref SshSubdomain
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'SshSubdomain' ] ]
   CanonicalWebUrl:
     Description: Canonical Web URL
-    Value: !Sub 'https://${Subdomain}.${HostedZoneName}'
+    Value: !Sub 'https://${HttpSubdomain}.${HostedZoneName}'
     Export:
       Name: !Join [ ':', [ !Ref 'AWS::StackName', 'CanonicalWebUrl' ] ]
diff --git a/single-primary/setup.env.template b/single-primary/setup.env.template
index b3689d9..f7398dc 100644
--- a/single-primary/setup.env.template
+++ b/single-primary/setup.env.template
@@ -2,7 +2,8 @@
 CLUSTER_INSTANCE_TYPE:=m4.large
 DNS_ROUTING_STACK_NAME:=$(AWS_PREFIX)-dns-routing
 HOSTED_ZONE_NAME:=mycompany.com
-SUBDOMAIN:=$(AWS_PREFIX)-primary-demo
+HTTP_SUBDOMAIN:=$(AWS_PREFIX)-http-primary-demo
+SSH_SUBDOMAIN:=$(AWS_PREFIX)-ssh-primary-demo
 DOCKER_REGISTRY_URI:=<your_aws_account_number>.dkr.ecr.us-east-2.amazonaws.com
 SSL_CERTIFICATE_ARN=arn:aws:acm:us-east-2:<your_aws_account_number>:certificate/41eb8e52-c82b-420e-a5b2-d79107f3e5e1
 GERRIT_RAM=6000