Skip to content

Commit

Permalink
COVID19
Browse files Browse the repository at this point in the history
  • Loading branch information
yann degat committed Mar 12, 2020
0 parents commit 4b3c4cd
Show file tree
Hide file tree
Showing 11 changed files with 516 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
clouds.yaml
.terraform
terraform.tfstate
.terragrunt-cache
27 changes: 27 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
The 3-Clause BSD License

Copyright (c) 2013-2017, OVH SAS.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of OVH SAS nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY OVH SAS AND CONTRIBUTORS ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL OVH SAS AND CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
89 changes: 89 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Terraform Recipe: Boot a single Jitsi Video conferencing instance on OVHCloud

## Description

This recipe helps you bootstrap a simple [Jitsi](https://jitsi.org) instance on
OVHCloud.

This could be very useful for small teams/companies which could have an
urging need of a simple videoconferencing solution due to covid19.

This is a very simple and stupid deployment, only secured with https and basic firewalling
feature. To use with CAUTION.

## Requirements

- an OVHCloud [public cloud](https://www.ovhcloud.com/fr/public-cloud) project.
- Hashicorp [terraform](https://www.terraform.io)

## Getting Started

1. Create your Openstack API clouds.yaml file.

```
mkdir -p ~/.config/openstack
cat >> ~/.config/openstack/clouds.yaml <<EOF
clouds:
jitsi:
auth:
auth_url: https://auth.cloud.ovh.net/v3/
domain_name: default
password: XXX
project_domain_name: default
project_name: 'YYY'
user_domain_name: default
username: ZZZ
region_name: REGION
EOF
```

2. Create a tfvar file and edit accordingly

```
cp myvars.tfvars.example myvars.tfvars
```

3. apply your plan

```
terraform init
...
terraform apply
...
```

4. Go to you private meeting space.

# Ssh into the machine

You can ssh into the VM by copy/pasting the result of the following command:

```
terraform output ssh_helper
```

# Destroy the infrastructure

If you want to destroy all the resources associated with this plan, run the following
command:

```
terraform destroy
```

## Troubleshooting

- You encounter connectivity issues

Maybe the instance is to small. Try a bigger flavor.

- This service is not HA, installed with dummy defaults. If you need
a more reliable service, try a professional one. You can try
with [jitsi.org](https://jitsi.org) services for a start.


## License

The 3-Clause BSD License. See [LICENSE](https://github.com/yanndegat/tf-ovh-jitsi/tree/master/LICENSE) for full details.
102 changes: 102 additions & 0 deletions install-letsencrypt-cert.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/bin/bash

set -e

# VARS FROM TERRAFORM
DOMAIN="${DOMAIN}"
EMAIL="${EMAIL}"
# END VARS FROM TERRAFORM

echo "-------------------------------------------------------------------------"
echo "This script will:"
echo "- Need a working DNS record pointing to this machine(for domain ${DOMAIN})"
echo "- Download certbot-auto from https://dl.eff.org to /usr/local/sbin"
echo "- Install additional dependencies in order to request Let’s Encrypt certificate"
echo "- If running with jetty serving web content, will stop Jitsi Videobridge"
echo "- Configure and reload nginx or apache2, whichever is used"
echo ""
echo "You need to agree to the ACME server's Subscriber Agreement (https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf) "
echo "by providing an email address for important account notifications"

cd /usr/local/sbin

if [ ! -f certbot-auto ] ; then
wget https://dl.eff.org/certbot-auto
chmod a+x ./certbot-auto
fi

CRON_FILE="/etc/cron.weekly/letsencrypt-renew"
echo "#!/bin/bash" > $CRON_FILE
echo "/usr/local/sbin/certbot-auto renew >> /var/log/le-renew.log" >> $CRON_FILE

CERT_KEY="/etc/letsencrypt/live/$DOMAIN/privkey.pem"
CERT_CRT="/etc/letsencrypt/live/$DOMAIN/fullchain.pem"

if [ -f /etc/nginx/sites-enabled/$DOMAIN.conf ] ; then

./certbot-auto certonly --noninteractive \
--webroot --webroot-path /usr/share/jitsi-meet \
-d $DOMAIN \
--agree-tos --email $EMAIL

echo "Configuring nginx"

CONF_FILE="/etc/nginx/sites-available/$DOMAIN.conf"
CERT_KEY_ESC=$(echo $CERT_KEY | sed 's/\./\\\./g')
CERT_KEY_ESC=$(echo $CERT_KEY_ESC | sed 's/\//\\\//g')
sed -i "s/ssl_certificate_key\ \/etc\/jitsi\/meet\/.*key/ssl_certificate_key\ $CERT_KEY_ESC/g" \
$CONF_FILE
CERT_CRT_ESC=$(echo $CERT_CRT | sed 's/\./\\\./g')
CERT_CRT_ESC=$(echo $CERT_CRT_ESC | sed 's/\//\\\//g')
sed -i "s/ssl_certificate\ \/etc\/jitsi\/meet\/.*crt/ssl_certificate\ $CERT_CRT_ESC/g" \
$CONF_FILE

echo "service nginx reload" >> $CRON_FILE
service nginx reload

elif [ -f /etc/apache2/sites-enabled/$DOMAIN.conf ] ; then

./certbot-auto certonly --noninteractive \
--webroot --webroot-path /usr/share/jitsi-meet \
-d $DOMAIN \
--agree-tos --email $EMAIL

echo "Configuring apache2"

CONF_FILE="/etc/apache2/sites-available/$DOMAIN.conf"
CERT_KEY_ESC=$(echo $CERT_KEY | sed 's/\./\\\./g')
CERT_KEY_ESC=$(echo $CERT_KEY_ESC | sed 's/\//\\\//g')
sed -i "s/SSLCertificateKeyFile\ \/etc\/jitsi\/meet\/.*key/SSLCertificateKeyFile\ $CERT_KEY_ESC/g" \
$CONF_FILE
CERT_CRT_ESC=$(echo $CERT_CRT | sed 's/\./\\\./g')
CERT_CRT_ESC=$(echo $CERT_CRT_ESC | sed 's/\//\\\//g')
sed -i "s/SSLCertificateFile\ \/etc\/jitsi\/meet\/.*crt/SSLCertificateFile\ $CERT_CRT_ESC/g" \
$CONF_FILE

echo "service apache2 reload" >> $CRON_FILE
service apache2 reload
else
service jitsi-videobridge stop

./certbot-auto certonly --noninteractive \
--standalone \
-d $DOMAIN \
--agree-tos --email $EMAIL

echo "Configuring jetty"

CERT_P12="/etc/jitsi/videobridge/$DOMAIN.p12"
CERT_JKS="/etc/jitsi/videobridge/$DOMAIN.jks"
# create jks from certs
openssl pkcs12 -export \
-in $CERT_CRT -inkey $CERT_KEY -passout pass:changeit > $CERT_P12
keytool -importkeystore -destkeystore $CERT_JKS \
-srckeystore $CERT_P12 -srcstoretype pkcs12 \
-noprompt -storepass changeit -srcstorepass changeit

service jitsi-videobridge start

fi

# the cron file that will renew certificates
chmod a+x $CRON_FILE
22 changes: 22 additions & 0 deletions live/terragrunt/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
terraform {
source = "../.."
}

remote_state {
backend = "swift"
config = {
cloud = "jitsi"
region_name = "GRA"
container = "jitsi"
archive_container = "archive-jitsi"
state_name = "tfstate.tf"
}
}

inputs = {
name = "jitsi"
cloud_name = "jitsi"
region_name = "GRA5"
email = "[email protected]"
allowed_prefixes = ["${chomp(run_cmd("/bin/sh", "-c", "curl --silent --fail https://api.ipify.org"))}/32"]
}
148 changes: 148 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
terraform {
backend "swift" {}
}

provider openstack {
cloud = var.cloud_name
region = var.region_name
}

resource tls_private_key priv {
algorithm = "ECDSA"
ecdsa_curve = "P384"
}

resource openstack_compute_keypair_v2 keypair {
name = var.ssh_keypair_name
public_key = tls_private_key.priv.public_key_openssh
}

#
# Network objects
#
data openstack_networking_network_v2 ext_net {
name = "Ext-Net"
tenant_id = ""
}

data openstack_images_image_v2 image {
name = var.image_name
most_recent = true
}

resource openstack_networking_secgroup_v2 secgroup {
name = var.name
description = "Security gropup for Jitsi"
}

resource openstack_networking_secgroup_rule_v2 ingress_https_jitsi {
for_each = var.allowed_prefixes

direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 443
port_range_max = 443
remote_ip_prefix = each.key
security_group_id = openstack_networking_secgroup_v2.secgroup.id
}

resource openstack_networking_secgroup_rule_v2 ingress_http_01_challenge {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 80 # required for http letsencrypt challenge
port_range_max = 80
remote_ip_prefix = "0.0.0.0/0"
security_group_id = openstack_networking_secgroup_v2.secgroup.id
}

resource openstack_networking_secgroup_rule_v2 ingress_tcp_ssh {
for_each = var.allowed_prefixes

direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 22
port_range_max = 22
remote_ip_prefix = each.key
security_group_id = openstack_networking_secgroup_v2.secgroup.id
}

resource openstack_networking_port_v2 fip {
name = var.name
network_id = data.openstack_networking_network_v2.ext_net.id
admin_state_up = "true"

security_group_ids = [openstack_networking_secgroup_v2.secgroup.id]
}


locals {
jitsi = [
for ip in openstack_networking_port_v2.fip.all_fixed_ips :
ip
if length(replace(ip, "/[[:alnum:]]+:[^,]+/", "")) > 0
][0]

ip_parts = split(".", local.jitsi)
fqdn = format("ip%s.ip-%s-%s-%s.eu", local.ip_parts[3], local.ip_parts[0], local.ip_parts[1], local.ip_parts[2])

user_data = {
hostname = local.fqdn
fqdn = local.fqdn
}

}

resource openstack_compute_instance_v2 vm {
name = var.name
image_id = data.openstack_images_image_v2.image.id
flavor_name = var.flavor_name
key_pair = openstack_compute_keypair_v2.keypair.name

user_data = <<EOF
#cloud-config
${yamlencode(local.user_data)}
EOF
network {
port = openstack_networking_port_v2.fip.id
access_network = true
}
}

data template_file install_letsencrypt_cert {
template = file("${path.module}/install-letsencrypt-cert.sh")
vars = {
DOMAIN = local.fqdn
EMAIL = var.email
}
}

resource null_resource provision {
triggers = {
jitsi = openstack_compute_instance_v2.vm.id
provision = md5(file("${path.module}/provision.sh"))
}

provisioner "file" {
connection {
user = "ubuntu"
host = local.jitsi
private_key = tls_private_key.priv.private_key_pem
}

content = data.template_file.install_letsencrypt_cert.rendered
destination = "/tmp/install-letsencrypt-cert.sh"
}

provisioner "remote-exec" {
connection {
user = "ubuntu"
host = local.jitsi
private_key = tls_private_key.priv.private_key_pem
}

script = "${path.module}/provision.sh"
}
}
Loading

0 comments on commit 4b3c4cd

Please sign in to comment.