1. Home
  2. Docs
  3. Infrastructure
  4. Rocket.Chat

Rocket.Chat

Rocket.Chat (upstream) is the basis of our Soluvas Chat product.

Resources

Deployment Architecture

Our Rocket.chat is deployed on:

  1. DigitalOcean, Singapore region:
  2. MongoDB Atlas, AWS Singapore region (lovia-sg cluster)
  3. Preconfigured Push Notification (for now, 1000 messages/month soft cap)

Kubernetes Deployment

We don’t use the Snap installation because we want to have flexibility to deploy bleeding edge code soon. We mirror the Docker Compose installation to setup the Kubernetes deployment. Although there is a Rocket.Chat helm chart [source], currently we’re not Helm-savvy enough to customize it. (Tip: Kompose may be used to convert docker-compose.yml to Kubernetes easily, but after that’s done we prefer doing it the hard way🤘)

⚠ Warning: There are two “official” Rocket.Chat images, rocketchat/rocket.chat is what we use, and not _/rocket.chat.

Repository: lovia/lovia-devops

Tip: To learn about Ingress & TLS LetsEncrypt in Kubernetes DigitalOcean, see:

  1. How to Install Software on Kubernetes Clusters with the Helm 3 Package Manager
  2. How To Set Up an Nginx Ingress on DigitalOcean Kubernetes Using Helm
D:\project_amanah\Lovia\lovia-devops\hello-kubernetes-first>kubectl port-forward service/hello-kubernetes-first 14000:80
Forwarding from 127.0.0.1:14000 -> 8080
Forwarding from [::1]:14000 -> 8080

Important: You’ll need to setup Nginx Ingress Controller first (perhaps with kind: DaemonSet).

Deploy rocketchat-ingress.yaml:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: lovia-chat-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    # https://github.com/nginxinc/kubernetes-ingress/issues/21#issuecomment-521338887
    nginx.ingress.kubernetes.io/proxy-body-size: 64m
    # https://pumpingco.de/blog/using-signalr-in-kubernetes-behind-nginx-ingress/
    nginx.ingress.kubernetes.io/affinity: cookie
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  # REQUIRES helm cert-manager
  tls:
    - hosts:
        - chat.lovia.life
      secretName: lovia-chat-tls
  rules:
    - host: chat.lovia.life
      http:
        paths:
          - backend:
              serviceName: lovia-chat-rocketchat
              servicePort: 80

Get the application URL by running these commands:

export HTTP_NODE_PORT=$(kubectl --namespace default get services -o jsonpath="{.spec.ports[0].nodePort}" nginx-ingress-controller)
export HTTPS_NODE_PORT=$(kubectl --namespace default get services -o jsonpath="{.spec.ports[1].nodePort}" nginx-ingress-controller)
export NODE_IP=$(kubectl --namespace default get nodes -o jsonpath="{.items[0].status.addresses[1].address}")

echo "Visit http://$NODE_IP:$HTTP_NODE_PORT to access your application via HTTP."
echo "Visit https://$NODE_IP:$HTTPS_NODE_PORT to access your application via HTTPS."

e.g. https://hw1.lovia.life:32020/

Prepare values.yaml first.

Install Rocket.Chat using Helm chart:

helm repo add stable https://kubernetes-charts.storage.googleapis.com
helm install lovia-chat -f values.yaml stable/rocketchat

Administration

File Upload: DigitalOcean Spaces

🔗 Minio in Rocket.Chat

SAML: Google Cloud Identity Platform

🔗 SAML Authentication in Rocket.Chat

Assets

Make sure icons and Safari pinned tab are set.

OpenID Connect (SSO) with FusionAuth

  1. Admin > OAuth > Setup FusionAuth OpenID Connect as Custom OAuth Provider.
    • URL: https://login.lovia.life
    • Token Path: /oauth2/token
    • Token Set Via: Header
    • Identity Token Sent Via: Same as “Token Sent Via”
    • Identity Path: /oauth2/userinfo
    • Authorize Path: /oauth2/authorize
    • Scope: offline_access
    • Param Name for access token: access_token
    • Id/Secret: ***
    • Login Style: Redirect
    • Button Text: Sign In
    • Username field: preferred_username
    • Name field: name
    • Avatar field: picture
    • Roles/Groups field name: roles
    • Merge Roles from SSO: checked
    • Show Button on Login Page: checked
  2. Admin > Accounts:
    1. Disable default login form.
    2. Disable: Allow User Avatar change.
    3. Disable: Allow Name change.
    4. Disable: Allow Username change.
    5. Disable: Allow Email change.
    6. Disable: Allow Password change.
    7. [Optional] Disable: Allow User Profile Change.
    8. Registration > Registration Form: Disabled.

