diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 5d9493a9ee..5f044837ab 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -82,9 +82,11 @@ jobs: run: curl --retry-delay 1 --retry 30 --retry-all-error http://localhost:8080 # medium.com => was being rate limited: HTTP 429 + # twitter.com => too many redirections - run: | ./muffet \ -e 'https://medium.com/runatlantis' \ + -e 'https://twitter.com/*' \ -e 'https://github\.com/runatlantis/atlantis/edit/main/.*' \ -e 'https://github.com/runatlantis/helm-charts#customization' \ -e 'https://github.com/sethvargo/atlantis-on-gke/blob/master/terraform/tls.tf#L64-L84' \ diff --git a/.markdownlint.yaml b/.markdownlint.yaml index efc157fb61..9f4f9cacdc 100644 --- a/.markdownlint.yaml +++ b/.markdownlint.yaml @@ -31,3 +31,8 @@ MD024: # # https://github.com/DavidAnson/markdownlint/blob/main/doc/md051.md MD051: false + +# for blog posts +MD025: false +MD045: false +MD001: false diff --git a/netlify.toml b/netlify.toml index d19fe178dc..86030bdfcb 100644 --- a/netlify.toml +++ b/netlify.toml @@ -21,8 +21,7 @@ [headers.values] X-Frame-Options = "DENY" X-XSS-Protection = "1; mode=block" - Content-Security-Policy = "default-src 'self'; frame-src 'self' https://app.netlify.com; script-src 'self' https://*.google-analytics.com https://www.googletagmanager.com https://*.algolianet.com https://*.algolia.net 'unsafe-inline'; style-src 'self' https://fonts.googleapis.com https://*.algolianet.com https://*.algolia.net 'unsafe-inline'; img-src 'self' https://*.google-analytics.com data:; font-src 'self' data: https://fonts.googleapis.com https://fonts.gstatic.com; connect-src 'self' https://*.google-analytics.com https://www.googletagmanager.com https://*.algolianet.com https://*.algolia.net" - Cache-Control = "public, max-age=86400, must-revalidate" + Cache-Control = "public, max-age=86400" Strict-Transport-Security = "max-age=86400; includeSubDomains; preload" Referrer-Policy = "no-referrer" X-Content-Type-Options = "nosniff" diff --git a/package.json b/package.json index 0ae58e56c2..d2dda66b63 100644 --- a/package.json +++ b/package.json @@ -5,11 +5,12 @@ "@playwright/test": "^1.44.0", "@types/node": "^20.12.10", "@vueuse/core": "^10.9.0", + "markdown-it-footnote": "^4.0.0", + "markdownlint-cli": "^0.40.0", "sass": "^1.77.0", "sitemap-ts": "^1.6.1", "vitepress": "^1.1.4", - "vue": "^3.4.27", - "markdownlint-cli": "^0.40.0" + "vue": "^3.4.27" }, "scripts": { "website:dev": "vitepress dev --host localhost --port 8080 runatlantis.io", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b6f01364f..cd15bbe1aa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@vueuse/core': specifier: ^10.9.0 version: 10.9.0(vue@3.4.27) + markdown-it-footnote: + specifier: ^4.0.0 + version: 4.0.0 markdownlint-cli: specifier: ^0.40.0 version: 0.40.0 @@ -712,6 +715,9 @@ packages: mark.js@8.11.1: resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} + markdown-it-footnote@4.0.0: + resolution: {integrity: sha512-WYJ7urf+khJYl3DqofQpYfEYkZKbmXmwxQV8c8mO/hGIhgZ1wOe7R4HLFNwqx7TjILbnC98fuyeSsin19JdFcQ==} + markdown-it@14.1.0: resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} hasBin: true @@ -1632,6 +1638,8 @@ snapshots: mark.js@8.11.1: {} + markdown-it-footnote@4.0.0: {} + markdown-it@14.1.0: dependencies: argparse: 2.0.1 diff --git a/runatlantis.io/.vitepress/config.ts b/runatlantis.io/.vitepress/config.ts index 9e3e7f7669..a688f3f362 100644 --- a/runatlantis.io/.vitepress/config.ts +++ b/runatlantis.io/.vitepress/config.ts @@ -1,4 +1,5 @@ import { generateSitemap as sitemap } from "sitemap-ts" +import footnote from 'markdown-it-footnote' import { defineConfig } from 'vitepress'; import * as navbars from "./navbars"; import * as sidebars from "./sidebars"; @@ -114,6 +115,11 @@ export default defineConfig({ })();`, ] ], + markdown: { + config: (md) => { + md.use(footnote) + } + }, vite: { server: { fs: { diff --git a/runatlantis.io/.vitepress/navbars.ts b/runatlantis.io/.vitepress/navbars.ts index 84e6cf6034..e5a7ebfbbf 100644 --- a/runatlantis.io/.vitepress/navbars.ts +++ b/runatlantis.io/.vitepress/navbars.ts @@ -3,7 +3,7 @@ const en = [ { text: "Guide", link: "/guide" }, { text: "Docs", link: "/docs" }, { text: "Contributing", link: "/contributing" }, - { text: "Blog", link: "https://medium.com/runatlantis" }, + { text: "Blog", link: "/blog" }, ]; export { en }; diff --git a/runatlantis.io/.vitepress/sidebars.ts b/runatlantis.io/.vitepress/sidebars.ts index 1afacb11c2..7b0717e745 100644 --- a/runatlantis.io/.vitepress/sidebars.ts +++ b/runatlantis.io/.vitepress/sidebars.ts @@ -94,6 +94,56 @@ const en = [ { text: "Glossary", link: "/contributing/glossary" }, ] + }, + { + text: "Blog", + link: "/blog", + collapsed: false, + items: [ + { + text: "2019", + collapsed: true, + items: [ + { + text: "4 Reasons To Try HashiCorp's (New) Free Terraform Remote State Storage", + link: "/blog/2019/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage" + }, + ] + }, + { + text: "2018", + collapsed: true, + items: [ + { + text: "I'm Joining HashiCorp!", + link: "/blog/2018/joining-hashicorp" + }, + { + text: "Putting The Dev Into DevOps: Why Your Developers Should Write Terraform Too", + link: "/blog/2018/putting-the-dev-into-devops-why-your-developers-should-write-terraform-too" + }, + { + text: "Atlantis 0.4.4 Now Supports Bitbucket", + link: "/blog/2018/atlantis-0-4-4-now-supports-bitbucket" + }, + { + text: "Terraform And The Dangers Of Applying Locally", + link: "/blog/2018/terraform-and-the-dangers-of-applying-locally" + }, + { + text: "Hosting Our Static Site over SSL with S3, ACM, CloudFront and Terraform", + link: "/blog/2018/hosting-our-static-site-over-ssl-with-s3-acm-cloudfront-and-terraform" + }, + ] + }, + { + text: "2017", + collapsed: true, + items: [ + { text: "Introducing Atlantis", link: "/blog/2017/introducing-atlantis" }, + ] + }, + ] } ] diff --git a/runatlantis.io/blog.md b/runatlantis.io/blog.md new file mode 100644 index 0000000000..6ad783293c --- /dev/null +++ b/runatlantis.io/blog.md @@ -0,0 +1,28 @@ +--- +title: Welcome to Our Blog +aside: false +--- + +# Welcome to Our Blog + +We are thrilled to have you here! Our blog is a collection of insightful articles, tips, and updates from our team. Whether you're new or have been following us for a while, there's always something new to learn and explore. + +### Explore Our Popular Posts + +We have a rich history of blog posts dating back to 2017-2019. Here are some of our popular posts: + +- [4 Reasons To Try HashiCorp's (New) Free Terraform Remote State Storage](/blog/2019/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage) +- [I'm Joining HashiCorp!](/blog/2018/joining-hashicorp) +- [Putting The Dev Into DevOps: Why Your Developers Should Write Terraform Too](/blog/2018/putting-the-dev-into-devops-why-your-developers-should-write-terraform-too) +- [Atlantis 0.4.4 Now Supports Bitbucket](/blog/2018/atlantis-0-4-4-now-supports-bitbucket) +- [Terraform And The Dangers Of Applying Locally](/blog/2018/terraform-and-the-dangers-of-applying-locally) +- [Hosting Our Static Site over SSL with S3, ACM, CloudFront and Terraform](/blog/2018/hosting-our-static-site-over-ssl-with-s3-acm-cloudfront-and-terraform) +- [Introducing Atlantis](/blog/2017/introducing-atlantis) + +### Welcoming New Blog Authors + +We are excited to welcome new authors to our blog. Our diverse team brings a wealth of knowledge and experience to share with our readers. Stay tuned for fresh perspectives and in-depth articles on the latest trends and technologies. + +If you have any questions or topics you would like us to cover, feel free to reach out [on Slack](https://join.slack.com/t/atlantis-community/shared_invite/zt-9xlxtxtc-CUSKB1ATt_sQy6um~LDPNw). We are always looking to engage with our community and provide valuable content. + +Happy reading! diff --git a/runatlantis.io/blog/2017/introducing-atlantis.md b/runatlantis.io/blog/2017/introducing-atlantis.md new file mode 100644 index 0000000000..2957d994e7 --- /dev/null +++ b/runatlantis.io/blog/2017/introducing-atlantis.md @@ -0,0 +1,113 @@ +--- +title: Introducing Atlantis +lang: en-US +--- + +# Introducing Atlantis + +::: info +This post was originally written on September 11th, 2017 + +Original post: +::: + +We're very excited to announce the open source release of Atlantis! Atlantis is a tool for +collaborating on Terraform that's been in use at Hootsuite for over a year. The core +functionality of Atlantis enables developers and operators to run `terraform plan` and +`apply` directly from Terraform pull requests. Atlantis then comments back on the pull +request with the output of the commands: + +![](/blog/intro/intro1.gif) + +This is a simple feature, however it has had a massive effect on how our team writes Terraform. +By bringing a Terraform workflow to pull requests, Atlantis helped our Ops team collaborate +better on Terraform and also enabled our entire development team to write and execute Terraform safely. + +Atlantis was built to solve two problems that arose at Hootsuite as we adopted Terraform: + +### 1. Effective Collaboration + +What's the best way to collaborate on Terraform in a team setting? + +### 2. Developers Writing Terraform + +How can we enable our developers to write and apply Terraform safely? + +## Effective Collaboration + +When writing Terraform, there are a number of workflows you can follow. The simplest workflow is just using `master`: + +![](/blog/intro/intro2.webp) + +In this workflow, you work on `master` and run `terraform` locally. +The problem with this workflow is that there is no collaboration or code review. +So we start to use pull requests: + +![](/blog/intro/intro3.webp) + +We still run `terraform plan` locally, but once we're satisfied with the changes we create a pull request for review. When the pull request is approved, we run `apply` locally. + +This workflow is an improvement, but there are still problems. The first problem is that it's hard to review just the diff on the pull request. To properly review a change, you really need to see the output from `terraform plan`. + +![](/blog/intro/intro4.webp) + +What looks like a small change... + +![](/blog/intro/intro5.webp) + +...can have a big plan + +The second problem is that now it's easy for `master` to get out of sync with what's actually been applied. This can happen if you merge a pull request without running `apply` or if the `apply` has an error halfway through, you forget to fix it and then you merge to `master`. Now what's in `master` isn't actually what's running on production. At best, this causes confusion the next time someone runs `terraform plan`. At worst, it causes an outage when someone assumes that what's in `master` is actually running, and depends on it. + +With the Atlantis workflow, these problems are solved: + +![](/blog/intro/intro6.webp) + +Now it's easy to review changes because you see the `terraform plan` output on the pull request. + +![](/blog/intro/intro7.webp) + +Pull requests are easy to review since you can see the plan + +It's also easy to ensure that the pull request is `terraform apply`'d before merging to master because you can see the actual `apply` output on the pull request. + +![](/blog/intro/intro8.webp) + +So, Atlantis makes working on Terraform within an operations team much easier, but how does it help with getting your whole team to write Terraform? + +## Developers Writing Terraform + +Terraform usually starts out being used by the Ops team. As a result of using Terraform, the Ops team becomes much faster at making infrastructure changes, but the way developers request those changes remains the same: they use a ticketing system or chat to ask operations for help, the request goes into a queue and later Ops responds that the task is complete. + +Soon however, the Ops team starts to realize that it's possible for developers to make some of these Terraform changes themselves! There are some problems that arise though: + +- Developers don't have the credentials to actually run Terraform commands +- If you give them credentials, it's hard to review what is actually being applied + +With Atlantis, these problems are solved. All `terraform plan` and `apply` commands are run from the pull request. This means developers don't need to have any credentials to run Terraform locally. Of course, this can be dangerous: how can you ensure developers (who might be new to Terraform) aren't applying things they shouldn't? The answer is code reviews and approvals. + +Since Atlantis comments back with the `plan` output directly on the pull request, it's easy for an operations engineer to review exactly what changes will be applied. And Atlantis can run in `require-approval` mode, that will require a GitHub pull request approval before allowing `apply` to be run: + +![](/blog/intro/intro9.webp) + +With Atlantis, developers are able to write and apply Terraform safely. They submit pull requests, can run `atlantis plan` until their change looks good and then get approval from Ops to `apply`. + +Since the introduction of Atlantis at Hootsuite, we've had **78** contributors to our Terraform repositories, **58** of whom are developers (**75%**). + +## Where we are now + +Since the introduction of Atlantis at Hootsuite we've grown to 144 Terraform repositories [^1] that manage thousands of Amazon resources. Atlantis is used for every single Terraform change throughout our organization. + +## Getting started with Atlantis + +If you'd like to try out Atlantis for your team you can download the latest release from . If you run `atlantis testdrive` you can get started in less than 5 minutes. To read more about Atlantis go to . + +Check out our video for more information: + + + +[^1]: We split our Terraform up into multiple states, each with its own repository (see [1], [2], [3]). + +[1]: https://blog.gruntwork.io/how-to-manage-terraform-state-28f5697e68fa +[2]: https://charity.wtf/2016/03/30/terraform-vpc-and-why-you-want-a-tfstate-file-per-env/ +[3]: https://www.nclouds.com/blog/terraform-multi-state-management/ diff --git a/runatlantis.io/blog/2018/atlantis-0-4-4-now-supports-bitbucket.md b/runatlantis.io/blog/2018/atlantis-0-4-4-now-supports-bitbucket.md new file mode 100644 index 0000000000..ce6e39f0cb --- /dev/null +++ b/runatlantis.io/blog/2018/atlantis-0-4-4-now-supports-bitbucket.md @@ -0,0 +1,102 @@ +--- +title: Atlantis 0.4.4 Now Supports Bitbucket +lang: en-US +--- + +# Atlantis 0.4.4 Now Supports Bitbucket + +::: info +This post was originally written on July 25th, 2018 + +Original post: +::: + +![](/blog/atlantis-0-4-4-now-supports-bitbucket/pic1.webp) + +Atlantis is an [open source](https://github.com/runatlantis/atlantis) platform for using Terraform in teams. I'm happy to announce that the [latest release](https://github.com/runatlantis/atlantis/releases) of Atlantis (0.4.4) now supports both Bitbucket Cloud (bitbucket.org) **and** Bitbucket Server (aka Stash). + +![](/blog/atlantis-0-4-4-now-supports-bitbucket/pic2.gif) + +Atlantis now supports the three major Git hosts: GitHub, GitLab and Bitbucket. The rest of this post will talk about how to use Atlantis with Bitbucket. + +## What is Atlantis? + +Atlantis is a self-hosted application that listens for Terraform pull request events via webhooks. It runs `terraform plan` and `apply` remotely and comments back on the pull request with the output. + +With Atlantis, you collaborate on the Terraform pull request itself instead of running `terraform apply` from your own computers which can be dangerous: + +Check out for more information. + +## Getting Started + +The easiest way to try out Atlantis with Bitbucket is to run Atlantis locally on your own computer. Eventually you'll want to deploy it as a standalone app but this is the easiest way to try it out. Follow [these instructions](https://www.runatlantis.io/guide/getting-started.html) to get Atlantis running locally. + +Create a Pull Request +If you've got the Atlantis webhook configured for your repository and Atlantis is running, it's time to create a new pull request. I recommend adding a `null_resource` to one of your Terraform files for the the test pull request. It won't actually create anything so it's safe to use as a test. + +Using the web editor, open up one of your Terraform files and add: + +```tf +resource "null_resource" "example" {} +``` + +![](/blog/atlantis-0-4-4-now-supports-bitbucket/pic3.webp) + +Click Commit and select **Create a pull request for this change**. + +![](/blog/atlantis-0-4-4-now-supports-bitbucket/pic4.webp) + +Wait a few seconds and then refresh. Atlantis should have automatically run `terraform plan` and commented back on the pull request: + +![](/blog/atlantis-0-4-4-now-supports-bitbucket/pic5.webp) + +Now it's easier for your colleagues to review the pull request because they can see the `terraform plan` output. + +### Terraform Apply + +Since all we're doing is adding a null resource, I think it's safe to run `terraform apply`. To do so, I add a comment to the pull request: `atlantis apply`: + +![](/blog/atlantis-0-4-4-now-supports-bitbucket/pic6.webp) + +Atlantis is listening for pull request comments and will run `terraform apply` remotely and comment back with the output: + +![](/blog/atlantis-0-4-4-now-supports-bitbucket/pic7.webp) + +### Pull Request Approvals + +If you don't want anyone to be able to `terraform apply`, you can run Atlantis with `--require-approval` or add that setting to your [atlantis.yaml file](https://www.runatlantis.io/docs/command-requirements.html#approved). + +This will ensure that the pull request has been approved before someone can run `apply`. + +## Other Features + +### Customizable Commands + +Apart from being able to `plan` and `apply` from the pull request, Atlantis also enables you to customize the exact commands that are run via an `atlantis.yaml` config file. For example to use the `-var-file` flag: + +```yaml{14} +# atlantis.yaml +version: 2 +projects: +- name: staging + dir: "." + workflow: staging + +workflows: + staging: + plan: + steps: + - init + - plan: + extra_args: ["-var-file", "staging.tfvars"] +``` + +### Locking For Coordination + +![](/blog/atlantis-0-4-4-now-supports-bitbucket/pic8.webp) + +Atlantis will prevent other pull requests from running against the same directory as an open pull request so that each plan is applied atomically. Once the first pull request is merged, other pull requests are unlocked. + +## Next Steps + +If you're interested in using Atlantis with Bitbucket, check out our Getting Started docs. Happy Terraforming! diff --git a/runatlantis.io/blog/2018/hosting-our-static-site-over-ssl-with-s3-acm-cloudfront-and-terraform.md b/runatlantis.io/blog/2018/hosting-our-static-site-over-ssl-with-s3-acm-cloudfront-and-terraform.md new file mode 100644 index 0000000000..a9506073f3 --- /dev/null +++ b/runatlantis.io/blog/2018/hosting-our-static-site-over-ssl-with-s3-acm-cloudfront-and-terraform.md @@ -0,0 +1,174 @@ +--- +title: Hosting Our Static Site over SSL with S3, ACM, CloudFront and Terraform +lang: en-US +--- + +# Hosting Our Static Site over SSL with S3, ACM, CloudFront and Terraform + +::: info +This post was originally written on March 4, 2018 + +Original post: +::: + +In this post I cover how I hosted using + +- S3 — for storing the static site +- CloudFront — for serving the static site over SSL +- AWS Certificate Manager — for generating the SSL certificates +- Route53 — for routing the domain name to the correct location + +I chose Terraform in this case because Atlantis is a tool for automating and collaborating on Terraform in a team (see github.com/runatlantis/atlantis)–and so obviously it made sense to host our homepage using Terraform–but also because it's now much easier to manage. I don't have to go into the AWS console and click around to find what settings I want to change. Instead I can just look at ~100 lines of code, make a change, and run `terraform apply`. + +::: info +NOTE: 4 months after this writing, I moved the site to [Netlify](https://www.netlify.com/) because it automatically builds from my master branch on any change, updates faster since I don't need to wait for the Cloudfront cache to expire and gives me [deploy previews](https://www.netlify.com/blog/2016/07/20/introducing-deploy-previews-in-netlify/) of changes. The DNS records are still hosted on AWS. +::: + +# Overview + +There's a surprising number of components required to get all this working so I'm going to start with an overview of what they're all needed for. Here's what the final architecture looks like: + +![](/blog/hosting-our-static-site/pic1.webp) + +That's what the final product looks like, but lets start with the steps required to get there. + +## Step 1 — Generate The Site + +The first step is to have a site generated. Our site uses [Hugo](https://gohugo.io/), a Golang site generator. Once it's set up, you just need to run `hugo` and it will generate a directory with HTML and all your content ready to host. + +## Step 2 — Host The Content + +Once you've got a website, you need it to be accessible on the internet. I used S3 for this because it's dirt cheap and it integrates well with all the other necessary components. I simply upload my website folder to the S3 bucket. + +## Step 3 — Generate an SSL Certificate + +I needed to generate an SSL certificate for . I used the AWS Certificate Manager for this because it's free and is easily integrated with the rest of the system. + +## Step 4 — Set up DNS + +Because I'm going to host the site on AWS services, I need requests to to be routed to those services. Route53 is the obvious solution. + +## Step 5 — Host with CloudFront + +At this point, we've generated an SSL certificate for and our website is available on the internet via its S3 url so can't we just CNAME to the S3 bucket and call it a day? Unfortunately not. + +Since we generated our own certificate, we would need S3 to sign its responses using our certificiate. S3 doesn't support this and thus we need CloudFront. CloudFront supports using our own SSL cert and will just pull its data from the S3 bucket. + +# Terraform Time + +Now that we know what our architecture should look like, it's simply a matter of writing the Terraform. + +## Initial Setup + +Create a new file `main.tf`: + +<<< @/public/blog/hosting-our-static-site/code/main.tf + +## S3 Bucket + +Assuming we've generated our site content already, we need to create an S3 bucket to host the content. + +<<< @/public/blog/hosting-our-static-site/code/s3-bucket.tf + +We should be able to run Terraform now to create the S3 bucket + +```sh +terraform init +`terraform apply` +``` + +![](/blog/hosting-our-static-site/pic2.webp) + +Now we want to upload our content to the S3 bucket: + +```sh +$ cd dir/with/website +# generate the HTML +$ hugo -d generated +$ cd generated +# send it to our S3 bucket +$ aws s3 sync . s3://www.runatlantis.io/ # change this to your bucket +``` + +Now we need the S3 url to see our content: + +```sh +$ terraform state show aws_s3_bucket.www | grep website_endpoint +website_endpoint = www.runatlantis.io.s3-website-us-east-1.amazonaws.com +``` + +You should see your site hosted at that url! + +## SSL Certificate + +Let's use the AWS Certificate Manager to create our SSL certificate. + +<<< @/public/blog/hosting-our-static-site/code/ssl-cert.tf + +Before you run `terraform apply`, ensure you're forwarding any of + +- `administrator@your_domain_name` +- `hostmaster@your_domain_name` +- `postmaster@your_domain_name` +- `webmaster@your_domain_name` +- `admin@your_domain_name` + +To an email address you can access. Then, run `terraform apply` and you should get an email from AWS to confirm you own this domain where you'll need to click on the link. + +## CloudFront + +Now we're ready for CloudFront to host our website using the S3 bucket for the content and using our SSL certificate. Warning! There's a lot of code ahead but most of it is just defaults. + +<<< @/public/blog/hosting-our-static-site/code/cloudfront.tf + +Apply the changes with `terraform apply` and then find the domain name that CloudFront gives us: + +```sh +$ terraform state show aws_cloudfront_distribution.www_distribution | grep ^domain_name +domain_name = d1l8j8yicxhafq.cloudfront.net +``` + +You'll probably get an error if you go to that URL right away. You need to wait a couple minutes for CloudFront to set itself up. It took me 10 minutes. You can view its progress in the console: + +## DNS + +We're almost done! We've got CloudFront hosting our site, now we need to point our DNS at it. + +<<< @/public/blog/hosting-our-static-site/code/dns.tf + +If you bought your domain from somewhere else like Namecheap, you'll need to point your DNS at the nameservers listed in the state for the Route53 zone you created. First `terraform apply` (which may take a while), then find out your nameservers. + +```sh +$ terraform state show aws_route53_zone.zone +id = Z2FNAJGFW912JG +comment = Managed by Terraform +force_destroy = false +name = runatlantis.io +name_servers.# = 4 +name_servers.0 = ns-1349.awsdns-40.org +name_servers.1 = ns-1604.awsdns-08.co.uk +name_servers.2 = ns-412.awsdns-51.com +name_servers.3 = ns-938.awsdns-53.net +tags.% = 0 +zone_id = Z2FNAJGFW912JG +``` + +Then look at your domain's docs for how to change your nameservers to all 4 listed. + +## That's it...? + +Once the DNS propagates you should see your site at `https://www.yourdomain`! But what about `https://yourdomain`? i.e. without the `www.`? Shouldn't this redirect to `https://www.yourdomain`? + +## Root Domain + +It turns out, we need to create a whole new S3 bucket, CloudFront distribution and Route53 record just to get this to happen. That's because although S3 can serve up a redirect to the www version of your site, it can't host SSL certs and so you need CloudFront. I've included all the terraform necessary for that below. + +Congrats! You're done! + + + +If you're using Terraform in a team, check out Atlantis: for automation and collaboration to make your team happier! + +Here's the Terraform needed to redirect your root domain: + +<<< @/public/blog/hosting-our-static-site/code/full.tf diff --git a/runatlantis.io/blog/2018/joining-hashicorp.md b/runatlantis.io/blog/2018/joining-hashicorp.md new file mode 100644 index 0000000000..69ab04cda8 --- /dev/null +++ b/runatlantis.io/blog/2018/joining-hashicorp.md @@ -0,0 +1,50 @@ +--- +title: I'm Joining HashiCorp! +lang: en-US +--- + +# I'm Joining HashiCorp + +::: info +This post was originally written on October 23th, 2018 + +Original post: +::: + +Dear Atlantis Community, + +My name is Luke and I'm the maintainer of [Atlantis](https://www.runatlantis.io/), an open source tool for Terraform collaboration. Today I'm excited to announce that I'm joining HashiCorp! + +![](/blog/joining-hashicorp/pic1.webp) + +## What Does This Mean For Atlantis? + +In the near term, nothing will change for Atlantis and its users. As a HashiCorp employee I will continue to maintain Atlantis, review pull requests, triage issues, and write code. + +In the long term, HashiCorp and I want to address collaboration workflows for all users of Terraform. We are still working out the details of how Atlantis will fit into the longer term plan, but whatever direction we take, we're committed to keeping Atlantis free and open source. + +## HashiCorp and Atlantis + +Why does HashiCorp want to support Atlantis? + +Today HashiCorp [announced their commitment to provide collaboration solutions to the whole Terraform community](https://www.hashicorp.com/blog/terraform-collaboration-for-everyone). They see the Atlantis project as one manifestation of this vision and understand its importance to many in the Terraform community. They believe that by working together, we can create a solution that will scale from a single user to hundreds of collaborators in a large organization. + +## Why am I joining? + +Those of you who know me, may wonder why I made this decision. It came down to wanting to continue working on Atlantis–and the larger story of Terraform collaboration–and finding a way to support myself. + +In January, 9 months ago, I quit my job at Hootsuite to work **full time** on Atlantis (Atlantis was originally created at Hootsuite by my friend [Anubhav Mishra](https://twitter.com/anubhavm)). I left because I knew that the Terraform community was in need of a solution for collaboration and that with full time development, Atlantis could be that solution. + +During the last 9 months, Atlantis matured into a fully fledged collaboration solution and gained many new users. It has been an amazing time, but I've been working for free! I've always known that for Atlantis to be successful in the long term, I would need to find a way to support myself. + +A couple of weeks ago, as I was playing around with Atlantis monetization strategies, HashiCorp contacted me. I learned that they shared a vision of building Terraform collaboration solutions for the broader community and that they were interested in combining forces. They also assured me that they wanted to do right by the Atlantis community. + +This was a compelling offer versus solo-founding a company around Atlantis: I would be able to focus on coding and product instead of business and sales and I could spend all of my time on Atlantis and the larger story of Terraform collaboration. As a result, I came to the conclusion that joining HashiCorp was the right decision for me and the community. + +## Conclusion + +Atlantis has been a passion of mine for almost two years now. I deeply care about the future of the project and its community and I know that this move will ensure that that future is bright. + +There are probably some questions I haven't answered in this post so please don't hesitate to reach out, either via [Twitter](https://twitter.com/lkysow) or on the [Atlantis Slack](https://join.slack.com/t/atlantis-community/shared_invite/zt-9xlxtxtc-CUSKB1ATt_sQy6um~LDPNw). + +I'm excited for the future of Atlantis and Terraform collaboration and I hope you are too. diff --git a/runatlantis.io/blog/2018/putting-the-dev-into-devops-why-your-developers-should-write-terraform-too.md b/runatlantis.io/blog/2018/putting-the-dev-into-devops-why-your-developers-should-write-terraform-too.md new file mode 100644 index 0000000000..88b28a1b16 --- /dev/null +++ b/runatlantis.io/blog/2018/putting-the-dev-into-devops-why-your-developers-should-write-terraform-too.md @@ -0,0 +1,244 @@ +--- +title: "Putting The Dev Into DevOps: Why Your Developers Should Write Terraform Too" +lang: en-US +--- + +# Putting The Dev Into DevOps: Why Your Developers Should Write Terraform Too + +::: info +This post was originally written on August 29th, 2018 + +Original post: +::: + +[Terraform](https://www.terraform.io/) is an amazing tool for provisioning infrastructure. Terraform enables your operators to perform their work faster and more reliably. + +**But if only your ops team is writing Terraform, you're missing out.** + +Terraform is not just a tool that makes ops teams more effective. Adopting Terraform is an opportunity to turn all of your developers into operators (at least for smaller tasks). This can make your entire engineering team more effective and create a better relationship between developers and operators. + +### Quick Aside — What is Terraform? + +Terraform is two things. It's a language for describing infrastructure: + +```tf +resource "aws_instance" "example" { + ami = "ami-2757f631" + instance_type = "t2.micro" +} +``` + +And it's a CLI tool that reads Terraform code and makes API calls to AWS (or any other cloud provider) to provision that infrastructure. + +In this example, we're using the CLI to run `terraform apply` which will create an EC2 instance: + +```sh +$ terraform apply + +Terraform will perform the following actions: + + # aws_instance.example + + aws_instance.example + ami: "ami-2757f631" + instance_type: "t2.micro" + ... + +Plan: 1 to add, 0 to change, 0 to destroy. + +Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: yes + +aws_instance.example: Creating... + ami: "" => "ami-2757f631" + instance_type: "" => "t2.micro" + ... + +aws_instance.example: Still creating... (10s elapsed) +aws_instance.example: Creation complete + +Apply complete! Resources: 1 added, 0 changed, 0 destroyed. +``` + +## Terraform Adoption From A Dev's Perspective + +Adopting Terraform is great for your operations team's effectiveness but it doesn't change much for devs. Before Terraform adoption, devs typically interacted with an ops team like this: + +![](/blog/putting-the-dev-into-devops/pic1.webp) + +1. **Dev: Creates ticket asking for some ops work** +2. **Dev: Waits** +3. _Ops: Looks at ticket when in queue_ +4. _Ops: Does work_ +5. _Ops: Updates ticket_ +6. **Dev: Continues their work** + +After the Ops team adopts Terraform, the workflow from a dev's perspective is the same! + +![](/blog/putting-the-dev-into-devops/pic2.webp) + +1. **Dev: Creates ticket asking for some ops work** +2. **Dev: Waits** +3. _Ops: Looks at ticket when in queue_ +4. _Ops: Does work. This time using Terraform (TF)_ +5. _Ops: Updates ticket_ +6. **Dev: Continues their work** + +With Terraform, there's less of Step 2 (Dev: Waits) but apart from that, not much has changed. + +> If only ops is writing Terraform, your developers' experience is the same. + +## Devs Want To Help + +Developers would love to help out with operations work. They know that for small changes they should be able to do the work themselves (with a review from ops). For example: + +- Adding a new security group rule +- Increasing the size of an autoscaling group +- Using a larger instance because their app needs more memory + +Developers could make all of these changes because they're small and well defined. Also, previous examples of doing the same thing can guide them. + +## ...But Often They're Not Allowed + +In many organizations, devs are locked out of the cloud console. + +![](/blog/putting-the-dev-into-devops/pic3.webp) + +They might be locked out for good reasons: + +- Security — You can do a lot of damage with full access to a cloud console +- Compliance — Maybe your compliance requires only certain groups to have access +- Cost — Devs might spin up some expensive resources and then forget about them + +Even if they have access, operations can be complicated: + +- It's often difficult to do seemingly simple things (think adding a security group rule that also requires peering VPCs). This means that just having access sometimes isn't enough. Devs might need help from an expert to get things done. + +## Enter Terraform + +With Terraform, everything changes. Or at least it can. + +Now Devs can see in code how infrastructure is built. They can see the exact spot where security group rules are configured: + +```tf +resource "aws_security_group_rule" "allow_all" { + type = "ingress" + from_port = 0 + to_port = 65535 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + security_group_id = "sg-123456" +} + +resource "aws_security_group_rule" "allow_office" { + ... +} +``` + +Or where the size of the autoscaling group is set: + +```tf +resource "aws_autoscaling_group" "asg" { + name = "my-asg" + max_size = 5 + desired_capacity = 4 + min_size = 2 + ... +} +``` + +Devs understand code (surprise!) so it's a lot easier for them to make those small changes. + +Here's the new workflow: + +![](/blog/putting-the-dev-into-devops/pic4.webp) + +1. **Dev: Writes Terraform code** +2. **Dev: Creates pull request** +3. _Ops: Reviews pull request_ +4. **Dev: Applies the change with Terraform (TF)** +5. **Dev: Continues their work** + +Now: + +- Devs are making small changes themselves. This saves time and increases the speed of the whole engineering organization. +- Devs can see exactly what is required to make the change. This means there's less back and forth over a ticket: “Okay so I know you need the security group opened between server A and B, but on which ports and with which protocol?” +- Devs start to see how infrastructure is built. This increases cooperation between dev and ops because they can understand each other's work. + +Great! But there's another problem. + +## Devs Are Locked Out Of Terraform Too + +In order to execute Terraform you need to have cloud credentials! It's really hard to write Terraform without being able to run `terraform init` and `terraform plan`, for the same reason it would be hard to write code if you could never run it locally! + +So are we back at square one? + +## Enter Atlantis + +[Atlantis](https://www.runatlantis.io/) is an [open source](https://github.com/runatlantis/atlantis) tool for running Terraform from pull requests. With Atlantis, Terraform is run on a separate server (Atlantis is self-hosted) so you don't need to give out credentials to everyone. Access is controlled through pull request approvals. + +Here's what the workflow looks like: + +### Step 1 — Create a Pull Request + +A developer creates a pull request with their change to add a security group rule. + +![](/blog/putting-the-dev-into-devops/pic5.webp) + +### Step 2 — Atlantis Runs Terraform Plan + +Atlantis automatically runs `terraform plan` and comments back on the pull request with the output. Now developers can fix their Terraform errors before asking for a review. + +![](/blog/putting-the-dev-into-devops/pic6.webp) + +### Step 3 — Fix The Terraform + +The developer pushes a new commit that fixes their error and Atlantis comments back with the valid `terraform plan` output. Now the developer can verify that the plan output looks good. + +![](/blog/putting-the-dev-into-devops/pic7.webp) + +### Step 4 — Get Approval + +You'll probably want to run Atlantis with the --require-approval flag that requires pull requests to be Approved before running atlantis apply. + +![](/blog/putting-the-dev-into-devops/pic8.webp) + +### Step 4a — Actually Get Approval + +An operator can now come along and review the changes and the output of `terraform plan`. This is much faster than doing the change themselves. + +![](/blog/putting-the-dev-into-devops/pic9.webp) + +### Step 5 — Apply + +To apply the changes, the developer or operator comments “atlantis apply”. + +![](/blog/putting-the-dev-into-devops/pic10.webp) + +## Success + +Now we've got a workflow that makes everyone happy: + +- Devs can write Terraform and iterate on the pull request until the `terraform plan` looks good +- Operators can review pull requests and approve the changes before they're applied + +Now developers can make small operations changes and learn more about how infrastructure is built. Everyone can work more effectively and with a shared understanding that enhances collaboration. + +## Does It Work In Practice? + +Atlantis has been used by my previous company, Hootsuite, for over 2 years. It's used daily by 20 operators but it's also used occasionally by over 60 developers! +Another company uses Atlantis to manage 600+ Terraform repos collaborated on by over 300 developers and operators. + +## Next Steps + +- If you'd like to learn more about Terraform, check out HashiCorp's [Introduction to Terraform](https://developer.hashicorp.com/terraform/intro) +- If you'd like to try out Atlantis, go to +- If you have any questions, reach out to me on Twitter ([at]lkysow) or in the comments below. + +## Credits + +- Thanks to [Seth Vargo](https://medium.com/@sethvargo) for his talk [Version-Controlled Infrastructure with GitHub](https://www.youtube.com/watch?v=2TWqi7dLSro) that inspired a lot of this post. +- Thanks to Isha for reading drafts of this post. +- Icons in graphics from made by [Freepik](http://freepik.com/) from [Flaticon](https://www.flaticon.com/) and licensed by [CC 3.0](https://creativecommons.org/licenses/by/3.0/) diff --git a/runatlantis.io/blog/2018/terraform-and-the-dangers-of-applying-locally.md b/runatlantis.io/blog/2018/terraform-and-the-dangers-of-applying-locally.md new file mode 100644 index 0000000000..081d2f1154 --- /dev/null +++ b/runatlantis.io/blog/2018/terraform-and-the-dangers-of-applying-locally.md @@ -0,0 +1,120 @@ +--- +title: Terraform And The Dangers Of Applying Locally +lang: en-US +--- + +# Terraform And The Dangers Of Applying Locally + +::: info +This post was originally written on July 13th, 2018 + +Original post: +::: + +If you're using Terraform then at some point you've likely ran a `terraform apply` that reverted someone else's change! + +Here's how that tends to happen: + +## The Setup + +Say we have two developers: Alice and Bob. Alice needs to add a new security group rule. She checks out a new branch, adds her rule and creates a pull request: + +![](/blog/terraform-and-the-dangers-of-applying-locally/pic1.webp) + +When she runs `terraform plan` locally she sees what she expects. + +![](/blog/terraform-and-the-dangers-of-applying-locally/pic2.webp) + +Meanwhile, Bob is working on an emergency fix. He checks out a new branch and adds a different security group rule called `emergency`: + +![](/blog/terraform-and-the-dangers-of-applying-locally/pic3.webp) + +And, because it's an emergency, he **immediately runs apply**: + +![](/blog/terraform-and-the-dangers-of-applying-locally/pic4.webp) + +Now back to Alice. She's just gotten approval on her pull request change and so she runs `terraform apply`: + +![](/blog/terraform-and-the-dangers-of-applying-locally/pic5.webp) + +Did you catch what happened? Did you notice that the `apply` deleted Bob's rule? + +![](/blog/terraform-and-the-dangers-of-applying-locally/pic6.webp) + +In this example, it wasn't too hard to see. However if the plan is much longer, or if the change is less obvious then it can be easy to miss. + +## Possible Solutions + +There are some ways to avoid this: + +### Use terraform plan `-out` + +If Alice had run `terraform plan -out plan.tfplan` then when she ran `terraform apply plan.tfplan` she would see: + +![](/blog/terraform-and-the-dangers-of-applying-locally/pic7.webp) + +The problem with this solution is that few people run `terraform plan` anymore, much less `terraform plan -out`! + + + +It's easier to just run `terraform apply` and humans will take the easier path most of the time. + +### Wrap `terraform apply` to ensure up to date with `master` + +Another possible solution is to write a wrapper script that ensures our branch is up to date with `master`. But this doesn't solve the problem of Bob running `apply` locally and not yet merging to `master`. In this case, Alice's branch would have been up to date with `master` but not the latest apply'd state. + +### Be more disciplined + +What if everyone: + +- ALWAYS created a branch, got a pull request review, merged to `master` and then ran apply. And also everyone +- ALWAYS checked to ensure their branch was rebased from `master`. And also everyone +- ALWAYS carefully inspected the `terraform plan` output and made sure it was exactly what they expected + +...then we wouldn't have a problem! + +Unfortunately this is not a real solution. We're all human and we're all going to make mistakes. Relying on people to follow a complicated process 100% of the time is not a solution because it doesn't work. + +## Core Problem + +The core problem is that everyone is applying from their own workstations and it's up to them to ensure that they're up to date and that they keep `master` up to date. This is like developers deploying to production from their laptops. + +### What if, instead of applying locally, a remote system did the apply's? + +This is why we built [Atlantis](https://www.runatlantis.io/) – an open source project for Terraform automation by pull request. You could also accomplished this with your own CI system or with [Terraform Enterprise](https://www.hashicorp.com/products/terraform). Here's how Atlantis solves this issue: + +When Alice makes her change, she creates a pull request and Atlantis automatically runs `terraform plan` and comments on the pull request. + +When Bob makes his change, he creates a pull request and Atlantis automatically runs `terraform plan` and comments on the pull request. + +![](/blog/terraform-and-the-dangers-of-applying-locally/pic8.webp) + +Atlantis also **locks the directory** to ensure that no one else can run `plan` or `apply` until Alice's plan has been intentionally deleted or she merges the pull request. + +If Bob creates a pull request for his emergency change he'd see this error: + +![](/blog/terraform-and-the-dangers-of-applying-locally/pic9.webp) + +Alice can then comment `atlantis apply` and Atlantis will run the apply itself: + +![](/blog/terraform-and-the-dangers-of-applying-locally/pic10.webp) + +Finally, she merges the pull request and unlocks Bob's branch: + +![](/blog/terraform-and-the-dangers-of-applying-locally/pic11.webp) + +### But what if Bob ran `apply` locally? + +In that case, Alice is still okay because when Atlantis ran `terraform plan` it used `-out`. If Alice tries to apply that plan, Terraform will give an error because the plan was generated against an old state. + +### Why does Atlantis run `apply` on the branch and not after a merge to `master`? + +We do this because `terraform apply` fails quite often, despite `terraform plan` succeeding. Usually it's because of a dependency issue between resources or because the cloud provider requires a certain format or a certain field to be set. Regardless, in practice we've found that `apply` fails a lot. + +By locking the directory, we're essentially ensuring that the branch being `apply`'d is `"master"` since no one else can modify that state. We then get the benefit of being able to iterate on the pull request and push small fixes until we're sure that the changeset is `apply`'d. If `apply` failed after merging to `master`, we'd have to open new pull requests over and over again. There is definitely a tradeoff here, however we believe it's the right tradeoff. + +## Conclusion + +In conclusion, running `terraform apply` when you're working with a team of operators can be dangerous. Look to solutions like your own CI, Atlantis or Terraform Enterprise to ensure you're always working off the latest code that was `apply`'d. + +If you'd like to try Atlantis, you can get started here: diff --git a/runatlantis.io/blog/2019/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage.md b/runatlantis.io/blog/2019/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage.md new file mode 100644 index 0000000000..07bfd8ccf9 --- /dev/null +++ b/runatlantis.io/blog/2019/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage.md @@ -0,0 +1,157 @@ +--- +title: 4 Reasons To Try HashiCorp's (New) Free Terraform Remote State Storage +lang: en-US +--- + +# 4 Reasons To Try HashiCorp's (New) Free Terraform Remote State Storage + +::: info +This post was originally written on April 2nd, 2019 + +Original post: +::: + +Update (May 20/19) — Free State Storage is now called Terraform Cloud and is out of Beta, meaning anyone can sign up! + +HashiCorp is planning to offer free Terraform Remote State Storage and they have a beta version available now. In this article, I talk about 4 reasons you should try it (Disclosure: I work at HashiCorp). + +> _Sign up for Terraform Cloud [here](https://goo.gl/X5t5EM)._ + +## What is Terraform State? + +Before I get into why you should use the new remote state storage, let's talk about what exactly we mean by state in Terraform. + +Terraform uses _state_ to map your Terraform code to the real-world resources that it provisions. For example, if I have Terraform code to create an AWS EC2 instance: + +```tf +resource "aws_instance" "web" { + ami = "ami-e6d9d68c" + instance_type = "t2.micro" +} +``` + +When I run `terraform apply`, Terraform will make a “create EC2 instance” API call to AWS and AWS will return the unique ID of that instance (ex. `i-0ad17607e5ee026d0`). Terraform needs to record that ID somewhere so that later, it can make API calls to change or delete the instance. + +To store this information, Terraform uses a state file. For the above code, the state file will look something like: + +```json{4,7} +{ + ... + "resources": { + "aws_instance.web": { + "type": "aws_instance", + "primary": { + "id": "i-0ad17607e5ee026d0", + ... +} +``` + +Here you can see that the resource `aws_instance.web` from our Terraform code is mapped to the instance ID `i-0ad17607e5ee026d0`. + +So if Terraform state is just a file, then what is remote state? + +## Remote State + +By default, Terraform writes its state file to your local filesystem. This is okay for personal projects, but once you start working with a team, things get messy. In a team, you need to make sure everyone has an up to date version of the state file **and** ensure that two people aren't making concurrent changes. + +Enter remote state! Remote state is just storing the state file remotely, rather than on your filesystem. With remote state, there's only one copy so Terraform can ensure you're always up to date. To prevent team members from modifying state at the same time, Terraform can lock the remote state. + +> Remote state is just storing the state file remotely, rather than on your filesystem. + +Alright, so remote state is great, but unfortunately setting it up can be a bit tricky. In AWS, you can store it in an S3 bucket, but you need to create the bucket, configure it properly, set up its permissions properly, create a DynamoDB table for locking and then ensure everyone has proper credentials to write to it. It's much the same story in the other clouds. + +As a result, setting up remote state can be an annoying stumbling block as teams adopt Terraform. + +This brings us to the first reason to try HashiCorp's Free Remote State Storage... + +## Reason #1 — Easy To Set Up + +Unlike other remote state solutions that require complicated setup to get right, setting up free remote state storage is easy. + +> Setting up HashiCorp's free remote state storage is easy + +Step 1 — Sign up for your [free Terraform Cloud](https://app.terraform.io/signup) account + +Step 2 — When you log in, you'll land on this page where you'll create your organization: + +![](/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic1.webp) + +Step 3 — Next, go into User Settings and generate a token: + +![](/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic2.webp) + +Step 4 — Take this token and create a local ~/.terraformrc file: + +```tf +credentials "app.terraform.io" { + token = "mhVn15hHLylFvQ.atlasv1.jAH..." +} +``` + +Step 5 — That's it! Now you're ready to store your state. + +In your Terraform project, add a `terraform` block: + +```tf{3,5} +terraform { + backend "remote" { + organization = "my-org" # org name from step 2. + workspaces { + name = "my-app" # name for your app's state. + } + } +} +``` + +Run `terraform init` and tada! Your state is now being stored in Terraform Enterprise. You can see the state in the UI: + +![](/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic3.webp) + +Speaking of seeing state in a UI... + +## Reason #2 — Fully Featured State Viewer + +The second reason to try Terraform Cloud is its fully featured state viewer: + +![](/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic4.webp) + +If you've ever messed up your Terraform state and needed to download an old version or wanted an audit log to know who changed what, then you'll love this feature. + +You can view the full state file at each point in time: + +![](/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic5.webp) + +You can also see the diff of what changed: + +![](/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic6.webp) + +Of course, you can find a way to get this information from some of the other state backends, but it's difficult. With HashiCorp's remote state storage, you get it for free. + +## Reason #3 — Manual Locking + +The third reason to try Terraform Cloud is the ability to manually lock your state. + +Ever been working on a piece of infrastructure and wanted to ensure that no one could make any changes to it at the same time? + +Terraform Cloud comes with the ability to lock and unlock states from the UI: + +![](/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic7.webp) + +While the state is locked, `terraform` operations will receive an error: + +![](/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic8.webp) + +This saves you a lot of these: + +![](/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic9.webp) + +## Reason #4 — Works With Atlantis + +The final reason to try out Terraform Cloud is that it works flawlessly with [Atlantis](https://www.runatlantis.io/)! + +Set a `ATLANTIS_TFE_TOKEN` environment variable to a TFE token and you're ready to go. Head over to to learn more. + +Conclusion +I highly encourage you to try out the new free Remote State Storage backend. It's a compelling offering over other state backends thanks to its ease of set up, fully featured state viewer and locking capabilities. + +If you're not on the waitlist, sign up here: . diff --git a/runatlantis.io/index.md b/runatlantis.io/index.md index e1f3e90d62..537c45de24 100644 --- a/runatlantis.io/index.md +++ b/runatlantis.io/index.md @@ -15,7 +15,7 @@ hero: link: /guide - theme: alt text: What is Atlantis? - link: https://medium.com/runatlantis/introducing-atlantis-6570d6de7281 + link: /blog/2017/introducing-atlantis - theme: alt text: Join us on Slack link: https://join.slack.com/t/atlantis-community/shared_invite/zt-9xlxtxtc-CUSKB1ATt_sQy6um~LDPNw diff --git a/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic1.webp b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic1.webp new file mode 100644 index 0000000000..50d4156d52 Binary files /dev/null and b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic1.webp differ diff --git a/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic2.webp b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic2.webp new file mode 100644 index 0000000000..fe15cbf47e Binary files /dev/null and b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic2.webp differ diff --git a/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic3.webp b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic3.webp new file mode 100644 index 0000000000..b448df066d Binary files /dev/null and b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic3.webp differ diff --git a/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic4.webp b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic4.webp new file mode 100644 index 0000000000..79418e0b3e Binary files /dev/null and b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic4.webp differ diff --git a/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic5.webp b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic5.webp new file mode 100644 index 0000000000..3c0086d447 Binary files /dev/null and b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic5.webp differ diff --git a/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic6.webp b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic6.webp new file mode 100644 index 0000000000..3be25b55b5 Binary files /dev/null and b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic6.webp differ diff --git a/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic7.webp b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic7.webp new file mode 100644 index 0000000000..bf38895ebc Binary files /dev/null and b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic7.webp differ diff --git a/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic8.webp b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic8.webp new file mode 100644 index 0000000000..9220492f87 Binary files /dev/null and b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic8.webp differ diff --git a/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic9.webp b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic9.webp new file mode 100644 index 0000000000..1aaad9cc7b Binary files /dev/null and b/runatlantis.io/public/blog/4-reasons-to-try-hashicorps-new-free-terraform-remote-state-storage/pic9.webp differ diff --git a/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic1.webp b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic1.webp new file mode 100644 index 0000000000..72dbca2425 Binary files /dev/null and b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic1.webp differ diff --git a/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic2.gif b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic2.gif new file mode 100644 index 0000000000..5846753a4f Binary files /dev/null and b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic2.gif differ diff --git a/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic3.webp b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic3.webp new file mode 100644 index 0000000000..8119b862e5 Binary files /dev/null and b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic3.webp differ diff --git a/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic4.webp b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic4.webp new file mode 100644 index 0000000000..96a6eb388d Binary files /dev/null and b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic4.webp differ diff --git a/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic5.webp b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic5.webp new file mode 100644 index 0000000000..936b7a02ab Binary files /dev/null and b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic5.webp differ diff --git a/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic6.webp b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic6.webp new file mode 100644 index 0000000000..aafbc40298 Binary files /dev/null and b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic6.webp differ diff --git a/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic7.webp b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic7.webp new file mode 100644 index 0000000000..5e55af24fe Binary files /dev/null and b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic7.webp differ diff --git a/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic8.webp b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic8.webp new file mode 100644 index 0000000000..ced941c865 Binary files /dev/null and b/runatlantis.io/public/blog/atlantis-0-4-4-now-supports-bitbucket/pic8.webp differ diff --git a/runatlantis.io/public/blog/hosting-our-static-site/code/cloudfront.tf b/runatlantis.io/public/blog/hosting-our-static-site/code/cloudfront.tf new file mode 100644 index 0000000000..3f0a3a4715 --- /dev/null +++ b/runatlantis.io/public/blog/hosting-our-static-site/code/cloudfront.tf @@ -0,0 +1,59 @@ +resource "aws_cloudfront_distribution" "www_distribution" { + // origin is where CloudFront gets its content from. + origin { + // We need to set up a "custom" origin because otherwise CloudFront won't + // redirect traffic from the root domain to the www domain, that is from + // runatlantis.io to www.runatlantis.io. + custom_origin_config { + // These are all the defaults. + http_port = "80" + https_port = "443" + origin_protocol_policy = "http-only" + origin_ssl_protocols = ["TLSv1", "TLSv1.1", "TLSv1.2"] + } + + // Here we're using our S3 bucket's URL! + domain_name = "${aws_s3_bucket.www.website_endpoint}" + // This can be any name to identify this origin. + origin_id = "${var.www_domain_name}" + } + + enabled = true + default_root_object = "index.html" + + // All values are defaults from the AWS console. + default_cache_behavior { + viewer_protocol_policy = "redirect-to-https" + compress = true + allowed_methods = ["GET", "HEAD"] + cached_methods = ["GET", "HEAD"] + // This needs to match the `origin_id` above. + target_origin_id = "${var.www_domain_name}" + min_ttl = 0 + default_ttl = 86400 + max_ttl = 31536000 + + forwarded_values { + query_string = false + cookies { + forward = "none" + } + } + } + + // Here we're ensuring we can hit this distribution using www.runatlantis.io + // rather than the domain name CloudFront gives us. + aliases = ["${var.www_domain_name}"] + + restrictions { + geo_restriction { + restriction_type = "none" + } + } + + // Here's where our certificate is loaded in! + viewer_certificate { + acm_certificate_arn = "${aws_acm_certificate.certificate.arn}" + ssl_support_method = "sni-only" + } +} diff --git a/runatlantis.io/public/blog/hosting-our-static-site/code/dns.tf b/runatlantis.io/public/blog/hosting-our-static-site/code/dns.tf new file mode 100644 index 0000000000..3d1c0a4a57 --- /dev/null +++ b/runatlantis.io/public/blog/hosting-our-static-site/code/dns.tf @@ -0,0 +1,18 @@ +// We want AWS to host our zone so its nameservers can point to our CloudFront +// distribution. +resource "aws_route53_zone" "zone" { + name = "${var.root_domain_name}" +} + +// This Route53 record will point at our CloudFront distribution. +resource "aws_route53_record" "www" { + zone_id = "${aws_route53_zone.zone.zone_id}" + name = "${var.www_domain_name}" + type = "A" + + alias = { + name = "${aws_cloudfront_distribution.www_distribution.domain_name}" + zone_id = "${aws_cloudfront_distribution.www_distribution.hosted_zone_id}" + evaluate_target_health = false + } +} diff --git a/runatlantis.io/public/blog/hosting-our-static-site/code/full.tf b/runatlantis.io/public/blog/hosting-our-static-site/code/full.tf new file mode 100644 index 0000000000..c35ac47529 --- /dev/null +++ b/runatlantis.io/public/blog/hosting-our-static-site/code/full.tf @@ -0,0 +1,84 @@ +resource "aws_s3_bucket" "root" { + bucket = "${var.root_domain_name}" + acl = "public-read" + policy = <