Skip to content


Repository files navigation


This repository contains Terraform code to create an Jitsi Meet instance on AWS backed by an RDS Aurora Serverless database for authentication.

Table of Contents


You need the following before deploying this Terraform module:

  1. AWS Account and IAM Role to deploy these AWS resources
  2. Route53 Public Hosted Zone
  3. Route53 Private Hosted Zone
  4. OPTIONAL: If your Route53 zones are in a different AWS Account, the IAM Role in this account to create records in the above zones.


  • ✅ Jitsi Meet (Ubuntu 18.04)
    • ✅ Authentication (Users need to be authenticated to create new conferences) + Guest access (can only join existing conferences)
    • ✅ LetsEncrypt certificate for HTTPS
    • ✅ Collaborative working on a shared document during Jitsi conference (etherpad-lite)
    • ✅ SQL Database for Jitsi authorized accounts
  • ✅ Aurora Serverless
    • ✅ MySQL
    • ✅ Can scale down to 0 to reduce costs
    • ❌ PostgreSQL (can't yet scale down to zero)
  • ✅ AutoScalingGroup
    • ✅ ASG notifications (+ SNS Topic)
    • ❌ Mulitple EC2 instances (ASG > 1)
  • ✅ CloudWatch Logs (+ CloudWatch Agent)
  • ✅ Route53 Public & Private records
    • OPTIONAL: Cross-Account for Public & Private records
  • SecurityGroup
    • ✅ Allow SSH by workstation IPv4 (can be disabled)
    • ✅ Add other allowed IPv4 CIDRs for SSH
    • ✅ Restrict Jitsi access CIDRs (Default: not restricted)
  • OPTIONAL: AWS Key Pair (Default: true)
  • OPTIONAL: SSM Parameters for AWS Key Pair (Default: true)
  • OPTIONAL: Automatic EBS Snapshots via Data Lifecycle Manager (Default: true)


MySQL with cross-account

✔ Cross-account for Route53 records

✔ Allow additional CIDRs (+ your workstation's IPV4 CIDR) for SSH access

module "jitsi" {
  source  = "hajowieland/jitsi/aws"
  version = "1.0.0"

  aws_region = "eu-central-1"

  name   = "jitsi-meet"
  host   = "meet"
  domain = "" # should match public and private hosted zone
  # will result in FQDN =>

  ec2_instance_type = "t3a.large"
  vpc_id            = "vpc-123"
  public_subnet_ids = ["subnet-id-1", "subnet-id-2", "subnet-id-3"]
  # If the Route53 zones are in a different AWS Account:
  enable_cross_account = "1"
  arn_role             = "arn:aws:iam::other-account-id:role/route53-jitsi-other-account"

  public_zone_id  = "Z0123publiczone"
  private_zone_id = "Z456privatezone
  letsencrypt_email = ""

  # If you want to allow other SSH IPv4 CIDRs (in addition to your workstation's IPV4 address):
  ssh_cidrs = {
    "first-ip-to-allow"  = "",
    "second-ip-to-allow" = ""

MySQL with one account

✔ Cross-account for Route53 records

✔ Only allow your workstation's IPV4 CIDR for SSH access

module "jitsi" {
  source     = "hajowieland/jitsi/aws"
  version    = "1.0.0"

  aws_region = "eu-west-1"

  name   = "jitsi-meet"
  host   = "meet"
  domain = "" # should match public and private hosted zone
  # will result in FQDN =>

  db_driver  = "postgresql" # Set this for Postgres

  ec2_instance_type = "t3a.medium"
  vpc_id            = "vpc-123"
  public_subnet_ids = ["subnet-id-1", "subnet-id-2", "subnet-id-3"]
  public_zone_id  = "Z0819publiczone"
  private_zone_id = "Z134rivatezone
  letsencrypt_email = ""

Add authenticated Users

To create a new user in Prosody which can create new conferences, ssh into the Jitsi instance and execute:

prosodyctl adduser newuser@<HOST>.<DOMAIN>

# Example
prosodyctl adduser


  • ↪️ The Jitsi instance can be terminated at any time (AutoScalingGroup will then start a fresh new instance, but the authorized users in the SQL database will retain)
  • 💰To reduce costs, you can stop the instance (e.g. with diodonfrost/lambda-scheduler-stop-start) - Aurora Serverless will then scale down to zero.
  • If you do not specify a RDS DB Subnet Group (´var.db_subnet_group_name`), then the Aurora DB will be created in the same subnets as Jitsi (⚠️Public Subnets!)
  • When you enable var.enable_cross_account you need to specify (var.arn_role) an IAM role in the AWS Account where the Public & Private Route53 Zones reside in. This role has to have the policy to allow route53:ChangeResourceRecordSets on the desired Route53 Zones.
  • Route53 records will be created in UserData => during a terraform destroy these records have be deleted manually (see TODO)
  • Only MySQL is supported at the moment, because PostgreSQL in Aurora-Serverless can not scale down to zero



  • 08/02/2021: v1.1.0 (Thanks @leonardehrenfried )
  • 19/04/2020: Initial commit 🚀


  • Enable SG restriction of IPv6 subnets, too
  • Enable Clustering with multiple jvb-videobridges for high availability and load balancing
  • Aurora optional so user can provide pre-existing Aurora DB
  • Add PostgreSQL even if it does not support scaling down to zero
  • Create Terraform null_resource for destroy to delete Route53 records


Name Version
terraform ~> 0.12
aws ~> 2.40
http ~> 1.2
random ~> 2.2
tls ~> 2.1


Name Version
aws ~> 2.40
http ~> 1.2
random ~> 2.2
tls ~> 2.1


Name Description Type Default Required
allow_workstation_ipv4 Enable / Disable to allow workstation IPv4 address to be allowed in SecurityGroup for SSH access bool true no
apply_immediately Whether to apply changes to the cluster immediately or at the next maintenance window bool true no
arn_role ARN of IAM role to assume in cross-account scenarios string "" no
asg_metrics List of metrics to collect of AutoScalingGroup list(string)
aws_account_id AWS account ID string "" no
aws_region AWS Region (e.g. eu-central-1) string n/a yes
backup_retention_days Days for how long Backups will be retained number 30 no
backup_window Daily time range during automated backups (if enabled - Default = true) will are created (UTC) string "01:00-02:00" no
copy_tags Copy all user-defined tags on a source volume to snapshots of the volume created by this policy bool true no
cw_kms_arn KMS Key ARN for CloudWatch encryption string null no
cw_retention Specifies the number of days you want to retain log events in the specified log groups (e.g. 30 => 30 days) number 30 no
db_name Name of Database string "jitsi" no
db_subnet_group_name Name for DB subnet group to associate with this Aurora Cluster string null no
deletion_protection Enable / Disable deletion protection for this Aurora Cluster bool false no
domain The domain part of the Route53 A record referencing the Jitsi DNS (e.g. example for string n/a yes
ebs_size EBS root block device size in gigabytes (e.g. 20) number 10 no
ebs_type EBS root block device type (e.g. standard, gp2) string "gp2" no
ec2_instance_type EC2 instance type string n/a yes
enable_cross_account Enable cross-account with IAM Role to assume by UserData for updating of Route53 records (Valid values: 1 => Enable, 0 => Disable) string "0" no
enable_dlm Enable / Disable Data Lifecycle Manager for automatic EBS Snapshots bool true no
host The host part of the Route53 A record referencing the Jitsi DNS (e.g. jitsi for string "meet" no
jitsi_cidrs IPV4 CIDRs to allow for Jitsi access map(string)
"ALL-IPv4": ""
key_pair_name Name of pre-existing AWS Key Pair name to associate with Jitsi string null no
kms_key The ARN, ID or AliasARN for the KMS encryption key (RDS encryption-at-rest) string null no
letsencrypt_email E-Mail address for LetsEncrypt string n/a yes
name Name for all resources (preferably generated by terraform-null-label string "jitsi-meet" no
preferred_maintenance_window Weekly time range during which system changes can occur (in UTC - e.g. wed:04:00-wed:04:30 => Wednesday between 04:00-04:30) string "sun:02:30-sun:03:30" no
private_zone_id Route53 Private Hosted Zone ID to create Bastion Host DNS records string n/a yes
public_subnet_ids AutoScalingGroup Subnet IDs to create Jitsi Host into (=> public) list(string) n/a yes
public_zone_id Route53 Public Hosted Zone ID to create Bastion Host DNS records string n/a yes
retain_count How many snapshots to keep (valid value: integeger between 1 and 1000) string 7 no
schedule_interval How often this lifecycle policy should be evaluated (valid values: 1, 2, 3, 4, 6, 8, 12 or 24) number 24 no
schedule_name Name of the DLM policy schedule string "1 week of daily snapshots" no
schedule_time Time in 24 hour format when the policy should be evaluated (e.g. 02:30) string "02:30" no
serverless_auto_pause SERVERLESS: Enable auto-pause after seconds_until_auto_pause - NOTE: If cluster is paused for >7d, cluster might be backed up with a snapshot and then restored when there is a request to connect to it) bool true no
serverless_http_endpoint Enable / Disbale the Aurora Serverless Data API HTTP endpoint bool false no
serverless_max SERVERLESS: Maximum capacity units number 2 no
serverless_min SERVERLESS: Minimum capacity units number 1 no
serverless_seconds_pause SERVERLESS: Seconds after which the the Serverless Aurora DB Cluster will be paused (valid values: 300 through 86400) number 300 no
serverless_timeout_action SERVERLESS: Action to take when a Aurora Serverless action timeouts (e.g. ForceApplyCapacityChange or RollbackCapacityChange) string "RollbackCapacityChange" no
ssh_cidrs IPV4 CIDRs to allow for SSH access map(string) {} no
state Enable / Disable DLM Lifecycle Policy (e.g. ENABLED or DISABLED) string "ENABLED" no
tags Tags as map (preferably generated by terraform-null-label module.tags) map(string)
"Module": "terraform-aws-jitsi",
"Project": "Jitsi"
tags_to_add_map Map of extra tags to add to the snapshots map(string)
"SnapshotCreator": "DLM"
timezone Timezone set in the EC2 instance UserData string "Europe/Berlin" no
vpc_id ID of VPC string n/a yes


Name Description
endpoint Endpoint for RDS Aurora cluster
fqdn FQDN of Jitsi-Meet
instance_profile_arn ARN of EC2 Instance Profile
role_arn ARN of EC2 role
sg_id Jitsi SG ID (e.g. for adding it outside of the module to other SGs)
sns_topic_arn Jitsi ASG scaling events SNS topic ARN