The roles are only synced on first login, and not being refreshed on each login. Please see the bug report for current state.

Troubleshooting

{"line":"392","file":"oauth_server.js","message":"Error in OAuth Server: Failed to fetch identity from fusionauth at https://login.lovia.life/oauth2/userinfo. failed [401]","time":{"$date":1587229101993},"level":"warn"}
Exception while invoking method 'login' Error: Failed to fetch identity from fusionauth at https://login.lovia.life/oauth2/userinfo. failed [401]
    at CustomOAuth.getIdentity (app/custom-oauth/server/custom_oauth_server.js:282:18)
    at Object.handleOauthRequest (app/custom-oauth/server/custom_oauth_server.js:291:26)
    at OAuth._requestHandlers.<computed> (packages/oauth2/oauth2_server.js:10:33)
    at middleware (packages/oauth/oauth_server.js:161:5)
    at /app/bundle/programs/server/npm/node_modules/meteor/promise/node_modules/meteor-promise/fiber_pool.js:43:40

Cause/Solution: Whitelist headers in CloudFront.

Email

Admin > Email: Use port 587, make sure IgnoreTLS is unchecked.

CloudFront

Discussion: We probably should disable CloudFront on the main app server to minimize issues with caching behavior, SSL, etc. We can enable CloudFront again after we’re more confident with internal behavior of Rocket.Chat Server, Rocket.Chat React Native, and nginx-ingress. Currently we set CloudFront’s Default TTL to 0 but if problem persists then probably we can disable CloudFront entirely.

chat.lovia.life is fronted by CloudFront CDN d363egvcze92jw.cloudfront.net. These REST API headers must be whitelisted in addition to the usual headers:

  • X-User-Id
  • X-Auth-Token

File Upload: Switch from GridFS to AWS S3

It’s not entirely clear why GridFS is recommended by Rocket.Chat. But logically it increases overhead as it requires the app server to be a “reverse proxy” for GridFS. So we think AWS S3 is best suited for Rocket.Chat File Upload storage.

Quick steps:

  1. Create media-chat.lovia.life bucket in ap-southeast-1 region
    • Unblock public access
  2. Set bucket CORS configuration:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>https://chat.lovia.life</AllowedOrigin>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>
  1. Create IAM user lovia-rocketchat with limited inline policy:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ListObjectsInBucket",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::media-chat.lovia.life"
            ]
        },
        {
            "Sid": "AllObjectActions",
            "Effect": "Allow",
            "Action": [
                "s3:*Object",
                "s3:*ObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::media-chat.lovia.life/*"
            ]
        }
    ]
}
  1. Create CloudFront distribution for media-chat.lovia.life
  2. Add the CloudFront distribution CNAME (not proxied) to CloudFlare DNS
    • Use Alternate CNAME media-chat.lovia.life

Rocket. File Upload Configuration:

Bucket name: media-chat.lovia.life
Acl: (leave blank)
CDN Domain for Downloads: media-chat.lovia.life
Region: ap-southeast-1

CSS & Fonts

As recommended by our logo designer Dany Nofiyanto, we use Baloo 2 for headings and Montserrat / Open Sans for body text.

Administration > Layout:

CSS:

@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,400;0,700;1,400;1,700&amp;display=swap');

@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,400;0,700;1,400;1,700&amp;display=swap');

Font > Body text: 'Open Sans', sans-serif

Font > Body text: 'Montserrat', sans-serif

Google Summer of Code

Rocket.Chat has been a Google Summer of Code Organization in 2020, and hopefully in upcoming years. It’s good to help this effort by becoming mentors and/or students.

Was this article helpful to you? Yes No

How can we help?