├── CODE_OF_CONDUCT.md ├── terraform ├── versions.tf ├── terraform.tfvars.example ├── .gitignore ├── outputs.tf ├── data.tf ├── variables.tf ├── test │ └── terraform_test.go ├── user_data.sh ├── main.tf └── README.md ├── LICENSE ├── CONTRIBUTING.md ├── README.md └── code-server-stack.yaml /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /terraform/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = "~> 5.0" 8 | } 9 | random = { 10 | source = "hashicorp/random" 11 | version = "~> 3.1" 12 | } 13 | } 14 | } 15 | 16 | provider "aws" { 17 | region = var.aws_region 18 | } 19 | -------------------------------------------------------------------------------- /terraform/terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | # AWS Region (must be one of: us-west-2, us-east-1, ap-southeast-1) 2 | aws_region = "us-west-2" 3 | 4 | # Code-server version to install 5 | vscode_server_version = "4.91.1" 6 | 7 | # EC2 instance type 8 | instance_type = "t2.xlarge" 9 | 10 | # Optional: Specify existing VPC ID (leave empty to use default VPC) 11 | # vpc_id = "vpc-12345678" 12 | 13 | # Optional: Specify existing subnet ID (leave empty to use default subnet) 14 | # subnet_id = "subnet-12345678" 15 | 16 | # CIDR block for internet access 17 | internet_cidr_block = "0.0.0.0/0" 18 | 19 | # CloudFront origin request policy ID 20 | origin_request_policy_id = "216adef6-5c7f-47e4-b989-5492eafa07d3" 21 | 22 | # Common tags to apply to all resources 23 | common_tags = { 24 | Project = "code-server" 25 | Environment = "dev" 26 | Owner = "your-name" 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT No Attribution 2 | 3 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 14 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 15 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | -------------------------------------------------------------------------------- /terraform/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | crash.*.log 11 | 12 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 13 | # password, private keys, and other secrets. These should not be part of version 14 | # control as they are data points which are potentially sensitive and subject 15 | # to change depending on the environment. 16 | *.tfvars 17 | *.tfvars.json 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # !example_override.tf 28 | 29 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 30 | # example: *tfplan* 31 | 32 | # Ignore CLI configuration files 33 | .terraformrc 34 | terraform.rc 35 | 36 | # Ignore Mac system files 37 | .DS_Store 38 | 39 | # Ignore editor files 40 | *.swp 41 | *.swo 42 | *~ 43 | 44 | # Ignore test cache 45 | .terraform.lock.hcl 46 | 47 | # Keep example files 48 | !terraform.tfvars.example 49 | !*.tf 50 | !*.md 51 | -------------------------------------------------------------------------------- /terraform/outputs.tf: -------------------------------------------------------------------------------- 1 | output "vscode_server_cloudfront_domain_name" { 2 | description = "CloudFront distribution domain name for accessing code-server" 3 | value = "https://${aws_cloudfront_distribution.vscode_server_cloudfront.domain_name}" 4 | } 5 | 6 | output "vscode_server_public_ip" { 7 | description = "Public IP address of the code-server instance" 8 | value = aws_eip.vscode_server_eip.public_ip 9 | } 10 | 11 | output "vscode_server_private_ip" { 12 | description = "Private IP address of the code-server instance" 13 | value = aws_instance.vscode_server.private_ip 14 | } 15 | 16 | output "vscode_server_instance_id" { 17 | description = "Instance ID of the code-server EC2 instance" 18 | value = aws_instance.vscode_server.id 19 | } 20 | 21 | output "vscode_server_role_arn" { 22 | description = "ARN of the IAM role attached to the code-server instance" 23 | value = aws_iam_role.vscode_server_iam_role.arn 24 | } 25 | 26 | output "vscode_server_password_ssm" { 27 | description = "SSM Parameter path containing the code-server password" 28 | value = "/code-server/password" 29 | } 30 | 31 | output "password_retrieval_command" { 32 | description = "AWS CLI command to retrieve the code-server password" 33 | value = "aws ssm get-parameter --name '/code-server/password' --with-decryption --region ${data.aws_region.current.name}" 34 | } 35 | -------------------------------------------------------------------------------- /terraform/data.tf: -------------------------------------------------------------------------------- 1 | # Get default VPC if vpc_id is not specified 2 | data "aws_vpc" "default" { 3 | count = var.vpc_id == "" ? 1 : 0 4 | default = true 5 | } 6 | 7 | # Get specified VPC if vpc_id is provided 8 | data "aws_vpc" "selected" { 9 | count = var.vpc_id != "" ? 1 : 0 10 | id = var.vpc_id 11 | } 12 | 13 | # Get default subnet if subnet_id is not specified 14 | data "aws_subnets" "default" { 15 | count = var.subnet_id == "" ? 1 : 0 16 | filter { 17 | name = "vpc-id" 18 | values = [local.vpc_id] 19 | } 20 | filter { 21 | name = "default-for-az" 22 | values = ["true"] 23 | } 24 | } 25 | 26 | # Get latest Ubuntu 22.04 LTS AMI 27 | data "aws_ami" "ubuntu" { 28 | most_recent = true 29 | owners = ["099720109477"] # Canonical 30 | 31 | filter { 32 | name = "name" 33 | values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] 34 | } 35 | 36 | filter { 37 | name = "virtualization-type" 38 | values = ["hvm"] 39 | } 40 | } 41 | 42 | # Get CloudFront managed prefix list for the region 43 | data "aws_ec2_managed_prefix_list" "cloudfront" { 44 | name = "com.amazonaws.global.cloudfront.origin-facing" 45 | } 46 | 47 | # Get current AWS account ID and region 48 | data "aws_caller_identity" "current" {} 49 | data "aws_region" "current" {} 50 | 51 | # Local values for computed resources 52 | locals { 53 | vpc_id = var.vpc_id != "" ? var.vpc_id : data.aws_vpc.default[0].id 54 | subnet_id = var.subnet_id != "" ? var.subnet_id : data.aws_subnets.default[0].ids[0] 55 | } 56 | -------------------------------------------------------------------------------- /terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "AWS region to deploy resources" 3 | type = string 4 | default = "us-west-2" 5 | 6 | validation { 7 | condition = contains([ 8 | "us-west-2", 9 | "us-east-1", 10 | "ap-southeast-1" 11 | ], var.aws_region) 12 | error_message = "Region must be one of: us-west-2, us-east-1, ap-southeast-1." 13 | } 14 | } 15 | 16 | variable "vscode_server_version" { 17 | description = "Version of code-server to install" 18 | type = string 19 | default = "4.91.1" 20 | } 21 | 22 | variable "internet_cidr_block" { 23 | description = "CIDR block for internet access" 24 | type = string 25 | default = "0.0.0.0/0" 26 | } 27 | 28 | variable "vpc_id" { 29 | description = "VPC ID to deploy resources (optional, uses default VPC if not specified)" 30 | type = string 31 | default = "" 32 | } 33 | 34 | variable "subnet_id" { 35 | description = "Subnet ID to deploy EC2 instance (optional, uses default subnet if not specified)" 36 | type = string 37 | default = "" 38 | } 39 | 40 | variable "instance_type" { 41 | description = "EC2 instance type for code-server" 42 | type = string 43 | default = "t2.xlarge" 44 | } 45 | 46 | variable "origin_request_policy_id" { 47 | description = "CloudFront origin request policy ID" 48 | type = string 49 | default = "216adef6-5c7f-47e4-b989-5492eafa07d3" 50 | } 51 | 52 | variable "common_tags" { 53 | description = "Common tags to apply to all resources" 54 | type = map(string) 55 | default = { 56 | Project = "code-server" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /terraform/test/terraform_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/gruntwork-io/terratest/modules/aws" 8 | "github.com/gruntwork-io/terratest/modules/terraform" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestTerraformCodeServer(t *testing.T) { 13 | t.Parallel() 14 | 15 | // Pick a random AWS region to test in 16 | awsRegion := "us-west-2" 17 | 18 | terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ 19 | // The path to where our Terraform code is located 20 | TerraformDir: "../", 21 | 22 | // Variables to pass to our Terraform code using -var options 23 | Vars: map[string]interface{}{ 24 | "aws_region": awsRegion, 25 | }, 26 | 27 | // Environment variables to set when running Terraform 28 | EnvVars: map[string]string{ 29 | "AWS_DEFAULT_REGION": awsRegion, 30 | }, 31 | }) 32 | 33 | // At the end of the test, run `terraform destroy` to clean up any resources that were created 34 | defer terraform.Destroy(t, terraformOptions) 35 | 36 | // This will run `terraform init` and `terraform apply` and fail the test if there are any errors 37 | terraform.InitAndApply(t, terraformOptions) 38 | 39 | // Run `terraform output` to get the value of an output variable 40 | instanceId := terraform.Output(t, terraformOptions, "vscode_server_instance_id") 41 | publicIp := terraform.Output(t, terraformOptions, "vscode_server_public_ip") 42 | cloudfrontUrl := terraform.Output(t, terraformOptions, "vscode_server_cloudfront_domain_name") 43 | ssmParameter := terraform.Output(t, terraformOptions, "vscode_server_password_ssm") 44 | 45 | // Verify the outputs are not empty 46 | assert.NotEmpty(t, instanceId) 47 | assert.NotEmpty(t, publicIp) 48 | assert.NotEmpty(t, cloudfrontUrl) 49 | assert.Equal(t, "/code-server/password", ssmParameter) 50 | 51 | // Verify the EC2 instance is running 52 | aws.GetInstancesByTag(t, awsRegion, "Name", "VSCodeServer") 53 | 54 | // Wait for the instance to be ready (UserData script to complete) 55 | time.Sleep(5 * time.Minute) 56 | 57 | // Verify SSM parameter exists 58 | parameterValue := aws.GetParameter(t, awsRegion, "/code-server/password") 59 | assert.NotEmpty(t, parameterValue) 60 | } 61 | -------------------------------------------------------------------------------- /terraform/user_data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "INFO: Starting UserData script execution" 3 | 4 | # Install AWS CLI 5 | echo "INFO: Installing AWS CLI prerequisites" 6 | apt-get -o DPkg::Lock::Timeout=-1 update 7 | DEBIAN_FRONTEND=noninteractive apt-get -o DPkg::Lock::Timeout=-1 install -y curl unzip 8 | echo "INFO: Prerequisites installed, downloading AWS CLI" 9 | curl -fsSL https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip -o /tmp/aws-cli.zip 10 | echo "INFO: Extracting AWS CLI" 11 | unzip -q -d /tmp /tmp/aws-cli.zip 12 | echo "INFO: Installing AWS CLI" 13 | sudo /tmp/aws/install 14 | rm -rf /tmp/aws /tmp/aws-cli.zip 15 | echo "INFO: AWS CLI installation complete" 16 | aws --version 17 | 18 | # Install code-server 19 | echo "INFO: Installing code-server" 20 | curl -fOL https://github.com/coder/code-server/releases/download/v${version}/code-server_${version}_amd64.deb 21 | sudo dpkg -i code-server_${version}_amd64.deb 22 | echo "INFO: Enabling and starting code-server" 23 | sudo systemctl enable --now code-server@ubuntu 24 | sleep 30 25 | 26 | # Configure password 27 | echo "INFO: Configuring code-server" 28 | # sed -i.bak 's/auth: password/auth: none/' /home/ubuntu/.config/code-server/config.yaml 29 | # Expose code server service 30 | sed -i.bak 's/bind-addr: 127.0.0.1:8080/bind-addr: 0.0.0.0:8080/' /home/ubuntu/.config/code-server/config.yaml 31 | 32 | # Restart code server 33 | echo "INFO: Restarting code-server" 34 | sudo systemctl restart code-server@ubuntu 35 | 36 | # Install extension amazonwebservices.amazon-q-vscode 37 | echo "INFO: Installing Amazon Q extension" 38 | sudo -u ubuntu code-server --install-extension amazonwebservices.amazon-q-vscode 39 | 40 | # Restart code server 41 | echo "INFO: Final restart of code-server" 42 | sudo systemctl restart code-server@ubuntu 43 | 44 | # Store password in SSM Parameter Store for easy retrieval 45 | echo "INFO: Storing password in SSM Parameter Store" 46 | sleep 10 # Wait for config file to be fully written 47 | CODE_SERVER_PASSWORD=$(sudo grep "^password:" /home/ubuntu/.config/code-server/config.yaml | cut -d' ' -f2) 48 | echo "INFO: Extracted password, creating SSM parameter" 49 | aws ssm put-parameter \ 50 | --name "/code-server/password" \ 51 | --value "$CODE_SERVER_PASSWORD" \ 52 | --type "SecureString" \ 53 | --region ${region} \ 54 | --overwrite 55 | echo "INFO: SSM parameter creation complete" 56 | echo "INFO: UserData script execution finished" 57 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hosting Code Server on EC2 and CloudFront Distribution 3 | author: haimtran 4 | date: 08/08/2024 5 | --- 6 | 7 | ## Supported Region 8 | 9 | By default, the provided template supports the following regions. 10 | 11 | | Region | CloudFront Prefix List ID | 12 | | -------------- | ------------------------- | 13 | | us-west-2 | pl-82a045eb | 14 | | us-east-1 | pl-3b927c52 | 15 | | ap-southeast-1 | pl-31a34658 | 16 | 17 | To deploy in other region, you have to update the CloudFront prefix list id map. Check [docs](https://docs.aws.amazon.com/vpc/latest/userguide/working-with-aws-managed-prefix-lists.html) for more details how to find the CloudFront prefix list per region. 18 | 19 | ```yaml 20 | Mappings: 21 | CloudFrontPrefixListIdMappings: 22 | us-west-2: 23 | PrefixListId: "pl-82a045eb" 24 | us-east-1: 25 | PrefixListId: "pl-3b927c52" 26 | ap-southeast-1: 27 | PrefixListId: "pl-31a34658" 28 | : 29 | PrefixListId: 30 | ``` 31 | 32 | ## Deploy 33 | 34 | To deploy the stack, you can use CLI as the below command or use the AWS CloudFormation console. 35 | 36 | ```bash 37 | aws cloudformation create-stack \ 38 | --stack-name code-server-stack \ 39 | --template-body file://code-server-stack.yaml \ 40 | --capabilities CAPABILITY_NAMED_IAM 41 | ``` 42 | 43 | The code-server-stack.yaml stack will: 44 | 45 | - Create an EC2 instance and install the [code server](https://github.com/coder/code-server) using UserData. 46 | - Expose the code server via a CloudFront distribution. 47 | 48 | ## Code Server Configuration 49 | 50 | You can change the following parameters by editing the code-server-stack.yaml. 51 | 52 | - EC2 instance type to host the code server (default t2.medium) 53 | - Amazon Machine Image (AMI) (default [latest amazon linux 2023 in us-west-2](https://docs.aws.amazon.com/linux/al2023/ug/ec2.html)) 54 | - Code server [release version](https://github.com/coder/code-server/releases) (default [4.9.11](https://github.com/coder/code-server/releases/download/v4.91.1/code-server-4.91.1-linux-amd64.tar.gz)) 55 | - Select an existing VPCID and SubnetID (otherwise default VPC is selected) 56 | 57 | You can change configuration of the code server by editting config.yaml at the below path. 58 | 59 | ```bash 60 | /home/ec2-user/.config/code-server/config.yaml 61 | ``` 62 | 63 | Here is a sample content of config.yaml with authentication disabled. 64 | 65 | ```yaml 66 | bind-addr: 0.0.0.0:8080 67 | auth: none 68 | password: 8766aa4b66cf555763e9564d 69 | cert: false 70 | ``` 71 | 72 | ## Access Code Server 73 | 74 | **Option 1.** The code server has been exposed via a CloudFront distribution. You can find the https endpoint in the CloudFormation console output. 75 | 76 | **Password Retrieval:** The code-server password is automatically stored in AWS Systems Manager Parameter Store. Retrieve it using: 77 | ```bash 78 | aws ssm get-parameter --name "/code-server/password" --with-decryption --region 79 | ``` 80 | 81 | **Option 2.** Use AWS System Manager (SSM) and port forwarding to forward the code server to local host as the following command. In this case, there are prerequisites: 82 | 83 | - Setup [aws-cli](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html) 84 | - Setup AWS credentials for a profile in ~/.aws/credentials 85 | - Replace INSTANCE_ID, PROFILE_NAME, REGION into the below command 86 | 87 | ```bash 88 | aws ssm start-session \ 89 | --target \ 90 | --document-name AWS-StartPortForwardingSessionToRemoteHost \ 91 | --parameters "{\"portNumber\":[\"8080\"],\"localPortNumber\":[\"8080\"],\"host\":[\"\"]}" \ 92 | --profile \ 93 | --region 94 | ``` 95 | -------------------------------------------------------------------------------- /terraform/main.tf: -------------------------------------------------------------------------------- 1 | # Security Group for VSCode Server 2 | resource "aws_security_group" "vscode_server_security_group" { 3 | name_prefix = "vscode-server-sg-" 4 | description = "Allow ingress from CloudFront prefix list" 5 | vpc_id = local.vpc_id 6 | 7 | tags = merge(var.common_tags, { 8 | Name = "VSCodeServer-SecurityGroup" 9 | }) 10 | } 11 | 12 | # Security Group Ingress Rule 13 | resource "aws_security_group_rule" "vscode_server_security_group_ingress" { 14 | type = "ingress" 15 | description = "Open port 8080 for the CloudFront prefix list" 16 | from_port = 8080 17 | to_port = 8080 18 | protocol = "tcp" 19 | prefix_list_ids = [data.aws_ec2_managed_prefix_list.cloudfront.id] 20 | security_group_id = aws_security_group.vscode_server_security_group.id 21 | } 22 | 23 | # Security Group Egress Rule 24 | resource "aws_security_group_rule" "vscode_server_security_group_egress" { 25 | type = "egress" 26 | description = "Egress for vscode security group" 27 | from_port = 0 28 | to_port = 0 29 | protocol = "-1" 30 | cidr_blocks = [var.internet_cidr_block] 31 | security_group_id = aws_security_group.vscode_server_security_group.id 32 | } 33 | 34 | # IAM Role for VSCode Server 35 | resource "aws_iam_role" "vscode_server_iam_role" { 36 | name_prefix = "VSCodeServer-Role-" 37 | 38 | assume_role_policy = jsonencode({ 39 | Version = "2012-10-17" 40 | Statement = [ 41 | { 42 | Action = "sts:AssumeRole" 43 | Effect = "Allow" 44 | Principal = { 45 | Service = "ec2.amazonaws.com" 46 | } 47 | } 48 | ] 49 | }) 50 | 51 | managed_policy_arns = [ 52 | "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" 53 | ] 54 | 55 | inline_policy { 56 | name = "SSMParameterAccess" 57 | policy = jsonencode({ 58 | Version = "2012-10-17" 59 | Statement = [ 60 | { 61 | Effect = "Allow" 62 | Action = [ 63 | "ssm:PutParameter", 64 | "ssm:GetParameter" 65 | ] 66 | Resource = "arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:parameter/code-server/*" 67 | } 68 | ] 69 | }) 70 | } 71 | 72 | tags = var.common_tags 73 | } 74 | 75 | # Instance Profile 76 | resource "aws_iam_instance_profile" "instance_profile" { 77 | name_prefix = "VSCodeServer-InstanceProfile-" 78 | role = aws_iam_role.vscode_server_iam_role.name 79 | 80 | tags = var.common_tags 81 | } 82 | 83 | # Elastic IP 84 | resource "aws_eip" "vscode_server_eip" { 85 | domain = "vpc" 86 | 87 | tags = merge(var.common_tags, { 88 | Name = "VSCodeServer-EIP" 89 | }) 90 | } 91 | 92 | # User Data Script 93 | locals { 94 | user_data = base64encode(templatefile("${path.module}/user_data.sh", { 95 | version = var.vscode_server_version 96 | region = data.aws_region.current.name 97 | })) 98 | } 99 | 100 | # EC2 Instance 101 | resource "aws_instance" "vscode_server" { 102 | ami = data.aws_ami.ubuntu.id 103 | instance_type = var.instance_type 104 | subnet_id = local.subnet_id 105 | vpc_security_group_ids = [aws_security_group.vscode_server_security_group.id] 106 | iam_instance_profile = aws_iam_instance_profile.instance_profile.name 107 | user_data_base64 = local.user_data 108 | monitoring = true 109 | 110 | tags = merge(var.common_tags, { 111 | Name = "VSCodeServer" 112 | }) 113 | 114 | lifecycle { 115 | create_before_destroy = true 116 | } 117 | } 118 | 119 | # Associate Elastic IP 120 | resource "aws_eip_association" "vscode_server_eip_association" { 121 | instance_id = aws_instance.vscode_server.id 122 | allocation_id = aws_eip.vscode_server_eip.id 123 | } 124 | 125 | # CloudFront Cache Policy 126 | resource "aws_cloudfront_cache_policy" "vscode_server_cloudfront_cache_policy" { 127 | name = "VSCodeServer-${random_id.cache_policy_suffix.hex}" 128 | comment = "Cache policy for VSCode Server" 129 | default_ttl = 86400 130 | max_ttl = 31536000 131 | min_ttl = 1 132 | 133 | parameters_in_cache_key_and_forwarded_to_origin { 134 | enable_accept_encoding_gzip = false 135 | 136 | cookies_config { 137 | cookie_behavior = "all" 138 | } 139 | 140 | headers_config { 141 | header_behavior = "whitelist" 142 | headers { 143 | items = [ 144 | "Accept-Charset", 145 | "Authorization", 146 | "Origin", 147 | "Accept", 148 | "Referer", 149 | "Host", 150 | "Accept-Language", 151 | "Accept-Encoding", 152 | "Accept-Datetime" 153 | ] 154 | } 155 | } 156 | 157 | query_strings_config { 158 | query_string_behavior = "all" 159 | } 160 | } 161 | } 162 | 163 | # Random ID for cache policy name uniqueness 164 | resource "random_id" "cache_policy_suffix" { 165 | byte_length = 4 166 | } 167 | 168 | # CloudFront Distribution 169 | resource "aws_cloudfront_distribution" "vscode_server_cloudfront" { 170 | origin { 171 | domain_name = aws_eip.vscode_server_eip.public_dns 172 | origin_id = "VS-code-server" 173 | 174 | custom_origin_config { 175 | http_port = 8080 176 | https_port = 443 177 | origin_protocol_policy = "http-only" 178 | origin_ssl_protocols = ["TLSv1.2"] 179 | } 180 | } 181 | 182 | enabled = true 183 | 184 | default_cache_behavior { 185 | allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] 186 | cached_methods = ["GET", "HEAD"] 187 | target_origin_id = "VS-code-server" 188 | compress = false 189 | viewer_protocol_policy = "allow-all" 190 | cache_policy_id = aws_cloudfront_cache_policy.vscode_server_cloudfront_cache_policy.id 191 | origin_request_policy_id = var.origin_request_policy_id 192 | } 193 | 194 | restrictions { 195 | geo_restriction { 196 | restriction_type = "none" 197 | } 198 | } 199 | 200 | viewer_certificate { 201 | cloudfront_default_certificate = true 202 | } 203 | 204 | tags = var.common_tags 205 | 206 | depends_on = [aws_eip_association.vscode_server_eip_association] 207 | } 208 | -------------------------------------------------------------------------------- /terraform/README.md: -------------------------------------------------------------------------------- 1 | # Code-Server Terraform Template 2 | 3 | This Terraform template deploys a code-server instance on AWS EC2 with CloudFront distribution and automatic password storage in AWS Systems Manager Parameter Store. 4 | 5 | ## Architecture 6 | 7 | The template creates: 8 | - EC2 instance running Ubuntu 22.04 LTS with code-server 9 | - Security Group allowing CloudFront access on port 8080 10 | - CloudFront distribution for global access 11 | - Elastic IP for static public IP 12 | - IAM role with SSM permissions 13 | - SSM Parameter Store for secure password storage 14 | 15 | ## Supported Regions 16 | 17 | - `us-west-2` (default) 18 | - `us-east-1` 19 | - `ap-southeast-1` 20 | 21 | ## Prerequisites 22 | 23 | - [Terraform](https://www.terraform.io/downloads.html) >= 1.0 24 | - [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) configured with appropriate permissions 25 | - AWS credentials configured (via AWS CLI, environment variables, or IAM roles) 26 | 27 | ## Required AWS Permissions 28 | 29 | Your AWS credentials need the following permissions: 30 | - EC2: Create/manage instances, security groups, elastic IPs 31 | - IAM: Create/manage roles and instance profiles 32 | - CloudFront: Create/manage distributions and cache policies 33 | - SSM: Create/read parameters 34 | - VPC: Describe VPCs and subnets (if using default VPC) 35 | 36 | ## Quick Start 37 | 38 | 1. **Clone and navigate to the terraform directory:** 39 | ```bash 40 | git clone 41 | cd terraform/ 42 | ``` 43 | 44 | 2. **Copy and customize the example variables:** 45 | ```bash 46 | cp terraform.tfvars.example terraform.tfvars 47 | # Edit terraform.tfvars with your preferred settings 48 | ``` 49 | 50 | 3. **Initialize and apply Terraform:** 51 | ```bash 52 | terraform init 53 | terraform plan 54 | terraform apply 55 | ``` 56 | 57 | 4. **Retrieve the code-server password:** 58 | ```bash 59 | # Get just the password value 60 | aws ssm get-parameter --name "/code-server/password" --with-decryption --region --query 'Parameter.Value' --output text 61 | 62 | # Or get full parameter details 63 | aws ssm get-parameter --name "/code-server/password" --with-decryption --region 64 | 65 | # Using the terraform output command 66 | $(terraform output -raw password_retrieval_command) 67 | ``` 68 | 69 | 5. **Access code-server:** 70 | - Get the CloudFront URL from terraform output: `terraform output vscode_server_cloudfront_domain_name` 71 | - Open the URL in your browser 72 | - Enter the password retrieved from SSM 73 | 74 | ## Configuration 75 | 76 | ### Variables 77 | 78 | | Variable | Description | Default | Required | 79 | |----------|-------------|---------|----------| 80 | | `aws_region` | AWS region to deploy resources | `us-west-2` | No | 81 | | `vscode_server_version` | Version of code-server to install | `4.91.1` | No | 82 | | `instance_type` | EC2 instance type | `t2.xlarge` | No | 83 | | `vpc_id` | VPC ID (uses default VPC if empty) | `""` | No | 84 | | `subnet_id` | Subnet ID (uses default subnet if empty) | `""` | No | 85 | | `internet_cidr_block` | CIDR block for internet access | `0.0.0.0/0` | No | 86 | | `origin_request_policy_id` | CloudFront origin request policy ID | `216adef6-5c7f-47e4-b989-5492eafa07d3` | No | 87 | | `common_tags` | Common tags for all resources | `{Project = "code-server"}` | No | 88 | 89 | ### Example terraform.tfvars 90 | 91 | ```hcl 92 | aws_region = "us-west-2" 93 | vscode_server_version = "4.91.1" 94 | instance_type = "t2.xlarge" 95 | 96 | # Optional: Use existing VPC/subnet 97 | # vpc_id = "vpc-12345678" 98 | # subnet_id = "subnet-12345678" 99 | 100 | common_tags = { 101 | Project = "code-server" 102 | Environment = "dev" 103 | Owner = "your-name" 104 | } 105 | ``` 106 | 107 | ## Outputs 108 | 109 | | Output | Description | 110 | |--------|-------------| 111 | | `vscode_server_cloudfront_domain_name` | CloudFront URL for accessing code-server | 112 | | `vscode_server_public_ip` | Public IP address of the instance | 113 | | `vscode_server_private_ip` | Private IP address of the instance | 114 | | `vscode_server_instance_id` | EC2 instance ID | 115 | | `vscode_server_role_arn` | IAM role ARN | 116 | | `vscode_server_password_ssm` | SSM parameter path for password | 117 | | `password_retrieval_command` | AWS CLI command to get password | 118 | 119 | ## Code-Server Configuration 120 | 121 | The code-server is configured to: 122 | - Listen on `0.0.0.0:8080` (accessible via CloudFront) 123 | - Use password authentication (stored in SSM) 124 | - Include the Amazon Q extension pre-installed 125 | - Run as a systemd service under the `ubuntu` user 126 | 127 | You can modify the configuration by connecting to the instance: 128 | ```bash 129 | # Connect via SSM Session Manager 130 | aws ssm start-session --target --region 131 | 132 | # Edit configuration 133 | sudo nano /home/ubuntu/.config/code-server/config.yaml 134 | 135 | # Restart service 136 | sudo systemctl restart code-server@ubuntu 137 | ``` 138 | 139 | ## Access Methods 140 | 141 | ### Option 1: CloudFront (Recommended) 142 | Access via the CloudFront distribution URL (from terraform output). This provides: 143 | - Global edge locations for better performance 144 | - HTTPS termination 145 | - DDoS protection 146 | 147 | ### Option 2: Direct IP Access 148 | Access directly via the public IP on port 8080 (HTTP only). 149 | 150 | ### Option 3: SSM Port Forwarding 151 | Forward the code-server port to your local machine: 152 | ```bash 153 | aws ssm start-session \ 154 | --target \ 155 | --document-name AWS-StartPortForwardingSessionToRemoteHost \ 156 | --parameters '{"portNumber":["8080"],"localPortNumber":["8080"],"host":[""]}' \ 157 | --region 158 | ``` 159 | 160 | ## Security Considerations 161 | 162 | - The security group only allows access from CloudFront IP ranges 163 | - Password is stored encrypted in SSM Parameter Store 164 | - Instance uses IAM roles (no hardcoded credentials) 165 | - All traffic to CloudFront is over HTTPS 166 | - Consider restricting `internet_cidr_block` for additional security 167 | 168 | ## Troubleshooting 169 | 170 | ### Check instance status: 171 | ```bash 172 | # Get instance ID from terraform output 173 | terraform output vscode_server_instance_id 174 | 175 | # Check instance status 176 | aws ec2 describe-instances --instance-ids --region 177 | ``` 178 | 179 | ### Check UserData script execution: 180 | ```bash 181 | # Connect to instance 182 | aws ssm start-session --target --region 183 | 184 | # Check cloud-init logs 185 | sudo cat /var/log/cloud-init-output.log | grep "INFO:" 186 | 187 | # Check code-server service 188 | sudo systemctl status code-server@ubuntu 189 | ``` 190 | 191 | ### Verify SSM parameter: 192 | ```bash 193 | aws ssm get-parameter --name "/code-server/password" --region 194 | ``` 195 | 196 | ## Testing 197 | 198 | Basic Terratest is included in the `test/` directory: 199 | 200 | ```bash 201 | cd test/ 202 | go mod init terraform-test 203 | go mod tidy 204 | go test -v -timeout 30m 205 | ``` 206 | 207 | ## Cleanup 208 | 209 | To destroy all resources: 210 | ```bash 211 | terraform destroy 212 | ``` 213 | 214 | ## Differences from CloudFormation Template 215 | 216 | This Terraform template provides the same functionality as the CloudFormation version with these improvements: 217 | - Dynamic AMI lookup (always uses latest Ubuntu 22.04 LTS) 218 | - Dynamic CloudFront prefix list lookup (works in any supported region) 219 | - Additional output with password retrieval command 220 | - Terraform validation for region constraints 221 | - Modular file structure for better maintainability 222 | 223 | ## Support 224 | 225 | For issues or questions: 226 | 1. Check the troubleshooting section above 227 | 2. Review AWS CloudWatch logs for the EC2 instance 228 | 3. Verify your AWS permissions and region support 229 | -------------------------------------------------------------------------------- /code-server-stack.yaml: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------ 2 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # SPDX-License-Identifier: MIT-0 4 | #------------------------------------------------------ 5 | AWSTemplateFormatVersion: "2010-09-09" 6 | Description: deploy a vscode-server on an ec2 7 | #------------------------------------------------------ 8 | # Mappings CloudFront PrefixListId 9 | #------------------------------------------------------ 10 | Mappings: 11 | CloudFrontPrefixListIdMappings: 12 | us-west-2: 13 | PrefixListId: "pl-82a045eb" 14 | us-east-1: 15 | PrefixListId: "pl-3b927c52" 16 | us-east-2: 17 | PrefixListId: "pl-b6a144df" 18 | ap-southeast-1: 19 | PrefixListId: "pl-31a34658" 20 | #------------------------------------------------------ 21 | # Parameters 22 | #------------------------------------------------------ 23 | Parameters: 24 | VPCID: 25 | Description: imported vpc id 26 | Type: String 27 | Default: "" 28 | SubnetID: 29 | Description: imported subnet id 30 | Type: String 31 | Default: "" 32 | InstanceType: 33 | Description: WebServer EC2 instance type 34 | Type: String 35 | Default: t2.xlarge 36 | ConstraintDescription: must be a valid EC2 instance type. 37 | LatestAmiId: 38 | Description: latest image id for ubuntu 39 | Type: "AWS::SSM::Parameter::Value" 40 | # Default: "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64" 41 | Default: "/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id" 42 | InternetCidrBlock: 43 | Type: String 44 | Description: UserCidrBlock 45 | Default: 0.0.0.0/0 46 | VSCodeServerVersion: 47 | Type: String 48 | Description: VSCodeServerVersion 49 | Default: 4.91.1 50 | OriginRequestPolicyId: 51 | Type: String 52 | Description: origin request policy id 53 | Default: 216adef6-5c7f-47e4-b989-5492eafa07d3 54 | Conditions: 55 | ImportVPCIDNotEmpty: 56 | Fn::Not: 57 | - Fn::Equals: 58 | - Ref: VPCID 59 | - "" 60 | ImportSubnetIDNotEmpty: 61 | Fn::Not: 62 | - Fn::Equals: 63 | - Ref: SubnetID 64 | - "" 65 | #------------------------------------------------------ 66 | # Security Group 67 | #------------------------------------------------------ 68 | Resources: 69 | VSCodeServerSecurityGroup: 70 | Type: AWS::EC2::SecurityGroup 71 | Metadata: 72 | cfn_nag: 73 | rules_to_suppress: 74 | - id: W40 75 | reason: allow ingress from the cloudfront prefix list 76 | - id: W5 77 | reason: allow ingress from the cloudfront prefix list 78 | Properties: 79 | GroupDescription: allow ingress from cloudfront prefix list 80 | VpcId: 81 | Fn::If: 82 | - ImportVPCIDNotEmpty 83 | - Ref: VPCID 84 | - Ref: AWS::NoValue 85 | 86 | VSCodeServerSecurityGroupIngress: 87 | Type: AWS::EC2::SecurityGroupIngress 88 | Properties: 89 | Description: open port 8080 for the cloudfront prefix list 90 | GroupId: 91 | Fn::GetAtt: 92 | - VSCodeServerSecurityGroup 93 | - GroupId 94 | IpProtocol: tcp 95 | FromPort: 8080 96 | ToPort: 8080 97 | SourcePrefixListId: 98 | Fn::FindInMap: 99 | - CloudFrontPrefixListIdMappings 100 | - Ref: AWS::Region 101 | - PrefixListId 102 | 103 | VSCodeServerSecurityGroupEgress: 104 | Type: AWS::EC2::SecurityGroupEgress 105 | Properties: 106 | Description: egress for vscode security group 107 | GroupId: 108 | Fn::GetAtt: 109 | - VSCodeServerSecurityGroup 110 | - GroupId 111 | IpProtocol: -1 112 | CidrIp: !Ref InternetCidrBlock 113 | #------------------------------------------------------ 114 | # Role and Instance Profile 115 | #------------------------------------------------------ 116 | VSCodeServerIAMRole: 117 | Type: AWS::IAM::Role 118 | Properties: 119 | AssumeRolePolicyDocument: 120 | Version: 2012-10-17 121 | Statement: 122 | - Action: 123 | - sts:AssumeRole 124 | Effect: Allow 125 | Principal: 126 | Service: 127 | - ec2.amazonaws.com 128 | ManagedPolicyArns: 129 | - arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM 130 | Policies: 131 | - PolicyName: SSMParameterAccess 132 | PolicyDocument: 133 | Version: 2012-10-17 134 | Statement: 135 | - Effect: Allow 136 | Action: 137 | - ssm:PutParameter 138 | - ssm:GetParameter 139 | Resource: !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/code-server/*" 140 | InstanceProfile: 141 | Type: AWS::IAM::InstanceProfile 142 | Properties: 143 | Roles: 144 | - Ref: VSCodeServerIAMRole 145 | #------------------------------------------------------ 146 | # Elastic IP for EC2 Instance 147 | #------------------------------------------------------ 148 | VSCodeServerEIP: 149 | Type: AWS::EC2::EIP 150 | Properties: 151 | Domain: vpc 152 | Tags: 153 | - Key: Name 154 | Value: VSCodeServer-EIP 155 | 156 | VSCodeServerEIPAssociation: 157 | Type: AWS::EC2::EIPAssociation 158 | Properties: 159 | AllocationId: !GetAtt VSCodeServerEIP.AllocationId 160 | InstanceId: !Ref VSCodeServer 161 | #------------------------------------------------------ 162 | # EC2 Instance for VSCode Server 163 | #------------------------------------------------------ 164 | VSCodeServer: 165 | Type: AWS::EC2::Instance 166 | Metadata: 167 | cfn_nag: 168 | rules_to_suppress: 169 | - id: W40 170 | reason: allow tcp 8080 from the cloudfront prefix list 171 | Properties: 172 | ImageId: !Ref LatestAmiId 173 | InstanceType: !Ref InstanceType 174 | IamInstanceProfile: !Ref InstanceProfile 175 | Tags: 176 | - Key: Name 177 | Value: VSCodeServer 178 | NetworkInterfaces: 179 | - DeviceIndex: "0" 180 | AssociatePublicIpAddress: "true" 181 | SubnetId: 182 | Fn::If: 183 | - ImportSubnetIDNotEmpty 184 | - Ref: SubnetID 185 | - Ref: AWS::NoValue 186 | GroupSet: 187 | - Fn::GetAtt: 188 | - VSCodeServerSecurityGroup 189 | - GroupId 190 | Monitoring: true 191 | UserData: 192 | Fn::Base64: 193 | Fn::Sub: 194 | - | 195 | #!/bin/bash 196 | echo "INFO: Starting UserData script execution" 197 | 198 | # Install AWS CLI 199 | echo "INFO: Installing AWS CLI prerequisites" 200 | apt-get -o DPkg::Lock::Timeout=-1 update 201 | DEBIAN_FRONTEND=noninteractive apt-get -o DPkg::Lock::Timeout=-1 install -y curl unzip 202 | echo "INFO: Prerequisites installed, downloading AWS CLI" 203 | curl -fsSL https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip -o /tmp/aws-cli.zip 204 | echo "INFO: Extracting AWS CLI" 205 | unzip -q -d /tmp /tmp/aws-cli.zip 206 | echo "INFO: Installing AWS CLI" 207 | sudo /tmp/aws/install 208 | rm -rf /tmp/aws /tmp/aws-cli.zip 209 | echo "INFO: AWS CLI installation complete" 210 | aws --version 211 | 212 | # Install code-server 213 | echo "INFO: Installing code-server" 214 | curl -fOL https://github.com/coder/code-server/releases/download/v${VERSION}/code-server_${VERSION}_amd64.deb 215 | sudo dpkg -i code-server_${VERSION}_amd64.deb 216 | echo "INFO: Enabling and starting code-server" 217 | sudo systemctl enable --now code-server@ubuntu 218 | sleep 30 219 | 220 | # Configure password 221 | echo "INFO: Configuring code-server" 222 | # sed -i.bak 's/auth: password/auth: none/' /home/ubuntu/.config/code-server/config.yaml 223 | # Expose code server service 224 | sed -i.bak 's/bind-addr: 127.0.0.1:8080/bind-addr: 0.0.0.0:8080/' /home/ubuntu/.config/code-server/config.yaml 225 | 226 | # Restart code server 227 | echo "INFO: Restarting code-server" 228 | sudo systemctl restart code-server@ubuntu 229 | 230 | # Install extension amazonwebservices.amazon-q-vscode 231 | echo "INFO: Installing Amazon Q extension" 232 | sudo -u ubuntu code-server --install-extension amazonwebservices.amazon-q-vscode 233 | 234 | # Restart code server 235 | echo "INFO: Final restart of code-server" 236 | sudo systemctl restart code-server@ubuntu 237 | 238 | # Store password in SSM Parameter Store for easy retrieval 239 | echo "INFO: Storing password in SSM Parameter Store" 240 | sleep 10 # Wait for config file to be fully written 241 | CODE_SERVER_PASSWORD=$(sudo grep "^password:" /home/ubuntu/.config/code-server/config.yaml | cut -d' ' -f2) 242 | echo "INFO: Extracted password, creating SSM parameter" 243 | aws ssm put-parameter \ 244 | --name "/code-server/password" \ 245 | --value "$CODE_SERVER_PASSWORD" \ 246 | --type "SecureString" \ 247 | --region ${AWS::Region} \ 248 | --overwrite 249 | echo "INFO: SSM parameter creation complete" 250 | echo "INFO: UserData script execution finished" 251 | - VERSION: !Ref VSCodeServerVersion 252 | #------------------------------------------------------ 253 | # CloudFront Cached Policy 254 | #------------------------------------------------------ 255 | VSCodeServerCloudFrontCachePolicy: 256 | Type: AWS::CloudFront::CachePolicy 257 | Properties: 258 | CachePolicyConfig: 259 | DefaultTTL: 86400 260 | MaxTTL: 31536000 261 | MinTTL: 1 262 | Name: !Join ['-', ['VSCodeServer', !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]]] 263 | ParametersInCacheKeyAndForwardedToOrigin: 264 | CookiesConfig: 265 | CookieBehavior: all 266 | EnableAcceptEncodingGzip: False 267 | HeadersConfig: 268 | HeaderBehavior: whitelist 269 | Headers: 270 | - Accept-Charset 271 | - Authorization 272 | - Origin 273 | - Accept 274 | - Referer 275 | - Host 276 | - Accept-Language 277 | - Accept-Encoding 278 | - Accept-Datetime 279 | QueryStringsConfig: 280 | QueryStringBehavior: all 281 | #------------------------------------------------------ 282 | # CloudFront Distribution 283 | #------------------------------------------------------ 284 | VSCodeServerCloudFront: 285 | Type: AWS::CloudFront::Distribution 286 | DependsOn: VSCodeServerEIPAssociation 287 | Metadata: 288 | cfn_nag: 289 | rules_to_suppress: 290 | - id: W10 291 | reason: disable access logging for demo purpose 292 | - id: W70 293 | reason: no TLS version for demo purpose 294 | Properties: 295 | DistributionConfig: 296 | Origins: 297 | - DomainName: !GetAtt VSCodeServer.PublicDnsName 298 | Id: VS-code-server 299 | CustomOriginConfig: 300 | HTTPPort: 8080 301 | OriginProtocolPolicy: http-only 302 | Enabled: true 303 | DefaultCacheBehavior: 304 | AllowedMethods: 305 | - GET 306 | - HEAD 307 | - OPTIONS 308 | - PUT 309 | - POST 310 | - PATCH 311 | - DELETE 312 | ForwardedValues: 313 | QueryString: 'false' 314 | Compress: false 315 | TargetOriginId: VS-code-server 316 | ViewerProtocolPolicy: allow-all 317 | OriginRequestPolicyId: !Ref OriginRequestPolicyId 318 | CachePolicyId: !Ref VSCodeServerCloudFrontCachePolicy 319 | #------------------------------------------------------ 320 | # Exported output 321 | #------------------------------------------------------ 322 | Outputs: 323 | VSCodeServerCloudFrontDomainName: 324 | Value: 325 | !Sub 326 | - "https://${domain}" 327 | - { domain: !GetAtt VSCodeServerCloudFront.DomainName } 328 | Export: 329 | Name: !Sub ${AWS::StackName}-domain-name 330 | VSCodeServerPublicIP: 331 | Value: !Ref VSCodeServerEIP 332 | Export: 333 | Name: !Sub ${AWS::StackName}-code-server-public-ip 334 | VSCodeServerPrivateIP: 335 | Value: !GetAtt VSCodeServer.PrivateIp 336 | Export: 337 | Name: !Sub ${AWS::StackName}-code-server-private-ip 338 | VSCodeServerRoleARN: 339 | Value: !GetAtt VSCodeServerIAMRole.Arn 340 | Export: 341 | Name: !Sub ${AWS::StackName}-code-server-role-arn 342 | VSCodeServerInstanceId: 343 | Value: !Ref VSCodeServer 344 | Export: 345 | Name: !Sub ${AWS::StackName}-code-server-instance-id 346 | VSCodeServerPasswordSSM: 347 | Description: SSM Parameter containing the code-server password 348 | Value: "/code-server/password" 349 | Export: 350 | Name: !Sub ${AWS::StackName}-code-server-password-ssm 351 | --------------------------------------------------------------------------------