Redocly Scout
Redocly Scout is a discovery and publishing tool for APIs and documentation. It is designed to be deployed in a customer's infrastructure and to be used with Reunite.
Before you begin
Make sure the following before you begin:
- create or use the existing Redocly organization and portal IDs
- register Scout as a GitHub App to the GitHub organization account
- build the Docker image
Deploy with AWS Console
Create ECR repository
- Open AWS ECR Repositories.
- Click "Create repository".
- Fill "Repository name" field.
- Click "Create repository".
Build docker image and push to ECR repository
- Open created repository.
- Click "View push command".
- Execute provided commands.
NOTE: Skip second step since you already built the Docker image.
Create secrets
Sensitive data such as the GitHub private key, Redocly API key, and GitHub webhook secret should be stored in the AWS secret manager.
- Open AWS Secrets Manager.
- Click "Store a new secret".
- Choose secret type: "Other type of secret" -> "Plaintext" and specify its value and click " Next".
- Fill "Secret name" field and click "Next".
- Click "Store".
Create task execution role
- Open AWS IAM Roles
- Click "Create role"
- Select "Custom trust policy"
- Insert the following configuration in the "Custom trust policy" field.
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
- Click "Next"
- Select
AmazonECSTaskExecutionRolePolicy
permission policy and click "Next" - Fill "Role name" and "Description" and click "Create role"
Assign read secrets permission to the role
- Open created on the previous step role
- Click "Permissions policies" -> "Add permission" -> "Create inline policy"
- Select "Secrets Manager" service -> Access level "Read" -> "GetSecretValue"
- In the "Resources" section specify ARNs of created secrets.
- Click "Next"
- Fill "Policy name" and click "Create policy".
Create task definition
- Open AWS ECS Task definitions.
- Click "Create new task definition".
- Fill "Task definition family" field and container image URI.
- Add container port mappings and environment variables.
The list of ENV variables:
- PORT - the port the application is run on (default
8080
). - MAX_CONCURRENT_JOBS - the number of jobs that can be executed in parallel (default
2
). - AUTO_MERGE - merge PRs when updates are pushed to the main branch. One of [
true
,false
] (defaultfalse
). - API_FOLDER - the path in the repository where Scout looks for API definitions (default
/
). - DATA_FOLDER - the path to the folder where Scout stores temporary data.
- REDOCLY_API_URL - Redocly API base URL.
- REDOCLY_API_KEY - Redocly organization API token.
- REDOCLY_ORG_ID - Redocly organization ID.
- REDOCLY_PROJECT_ID - Redocly project ID.
- PORTAL_APIS_FOLDER - the path where Scout pushes discovered API definitions.
- REDOCLY_APIS - A JSON array of API configurations. Each configuration has the following fields:
name
- API name.url
- API URL.apiKey
- API key.orgId
- Organization ID.projectId
- Project ID.jobContext
- A job execution context.metadataRequired
- If set totrue
, Scout requires metadata in the repository to run.detectChanges
- If set totrue
, Scout detects changes in the API definitions and create a changelog.autoMerge
- If set totrue
, Scout merges PRs when updates are pushed to the main branch.destFolderPath
- The path to the location where Scout pushes discovered API definitions.mountBranchName
- The branch name to mount the API definitions to.NOTE: Extract sensitive data from a secrets manager. The sensitive data can be referred to within the definition of other values:
REDOCLY_APIS='[{ "name": "external", "url": "https://api.redocly.com/api", "apiKey": "${REDOCLY_API_KEY}", "orgId": "org_xxx", "projectId": "prj_xxx", "jobContext": "{metadata.team}", "metadataRequired": true, "detectChanges": true, "autoMerge": true, "destFolderPath": "apis/{metadata.team}/{repoId}/{title}", }]' REDOCLY_API_KEY='sk_xxx'
- LOG_FORMAT - one of [
pretty
,json
] (defaultjson
). - LOG_LEVEL - one of [
trace
,debug
,info
,warn
,error
,fatal
] (defaultinfo
). - GITHUB_PROVIDERS - JSON array of GitHub app configurations. Each configuration has the following fields:
url
- GitHub server url. Omit in case of GitHub cloud.appId
- GitHub application ID.https://{github-server-url}/organizations/{org}/settings/apps
-> Redocly Scout ->App ID
.appUserId
- GitHub application user that leaves Scout-related comments.https://{github-server-url}/users/{app slug name}[bot]
privateKey
- GitHub application private key created during application configuration.webhookSecret
- GitHub webhook secret, created during application configuration.NOTE: Sensitive data should be extracted from secrets manager. It can be referred to within the definition of other values:
GITHUB_PROVIDERS='[{ "appId": "123", "appUserId": "456", "privateKey": "${MY_PRIVATE_KEY}", "webhookSecret": "${MY_WH_SECRET}" }]' MY_PRIVATE_KEY='-----BEGIN RSA PRIVATE KEY----- MIIEp...6G2Hg== -----END RSA PRIVATE KEY-----' MY_WH_SECRET='my-secret'
GITLAB_PROVIDERS
- JSON array of GitLab instance configurations. Each configuration has the following fields:url
- GitLab instance url. Omit if you use GitLab.com (GitLab Cloud).userId
- GitLab user ID; instructions for how to obtain it are available in GitLab section.privateToken
- GitLab private token generated on the user's account.webhookSecret
- GitLab secret used when creating a webhook on GitLab.NOTE: Sensitive data should be stored in a secrets manager and referred to within the definition of other values:
GITLAB_PROVIDERS='[{ "userId": "456", "privateToken": "${MY_PRIVATE_TOKEN}", "webhookSecret": "${MY_WH_SECRET}" }]' MY_PRIVATE_TOKEN='my-private-token' MY_WH_SECRET='my-secret'
- Configure task resources CPU/memory/storage and select task execution role.
NOTE: There is a default
escTaskExecutionRole
role, but you could create a new one - Click "Create".
Create ECS cluster
- Open AWS ECS Clusters.
- Click "Create cluster".
- Fill "Cluster name" field, select VPC and subnets.
- Click "Create".
Create Service
- Open AWS ECS Clusters and select created cluster.
- On the "Services" tab click "Create".
- Fill service name and select the created task family.
- In the networking tab select VPC and its private subnets
NOTE: There are shouldn't be public subnets
- Configure a new security group
- Turn off "Public IP" switch.
- Create a new Application load balancer.
- Configure SSL certificates, target group and its healthcheck.
- Click "Create".
Configure Load Balancer subnets
- Open created service
- Click "View load balancer"
- Click "Actions" -> "Edit subnets"
- In the networking mapping section select public subnets
- Click "Save changes"
Assign domain name
- Copy load balancer domain name. "View load balancer" -> "DNS name".
- Open AWS Route 53.
- Select hosted zone for selected SSL certificate.
- Click "Create record".
- Fill record details.
- Click "Create records".
Deploy with AWS CLI
Create ECR repository
aws ecr create-repository --repository-name redocly-scout
Build docker image and push to ECR repository
docker tag redocly-scout:latest <ECR reposity ARN>:<image version>
docker push <ECR reposity ARN>:<image version>
Create task secrets
aws secretsmanager create-secret --name scout-redocly-api-key --secret-string <Redocly API key>
aws secretsmanager create-secret --name scout-github-private-key --secret-string <GitHub app private key>
aws secretsmanager create-secret --name scout-github-webhook-secret --secret-string <GitHub app webhook secret>
Create task definition
Please follow the official AWS tutorial to create ECS Task
Example of task_definition.json
:
{
"family": "redocly-scout-task",
"containerDefinitions": [
{
"name": "redocly-scout",
"image": "<image ARN>",
"portMappings": [
{
"name": "redocly-scout-8080-tcp",
"containerPort": 8080,
"hostPort": 8080,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [
{
"name": "PORT",
"value": "8080"
},
{
"name": "DATA_FOLDER",
"value": "/tmp/redocly/scout-data/"
},
{
"name": "REDOCLY_API_URL",
"value": "https://<Redocly hostname>/api"
},
{
"name": "MAX_CONCURRENT_JOBS",
"value": "5"
},
{
"name": "PORTAL_APIS_FOLDER",
"value": "/apis"
},
{
"name": "REDOCLY_PROJECT_ID",
"value": "<Redocly project ID>"
},
{
"name": "API_FOLDER",
"value": "/"
},
{
"name": "AUTO_MERGE",
"value": "true"
},
{
"name": "LOG_FORMAT",
"value": "json"
},
{
"name": "REDOCLY_ORG_ID",
"value": "<Redocly organization ID>"
},
{
"name": "LOG_LEVEL",
"value": "debug"
},
{
"name": "GITHUB_PROVIDERS",
"value": "[{\"appId\": \"123\",\"appUserId\": \"456\",\"privateKey\": \"${MY_PRIVATE_KEY}\",\"webhookSecret\": \"${MY_WH_SECRET}\"}]"
}
],
"secrets": [
{
"name": "REDOCLY_API_KEY",
"valueFrom": "<Redocly API key secret ARN>"
},
{
"name": "MY_WH_SECRET",
"valueFrom": "<GitHub app webhook secret ARN>"
},
{
"name": "MY_PRIVATE_KEY",
"valueFrom": "<GitHub app private key secret ARN>"
}
]
}
],
"requiresCompatibilities": ["FARGATE"],
"executionRoleArn": "<Execution role ARN>",
"volumes": [],
"networkMode": "awsvpc",
"cpu": "1024",
"memory": "2048"
}