{"id":17647964,"url":"https://github.com/kaklakariada/aws-ec2-controller","last_synced_at":"2025-05-07T06:02:50.044Z","repository":{"id":38851010,"uuid":"240875790","full_name":"kaklakariada/aws-ec2-controller","owner":"kaklakariada","description":"An AWS serverless web app for starting/stopping EC2 instances.","archived":false,"fork":false,"pushed_at":"2024-09-02T08:34:13.000Z","size":7564,"stargazers_count":5,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-31T07:02:32.654Z","etag":null,"topics":["amazon-web-services","aws","ec2","serverless","webapp"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kaklakariada.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-16T10:59:29.000Z","updated_at":"2024-09-16T09:31:55.000Z","dependencies_parsed_at":"2024-05-02T07:50:52.450Z","dependency_job_id":"e8d681ec-3fdd-4ee3-bf35-2c2b248d7ff1","html_url":"https://github.com/kaklakariada/aws-ec2-controller","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaklakariada%2Faws-ec2-controller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaklakariada%2Faws-ec2-controller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaklakariada%2Faws-ec2-controller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaklakariada%2Faws-ec2-controller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kaklakariada","download_url":"https://codeload.github.com/kaklakariada/aws-ec2-controller/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252823910,"owners_count":21809711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amazon-web-services","aws","ec2","serverless","webapp"],"created_at":"2024-10-23T11:15:16.815Z","updated_at":"2025-05-07T06:02:49.997Z","avatar_url":"https://github.com/kaklakariada.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EC2 Controller\n\nAn AWS serverless web app for starting/stopping EC2 instances.\n\n[![Build](https://github.com/kaklakariada/aws-ec2-controller/actions/workflows/build.yml/badge.svg)](https://github.com/kaklakariada/aws-ec2-controller/actions/workflows/build.yml)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=aws-ec2-controller-backend\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=aws-ec2-controller-backend)\n\n## Architecture\n\nEC2 controller uses the following technologies:\n\n* Authentication and Authorization: Cognito\n* Static web content: Cloudfront and S3\n* Frontend: React and AWS Amplify\n* Backend: API-Gateway (REST API) and Lambda\n* Storage: DynamoDb\n* Deployment: CloudFormation / CDK\n* Backend framework: Java 21 and Micronaut with SnapStart\n\n![Architecture](arch/architecture.png \"Architecture\")\n\n## Deployment to AWS\n\n### Preconitions\n\nTo deploy this in your AWS account you will need the following:\n\n* A region where you want to deploy, e.g. `eu-west-1`\n* A Route53 hosted zone, e.g. `example.com.` and its ID `XXXXXXXXXXXXXX`\n* A subdomain of `example.com` you want to use for the web app, e.g. `ec2-controller.example.com`\n* An ACM certificate for `ec2-controller.example.com` or `*.example.com` in `us-east-1` and its ARN `arn:aws:acm:us-east-1:000000000000:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`\n\nOn your local machine you will need the following:\n\n* [Node.js](https://nodejs.org/en/) 22\n* Java Development Kit (JDK) 21 (e.g. from [Adoptium](https://adoptium.net/?variant=openjdk21\u0026jvmVariant=hotspot))\n* [AWS Command line interface](https://aws.amazon.com/cli/)\n  * Configure AWS credentials for the AWS CLI by calling `aws configure`\n\n### Build backend\n\n```sh\ncd backend\n./gradlew clean build\n```\n\nThe backend will be deployed later when we deploy the infrastructure.\n\nTo update the backend after making changes, first build it `./gradlew build`, then deploy the infrastructure with `npm run cdk deploy`.\n\n### Configure infrastructure\n\nCreate file `infrastructure/infrastructure-config.ts` based on the following template and fill in your configuration:\n\n```typescript\nimport { InfrastructureConfig } from \"./lib/infrastructure-config-interface\";\n\nexport const CONFIG: InfrastructureConfig = {\n    region: \"eu-west-1\",\n    domain: \"ec2-controller.example.com\",\n    hostedZoneName: \"example.com.\",\n    hostedZoneId: \"XXXXXXXXXXXXXX\",\n    sslCertificateArn: \"arn:aws:acm:us-east-1:000000000000:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n    stackName: \"ec2-controller\",\n    contactEmailAddress: \"admin@example.com\"\n};\n```\n\n### Deploy infrastructure and backend\n\n```sh\ncd infrastructure\nnpm run cdk deploy\n```\n\nThis command will take up to 30 minutes. At the end it will output information you need for configuring the frontend in the next step.\n\n### Configure frontend\n\nCreate file `frontend/src/frontend-config.ts` based on the following template and fill in the values for your deployed stack:\n\n```typescript\nimport { FrontendConfig } from \"./environment\";\n\nexport const CONFIG: FrontendConfig = {\n    region: \"eu-west-1\",\n    apiGatewayEndpointUrl: \"https://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/prod\",\n    cognitoIdentityPoolId: \"eu-west-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n    cognitoUserPoolId: \"eu-west-1_xxxxxxxxx\",\n    cognitoUserPoolWebClientId: \"xxxxxxxxxxxxxxxxxxxxxxxxxx\"\n};\n```\n\nCreate file `frontend/deploy/deploy-config.js` based on the following template and fill in the values for your deployed stack:\n\n```javascript\nexports.CONFIG = {\n    staticWebsiteBucket: 'ec2-controller-staticcontentbucketxxxxxxxxxxxxxxxxxxxxxx',\n    cloudfrontDistributionId: 'XXXXXXXXXXXXXX'\n}\n```\n\n### Deploy frontend\n\n```sh\ncd frontend\nnpm run deploy\n```\n\n### Configure backend\n\n#### Add EC2 instances to whitelist\n\nAdd entries to the DynamoDB table for instances that you want to control:\n\n```json\n{\n    \"id\": \"i-xxxxxxxxxxxxxxxxx\",\n    \"controlAllowed\": true,\n    \"domain\": \"instance.example.com\",\n    \"sortOrder\": 1\n}\n```\n\n* `id`: AWS EC2 instance ID.\n* `controlAllowed`: Allow starting/stopping this instance.\n* `domain`: Domain name for this instance. Used to check if DNS entry is in sync.\n* `sortOrder`: Specify order in which to display entries in the web app.\n\n#### Create Cognito users\n\nGo to the AWS Cognito console and create users for your new web app. Don't forget to add them to group `Users`.\n\n## Development\n\n### Backend\n\n#### Run local backend server\n\nConfigure environment variables for local server: create file `backend/local-server-env.properties` based on the following template and fill in the values for your deployed stack:\n\n```properties\nTABLENAME_DYNAMODBINSTANCE = ec2-controller-instances-Backend\nHOSTED_ZONE_ID = XXXXXXXXXXXXXX\n```\n\nThen start the local server:\n\n```sh\ncd backend\n./gradlew runServer\n```\n\n#### Check for dependency updates\n\n```sh\n./gradlew dependencyUpdates\n```\n\n#### Configure eclipse project\n\n```sh\ncd backend\n./gradlew eclipse\n```\n\n### Frontend\n\nRun local frontend during development:\n\n```sh\ncd frontend\nnpm start\n```\n\n### Upgrade dependencies in `package.json`\n\n```sh\nnpx npm-check-updates -u \u0026\u0026 npm install\n```\n\n### Managing configuration in a private branch\n\nThis project requires some configuration files with deployment specific information, e.g. domain names that should not be stored in a public git repository. That's why these files are added to `.gitignore`. If you want to still keep your configuration under version control you can do so in a private branch (e.g. `private-main`) that you could push to a private repository only.\n\nWhen switching from `private-main` to the public `main` branch, git will delete the configuration files. To restore them you can use the following command:\n\n```sh\ngit show private-main:frontend/deploy/deploy-config.js \u003e frontend/deploy/deploy-config.js \\\n  \u0026\u0026 git show private-main:frontend/src/frontend-config.ts \u003e frontend/src/frontend-config.ts \\\n  \u0026\u0026 git show private-main:backend/local-server-env.properties \u003e backend/local-server-env.properties \\\n  \u0026\u0026 git show private-main:infrastructure/infrastructure-config.ts \u003e infrastructure/infrastructure-config.ts\n```\n\n### Troubleshooting\n\n#### Building frontend fails because `./frontend-config` is not found\n\n```.\\src\\environment.ts\nCannot find file './frontend-config' in '.\\src'.\n```\n\nCreate `frontend/src/frontend-config.ts` as described above.\n\n#### There is no \"Run\" button for my EC2 instance in the web app\n\nAdd an entry for your instance to the DynamoDB table and set `controlAllowed` to `true`.\n\n#### Local server returns `404` when running in Eclipse\n\nConfigure project using gradle and refresh project in Eclipse:\n\n```sh\ncd backend \u0026\u0026 ./gradlew eclipse\n```\n\n#### Unit test fail with a `NullPointerException` when running in Eclipse\n\nConfigure project using gradle and refresh project in Eclipse:\n\n```sh\ncd backend \u0026\u0026 ./gradlew eclipse\n```\n\n#### `GET /instances` returns error 403 Forbidden\n\nMake sure your Cognito user has role `Users`.\n\n#### Creating a new account does not work.\n\nCreating an account on the login page fails with message `SignUp is not permitted for this user pool`.\n\nRegistering of new users is deactivated for the Cognito user pool. You can change this by setting `allowAdminCreateUserOnly` to `false` in `cognito.ts`.\n\n#### Loading instances sometimes takes up to 10s\n\nThe backend uses Java Lambdas which need some time for initialization when inactive for araound 15 minutes (cold start).\n\nSolution: rewrite Lambda code e.g. in TypeScript.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkaklakariada%2Faws-ec2-controller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkaklakariada%2Faws-ec2-controller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkaklakariada%2Faws-ec2-controller/lists"}