{"id":14008257,"url":"https://github.com/fedekau/terraform-with-circleci-example","last_synced_at":"2025-09-14T14:32:59.979Z","repository":{"id":31512488,"uuid":"125406807","full_name":"fedekau/terraform-with-circleci-example","owner":"fedekau","description":"This is an example of automatic deployments of your infrastructure using terraform and CircleCI 2.0 workflows","archived":false,"fork":false,"pushed_at":"2022-03-19T16:31:54.000Z","size":630,"stargazers_count":154,"open_issues_count":1,"forks_count":61,"subscribers_count":8,"default_branch":"staging","last_synced_at":"2025-04-01T16:52:44.258Z","etag":null,"topics":["circleci","deployment","example","infrastructure","infrastructure-as-code","terraform"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fedekau.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-15T17:59:31.000Z","updated_at":"2024-11-14T19:29:50.000Z","dependencies_parsed_at":"2022-08-07T16:30:23.907Z","dependency_job_id":null,"html_url":"https://github.com/fedekau/terraform-with-circleci-example","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/fedekau%2Fterraform-with-circleci-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fedekau%2Fterraform-with-circleci-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fedekau%2Fterraform-with-circleci-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fedekau%2Fterraform-with-circleci-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fedekau","download_url":"https://codeload.github.com/fedekau/terraform-with-circleci-example/tar.gz/refs/heads/staging","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250150588,"owners_count":21383190,"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":["circleci","deployment","example","infrastructure","infrastructure-as-code","terraform"],"created_at":"2024-08-10T11:01:30.748Z","updated_at":"2025-04-21T23:30:50.836Z","avatar_url":"https://github.com/fedekau.png","language":"HCL","funding_links":[],"categories":["HCL","Building"],"sub_categories":["Workflows"],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/fedekau/terraform-with-circleci-example/staging/.images/gears.png\" height=\"200px\"\u003e\u003c/p\u003e\n\n# terraform-with-circleci-example\n\nWe all know how complex apps this days can get, so that is why I created this.\n\nIt is just minor contribution to help you achieve \"The Basic Web App Architecture\", which looks something like the image below.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/fedekau/terraform-with-circleci-example/staging/.images/web-app.jpg\" height=\"300px\"\u003e\u003c/p\u003e\n\nThis is an example repository that you can use to kickstart your project or to\nmake your current project better with some of the ideas included here.\n\nThe main purpose is to show one of the many possible ways\nyou could manage your infrastructure using an Infrastructure as Code (IAC) tool\nlike [Terraform](https://www.terraform.io/) and a continuous integration tool\nlike [CircleCI](https://circleci.com).\n\nI have followed many of the good practices described in the book [Terraform: Up \u0026 Running](https://www.terraformupandrunning.com/) and in the [CircleCI 2.0 Documentation](https://circleci.com/docs/2.0/). I will also assume you have some knowledge about those tools and [Amazon Web Services](https://aws.amazon.com) in general, no need to be an expert.\n\n## Suggested workflow\n\nAssuming you have two environments, `production` and `staging`, when a new feature is requested you branch from `staging`, commit the code and open a PR to the `staging` branch, when you do, CircleCI will run two jobs, one for linting and one that will plan the changes to your `staging` infrastructure so you can review them (see image below).\n\n![Image of PR creation jobs](https://raw.githubusercontent.com/fedekau/terraform-with-circleci-example/staging/.images/pr.png)\n\nOnce you merge the PR, if everything goes as planned CircleCI will run your jobs and will automatically deploy your infrastructure!\n\n![Image of jobs after staging merge](https://raw.githubusercontent.com/fedekau/terraform-with-circleci-example/staging/.images/staging-merge.png)\n\nAfter you have tested your infrastructure in `staging` you just need to open a PR from `staging` into `master` to \"promote\" you infrastructure into `production`.\n\nIn this case we want someone to manually approve the release into master, so after you merge you need to tell CircleCI that it can proceed and it will deploy the infrastructure after the confirmation.\n\n![Image of jobs after master merge](https://raw.githubusercontent.com/fedekau/terraform-with-circleci-example/staging/.images/master-merge.png)\n\nNow that you know what we want to achieve we will dive into the code...get ready!\n\n## How is this repo structured?\n\nI will explain each folder in the root level and dive into some of them, in another section I will explain the files contained in each folder (or at least the most important ones).\n\n### Folder `.circleci`\n\nThis folder is where the configuration file for CircleCI is included, it usually\ncontains one file `config.yml`. But you can have scripts to do whatever you need to help you run your tests or checks there. In this case we only have one file: [config.yml](https://github.com/fedekau/terraform-with-circleci-example/blob/master/.circleci/config.yml).\n\n### Folder `.keys`\n\nIt contains a public/private key pair, and before you shout at me, I know you **should never** have private keys in version control but for simplicity I have included them here.\n\n### Folder `environments`\n\nThis folder has one folder for each environment, in this case it has `production` and `staging`, but it could have as many as you need! For example if you want each developer to have its own environment they could copy one of those folders and have one new environment, as easy as it sounds!\n\nEach folder has some files that basically wrap the contents of the modules folder.\n\n### Folder `modules`\n\nHere we define all our infrastructure leaving some open parameters for customizing each environment, for example in `production` you want to run some powerful machines, but for `staging` you might want low power machines to reduce costs.\n\nThis folder has two folders, `state` which is a module for creating the required resources for managing terraform state remotely, an S3 bucket and a DynamoDB table, which we use in each environment. This is one possibility of the [many available](https://www.terraform.io/docs/backends/). The second folder `infrastructure` contains the definition of all the infrastructure which we use in each environment.\n\n### Folder `shared`\n\nThis folder is for throwing some shared files. In order to use the files we simply create a symbolic link wherever we need to use its contents.\n\n## Modules\n\nTerraform allows you to create and use modules. That enables us to reuse code.\n\n## State module\n\nWe have a `state` module which we use to encapsulate the resources for our backend of choice: S3 Bucket for the state file and DynamoDB for state locking.\n\nThe reason to have the `state` module independent of the `infrastructure` module is to give us more flexibility, for example, if you want to have one environment per developer they don't need remote storage or locking, they can simply use a local state file. See [Terraform Backends](https://www.terraform.io/docs/backends/index.html) for all the alternatives.\n\n## Infrastructure module\n\nHere I have used the module idea to create a `infrastructure` module that represents everything that is needed to run our apps, that means that every time you use that module you get an exact copy of your infrastructure.\n\nIn this repo I use it to create different environments, but you could also use it for creating your custom version of [Heroku's Review Apps](https://devcenter.heroku.com/articles/github-integration-review-apps)\n\nThis module is only glue for the modules it includes, in the [modules/environment/main.tf](https://github.com/fedekau/terraform-with-circleci-example/blob/staging/modules/infrastructure/main.tf) file we glue the `network`, `instances` and `databases` modules.\n\n### Network module\n\nIt represents the \"cables\" of our infrastructure, it only has [one variable](https://github.com/fedekau/terraform-with-circleci-example/blob/staging/modules/infrastructure/modules/network/variables.tf) that is the name of the environment.\n\nIt outputs some other variables like the [CIDR Blocks](https://es.wikipedia.org/wiki/Classless_Inter-Domain_Routing) of the network, the ID of the VPC, and IDs of the public and private subnets.\n\nThis was inspired by [AWS VPC with Public and Private Subnets](https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Scenario2.html)\n\n### Databases module\n\nThis module receives as input the current environment, the IDs of the private subnets and creates the required resources for a Multi AZ highly available database instance.\n\nAfter creating the module it exports the endpoint of the database and some other data.\n\nNotice that here we have some **VERY DUMMY** user and password. Ideally after you create a database you either change the password or manage the passwords in an external way.\n\n### Instances module\n\nThe `instances` module represents the VMs that will be running the code, in this case I also include an [AWS Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html)\n\nAs part of the creation of the instances I have used some [Terraform Provisioners](https://www.terraform.io/docs/provisioners/index.html) to execute some commands and create a dummy app to test that everything is working as expected.\n\n## License\n\nterraform-with-circleci-example is licensed under the MIT license.\n\nSee [LICENSE.md](https://github.com/fedekau/terraform-with-circleci-example/blob/staging/LICENSE.md) for the full license text.\n\n## Credits\n\n- Icons made by [Gregor Cresnar](https://www.flaticon.com/authors/gregor-cresnar) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/)\n- [WyeWorks](https://www.wyeworks.com) for allowing me to create 40% of this repository during my working hours as part of the [Continuous Learning policy](https://wyeworks.com/blog/2015/7/16/technical-thursdays-or-how-we-do-continuous-learning)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffedekau%2Fterraform-with-circleci-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffedekau%2Fterraform-with-circleci-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffedekau%2Fterraform-with-circleci-example/lists"}