-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
Adding terraform template configuration for AWS
1 parent
89689db
commit 26b0d5f
Showing
13 changed files
with
1,013 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
name: Publish the project on AWS | ||
|
||
on: | ||
push: | ||
branches: | ||
- test | ||
|
||
jobs: | ||
build: | ||
name: Building a release and version file | ||
runs-on: ubuntu-22.04 | ||
outputs: | ||
tag: ${{ steps.save-tag.outputs.tag }} | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Setup BEAM | ||
uses: erlef/setup-beam@v1 | ||
with: | ||
version-file: .tool-versions | ||
version-type: strict | ||
rebar3-version: '3.24.0' | ||
|
||
- name: Capture GITHUB_SHORT_SHA | ||
run: | | ||
GITHUB_SHORT_SHA=$(git rev-parse --short ${{ github.sha }}) | ||
echo "GITHUB_SHORT_SHA=${GITHUB_SHORT_SHA}" >> $GITHUB_ENV | ||
- name: Capture and update project mix version | ||
id: save-tag | ||
run: | | ||
GLEAM_VERSION=`grep "version =" gleam.toml | awk -F'"' '{print $2}'` | ||
PROJ_TAG=${GLEAM_VERSION}-${GITHUB_SHORT_SHA} | ||
echo "PROJ_TAG=${PROJ_TAG}" >> $GITHUB_ENV | ||
echo "tag=$PROJ_TAG" >> "$GITHUB_OUTPUT" | ||
echo "Creating the tag: $PROJ_TAG" | ||
- name: Update project gleam version | ||
run: | | ||
sed -i "s/.*version =.*/version = \"${{ env.PROJ_TAG }}\"/" gleam.toml | ||
- name: Install Gleam dependencies | ||
run: gleam deps download | ||
|
||
- name: Generate the release files | ||
run: gleam export erlang-shipment | ||
|
||
- name: Generate tarball to publish | ||
run: | | ||
cd build | ||
tar -czvf cochito-${{ env.PROJ_TAG }}.tar.gz erlang-shipment | ||
- name: Create Release file version | ||
run: | | ||
echo "{\"version\":\"${{ env.PROJ_TAG }}\",\"hash\":\"${GITHUB_SHA}\"}" | jq > current.json | ||
- name: 'Upload release file artifact' | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: release-file | ||
path: build/cochito-${{ env.PROJ_TAG }}.tar.gz | ||
retention-days: 5 | ||
|
||
- name: 'Upload version file artifact' | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: version-file | ||
path: current.json | ||
retention-days: 5 | ||
|
||
upload_aws: | ||
name: Upload files to AWS environment | ||
needs: build | ||
runs-on: ubuntu-22.04 | ||
env: | ||
VERSION_SHA: ${{ needs.build.outputs.tag }} | ||
permissions: | ||
contents: write | ||
steps: | ||
- name: Download version file artefact | ||
uses: actions/download-artifact@v4 | ||
with: | ||
name: version-file | ||
|
||
- name: Download release file artefact | ||
uses: actions/download-artifact@v4 | ||
with: | ||
name: release-file | ||
|
||
- name: Copy a release file to the s3 distribution folder | ||
uses: prewk/s3-cp-action@v2 | ||
with: | ||
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} | ||
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | ||
aws_region: "us-east-1" | ||
source: "cochito-${VERSION_SHA}.tar.gz" | ||
dest: "s3://cochito-${{ secrets.CLOUD_ENV_NAME }}-distribution/dist/cochito/cochito-${VERSION_SHA}.tar.gz" | ||
|
||
- name: Copy a version file to the s3 version folder | ||
uses: prewk/s3-cp-action@v2 | ||
with: | ||
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} | ||
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | ||
aws_region: "us-east-1" | ||
source: "current.json" | ||
dest: "s3://cochito-${{ secrets.CLOUD_ENV_NAME }}-distribution/versions/cochito/${{ secrets.CLOUD_ENV_NAME }}/current.json" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
erlang 26.1.2 | ||
gleam 1.5.1 | ||
terraform 1.5.6 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
# AWS Deployment for Gleam with Terraform | ||
|
||
This guide demonstrates how to deploy DeployEx in Amazon Web Services (AWS) using Terraform to programmatically set up the environment. | ||
|
||
## Setup | ||
|
||
To begin, ensure the following applications are installed: | ||
|
||
* Terraform | ||
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) | ||
|
||
### 1. SSH Key Pair | ||
|
||
Create an SSH key pair named, e. g. `cochito-web-ec2` by visiting the [AWS Key Pair page](https://sa-east-1.console.aws.amazon.com/ec2/home?region=sa-east-1#KeyPairs:). Save the private key in your local SSH folder (`~/.ssh`). The name `cochito-web-ec2` will be used by this file `devops/terraform/modules/standard-account/variables.tf` within terraform templates. | ||
|
||
### 2. Environment Secrets | ||
|
||
Ensure you have access to the following secrets for storage in Secrets Manager: | ||
|
||
| SECRET NAME | EXAMPLE | SOURCE | | ||
|----------|-------------|------:| | ||
| DEPLOYEX_SECRET_KEY_BASE | 42otsNl...Fpq3dIJ02 | mix phx.gen.secret | | ||
| DEPLOYEX_ERLANG_COOKIE| my-cookie | | | ||
| DEPLOYEX_ADMIN_HASHED_PASSWORD | $2b$12$...3Lu6ys538TW | Bcrypt.hash_pwd_salt("my-pass") | | ||
|
||
### 3. Variables Configuration | ||
|
||
Rename the file [main_example.tf_](./environments/prod/main_example.tf_) to [main.tf](./environments/prod/main.tf) and verify and configure the variables according to your specific environment. Ensure that you also review and update the [variables file](./modules/standard-account/variables.tf). These variables will be utilized across all Terraform templates to ensure correct setup. | ||
|
||
### 4. Provisioning the Environment | ||
|
||
Check you have the correct credentials to create/update resources in aws: | ||
```bash | ||
cat ~/.aws/credentials | ||
[default] | ||
aws_access_key_id=access_key_id | ||
aws_secret_access_key=secret_access_key | ||
``` | ||
|
||
Once the key is configured, proceed with provisioning the environment. Navigate to the `./environments/prod` folder and execute the following commands: | ||
|
||
```bash | ||
terraform plan # Check if the templates are configured correctly | ||
terraform apply # Apply the configurations to create the environment | ||
``` | ||
|
||
Wait for the environment to be created. Once the provisioning is complete, you can check the instance at this [address](https://console.aws.amazon.com/ec2/home). | ||
|
||
#### Updating Secret Manager | ||
|
||
Navigate to [AWS Secrets Manager](https://console.aws.amazon.com/secretsmanager/listsecrets), locate and update the following secret: | ||
|
||
* *__deployex-cochito-prod-secrets__* | ||
|
||
Click on the secret, then select "Retrieve Secret Value" and edit the secret by adding the new key/value pairs: | ||
|
||
```bash | ||
DEPLOYEX_SECRET_KEY_BASE=xxxxxxxxxx | ||
DEPLOYEX_ERLANG_COOKIE=xxxxxxxxxx | ||
DEPLOYEX_ADMIN_HASHED_PASSWORD=xxxxxxxxxx | ||
``` | ||
|
||
* *__cochito-stage-otp-tls-ca__*, *__cochito-stage-otp-tls-key__*, *__cochito-stage-otp-tls-crt__*: | ||
|
||
Create the TLS certificates for OTP distribution using the [Following script](../../../devops/scripts/tls-distribution-certs), changing the appropriate names and regions inside it. | ||
|
||
```bash | ||
make tls-distribution-certs | ||
``` | ||
|
||
The command will generate three files: `ca.crt`, `deployex.key` and `deployex.crt`. Click in each secret in AWS, then select "Retrieve Secret Value" and edit the secret by adding them as plain text, For guidance, you can refer to this [eaxample](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-ranger-tls-certificates.html). | ||
|
||
### 5. EC2 Provisioning (Manual Steps) | ||
|
||
When running Terraform for the first time, AWS secrets are not yet created. Consequently, attempts to execute deployex or certificates installation will fail. Once these AWS secrets, including certificates and other sensitive information, are updated, subsequent iterations of Terraform's EC2 destroy/create process will no longer require manual intervention. | ||
|
||
For initial installations or updates to deployex, follow these steps: | ||
|
||
*__PS__*: make sure you have the pair cochito-web-ec2.pem saved in `~/.ssh/` | ||
|
||
```bash | ||
ssh -i "cochito-web-ec2.pem" [email protected] | ||
ubuntu@ip-10-0-1-56:~$ | ||
``` | ||
|
||
After getting access to EC2, you need to grant root permissions: | ||
|
||
```bash | ||
ubuntu@ip-10-0-1-56:~$ sudo su | ||
root@ip-10-0-1-56:/home/ubuntu$ | ||
``` | ||
|
||
Since the secrets are already updated, we are going to install them in the appropriate addresses | ||
```bash | ||
./install-otp-certificates.sh | ||
|
||
# Installing Certificates env: stage at /usr/local/share/ca-certificates # | ||
Retrieving and saving ...... | ||
[OK] | ||
``` | ||
|
||
Check that the certificates are correctly installed: | ||
```bash | ||
ls /usr/local/share/ca-certificates | ||
ca.crt cochito.crt cochito.key deployex.crt deployex.key | ||
``` | ||
If you are updating DeployEx, you may need to update the `deployex.sh` script. This step is not necessary during the initial installation, as the script is already installed by default. To update the script, use the following commands: | ||
|
||
```bash | ||
version=0.3.0 | ||
rm deployex.sh | ||
wget https://github.com/thiagoesteves/deployex/releases/download/${version}/deployex.sh -P /home/ubuntu | ||
chmod a+x deployex.sh | ||
|
||
Run the script to install (or update) deployex: | ||
|
||
```bash | ||
root@ip-10-0-1-116:/home/ubuntu# ./deployex.sh --install deployex-config.json | ||
# Removing Deployex # | ||
... | ||
# Clean and create a new directory # | ||
# Start systemd # | ||
# Start new service # | ||
Created symlink /etc/systemd/system/multi-user.target.wants/deployex.service → /etc/systemd/system/deployex.service. | ||
``` | ||
|
||
If you need to update Deployex, follow these steps to ensure that the configuration file reflects the new version: | ||
|
||
```bash | ||
vi deployex-config.json | ||
{ | ||
... | ||
"version": "0.3.0-rc15", | ||
"os_target": "ubuntu-22.04", | ||
... | ||
} | ||
``` | ||
|
||
Once the file is updated, run the update command: | ||
```bash | ||
root@ip-10-0-1-116:/home/ubuntu# ./deployex.sh --update deployex-config.json | ||
``` | ||
|
||
> [!IMPORTANT] | ||
> Depending on the new version of DeployEx, you may need to update both the `deployex-config.json` file and the `deployex.sh` script | ||
|
||
At this point, DeployEx should be running. You can view the logs using the following commands: | ||
```bash | ||
tail -f /var/log/deployex/deployex-stdout.log | ||
tail -f /var/log/deployex/deployex-stderr.log | ||
``` | ||
|
||
### 6. Monitored App deployment | ||
|
||
Once DeployEx is running, you __MUST__ deploy the monitored app. This deployment involves creating the release package and the current version JSON file in the designated storage path. | ||
|
||
#### Release Version | ||
|
||
The release version file __MUST__ be formatted in JSON and include the following information: | ||
|
||
```bash | ||
{ | ||
"version": "0.1.0-9cad9cd", | ||
"hash": "9cad9cd3581c69fdd02ff60765e1c7dd4599d84a", | ||
"pre_commands": [] | ||
} | ||
``` | ||
|
||
The JSON file __MUST__ be stored at the following path: `/versions/{monitored_app}/{env}/current.json` | ||
|
||
#### Release package | ||
|
||
After DeployEx fetches the release file, it will download the release package for installation. The package should be located at: `/dist/{monitored_app}/{monitored_app}-{version}.tar.gz` | ||
|
||
|
||
#### [CI/CD] Upload files to AWS from Github | ||
|
||
Here are some useful resources with suggestions on how to automate the upload of version and release files to your environment using GitHub Actions: | ||
|
||
* [Guthub Actions - S3 Downloader/Uploader](https://github.com/marketplace/actions/s3-cp) | ||
* [Calori Webserver Example with AWS](https://github.com/thiagoesteves/calori/tree/main/devops/aws/terraform) | ||
|
||
### 7. Setting Up HTTPS Certificates with Let's Encrypt | ||
|
||
> [!IMPORTANT] | ||
> Before proceeding, make sure that the DNS is correctly configured to point to the AWS instance. | ||
|
||
|
||
For HTTPS, you can use free certificates from [Let's encrypt](https://letsencrypt.org/getting-started/). In this example, we'll use [cert bot for ubuntu](https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal) to obtain and configure the certificates: | ||
|
||
```bash | ||
sudo su | ||
apt update | ||
apt install snapd | ||
snap install --classic certbot | ||
ln -s /snap/bin/certbot /usr/bin/certbot | ||
``` | ||
|
||
Before installing the certificate, make a backup of the current Nginx configuration file located at `/etc/nginx/sites-available/default`. Certbot may modify this file, so keeping a local copy ensures you can restore it if needed. Once the backup is created, run the following command: | ||
```bash | ||
certbot --nginx | ||
``` | ||
|
||
This command will install Certbot and automatically configure Nginx to use the obtained certificates. After Nginx is configured, the certificate paths will be set up and will look something like this: | ||
|
||
```bash | ||
vi /etc/nginx/sites-available/default | ||
... | ||
ssl_certificate /etc/letsencrypt/live/cochito.com/fullchain.pem; # managed by Certbot | ||
ssl_certificate_key /etc/letsencrypt/live/cochito.com/privkey.pem; # managed by Certbot | ||
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot | ||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot | ||
``` | ||
|
||
Update your configuration file to include the Let's Encrypt certificate paths. Find the section where it mentions: | ||
```bash | ||
# Add here the letsencrypt paths | ||
``` | ||
replace this comment with the actual certificate paths: | ||
```bash | ||
proxy_set_header Upgrade $http_upgrade; | ||
proxy_set_header Connection "upgrade"; | ||
proxy_pass http://deployex; | ||
} | ||
ssl_certificate /etc/letsencrypt/live/cochito.com/fullchain.pem; # managed by Certbot | ||
ssl_certificate_key /etc/letsencrypt/live/cochito.com/privkey.pem; # managed by Certbot | ||
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot | ||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot | ||
} | ||
``` | ||
Also, ensure that port 443 is enabled for both servers. For example: | ||
```bash | ||
server { | ||
listen 443 ssl; # managed by Certbot | ||
``` | ||
After modifying the configuration file, save the changes and restart Nginx: | ||
```bash | ||
sudo su | ||
vi /etc/nginx/sites-available/default | ||
# modify and save file | ||
systemctl reload nginx | ||
``` | ||
> [!NOTE] | ||
> After the changes, It may require a reboot. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
### macOS ### | ||
# General | ||
.DS_Store | ||
.AppleDouble | ||
.LSOverride | ||
|
||
# Thumbnails | ||
._* | ||
|
||
### Terraform ### | ||
# Local .terraform directories | ||
**/.terraform/* | ||
|
||
# .tfstate files | ||
*.tfstate | ||
*.tfstate.* | ||
|
||
# Crash log files | ||
crash.log | ||
crash.*.log | ||
|
||
# Exclude all .tfvars files, which are likely to contain sensitive data, such as | ||
# password, private keys, and other secrets. These should not be part of version | ||
# control as they are data points which are potentially sensitive and subject | ||
# to change depending on the environment. | ||
*.tfvars | ||
*.tfvars.json | ||
|
||
# Ignore override files as they are usually used to override resources locally and so | ||
# are not checked in | ||
override.tf | ||
override.tf.json | ||
*_override.tf | ||
*_override.tf.json | ||
|
||
# Include override files you do wish to add to version control using negated pattern | ||
# !example_override.tf | ||
|
||
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan | ||
# example: *tfplan* | ||
|
||
# Ignore CLI configuration files | ||
.terraformrc | ||
terraform.rc | ||
|
||
### Terragrunt ### | ||
# terragrunt cache directories | ||
**/.terragrunt-cache/* | ||
|
||
# Terragrunt debug output file (when using `--terragrunt-debug` option) | ||
# See: https://terragrunt.gruntwork.io/docs/reference/cli-options/#terragrunt-debug | ||
terragrunt-debug.tfvars.json | ||
|
||
### VisualStudioCode ### | ||
.vscode/* | ||
!.vscode/settings.json | ||
!.vscode/tasks.json | ||
!.vscode/launch.json | ||
!.vscode/extensions.json | ||
!.vscode/*.code-snippets |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
main.tf | ||
.terraform.lock.hcl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Rename me to main.tf and populated with the corrected values | ||
|
||
provider "aws" { | ||
region = "sa-east-1" | ||
allowed_account_ids = ["921999999999"] | ||
} | ||
|
||
module "standard_account" { | ||
source = "../../modules/standard-account" | ||
account_name = "prod" | ||
server_dns = "cochito.com" | ||
replicas = "3" | ||
ec2_instance_type = "t2.medium" | ||
deployex_dns = "deployex.cochito.com" | ||
deployex_version = "0.3.0-rc21" | ||
} |
191 changes: 191 additions & 0 deletions
191
devops/aws/terraform/modules/standard-account/cloud-config.tpl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
#cloud-config | ||
# | ||
# Cloud init template for EC2 cochito instances. | ||
# | ||
# In case you need it, the log of the cloud-init can be found at: | ||
# /var/log/cloud-init-output.log | ||
# | ||
packages: | ||
- unzip | ||
- nginx | ||
- jq | ||
|
||
write_files: | ||
- path: /home/ubuntu/install-otp-certificates.sh | ||
owner: root:root | ||
permissions: "0755" | ||
content: | | ||
#!/bin/bash | ||
# | ||
# Script to install certificates | ||
# | ||
echo "" | ||
echo "# Installing Certificates env: ${account_name} at /usr/local/share/ca-certificates #" | ||
echo "Retrieving and saving ......" | ||
aws secretsmanager get-secret-value --secret-id cochito-${account_name}-otp-tls-ca | jq -r .SecretString > /usr/local/share/ca-certificates/ca.crt | ||
aws secretsmanager get-secret-value --secret-id cochito-${account_name}-otp-tls-key | jq -r .SecretString > /usr/local/share/ca-certificates/deployex.key | ||
aws secretsmanager get-secret-value --secret-id cochito-${account_name}-otp-tls-key | jq -r .SecretString > /usr/local/share/ca-certificates/cochito.key | ||
aws secretsmanager get-secret-value --secret-id cochito-${account_name}-otp-tls-crt | jq -r .SecretString > /usr/local/share/ca-certificates/deployex.crt | ||
aws secretsmanager get-secret-value --secret-id cochito-${account_name}-otp-tls-crt | jq -r .SecretString > /usr/local/share/ca-certificates/cochito.crt | ||
echo "[OK]" | ||
- path: /home/ubuntu/deployex-config.json | ||
owner: root:root | ||
permissions: "0644" | ||
content: | | ||
{ | ||
"app_name": "cochito", | ||
"app_name": "gleam", | ||
"replicas": ${replicas}, | ||
"account_name": "${account_name}", | ||
"deployex_hostname": "${deployex_hostname}", | ||
"release_adapter": "s3", | ||
"release_bucket": "cochito-${account_name}-distribution", | ||
"secrets_adapter": "aws", | ||
"secrets_path": "deployex-cochito-${account_name}-secrets", | ||
"aws_region": "${aws_region}", | ||
"version": "${deployex_version}", | ||
"os_target": "ubuntu-22.04", | ||
"deploy_timeout_rollback_ms": 600000, | ||
"deploy_schedule_interval_ms": 5000, | ||
"env": { } | ||
} | ||
- path: /home/ubuntu/config.json | ||
owner: root:root | ||
permissions: "0644" | ||
content: | | ||
{ | ||
"agent": { | ||
"run_as_user": "root" | ||
}, | ||
"logs": { | ||
"logs_collected": { | ||
"files": { | ||
"collect_list": [ | ||
{ | ||
"file_path": "/var/log/deployex/deployex-stdout.log", | ||
"log_group_name": "${log_group_name}", | ||
"log_stream_name": "{instance_id}-deployex-stdout-log", | ||
"timezone": "UTC", | ||
"timestamp_format": "%H: %M: %S%Y%b%-d" | ||
}, | ||
{ | ||
"file_path": "/var/log/deployex/deployex-stderr.log", | ||
"log_group_name": "${log_group_name}", | ||
"log_stream_name": "{instance_id}-deployex-stderr-log", | ||
"timezone": "UTC", | ||
"timestamp_format": "%H: %M: %S%Y%b%-d" | ||
}, | ||
{ | ||
"file_path": "/var/log/cochito/cochito-*-stdout.log", | ||
"log_group_name": "${log_group_name}", | ||
"log_stream_name": "{instance_id}-cochito-stdout-log", | ||
"timezone": "UTC", | ||
"timestamp_format": "%H: %M: %S%Y%b%-d" | ||
}, | ||
{ | ||
"file_path": "/var/log/cochito/cochito-*-stderr.log", | ||
"log_group_name": "${log_group_name}", | ||
"log_stream_name": "{instance_id}-cochito-stderr-log", | ||
"timezone": "UTC", | ||
"timestamp_format": "%H: %M: %S%Y%b%-d" | ||
} | ||
] | ||
} | ||
} | ||
} | ||
} | ||
- path: /etc/nginx/sites-available/default | ||
owner: root:root | ||
permissions: "0644" | ||
content: | | ||
upstream gleam { | ||
server 127.0.0.1:4000 max_fails=5 fail_timeout=60s; | ||
server 127.0.0.1:4001 max_fails=5 fail_timeout=60s; | ||
server 127.0.0.1:4002 max_fails=5 fail_timeout=60s; | ||
} | ||
|
||
upstream deployex { | ||
server 127.0.0.1:5001 max_fails=5 fail_timeout=60s; | ||
} | ||
|
||
server { | ||
listen 80; | ||
server_name gleam.deployex.pro deployex.gleam.deployex.pro; | ||
if ($host = gleam.deployex.pro) { | ||
return 301 https://$host$request_uri; | ||
} # managed by Certbot | ||
|
||
|
||
if ($host = deployex.gleam.deployex.pro) { | ||
return 301 https://$host$request_uri; | ||
} # managed by Certbot | ||
|
||
return 404; # managed by Certbot | ||
} | ||
|
||
server { | ||
#listen 443 ssl; # managed by Certbot | ||
server_name deployex.gleam.deployex.pro; | ||
client_max_body_size 30M; | ||
location / { | ||
allow all; | ||
# Proxy Headers | ||
proxy_http_version 1.1; | ||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | ||
proxy_set_header Host $http_host; | ||
proxy_set_header X-Cluster-Client-Ip $remote_addr; | ||
# The Important Websocket Bits! | ||
proxy_set_header Upgrade $http_upgrade; | ||
proxy_set_header Connection "upgrade"; | ||
proxy_pass http://deployex; | ||
} | ||
|
||
# Add here the letsencrypt paths | ||
} | ||
|
||
server { | ||
#listen 443 ssl; # managed by Certbot | ||
server_name gleam.deployex.pro; | ||
client_max_body_size 30M; | ||
location / { | ||
allow all; | ||
# Proxy Headers | ||
proxy_http_version 1.1; | ||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | ||
proxy_set_header Host $http_host; | ||
proxy_set_header X-Cluster-Client-Ip $remote_addr; | ||
# The Important Websocket Bits! | ||
proxy_set_header Upgrade $http_upgrade; | ||
proxy_set_header Connection "upgrade"; | ||
proxy_pass http://gleam; | ||
} | ||
# Add here the letsencrypt paths | ||
} | ||
runcmd: | ||
- cd /tmp | ||
- curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" "-o" "awscliv2.zip" | ||
- unzip "awscliv2.zip" | ||
- ./aws/install | ||
- ./aws/install --update | ||
- /home/ubuntu/install-otp-certificates.sh | ||
- wget https://github.com/thiagoesteves/deployex/releases/download/${deployex_version}/deployex.sh -P /home/ubuntu | ||
- chmod a+x /home/ubuntu/deployex.sh | ||
- /home/ubuntu/deployex.sh --install /home/ubuntu/deployex-config.json | ||
- wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb | ||
- dpkg -i -E ./amazon-cloudwatch-agent.deb | ||
- /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/home/ubuntu/config.json -s | ||
- apt install -y build-essential libssl-dev libgtk-3-dev libncurses5-dev libncursesw5-dev libreadline-dev | ||
- wget https://github.com/erlang/otp/releases/download/OTP-26.1.2/otp_src_26.1.2.tar.gz | ||
- tar -xzf otp_src_26.1.2.tar.gz && cd otp_src_26.1.2 && ./configure && make && make install | ||
- systemctl enable --no-block nginx | ||
- systemctl start --no-block nginx | ||
- reboot |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
data "aws_ami" "ubuntu" { | ||
most_recent = true | ||
|
||
filter { | ||
name = "name" | ||
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] | ||
} | ||
|
||
filter { | ||
name = "virtualization-type" | ||
values = ["hvm"] | ||
} | ||
|
||
owners = ["099720109477"] # Canonical | ||
} | ||
|
||
resource "aws_security_group" "ec2_security" { | ||
name = "cochito-${var.account_name}-ec2-security-group" | ||
description = "Allow SSH traffic from everywhere" | ||
vpc_id = aws_vpc.custom_vpc.id | ||
} | ||
|
||
resource "aws_security_group_rule" "allow_ingress_ssh" { | ||
security_group_id = "${aws_security_group.ec2_security.id}" | ||
type = "ingress" | ||
protocol = "tcp" | ||
from_port = 22 | ||
to_port = 22 | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
|
||
resource "aws_security_group_rule" "allow_ingress_http" { | ||
security_group_id = "${aws_security_group.ec2_security.id}" | ||
type = "ingress" | ||
protocol = "tcp" | ||
from_port = 80 | ||
to_port = 80 | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
|
||
resource "aws_security_group_rule" "allow_ingress_https" { | ||
security_group_id = "${aws_security_group.ec2_security.id}" | ||
type = "ingress" | ||
protocol = "tcp" | ||
from_port = 443 | ||
to_port = 443 | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
|
||
resource "aws_security_group_rule" "allow_egress_all" { | ||
security_group_id = "${aws_security_group.ec2_security.id}" | ||
type = "egress" | ||
protocol = "-1" | ||
from_port = 0 | ||
to_port = 0 | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
|
||
data "aws_iam_policy_document" "ec2_assume_role" { | ||
statement { | ||
effect = "Allow" | ||
|
||
principals { | ||
type = "Service" | ||
identifiers = ["ec2.amazonaws.com"] | ||
} | ||
|
||
actions = ["sts:AssumeRole"] | ||
} | ||
} | ||
|
||
resource "aws_iam_role" "ec2_iam_role" { | ||
name = "cochito-${var.account_name}-instance-role" | ||
assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json | ||
} | ||
|
||
resource "aws_iam_role_policy_attachment" "attach-s3" { | ||
role = aws_iam_role.ec2_iam_role.name | ||
policy_arn = aws_iam_policy.s3_distribution_bucket_policy.arn | ||
} | ||
|
||
resource "aws_iam_role_policy_attachment" "attach-secrets" { | ||
role = aws_iam_role.ec2_iam_role.name | ||
policy_arn = aws_iam_policy.cochito_secrets_manager_policy.arn | ||
} | ||
|
||
resource "aws_iam_role_policy_attachment" "attach-cloudwatch" { | ||
role = aws_iam_role.ec2_iam_role.name | ||
policy_arn = aws_iam_policy.ec2_cloudwatch_policy.arn | ||
} | ||
|
||
resource "aws_iam_instance_profile" "cochito_node" { | ||
name = "cochito-${var.account_name}-ec2-profile" | ||
role = aws_iam_role.ec2_iam_role.name | ||
} | ||
|
||
data "cloudinit_config" "server_config" { | ||
gzip = true | ||
base64_encode = true | ||
part { | ||
content_type = "text/cloud-config" | ||
content = templatefile("${path.module}/cloud-config.tpl", { | ||
hostname = "${var.server_dns}" | ||
deployex_hostname = "${var.deployex_dns}" | ||
deployex_version = "${var.deployex_version}" | ||
log_group_name = aws_cloudwatch_log_group.ec2_instance_logs.name | ||
account_name = "${var.account_name}" | ||
aws_region = "${var.aws_region}" | ||
replicas = "${var.replicas}" | ||
}) | ||
} | ||
} | ||
|
||
resource "aws_instance" "ec2_cochito_instance" { | ||
ami = data.aws_ami.ubuntu.id | ||
instance_type = "${var.ec2_instance_type}" | ||
key_name = "${var.aws_key_name}" | ||
vpc_security_group_ids = [aws_security_group.ec2_security.id] | ||
subnet_id = aws_subnet.public_subnet.id | ||
iam_instance_profile = aws_iam_instance_profile.cochito_node.name | ||
associate_public_ip_address = true | ||
user_data = data.cloudinit_config.server_config.rendered | ||
user_data_replace_on_change = true | ||
|
||
tags = { | ||
Name = "cochito-${var.account_name}-instance" | ||
} | ||
lifecycle { | ||
create_before_destroy = true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# | ||
# Logs and metrics | ||
# | ||
|
||
resource "aws_cloudwatch_log_group" "ec2_instance_logs" { | ||
name = "cochito-${var.account_name}-ec2-instance-logs" | ||
} | ||
|
||
resource "aws_iam_policy" "ec2_cloudwatch_policy" { | ||
name = "cochito-${var.account_name}-ec2-cloudwatch-policy" | ||
|
||
policy = jsonencode({ | ||
Version = "2012-10-17" | ||
Statement = [ | ||
{ | ||
Action = [ | ||
"logs:Create*", | ||
"logs:PutLogEvents", | ||
"logs:DescribeLogStreams" | ||
] | ||
Effect = "Allow" | ||
Resource = "arn:aws:logs:*:*:*" | ||
}, | ||
] | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# | ||
# S3 definitions | ||
# | ||
|
||
variable "s3_folders" { | ||
type = list | ||
description = "S3 folders to create for distribution" | ||
default = ["dist/cochito", "versions/cochito"] | ||
} | ||
|
||
resource "aws_s3_bucket" "distribution" { | ||
bucket = "cochito-${var.account_name}-distribution" | ||
|
||
tags = { | ||
Name = "Distribution bucket" | ||
} | ||
} | ||
|
||
resource "aws_s3_object" "distribution_directory_structure" { | ||
count = "${length(var.s3_folders)}" | ||
|
||
bucket = "${aws_s3_bucket.distribution.id}" | ||
acl = "private" | ||
key = "${var.s3_folders[count.index]}/" | ||
content_type = "application/x-directory" | ||
source = "/dev/null" | ||
} | ||
|
||
# Grant EC2 instances read access to the central S3 distribution | ||
resource "aws_iam_policy" "s3_distribution_bucket_policy" { | ||
name = "cochito-${var.account_name}-s3-distribution-bucket" | ||
|
||
policy = jsonencode({ | ||
Version = "2012-10-17" | ||
Statement = [ | ||
{ | ||
Action = [ | ||
"s3:GetBucketLocation", | ||
"s3:GetBucketVersioning", | ||
"s3:ListBucket" | ||
] | ||
Effect = "Allow" | ||
Resource = "arn:aws:s3:::cochito-${var.account_name}-distribution" | ||
}, | ||
{ | ||
Action = [ | ||
"s3:GetObject", | ||
"s3:GetObjectVersion" | ||
] | ||
Effect = "Allow" | ||
Resource = "arn:aws:s3:::cochito-${var.account_name}-distribution/*" | ||
}, | ||
] | ||
}) | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# ATTENTION: The values are expected to be set manually by the DASHBOARD | ||
# | ||
# If it is not running on development, remove the recovery_window_in_days = 0 | ||
# from the secrets | ||
# | ||
locals { | ||
secret_tag = { | ||
ManagedManually = true | ||
} | ||
} | ||
|
||
resource "aws_secretsmanager_secret" "deployex_secrets" { | ||
name = "deployex-cochito-${var.account_name}-secrets" | ||
description = "All Deployex Secrets" | ||
recovery_window_in_days = 0 | ||
tags = local.secret_tag | ||
} | ||
|
||
resource "aws_secretsmanager_secret" "cochito_otp_tls_ca" { | ||
name = "cochito-${var.account_name}-otp-tls-ca" | ||
description = "TLS ca certificate for OTP distribution" | ||
recovery_window_in_days = 0 | ||
tags = local.secret_tag | ||
} | ||
|
||
resource "aws_secretsmanager_secret" "cochito_otp_tls_key" { | ||
name = "cochito-${var.account_name}-otp-tls-key" | ||
description = "TLS key certificate for OTP distribution" | ||
recovery_window_in_days = 0 | ||
tags = local.secret_tag | ||
} | ||
|
||
resource "aws_secretsmanager_secret" "cochito_otp_tls_crt" { | ||
name = "cochito-${var.account_name}-otp-tls-crt" | ||
description = "TLS key certificate for OTP distribution" | ||
recovery_window_in_days = 0 | ||
tags = local.secret_tag | ||
} | ||
|
||
# Create an IAM policy to grant access to Secrets Manager | ||
resource "aws_iam_policy" "cochito_secrets_manager_policy" { | ||
name = "cochito-${var.account_name}-secrets-manager-access-policy" | ||
description = "Policy for EC2 to access Secrets Manager" | ||
|
||
policy = jsonencode({ | ||
Version = "2012-10-17", | ||
Statement = [ | ||
{ | ||
Action = [ | ||
"secretsmanager:GetSecretValue", | ||
], | ||
Effect = "Allow", | ||
Resource = [ | ||
aws_secretsmanager_secret.cochito_otp_tls_ca.arn, | ||
aws_secretsmanager_secret.cochito_otp_tls_key.arn, | ||
aws_secretsmanager_secret.cochito_otp_tls_crt.arn, | ||
aws_secretsmanager_secret.deployex_secrets.arn, | ||
], | ||
}, | ||
], | ||
}) | ||
} |
40 changes: 40 additions & 0 deletions
40
devops/aws/terraform/modules/standard-account/variables.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
variable "account_name" { | ||
type = string | ||
nullable = false | ||
} | ||
|
||
variable "server_dns" { | ||
type = string | ||
nullable = false | ||
} | ||
|
||
variable "deployex_dns" { | ||
type = string | ||
nullable = false | ||
} | ||
|
||
variable "replicas" { | ||
type = string | ||
nullable = false | ||
} | ||
|
||
# ec2 key pair name | ||
variable "aws_key_name" { | ||
default = "cochito-web-ec2" | ||
} | ||
|
||
variable "aws_region" { | ||
description = "The AWS region to use" | ||
default = "us-east-1" | ||
} | ||
|
||
variable "deployex_version" { | ||
description = "The default deployex version to install" | ||
nullable = false | ||
} | ||
|
||
variable "ec2_instance_type" { | ||
description = "The EC2 instance type" | ||
type = string | ||
nullable = false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# | ||
# Virtual Private Network configuration. | ||
# | ||
# VPC (10.0.0.0/16) | ||
|
||
data "aws_availability_zones" "available" { | ||
state = "available" | ||
} | ||
|
||
resource "aws_vpc" "custom_vpc" { | ||
enable_dns_hostnames = true | ||
enable_dns_support = true | ||
|
||
cidr_block = "10.0.0.0/16" | ||
|
||
tags = { | ||
Name = "cochito-${var.account_name}-vpc" | ||
} | ||
} | ||
|
||
resource "aws_subnet" "public_subnet" { | ||
vpc_id = aws_vpc.custom_vpc.id | ||
cidr_block = "10.0.1.0/24" | ||
availability_zone = data.aws_availability_zones.available.names[0] | ||
|
||
tags = { | ||
Name = "cochito Public Subnet" | ||
} | ||
} | ||
|
||
resource "aws_subnet" "private_subnet" { | ||
vpc_id = aws_vpc.custom_vpc.id | ||
cidr_block = "10.0.2.0/24" | ||
availability_zone = data.aws_availability_zones.available.names[0] | ||
|
||
tags = { | ||
Name = "cochito Private Subnet" | ||
} | ||
} | ||
|
||
resource "aws_internet_gateway" "cochito_gateway" { | ||
vpc_id = aws_vpc.custom_vpc.id | ||
|
||
tags = { | ||
Name = "Some Internet Gateway" | ||
} | ||
} | ||
|
||
resource "aws_route_table" "public_rt" { | ||
vpc_id = aws_vpc.custom_vpc.id | ||
|
||
route { | ||
cidr_block = "0.0.0.0/0" | ||
gateway_id = aws_internet_gateway.cochito_gateway.id | ||
} | ||
|
||
route { | ||
ipv6_cidr_block = "::/0" | ||
gateway_id = aws_internet_gateway.cochito_gateway.id | ||
} | ||
|
||
tags = { | ||
Name = "Public Route Table" | ||
} | ||
} | ||
|
||
resource "aws_route_table_association" "public_1_rt_a" { | ||
subnet_id = aws_subnet.public_subnet.id | ||
route_table_id = aws_route_table.public_rt.id | ||
} |