diff --git a/.github/workflows/ecs-deploy.yml b/.github/workflows/backend-build-deploy.yml similarity index 99% rename from .github/workflows/ecs-deploy.yml rename to .github/workflows/backend-build-deploy.yml index 9d4a462538..00a717b114 100644 --- a/.github/workflows/ecs-deploy.yml +++ b/.github/workflows/backend-build-deploy.yml @@ -1,4 +1,4 @@ -name: Deploy to Amazon ECS +name: Build and Deploy Backend to ECS on: push: diff --git a/.github/workflows/frontend-build-deploy.yml b/.github/workflows/frontend-build-deploy.yml new file mode 100644 index 0000000000..b26a7a24f7 --- /dev/null +++ b/.github/workflows/frontend-build-deploy.yml @@ -0,0 +1,111 @@ +name: Build and Deploy Frontend to Cloudfront + +on: + push: + branches: + - "*" + paths: + - "frontend/**" + workflow_dispatch: + +jobs: + build: + name: Build Static Files + runs-on: ubuntu-latest + + environment: + name: ${{ github.ref_name == 'develop' && 'develop' || github.ref_name == 'staging' && 'staging' || github.ref_name == 'main' && 'main' || 'develop' }} + url: ${{ github.ref_name == 'develop' && 'https://tasks-dev.hotosm.org' || github.ref_name == 'staging' && 'https://tasks-stage.hotosm.org' || github.ref_name == 'main' && 'https://tasks.hotosm.org' || 'https://just.build.test' }} + + steps: + - name: Clone repository + uses: actions/checkout@v4 + + - name: Use Node.js 22.11.0 + uses: actions/setup-node@v4 + with: + node-version: 22.11.0 + + - name: Cache node_modules + uses: actions/cache@v4 + with: + path: frontend/node_modules + key: tm-fe-${{ runner.os }}-build-${{ hashFiles('frontend/package.json') }} + restore-keys: | + tm-fe-${{ runner.os }}-build-${{ hashFiles('frontend/package.json') }} + + - name: Install yarn + run: npm install -g yarn + + - name: Load Environment from GitHub variables & secrets. + uses: hotosm/gh-workflows/.github/actions/vars_n_secret_to_env@env_substitute/1.0.0 + with: + vars_context: ${{ toJson(vars) }} + secrets_context: ${{ toJson(secrets) }} + + - name: Create .env file + uses: hotosm/gh-workflows/.github/actions/env_substitute@env_substitute/1.0.0 + with: + working_directory: ./frontend + template_dotenv: .env.expand + output_file: .env + + - name: Install dependencies + working-directory: ./frontend + run: yarn install + + - name: Generate build + working-directory: ./frontend + run: | + yarn build + + - name: Upload Builds Artifacts + uses: actions/upload-artifact@v4 + with: + name: tm-fe-${{ github.sha }} + path: ./frontend/build + + deploy: + name: Deploy static files + needs: + - build + runs-on: ubuntu-latest + if: ${{ github.ref_name == 'develop' || github.ref_name == 'staging' || github.ref_name == 'main' }} + + environment: + name: ${{ github.ref_name == 'develop' && 'develop' || github.ref_name == 'staging' && 'staging' || github.ref_name == 'main' && 'main' || 'develop' }} + url: ${{ github.ref_name == 'develop' && 'https://tasks-dev.hotosm.org' || github.ref_name == 'staging' && 'https://tasks-stage.hotosm.org' || github.ref_name == 'main' && 'https://tasks.hotosm.org' || 'https://just.build.test' }} + + permissions: + contents: read + id-token: write + + steps: + - name: Clone repository + uses: actions/checkout@v4 + + - name: Download Build Artifacts + uses: actions/download-artifact@v4 + with: + name: tm-fe-${{ github.sha }} + path: ./build + + - name: Setup AWS Credentials + uses: hotosm/gh-workflows/.github/actions/configure_aws_credentials@configure_aws_credentials/1.0.0 + with: + USE_OIDC_FOR_AWS: true + AWS_CONFIG_FILE_PATH: ${{ github.workspace }}/.aws/credentials + AWS_OIDC_ROLE_ARN: ${{ secrets.AWS_OIDC_ROLE_ARN }} + AWS_REGION: ${{ vars.AWS_REGION }} + + - name: Copy static files to S3 + shell: bash + run: | + set -ex + aws s3 cp --recursive ./build s3://${{ vars.FRONTEND_S3_BUCKET }} + + - name: Create cloudfront redistribution + shell: bash + run: | + set -ex + aws cloudfront create-invalidation --distribution-id ${{ vars.FRONTEND_CLOUDFRONT_DISTRIBUTION_ID }} --paths / diff --git a/example.env b/example.env index af785fe5b5..7d27ce2911 100644 --- a/example.env +++ b/example.env @@ -1,7 +1,7 @@ # Tasking Manager configuration file # Copy to `tasking-manager.env` and adjust to make it work! -# +# # The TM_APP_BASE_URL defines the URL of the frontend and is used by the backend # to configure links on emails and some authentication callbacks. @@ -9,75 +9,75 @@ # Note: 127.0.0.1 is a hard requirement for OSM Auth (instead of `localhost`) # On production instances, use the public URL of your frontend # TM_APP_BASE_URL=https://tasks.hotosm.org -TM_APP_BASE_URL=http://127.0.0.1:3000 +TM_APP_BASE_URL=${TM_APP_BASE_URL:-http://127.0.0.1:3000} # The TM_APP_API_URL defines the URL of your backend server. It will be used by # both the backend and by the frontend # On development instances it should be 127.0.0.1:3000 # On production instances, use the public URL of your backend -TM_APP_API_URL=http://127.0.0.1:3000/api +TM_APP_API_URL=${TM_APP_API_URL:-http://127.0.0.1:3000/api} # Defines the version of the API and will be used after /api/ on the url -TM_APP_API_VERSION=v2 +TM_APP_API_VERSION=${TM_APP_API_VERSION:-v2} # Information about the hosting organization -TM_ORG_NAME="Humanitarian OpenStreetMap Team" -TM_ORG_CODE=HOT -TM_ORG_LOGO=https://cdn.img.url/logo.png -TM_ORG_URL=https://example.com -TM_ORG_PRIVACY_POLICY_URL=https://www.hotosm.org/privacy -TM_ORG_TWITTER=http://twitter.com/hotosm -TM_ORG_FB=https://www.facebook.com/hotosm -TM_ORG_INSTAGRAM=https://www.instagram.com/open.mapping.hubs/ -TM_ORG_YOUTUBE=https://www.youtube.com/user/hotosm -TM_ORG_GITHUB=https://github.com/hotosm +TM_ORG_NAME="${TM_ORG_NAME:-"Humanitarian OpenStreetMap Team"}" +TM_ORG_CODE=${TM_ORG_CODE:-HOT} +TM_ORG_LOGO=${TM_ORG_LOGO:-https://cdn.img.url/logo.png} +TM_ORG_URL=${TM_ORG_URL:-https://example.com} +TM_ORG_PRIVACY_POLICY_URL=${TM_ORG_PRIVACY_POLICY_URL:-https://www.hotosm.org/privacy} +TM_ORG_TWITTER=${TM_ORG_TWITTER:-http://twitter.com/hotosm} +TM_ORG_FB=${TM_ORG_FB:-https://www.facebook.com/hotosm} +TM_ORG_INSTAGRAM=${TM_ORG_INSTAGRAM:-https://www.instagram.com/open.mapping.hubs/} +TM_ORG_YOUTUBE=${TM_ORG_YOUTUBE:-https://www.youtube.com/user/hotosm} +TM_ORG_GITHUB=${TM_ORG_GITHUB:-https://github.com/hotosm} # Information about the OSM server - Customize your server here # By default, it's the public OpenStreetMap.org server -OSM_SERVER_URL=https://www.openstreetmap.org -OSM_SERVER_API_URL=https://api.openstreetmap.org -OSM_NOMINATIM_SERVER_URL=https://nominatim.openstreetmap.org -OSM_REGISTER_URL=https://www.openstreetmap.org/user/new +OSM_SERVER_URL=${OSM_SERVER_URL:-https://www.openstreetmap.org} +OSM_SERVER_API_URL=${OSM_SERVER_API_URL:-https://api.openstreetmap.org} +OSM_NOMINATIM_SERVER_URL=${OSM_NOMINATIM_SERVER_URL:-https://nominatim.openstreetmap.org} +OSM_REGISTER_URL=${OSM_REGISTER_URL:-https://www.openstreetmap.org/user/new} # Information about the Editor URLs. Those are the default values on the frontend. # You only need to modify it in case you want to direct users to map on a different OSM instance. -# ID_EDITOR_URL=https://www.openstreetmap.org/edit?editor=id& -# POTLATCH2_EDITOR_URL=https://www.openstreetmap.org/edit?editor=potlatch2 -# RAPID_EDITOR_URL=https://mapwith.ai/rapid +# ID_EDITOR_URL=${ID_EDITOR_URL:-https://www.openstreetmap.org/edit?editor=id&} +# POTLATCH2_EDITOR_URL=${POTLATCH2_EDITOR_URL:-https://www.openstreetmap.org/edit?editor=potlatch2} +# RAPID_EDITOR_URL=${RAPID_EDITOR_URL:-https://mapwith.ai/rapid} # Matomo configuration. Optional, configure it in case you have a Matomo instance. -# TM_MATOMO_ID="site_id" -# TM_MATOMO_ENDPOINT="https://..." +# TM_MATOMO_ID=${TM_MATOMO_ID:-"site_id"} +# TM_MATOMO_ENDPOINT=${TM_MATOMO_ENDPOINT:-"https://..."} # Mapbox access key to display the maps (optional) -# +# # In order to use the default basemap, you’ll need to set a # Mapbox token (https://docs.mapbox.com/help/glossary/access-token) from your Mapbox account. # Costs apply to usage of Mapbox maps above 50,000 map loads per month; if you’d like to ask for # account support to cover those costs, contact Mapbox Community https://mapbox.com/community. -# +# # If you do not set a token, then maps will fallback to using the raster tile based # Humanitarian Layer. -# -# TM_MAPBOX_TOKEN= +# +# TM_MAPBOX_TOKEN=${TM_MAPBOX_TOKEN} # If you want your TM app to work better offline and load faster, you can change # from 0 (unregister) to 1 (register) below. Note this comes with some pitfalls. # Learn more about service workers: https://bit.ly/CRA-PWA # It is more complex to use for TM if your frontend and backend are on same server. -# TM_ENABLE_SERVICEWORKER=0 +# TM_ENABLE_SERVICEWORKER=${TM_ENABLE_SERVICEWORKER:-0} # Define an API URL and KEY of an image upload service. # It will be used to store the Organisation logos and the images uploaded on comments input fields. # HOT uses this service: https://github.com/hotosm/cdn-upload-api/ to setup an image upload API -# TM_IMAGE_UPLOAD_API_URL= -# TM_IMAGE_UPLOAD_API_KEY= +# TM_IMAGE_UPLOAD_API_URL=${TM_IMAGE_UPLOAD_API_URL} +# TM_IMAGE_UPLOAD_API_KEY=${TM_IMAGE_UPLOAD_API_KEY} # Define the image to be used on the homepage main's banner. # If it's not defined, the default images will be used. # The high resolution image should be 2500px width. The low should be 824px. -# TM_HOMEPAGE_IMG_HIGH=https://cdn.img.url/banner-high.png -# TM_HOMEPAGE_IMG_LOW=https://cdn.img.url/banner-low.png +# TM_HOMEPAGE_IMG_HIGH=${TM_HOMEPAGE_IMG_HIGH:-https://cdn.img.url/banner-high.png} +# TM_HOMEPAGE_IMG_LOW=${TM_HOMEPAGE_IMG_LOW:-https://cdn.img.url/banner-low.png} # Define a video to be played on the background of the homepage's main banner. # On HOT instance we use https://cdn.hotosm.org/tasking-manager/mapping.mp4 @@ -86,85 +86,85 @@ OSM_REGISTER_URL=https://www.openstreetmap.org/user/new # TM_HOMEPAGE_VIDEO_URL= # API base URL and token(used to retrieve user stats only) for ohsomeNow Stats -# -OHSOME_STATS_BASE_URL=https://stats.now.ohsome.org -OHSOME_STATS_API_URL=https://stats.now.ohsome.org/api -OHSOME_STATS_TOKEN=testSuperSecretTestToken +# +OHSOME_STATS_BASE_URL=${OHSOME_STATS_BASE_URL:-https://stats.now.ohsome.org} +OHSOME_STATS_API_URL=${OHSOME_STATS_API_URL:-https://stats.now.ohsome.org/api} +OHSOME_STATS_TOKEN=${OHSOME_STATS_TOKEN:-testSuperSecretTestToken} # Secret (required) -# +# # A freely definable secret. Gives authorization to the front- and and back-end # to talk to each other. -# -TM_SECRET=s0m3l0ngr4nd0mstr1ng-b3cr34tiv3 +# +TM_SECRET=${TM_SECRET:-s0m3l0ngr4nd0mstr1ng-b3cr34tiv3} # OpenStreetMap OAuth2 client id and secret (required) -# -TM_CLIENT_ID=foo -TM_CLIENT_SECRET=s0m3l0ngr4nd0mstr1ng-b3cr34tiv3 +# +TM_CLIENT_ID=${TM_CLIENT_ID:-foo} +TM_CLIENT_SECRET=${TM_CLIENT_SECRET:-s0m3l0ngr4nd0mstr1ng-b3cr34tiv3} # Redirect uri registered while creating OAuth2 application (required) -TM_REDIRECT_URI=http://127.0.0.1:3000/authorized +TM_REDIRECT_URI=${TM_REDIRECT_URI:-"http://127.0.0.1:3000/authorized"} # Scope of TM defined while creating OAuth2 application (required) -TM_SCOPE=read_prefs write_api +TM_SCOPE=${TM_SCOPE:-"read_prefs write_api"} # Required by requests_oauthlib to work while making oauth2 requests from http server (required) -# OAUTHLIB_INSECURE_TRANSPORT = 1 +# OAUTHLIB_INSECURE_TRANSPORT=${OAUTHLIB_INSECURE_TRANSPORT:-1} # The default tag used in the OSM changeset comment # IMPORTANT! This must be unique on your instance -# -# TM_DEFAULT_CHANGESET_COMMENT="#{nameofyourorganisation}-project" - -#################################################### -# -# DATABASE CONNECTION PARAMETERS -# -#################################################### +# +# TM_DEFAULT_CHANGESET_COMMENT=${TM_DEFAULT_CHANGESET_COMMENT:-"#{nameofyourorganisation}-project"} + +# ################################################### +# +# DATABASE CONNECTION PARAMETERS +# +# ################################################### # The connection to the postgres database (required) -# +# # The parameter DB_CONNECT_PARAM_JSON needs to be a JSON string readable by # json.loads() with the following keys: "username", "password", "host", "port" # and "dbname" -# +# # If this parameter is set, then individual DB connection parameters are ignored # DB_CONNECT_PARAM_JSON='{ "username": "tm", "password": "myprivatesecret", "host": "tm4-database.example.org", "port": "5432", "dbname": "taskingmanager }' -# +# # NOTE: These are ignored if DB_CONNECT_PARAM_JSON is set -POSTGRES_DB=tasking-manager -POSTGRES_USER=tm -POSTGRES_PASSWORD=tm -POSTGRES_ENDPOINT=tm-db -POSTGRES_PORT=5432 +POSTGRES_DB=${POSTGRES_DB:-tasking-manager} +POSTGRES_USER=${POSTGRES_USER:-tm} +POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-tm} +POSTGRES_ENDPOINT=${POSTGRES_ENDPOINT:-tm-db} +POSTGRES_PORT=${POSTGRES_PORT:-5432} # The postgres database name used for testing (required). # All other configurations except the database name are inherited from the main database defined above. -POSTGRES_TEST_DB=tasking-manager-test +POSTGRES_TEST_DB=${POSTGRES_TEST_DB:-tasking-manager-test} # The address to use as the sender on auto generated emails # (optional, but required to send email) -# -# TM_EMAIL_FROM_ADDRESS=noreply@localhost +# +# TM_EMAIL_FROM_ADDRESS=${TM_EMAIL_FROM_ADDRESS:-noreply@localhost} # The address to use as the receiver in contact form. -# -# TM_EMAIL_CONTACT_ADDRESS=sysadmin@localhost +# +# TM_EMAIL_CONTACT_ADDRESS=${TM_EMAIL_CONTACT_ADDRESS:-sysadmin@localhost} # Email sending server configuration (optional) # This is required in order to send out messages. -# -TM_SMTP_HOST=smtp.gmail.com -TM_SMTP_PORT=587 -TM_SMTP_USER=enter-mail@gmail.com -TM_SMTP_PASSWORD=enter-app-password +# +TM_SMTP_HOST=${TM_SMTP_HOST:-smtp.gmail.com} +TM_SMTP_PORT=${TM_SMTP_PORT:-587} +TM_SMTP_USER=${TM_SMTP_USER:-enter-mail@gmail.com} +TM_SMTP_PASSWORD=${TM_SMTP_PASSWORD:-enter-app-password} # Following two variables can have value of either 0 or 1 -# TM_SMTP_USE_TLS=0 -# TM_SMTP_USE_SSL=1 +# TM_SMTP_USE_TLS=${TM_SMTP_USE_TLS:-0} +# TM_SMTP_USE_SSL=${TM_SMTP_USE_SSL:-1} # If disabled project update emails will not be sent. # Set it disabled in case of testing instances -TM_SEND_PROJECT_EMAIL_UPDATES = 1 +TM_SEND_PROJECT_EMAIL_UPDATES=${TM_SEND_PROJECT_EMAIL_UPDATES:-1} # TM_SERVICE_DESK # If the organisation has a service desk, configures the link @@ -174,44 +174,44 @@ TM_SEND_PROJECT_EMAIL_UPDATES = 1 # Logging settings (optional) # (e.g. ERROR, DEBUG, etc.) # If not specified DEBUG is default. ERROR is a good value for a live site. -# -# TM_LOG_LEVEL=DEBUG -# TM_LOG_DIR=logs +# +# TM_LOG_LEVEL=${TM_LOG_LEVEL:-DEBUG} +# TM_LOG_DIR=${TM_LOG_DIR:-logs} # Languages settings for the Tasking Manager -# -TM_DEFAULT_LOCALE=en +# +TM_DEFAULT_LOCALE=${TM_DEFAULT_LOCALE:-en} # By default all available languages are shown. You can restrict languages by modifying the following two variables. # Please note that there must be exactly the same number of codes as languages. -# -# TM_SUPPORTED_LANGUAGES_CODES="ar, cs, de, el, en, es, fa_IR, fr, he, hu, id, it, ja, ko, mg, ml, nl_NL, pt, pt_BR, ru, sv, sw, tl, tr, uk, zh_TW" -# TM_SUPPORTED_LANGUAGES="عربى, Čeština, Deutsch, Ελληνικά, English, Español, فارسی, Français, עברית, Magyar, Indonesia, Italiano, 日本語, 한국어, Malagasy, Malayalam, Nederlands, Português, Português (Brasil), Русский язык, Svenska, Kiswahili, Filipino (Tagalog), Türkçe, Українська, 繁體中文" +# +# TM_SUPPORTED_LANGUAGES_CODES=${TM_SUPPORTED_LANGUAGES_CODES:-"ar, cs, de, el, en, es, fa_IR, fr, he, hu, id, it, ja, ko, mg, ml, nl_NL, pt, pt_BR, ru, sv, sw, tl, tr, uk, zh_TW"} +# TM_SUPPORTED_LANGUAGES=${TM_SUPPORTED_LANGUAGES:-"عربى, Čeština, Deutsch, Ελληνικά, English, Español, فارسی, Français, עברית, Magyar, Indonesia, Italiano, 日本語, 한국어, Malagasy, Malayalam, Nederlands, Português, Português (Brasil), Русский язык, Svenska, Kiswahili, Filipino (Tagalog), Türkçe, Українська, 繁體中文"} # Time to wait until task auto-unlock (optional) # (e.g. '2h' or '7d' or '30m' or '1h30m') -# -# TM_TASK_AUTOUNLOCK_AFTER=2h +# +# TM_TASK_AUTOUNLOCK_AFTER=${TM_TASK_AUTOUNLOCK_AFTER:-2h} # Mapper Level values represent number of OSM changesets (optional) -# -# TM_MAPPER_LEVEL_INTERMEDIATE=250 -# TM_MAPPER_LEVEL_ADVANCED=500 +# +# TM_MAPPER_LEVEL_INTERMEDIATE=${TM_MAPPER_LEVEL_INTERMEDIATE:-250} +# TM_MAPPER_LEVEL_ADVANCED=${TM_MAPPER_LEVEL_ADVANCED:-500} # This sets a file size limit to allow when importing a project geometry from a file. Define it in bytes. -# TM_IMPORT_MAX_FILESIZE=1000000 +# TM_IMPORT_MAX_FILESIZE=${TM_IMPORT_MAX_FILESIZE:-1000000} # Defines the maximum area allowed to the Projects' AoI. Default is 5000. The unit is square kilometers. -# TM_MAX_AOI_AREA=5000 +# TM_MAX_AOI_AREA=${TM_MAX_AOI_AREA:-5000} # Sentry.io DSN Config (optional) -# TM_SENTRY_BACKEND_DSN=https://foo.ingest.sentry.io/1234567 -# TM_SENTRY_FRONTEND_DSN=https://bar.ingest.sentry.io/8901234 +# TM_SENTRY_BACKEND_DSN=${TM_SENTRY_BACKEND_DSN:-https://foo.ingest.sentry.io/1234567} +# TM_SENTRY_FRONTEND_DSN=${TM_SENTRY_FRONTEND_DSN:-https://bar.ingest.sentry.io/8901234} # Underpass API URL (for project live monitoring feature) -UNDERPASS_URL=https://underpass.hotosm.org +UNDERPASS_URL=${UNDERPASS_URL:-https://underpass.hotosm.org} -#EXPORT TOOL Integration with 0(Disable) and 1(Enable) and S3 URL for Export Tool -#EXPORT_TOOL_S3_URL=https://foorawdataapi.s3.amazonaws.com -#ENABLE_EXPORT_TOOL=0 -PROFILING=False -USE_SENTRY=false +# EXPORT TOOL Integration with 0(Disable) and 1(Enable) and S3 URL for Export Tool +# EXPORT_TOOL_S3_URL=${EXPORT_TOOL_S3_URL:-https://foorawdataapi.s3.amazonaws.com} +# ENABLE_EXPORT_TOOL=${ENABLE_EXPORT_TOOL:-0} +PROFILING=${PROFILING:-False} +USE_SENTRY=${USE_SENTRY:-false} diff --git a/scripts/aws/infra/_envcommon/cloudfront.hcl b/scripts/aws/infra/_envcommon/cloudfront.hcl new file mode 100644 index 0000000000..1d4a3daa17 --- /dev/null +++ b/scripts/aws/infra/_envcommon/cloudfront.hcl @@ -0,0 +1,44 @@ +# --------------------------------------------------------------------------------------------------------------------- +# COMMON TERRAGRUNT CONFIGURATION +# This is the common component configuration for mysql. The common variables for each environment to +# deploy mysql are defined here. This configuration will be merged into the environment configuration +# via an include block. +# --------------------------------------------------------------------------------------------------------------------- + +# Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the +# working directory, into a temporary folder, and execute your Terraform commands in that folder. If any environment +# needs to deploy a different module version, it should redefine this block with a different ref to override the +# deployed version. +terraform { + source = "${local.base_source_url}?ref=master" +} + +# --------------------------------------------------------------------------------------------------------------------- +# Locals are named constants that are reusable within the configuration. +# --------------------------------------------------------------------------------------------------------------------- +locals { + # Automatically load environment-level variables + environment_vars = read_terragrunt_config(find_in_parent_folders("deployment_env.hcl")) + + # Extract out common variables for reuse + environment = local.environment_vars.locals.environment + application = local.environment_vars.locals.application + team = local.environment_vars.locals.team + + distribution_name = format("%s-%s-%s-%s", local.application, local.team, local.environment, "cloudfront") + + + # Expose the base source URL so different versions of the module can be deployed in different environments. This will + # be used to construct the terraform block in the child terragrunt configurations. + base_source_url = "git::https://github.com/hotosm/terraform-aws-cloudfront/" +} + +# --------------------------------------------------------------------------------------------------------------------- +# MODULE PARAMETERS +# These are the variables we have to pass in to use the module. This defines the parameters that are common across all +# environments. +# --------------------------------------------------------------------------------------------------------------------- +# Defaults, overridden by env.hcl + +inputs = { +} diff --git a/scripts/aws/infra/_envcommon/s3.hcl b/scripts/aws/infra/_envcommon/s3.hcl new file mode 100644 index 0000000000..6ac4ebe556 --- /dev/null +++ b/scripts/aws/infra/_envcommon/s3.hcl @@ -0,0 +1,45 @@ +# --------------------------------------------------------------------------------------------------------------------- +# COMMON TERRAGRUNT CONFIGURATION +# This is the common component configuration for mysql. The common variables for each environment to +# deploy mysql are defined here. This configuration will be merged into the environment configuration +# via an include block. +# --------------------------------------------------------------------------------------------------------------------- + +# Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the +# working directory, into a temporary folder, and execute your Terraform commands in that folder. If any environment +# needs to deploy a different module version, it should redefine this block with a different ref to override the +# deployed version. +terraform { + source = "${local.base_source_url}?ref=main" +} + +# --------------------------------------------------------------------------------------------------------------------- +# Locals are named constants that are reusable within the configuration. +# --------------------------------------------------------------------------------------------------------------------- +locals { + # Automatically load environment-level variables + environment_vars = read_terragrunt_config(find_in_parent_folders("deployment_env.hcl")) + + # Extract out common variables for reuse + environment = local.environment_vars.locals.environment + application = local.environment_vars.locals.application + team = local.environment_vars.locals.team + + bucket_name = format("%s-%s-%s-%s", local.application, local.team, local.environment, "frontend-static") + + + # Expose the base source URL so different versions of the module can be deployed in different environments. This will + # be used to construct the terraform block in the child terragrunt configurations. + base_source_url = "git::https://github.com/hotosm/terraform-aws-s3/" +} + +# --------------------------------------------------------------------------------------------------------------------- +# MODULE PARAMETERS +# These are the variables we have to pass in to use the module. This defines the parameters that are common across all +# environments. +# --------------------------------------------------------------------------------------------------------------------- +# Defaults, overridden by env.hcl + +inputs = { + bucket = local.bucket_name +} diff --git a/scripts/aws/infra/develop/non-purgeable/cloudfront/terragrunt.hcl b/scripts/aws/infra/develop/non-purgeable/cloudfront/terragrunt.hcl new file mode 100644 index 0000000000..21e2892464 --- /dev/null +++ b/scripts/aws/infra/develop/non-purgeable/cloudfront/terragrunt.hcl @@ -0,0 +1,72 @@ +include "root" { + path = find_in_parent_folders("root.hcl") +} + +include "envcommon" { + path = "${dirname(find_in_parent_folders("root.hcl"))}/_envcommon/cloudfront.hcl" + # We want to reference the variables from the included config in this configuration, so we expose it. + expose = true +} + +terraform { + source = "${include.envcommon.locals.base_source_url}?ref=v1.0.0" +} + +dependency "s3" { + config_path = "../s3" +} + +inputs = { + # S3 bucket configuration - only need to provide the bucket name + s3_bucket_name = dependency.s3.outputs.bucket_name + create_s3_bucket_policy = true + + aliases = split(" ", get_env("CLOUDFRONT_DIST_ALIASES", "tasks-dev.hotosm.org")) + + # CloudFront configuration + enabled = true + is_ipv6_enabled = true + comment = "Frontend Static distribution for ${include.envcommon.locals.distribution_name}" + default_root_object = "index.html" + + # Price class - choose one of: [ + # - PriceClass_100 (US, Canada, Europe) + # - PriceClass_200 (PriceClass_100 + South America, Australia, New Zealand, and parts of Asia) + # - PriceClass_All (All regions) + # ] + + # Cache behavior + allowed_methods = ["GET", "HEAD", "OPTIONS"] + cached_methods = ["GET", "HEAD"] + forward_query_string = false + forward_cookies = "none" + viewer_protocol_policy = "redirect-to-https" + min_ttl = 0 + default_ttl = 3600 + max_ttl = 86400 + compress = true + + # Geo restrictions + geo_restriction_type = "none" + geo_restriction_locations = [] + + custom_error_response_pages = [ + { + error_code = 404 + response_page_path = "/index.html" + response_code = 404 + error_caching_min_ttl = 60 + }, + { + error_code = 403 + response_page_path = "/index.html" + response_code = 403 + error_caching_min_ttl = 60 + } + ] + + # SSL/TLS configuration + use_default_certificate = false + # If use_default_certificate is false, provide these: + acm_certificate_arn = get_env("ACM_TLS_CERT_FRONTEND_ARN", "arn:aws:acm:us-east-1:670261699094:certificate/1d74321b-1e5b-4e31-b97a-580deb39c539") +} diff --git a/scripts/aws/infra/develop/non-purgeable/s3/terragrunt.hcl b/scripts/aws/infra/develop/non-purgeable/s3/terragrunt.hcl new file mode 100644 index 0000000000..a855816945 --- /dev/null +++ b/scripts/aws/infra/develop/non-purgeable/s3/terragrunt.hcl @@ -0,0 +1,18 @@ +include "root" { + path = find_in_parent_folders("root.hcl") +} + +include "envcommon" { + path = "${dirname(find_in_parent_folders("root.hcl"))}/_envcommon/s3.hcl" + # We want to reference the variables from the included config in this configuration, so we expose it. + expose = true +} + +terraform { + source = "${include.envcommon.locals.base_source_url}?ref=v1.0.0" +} + +inputs = { + attach_public_policy = false + attach_policy = false +} diff --git a/scripts/aws/infra/infra.env.example b/scripts/aws/infra/infra.env.example index 4271dba5f5..09083ec162 100644 --- a/scripts/aws/infra/infra.env.example +++ b/scripts/aws/infra/infra.env.example @@ -1,17 +1,12 @@ +# ================ GHActions-START ================ # Environment required for CICD pipeline. Env here is not used for app but rather Infra deployment via CI or manual run. -# Terragrunt Infra -# assuming we have certificate already and manage certificate manually rather than from infra -ACM_TLS_CERT_BACKEND_ARN=arn:aws:acm:EU-east-66:123456789:certificate/ARN_EXAMPLE -TM_FRONTEND_ORIGIN=tasks.example.com - -# GHActions - -# ==== VARIABLES ==== -IMAGE_NAME=hotosm/tasking-manager-backend -AWS_REGION=us-east-1 - -# INFRA_TEAM=hotosm # optional if you want to override the team name +# ==== VARIABLES-START ==== +# Env-Variables (Redundant per environment) START +IMAGE_NAME=hotosm/tasking-manager-backend # [optional] image name for CI +FE_S3_BUCKET="your-s3-bucket-name" # mandatory frontend bucket name for CI +FE_CLOUDFRONT_DISTRIBUTION_ID = 'EXxxxxxxxxx' # your cloudfront distribution id for CI +# Env-Variables (Redundant per environment) END # ==== VARIABLES-END ==== @@ -21,4 +16,12 @@ AWS_OIDC_ROLE_ARN=arn:aws:iam::123456789012:role/YOUR_ROLE_NAME PLAN_FILE_ENCRYPTION_SECRET=UNSAFESTRINGUSEDUSECUSTOMSECRETKEY # ==== SECRETS-END ==== -# GHActions-END +# ================ GHActions-END ================ + +# ================ INFRA-START ================ +# Environment here are for infra application via CI +INFRA_TEAM=hotosm # [optional] if you want to override the team name +ACM_TLS_CERT_FRONTEND_ARN=arn:aws:acm:EU-east-66:123456789:certificate/ARN_EXAMPLE # [optional] ACM certificate for FRONTEND +ACM_TLS_CERT_BACKEND_ARN=arn:aws:acm:EU-east-66:123456789:certificate/ARN_EXAMPLE # [optional] ACM certificate for BACKEND +CLOUDFRONT_DIST_ALIASES="tasks.example.com more.example.com more2.example.com" # [optional] hostname for cloudfront. Your ACM should support it else fails. +# ================ INFRA-END ================ diff --git a/scripts/aws/infra/staging/non-purgeable/cloudfront/terragrunt.hcl b/scripts/aws/infra/staging/non-purgeable/cloudfront/terragrunt.hcl new file mode 100644 index 0000000000..5d9ff4a5b1 --- /dev/null +++ b/scripts/aws/infra/staging/non-purgeable/cloudfront/terragrunt.hcl @@ -0,0 +1,72 @@ +include "root" { + path = find_in_parent_folders("root.hcl") +} + +include "envcommon" { + path = "${dirname(find_in_parent_folders("root.hcl"))}/_envcommon/cloudfront.hcl" + # We want to reference the variables from the included config in this configuration, so we expose it. + expose = true +} + +terraform { + source = "${include.envcommon.locals.base_source_url}?ref=v1.0.0" +} + +dependency "s3" { + config_path = "../s3" +} + +inputs = { + # S3 bucket configuration - only need to provide the bucket name + s3_bucket_name = dependency.s3.outputs.bucket_name + create_s3_bucket_policy = true + + aliases = split(" ", get_env("CLOUDFRONT_DIST_ALIASES", "tasks-stage.hotosm.org")) + + # CloudFront configuration + enabled = true + is_ipv6_enabled = true + comment = "Frontend Static distribution for ${include.envcommon.locals.distribution_name}" + default_root_object = "index.html" + + # Price class - choose one of: [ + # - PriceClass_100 (US, Canada, Europe) + # - PriceClass_200 (PriceClass_100 + South America, Australia, New Zealand, and parts of Asia) + # - PriceClass_All (All regions) + # ] + + # Cache behavior + allowed_methods = ["GET", "HEAD", "OPTIONS"] + cached_methods = ["GET", "HEAD"] + forward_query_string = false + forward_cookies = "none" + viewer_protocol_policy = "redirect-to-https" + min_ttl = 0 + default_ttl = 3600 + max_ttl = 86400 + compress = true + + # Geo restrictions + geo_restriction_type = "none" + geo_restriction_locations = [] + + custom_error_response_pages = [ + { + error_code = 404 + response_page_path = "/index.html" + response_code = 404 + error_caching_min_ttl = 60 + }, + { + error_code = 403 + response_page_path = "/index.html" + response_code = 403 + error_caching_min_ttl = 60 + } + ] + + # SSL/TLS configuration + use_default_certificate = false + # If use_default_certificate is false, provide these: + acm_certificate_arn = get_env("ACM_TLS_CERT_FRONTEND_ARN", "arn:aws:acm:us-east-1:670261699094:certificate/1d74321b-1e5b-4e31-b97a-580deb39c539") +} diff --git a/scripts/aws/infra/staging/non-purgeable/s3/terragrunt.hcl b/scripts/aws/infra/staging/non-purgeable/s3/terragrunt.hcl new file mode 100644 index 0000000000..a855816945 --- /dev/null +++ b/scripts/aws/infra/staging/non-purgeable/s3/terragrunt.hcl @@ -0,0 +1,18 @@ +include "root" { + path = find_in_parent_folders("root.hcl") +} + +include "envcommon" { + path = "${dirname(find_in_parent_folders("root.hcl"))}/_envcommon/s3.hcl" + # We want to reference the variables from the included config in this configuration, so we expose it. + expose = true +} + +terraform { + source = "${include.envcommon.locals.base_source_url}?ref=v1.0.0" +} + +inputs = { + attach_public_policy = false + attach_policy = false +}