DEV Community

Ekemini Udongwo
Ekemini Udongwo

Posted on

Implementing an On-Demand Video Streaming Platform on AWS Using Terraform

In this project, we will deploy an on-demand video streaming platform utilizing AWS services and infrastructure automation with Terraform. The solution will incorporate AWS Route 53 for DNS management, CloudFront as a Content Delivery Network (CDN) to optimize content delivery, AWS Certificate Manager for SSL certificates, and Amazon S3 for video file storage. The following diagram outlines the infrastructure architecture that will be implemented.

Image description

Prerequisites:

  1. Domain name
  2. Knowledge of Terraform

Note: Before we move forward, make sure you have Terraform set up on your local machine, including the necessary provider, and that you’ve initialized your project. If you’re all set, let’s get started!

1. Register a domain on route53

First, log into the AWS Management Console and head over to the Route 53 service. From there, find the “Registered Domains” section and click on “Register Domain.”
Type in the domain name you want and check its availability. If it’s available, just fill in your details, and AWS will email you a verification link. Once verified, your new domain should be ready within a few minutes to an hour.

2. Create some variables

Let's create a vars.tf file and add some variables to it which will be used by other resources.

vars.tf

variable "domain" {
  type    = string
  default = "your-domain.com"
}

variable "cloudfront_priceClass" {
  type = string
  default = "PriceClass_100"
}

variable "environment" {
  type = string
  default = "dev"
}

Enter fullscreen mode Exit fullscreen mode

3. Create the S3 bucket

Next, we need to create an S3 bucket to store our video or videos we wanna serve to our users. In your text editor, create a S3.tf file where our S3 configuration is going to be written.

# Create an S3 bucket
resource "aws_s3_bucket" "video_bucket" {
  bucket = "kemzzy-new-video-bucket"

  tags = {
    Name = "Video bucket"
  }
}

# Enable versioning
resource "aws_s3_bucket_versioning" "video_bucket_versioning" {
  bucket = aws_s3_bucket.video_bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}
Enter fullscreen mode Exit fullscreen mode

This creates our bucket and also enables versioning on it.

4. Upload a video to the S3 bucket

Next we upload our video to the created S3 bucket

# replace with the path to the video you want to upload
resource "aws_s3_object" "new_video" {
  bucket       = aws_s3_bucket.video_bucket.id
  key          = "awesome-video"
  source       = "path-to-your-video-file"
  etag         = filemd5("path-to-your-video-file")
  content_type = "video/mp4"

  depends_on = [aws_s3_bucket.video_bucket]
}
Enter fullscreen mode Exit fullscreen mode

make sure to upload a mp4 video format otherwise you might have an issue (Speaking from personal experience )

5. Create and verify a SSL certificate with ACM

In other to use our domain with cloudfront we need a domain with SSL enabled. You can use the following terraform config to create and validate your SSL certificate for your domain.

 Create an ACM certificate
resource "aws_acm_certificate" "video_cert" {
  domain_name               = var.domain
  validation_method         = "DNS"

  lifecycle {
    create_before_destroy = true
  }
}

# Cert validation
resource "aws_acm_certificate_validation" "validate_cert" {
  certificate_arn         = aws_acm_certificate.video_cert.arn
  validation_record_fqdns = [for record in aws_route53_record.certificate_validation : record.fqdn]

  depends_on = [ aws_route53_record.certificate_validation ]
}

# create a record to use for validation
resource "aws_route53_record" "certificate_validation" {
  for_each = {
    for dvo in aws_acm_certificate.video_cert.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = aws_route53_zone.primary.zone_id

  depends_on = [ aws_acm_certificate.video_cert ]
}
Enter fullscreen mode Exit fullscreen mode

6. Create a CloudFront origin access identity

Now we can proceed to create our OAI for our cloudfront distribution. Create another file called main.tf

resource "aws_cloudfront_origin_access_identity" "cloudfront_OAI" {
  comment = "OAI for video streaming S3 bucket"
}
Enter fullscreen mode Exit fullscreen mode

Great, now that we’ve tackled that part, let’s move on to creating our CloudFront distribution!

resource "aws_cloudfront_distribution" "s3_distribution" {
  origin {
    domain_name = aws_s3_bucket.video_bucket.bucket_regional_domain_name
    origin_id   = aws_s3_bucket.video_bucket.id

    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.cloudfront_OAI.cloudfront_access_identity_path
    }
  }

  enabled         = true
  is_ipv6_enabled = true
  comment         = "play video"

  aliases = [var.subdomain]


  default_cache_behavior {
    allowed_methods  = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = aws_s3_bucket.video_bucket.id

    forwarded_values {
      query_string = false

      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "allow-all"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
  }

  price_class =var.cloudfront_priceClass

  restrictions {
    geo_restriction {
      restriction_type = "none"
      locations        = []
    }
  }

  tags = {
    Environment = var.environment
  }

  viewer_certificate {
    acm_certificate_arn = data.aws_acm_certificate.cert.arn
    ssl_support_method  = "sni-only"

  }
}
Enter fullscreen mode Exit fullscreen mode

6. Access the video through the CloudFront distribution

To set this up, we’ll create a bucket policy that restricts read access exclusively to our CloudFront service. This setup adds a layer of security by making sure users can only access content through CloudFront, not directly from the bucket. Simply add this policy to your *s3.tf * file.

# Bucket policy to allow read access from CloudFront and prevent direct access to our bucket
resource "aws_s3_bucket_policy" "video_stream" {
  bucket = aws_s3_bucket.video_bucket.id
  policy = <<POLICY
  {
    "Version": "2012-10-17",
    "Statement": [
         {
            "Sid": "AllowLegacyOAIReadOnly",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${aws_cloudfront_origin_access_identity.cloudfront_OAI.id}"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::${aws_s3_bucket.video_bucket.bucket}/*"
        }
      ]
  }
  POLICY
}
Enter fullscreen mode Exit fullscreen mode

7. Create an outputs file to get your outputs (optional)

Create an output.tf file and add these outputs

output "cloudfront_url" {
  value = aws_cloudfront_distribution.s3_distribution.domain_name
}

output "domain_url" {
  value = aws_route53_record.video_subdomain.name
}
Enter fullscreen mode Exit fullscreen mode

8. Deploy your infrastructure

Phew! That was a journey, but you’ve made it to the finish line. Now, it’s time to bring your project to life! Run terraform validate to check for any issues, then use terraform plan -out="tfplan" to generate a plan, and finally, terraform apply "tfplan" to deploy your infrastructure to AWS.

Now, to watch the video, just use your domain name, like your-domain.com/awesome-video, or the CloudFront URL provided in the output. Enjoy!

Conclusion

Congratulations on completing this tutorial. Make sure your you run terraform destroy when you are done to avoid accumulating any bills.

Top comments (0)