{"id":16594252,"url":"https://github.com/thomasmost/darkbridge","last_synced_at":"2026-04-08T20:46:53.739Z","repository":{"id":105260567,"uuid":"308446931","full_name":"thomasmost/darkbridge","owner":"thomasmost","description":"An opinionated infrastructure-forward modern web template built for continuous integration and delivery on GitHub Actions; using Docker, AWS Fargate, and NodeJS","archived":false,"fork":false,"pushed_at":"2022-03-06T22:13:50.000Z","size":17082,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-28T23:43:58.827Z","etag":null,"topics":["continuous-delivery","continuous-integration","docker","emotion","fargate","github-actions","koa","nodejs","react","ssr"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thomasmost.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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-10-29T20:51:51.000Z","updated_at":"2021-06-16T16:02:34.000Z","dependencies_parsed_at":"2023-05-22T02:15:16.128Z","dependency_job_id":null,"html_url":"https://github.com/thomasmost/darkbridge","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"purl":"pkg:github/thomasmost/darkbridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasmost%2Fdarkbridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasmost%2Fdarkbridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasmost%2Fdarkbridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasmost%2Fdarkbridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thomasmost","download_url":"https://codeload.github.com/thomasmost/darkbridge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasmost%2Fdarkbridge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31573788,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"ssl_error","status_checked_at":"2026-04-08T14:31:17.202Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["continuous-delivery","continuous-integration","docker","emotion","fargate","github-actions","koa","nodejs","react","ssr"],"created_at":"2024-10-11T23:45:41.468Z","updated_at":"2026-04-08T20:46:53.717Z","avatar_url":"https://github.com/thomasmost.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg width=\"200\" height=\"100\" src=\"/darkbridge.png\"\u003e\n\u003c/p\u003e\n\u003ch1 align=\"center\"\u003eDarkbridge\u003c/h1\u003e\n\nAn opinionated infrastructure-forward modern web template built for continuous integration and delivery; using Docker, AWS Fargate, and NodeJS\n\n![Code Quality](https://github.com/thomasmost/darkbridge/workflows/Code%20Quality/badge.svg)\n![Deploy to Staging](https://github.com/thomasmost/darkbridge/workflows/Deploy%20to%20Staging/badge.svg)\n![Deploy to Production](https://github.com/thomasmost/darkbridge/workflows/Deploy%20to%20Production/badge.svg)\n\n# Resources\n\nCreated in part with reference to the following guides:\n\n- https://aws.amazon.com/blogs/opensource/github-actions-aws-fargate/\n- https://itnext.io/run-your-containers-on-aws-fargate-c2d4f6a47fda\n- https://medium.com/@ariklevliber/aws-fargate-from-start-to-finish-for-a-nodejs-app-9a0e5fbf6361\n- https://docs.aws.amazon.com/AmazonECS/latest/userguide/create-application-load-balancer.html\n\n# Why\n\nThis is kind of a big question. Fundamentally, though, I think that 90% of tutorials, templates, and 'get started' guides only ever take you about half the way there (if that!) and as a relative newcomer to scalable, production-quality infrastructure, I could have really benefited from a guide like this one.\n\nFor a more detailed breakdown, see this [piece-by-piece rationale](/docs/Why.md).\n\n# Development\n\nHere's what to expect.\n\n## Tech Stack\n\n- Served by NodeJS using the Koa framework\n- Rendered by React\n- Styled with Emotion\n- Tested with Jest\n- Linted, prettified, and written in highly safe and readable TypeScript\n- Packaged into a Docker image on deploy\n\n**Note that you do not need Docker installed to run the application in development,** but you will likely want to have it eventually to customize your containers.\n\n## Getting Started in Development\n\n1. Clone the repository\n2. Run `npm install`\n3. Make a copy of the `template.env` file provided and rename it as your local `.env` file (this lets you connect to your local MySQL server)\n4. Create a `demodb` schema and run the `demodb.sql` file against your local MySQL server\n5. Run `npm run dev` to start the development servers and begin hacking\n\n## Debugging\n\nOne of the most critical pieces of development is easily being able to step through code. There are two ways to step through the server code:\n\n1. Attach to the currently running process, by running the `Attach to Server` configuration from VS Code's debug menu.\n2. Stop the server (`pm2 stop server`) and then run the `Launch Debug Server` configuration from VS Code's debug menu (configured in the [launch.json](/.vscode/launch.json) file) in order to step through the server code.\n\n## Next Steps\n\nWhen you're ready to deploy your application to a 'production-like' staging environment, follow the steps below ([Infrastructure](#Infrastructure)) to set up AWS resources for that environment (you will need to repeat these steps for your production environment). Once the resources are available, configure the necessary environment variables as secrets in the AWS Secrets Manager and replace the `[[arn]]` fields in your `task-def-staging.json` file.\n\nTest the deploy by going to your GitHub repository and navigating to **Actions** \u003e **Deploy to Staging** \u003e **Run workflow** and hitting the green button to run the workflow.\n\nOnce you've verified that your manual deploys are working, I'd recommend changing the run condition in `.github/workflow/deploy_staging.yml` to run the staging deploy on every push to the `main` branch. **The production deploy trigger should always be manual.**\n\n# Infrastructure\n\nYou will need the aws command line tool installed to execute these steps.\n\n## GitHub Actions Setup\n\n1. Create a new IAM Group \"DeployGroup\" with the following policies:\n\n- AmazonEC2ContainerRegistryFullAccess\n- AmazonECS_FullAccess\n\n2. Add a new IAM User \"GitHub\" to the DeployGroup\n\n## (FOR PROD) Create a VPC and Security Group\n\nSee [Tutorial: Creating a VPC with Public and Private Subnets for Your Clusters.](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-public-private-vpc.html)\n\n## Create Application Load Balancer\n\n1. Create a new security group for your fargate cluster (e.g. darkbridge-fargate-staging-sg)\n2. Ensure the security group is the same as Fargate's\n3. Create a new Application Load Balancer\n4. Set the target type to IP\n\n## Create a Container Registry\n\n```bash\naws ecr create-repository --repository-name darkbridge_registry --region us-east-1\n```\n\n## Set up a Fargate service\n\nThese first three steps are necessary for the GitHub Actions workflow to succeed.\n\nEnsure that the `ecsTaskExecutionRole` role is available and can be assumed by the GitHub workflow as [described here](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html).\n\n1. Create a role (if it does not already exist) called `ecsTaskExecutionRole` with the `AmazonECSTaskExecutionRolePolicy` policy\n2. Also add the `SecretsManagerReadWrite` policy\n3. Replace the trust relationship with the following:\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Principal\": {\n        \"Service\": \"ecs-tasks.amazonaws.com\"\n      },\n      \"Action\": \"sts:AssumeRole\"\n    }\n  ]\n}\n```\n\nNow register the task definition:\n\n```bash\naws ecs register-task-definition --region us-east-1 --cli-input-json file://$HOME/darkbridge/task-def-staging.json\n```\n\n## Create an ECS cluster\n\n```bash\naws ecs create-cluster --region us-east-1 --cluster-name darkbridge-cluster-staging\n```\n\n## Create a Fargate service\n\nMake sure to specify the cluster for your service\n\n**Also note that you have to associate the load balancer with the service at the time of the service creation**\n\nE.g.\n\n```bash\naws ecs create-service --region us-east-1 --service-name darkbridge-service-staging --task-definition darkbridge-task-staging:1 --desired-count 2 --launch-type \"FARGATE\" --network-configuration \"awsvpcConfiguration={subnets=[ [[private-subnet1]],[[public-subnet1]],[[private-subnet2]],[[public-subnet2]] ],securityGroups=[ [[security-group]] ]}\" --load-balancers \"targetGroupArn=[[arn]], containerName=darkbridge-container, containerPort=80\" --cluster darkbridge-cluster-staging\n```\n\n## Working with Environment Variables\n\n1. Go to the AWS Secrets Manager\n2. Add an 'Other' \u003e 'Plaintext' Secret\n3. Name it EXAMPLE_SECRET_VARIABLE and replace the arn in task-def.json\n4. Add the SecretsManagerReadWrite policy to your task-def's executionRole\n\nSee: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data-secrets.html\n\n## Gotchas\n\n- Make sure the security group has an HTTP inbound rule set to 0.0.0.0 to allow public access\n- The ALB must be created and the target group specified before the service is created (see above)\n- Similarly the app in the task definition file, the alb, and so on should be named better.\n- By default, Fargate containers are limited to 200 MiB of memory; running the server with ts-node for example creates an unstable service since ts-node compiles to memory -- it's much better to compile to disk for production.\n- RE: ENV VARIABLES, Fargate only supports secrets that are a single value, not the JSON or key value secrets. So choose OTHER when creating the secret and just put a single text value there.\n- If a cluster is expected but not provided, you'll occasionally see a confusing \"missing cluster: default\" error; this usually means a `--cluster` needs to be specified in the cli command\n\n## Testing the Docker Image Locally\n\n- Build the image\n\n```bash\ndocker build -t [tag_name] .\n```\n\n- Launch the image in the background, exposing port 80\n\n```bash\ndocker run -d -p 80:80 [tag_name]\n```\n\n- Navigate to `localhost` in your browser\n\n## Connecting to RDS\n\nSee [Database Management](/docs/DatabaseManagement.md)\n\n# Todos\n\n- [x] ~Connecting to RDS~\n- [x] ~Allow attaching to the server process for debugging~\n- [x] ~Optional connecting to Mailgun~\n- [x] ~Continuous integration tests run on push~\n- [ ] Connecting to S3\n- [ ] Sourcemaps for production error monitoring\n- [ ] Use the image output from the staging deploy for the prod deploy\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasmost%2Fdarkbridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomasmost%2Fdarkbridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasmost%2Fdarkbridge/lists"}