{"id":48686,"date":"2025-03-12T02:33:05","date_gmt":"2025-03-12T02:33:05","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=48686"},"modified":"2025-03-12T02:33:05","modified_gmt":"2025-03-12T02:33:05","slug":"terraform-tutorials-tflint-covering-installation-configuration-usage","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/terraform-tutorials-tflint-covering-installation-configuration-usage\/","title":{"rendered":"Terraform Tutorials: TFLint, covering installation, configuration, usage"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Comprehensive Guide to TFLint<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction to TFLint<\/h2>\n\n\n\n<p>TFLint is an open-source <strong>Terraform linter<\/strong> (static analysis tool) that checks Terraform configurations for errors, potential bugs, and stylistic or best-practice violations. It helps developers identify issues that Terraform&#8217;s built-in validation (<code>terraform validate<\/code>) might not catch, especially provider-specific problems like invalid AWS instance types or missing required Terraform versions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Key Benefits of TFLint:<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Early Error Detection<\/strong> \u2013 Catches issues before deployment, preventing costly failures.<\/li>\n\n\n\n<li><strong>Best Practice Enforcement<\/strong> \u2013 Ensures configurations align with Terraform and provider recommendations.<\/li>\n\n\n\n<li><strong>Security &amp; Compliance Checks<\/strong> \u2013 Detects security risks like open security groups.<\/li>\n\n\n\n<li><strong>CI\/CD Integration<\/strong> \u2013 Works in development workflows to maintain high-quality infrastructure as code (IaC).<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Installation<\/h2>\n\n\n\n<p>TFLint is available for macOS, Linux, and Windows. You can install it using package managers or download the binary.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">macOS (Homebrew):<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">brew install tflint\n<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Linux:<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">curl -s https:<span class=\"hljs-comment\">\/\/raw.githubusercontent.com\/terraform-linters\/tflint\/master\/install_linux.sh | bash<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Alternatively, install it via Snap:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">sudo snap install tflint\n<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Windows (Chocolatey):<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">choco install tflint\n<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Docker (Alternative):<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">docker run --rm -v $(pwd):<span class=\"hljs-regexp\">\/data -t ghcr.io\/<\/span>terraform-linters\/tflint\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Verify Installation:<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">tflint --version\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Basic Usage<\/h2>\n\n\n\n<p>TFLint is straightforward to use. Navigate to your Terraform project directory and run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">tflint\n<\/code><\/span><\/pre>\n\n\n<p>If using provider-specific rules, initialize plugins first:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">tflint --init\n<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Example Output:<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-number\">1<\/span> issue(s) found:\nWarning: terraform <span class=\"hljs-string\">\"required_version\"<\/span> attribute is required.\n\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here is the <strong>normal table<\/strong> representation of the <code>tflint --help<\/code> options:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th><strong>Option<\/strong><\/th><th><strong>Description<\/strong><\/th><\/tr><\/thead><tbody><tr><td><code>-v, --version<\/code><\/td><td>Print TFLint version<\/td><\/tr><tr><td><code>--init<\/code><\/td><td>Install plugins<\/td><\/tr><tr><td><code>--langserver<\/code><\/td><td>Start language server<\/td><\/tr><tr><td>`-f, &#8211;format=[default<\/td><td>json<\/td><\/tr><tr><td><code>-c, --config=FILE<\/code><\/td><td>Config file name (default: .tflint.hcl)<\/td><\/tr><tr><td><code>--ignore-module=SOURCE<\/code><\/td><td>Ignore module sources<\/td><\/tr><tr><td><code>--enable-rule=RULE_NAME<\/code><\/td><td>Enable rules from the command line<\/td><\/tr><tr><td><code>--disable-rule=RULE_NAME<\/code><\/td><td>Disable rules from the command line<\/td><\/tr><tr><td><code>--only=RULE_NAME<\/code><\/td><td>Enable only this rule, disabling all others (can be specified multiple times)<\/td><\/tr><tr><td><code>--enable-plugin=PLUGIN_NAME<\/code><\/td><td>Enable plugins from the command line<\/td><\/tr><tr><td><code>--var-file=FILE<\/code><\/td><td>Terraform variable file name<\/td><\/tr><tr><td><code>--var='foo=bar'<\/code><\/td><td>Set a Terraform variable<\/td><\/tr><tr><td>`&#8211;call-module-type=[all<\/td><td>local<\/td><\/tr><tr><td><code>--chdir=DIR<\/code><\/td><td>Switch to a different working directory before executing the command<\/td><\/tr><tr><td><code>--recursive<\/code><\/td><td>Run command in each directory recursively<\/td><\/tr><tr><td><code>--filter=FILE<\/code><\/td><td>Filter issues by file names or globs<\/td><\/tr><tr><td><code>--force<\/code><\/td><td>Return zero exit status even if issues are found<\/td><\/tr><tr><td>`&#8211;minimum-failure-severity=[error<\/td><td>warning<\/td><\/tr><tr><td><code>--color<\/code><\/td><td>Enable colorized output<\/td><\/tr><tr><td><code>--no-color<\/code><\/td><td>Disable colorized output<\/td><\/tr><tr><td><code>--fix<\/code><\/td><td>Fix issues automatically<\/td><\/tr><tr><td><code>--no-parallel-runners<\/code><\/td><td>Disable per-runner parallelism<\/td><\/tr><tr><td><code>--max-workers=N<\/code><\/td><td>Set maximum number of workers in recursive inspection (default: number of CPUs)<\/td><\/tr><tr><td><code>-h, --help<\/code><\/td><td>Show this help message<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>This table provides a <strong>clean and structured reference<\/strong> for <strong>TFLint<\/strong> command-line options. \ud83d\ude80 Let me know if you need any modifications!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configuration<\/h2>\n\n\n\n<p>TFLint can be customized using a <code>.tflint.hcl<\/code> configuration file.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Example <code>.tflint.hcl<\/code> Configuration:<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">tflint {\n  required_version = <span class=\"hljs-string\">\"&gt;= 0.50\"<\/span>\n}\n\nconfig {\n  format = <span class=\"hljs-string\">\"compact\"<\/span>\n  plugin_dir = <span class=\"hljs-string\">\"~\/.tflint.d\/plugins\"<\/span>\n  call_module_type = <span class=\"hljs-string\">\"local\"<\/span>\n}\n\nplugin <span class=\"hljs-string\">\"aws\"<\/span> {\n  enabled = <span class=\"hljs-literal\">true<\/span>\n  version = <span class=\"hljs-string\">\"0.4.0\"<\/span>\n  source  = <span class=\"hljs-string\">\"github.com\/terraform-linters\/tflint-ruleset-aws\"<\/span>\n}\n\nrule <span class=\"hljs-string\">\"terraform_required_version\"<\/span> {\n  enabled = <span class=\"hljs-literal\">false<\/span>\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Rules and Plugins<\/h2>\n\n\n\n<p>TFLint has built-in Terraform language rules and provider-specific plugins.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Built-in Rules:<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Required Terraform Version<\/strong> \u2013 Ensures <code>required_version<\/code> is defined.<\/li>\n\n\n\n<li><strong>Type Constraints<\/strong> \u2013 Checks explicit type constraints on variables.<\/li>\n\n\n\n<li><strong>Deprecated Syntax<\/strong> \u2013 Flags usage of removed Terraform features.<\/li>\n\n\n\n<li><strong>Unused Declarations<\/strong> \u2013 Identifies unused variables and outputs.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Provider Plugins:<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>AWS Plugin<\/strong> \u2013 Checks instance types, security group configurations, and more.<\/li>\n\n\n\n<li><strong>Azure Plugin<\/strong> \u2013 Validates Azure-specific configurations.<\/li>\n\n\n\n<li><strong>GCP Plugin<\/strong> \u2013 Ensures Google Cloud best practices.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Enabling a Plugin:<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">plugin <span class=\"hljs-string\">\"aws\"<\/span> {\n  enabled = <span class=\"hljs-literal\">true<\/span>\n  version = <span class=\"hljs-string\">\"0.24.1\"<\/span>\n  source  = <span class=\"hljs-string\">\"github.com\/terraform-linters\/tflint-ruleset-aws\"<\/span>\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">tflint --init\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">CI\/CD Integration<\/h2>\n\n\n\n<p>TFLint should be incorporated into CI\/CD pipelines to enforce Terraform quality standards.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">GitHub Actions Example:<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">jobs:\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n      - run: tflint --init\n      - run: tflint\n<\/code><\/span><\/pre>\n\n\n<h3 class=\"wp-block-heading\">GitLab CI Example:<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">lint:terraform:\n  image: terraform-linters\/tflint:latest\n  script:\n    - tflint --init\n    - tflint\n<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Best Practices<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Run TFLint Early<\/strong> \u2013 Use it during development, not just in CI\/CD.<\/li>\n\n\n\n<li><strong>Customize Rules<\/strong> \u2013 Enable or disable rules in <code>.tflint.hcl<\/code> based on project needs.<\/li>\n\n\n\n<li><strong>Use Provider Plugins<\/strong> \u2013 AWS, Azure, and GCP plugins catch cloud-specific issues.<\/li>\n\n\n\n<li><strong>Inline Rule Ignoring<\/strong> \u2013 Use <code># tflint-ignore: rule_name<\/code> for exceptions.<\/li>\n\n\n\n<li><strong>Enforce in CI\/CD<\/strong> \u2013 Make TFLint a required step before merging code.<\/li>\n\n\n\n<li><strong>Keep TFLint Updated<\/strong> \u2013 Regularly update TFLint and its plugins.<\/li>\n\n\n\n<li><strong>Combine with Other Tools<\/strong> \u2013 Use it alongside <code>terraform fmt<\/code>, <code>terraform validate<\/code>, and security scanners like <code>tfsec<\/code>.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>TFLint is an essential tool for ensuring Terraform code quality, catching errors early, enforcing best practices, and integrating seamlessly into CI\/CD workflows. Implement it in your Terraform projects to maintain consistent and error-free infrastructure as code.<\/p>\n\n\n\n<p>Here&#8217;s a comprehensive tutorial for using TFLint, a powerful linter for Terraform code:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installation<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Install TFLint using one of the following methods:<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>macOS: <code>brew install tflint<\/code><\/li>\n\n\n\n<li>Windows: <code>choco install tflint<\/code><\/li>\n\n\n\n<li>Linux: <code>curl -s https:\/\/raw.githubusercontent.com\/terraform-linters\/tflint\/master\/install_linux.sh | bash<\/code><a href=\"https:\/\/www.terraformpilot.com\/articles\/debugging-with-tflint\/\" target=\"_blank\" rel=\"noreferrer noopener\">1<\/a><a href=\"https:\/\/github.com\/terraform-linters\/tflint\" target=\"_blank\" rel=\"noreferrer noopener\">3<\/a><\/li>\n<\/ul>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>Verify the installation by running: text<code>tflint --version<\/code><\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Setup and Configuration<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Navigate to your Terraform project directory.<\/li>\n\n\n\n<li>Create a <code>.tflint.hcl<\/code> configuration file in your project root: text<code>plugin \"terraform\" { enabled = true preset = \"recommended\" }<\/code><\/li>\n\n\n\n<li>Initialize TFLint in your project: text<code>tflint --init<\/code> This command will download and install necessary plugins based on your configuration<a href=\"https:\/\/www.terraformpilot.com\/articles\/debugging-with-tflint\/\" target=\"_blank\" rel=\"noreferrer noopener\">1<\/a>.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Using TFLint<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Run TFLint in your project directory: text<code>tflint<\/code> This will scan your Terraform files and report any issues it finds<a href=\"https:\/\/www.terraformpilot.com\/articles\/debugging-with-tflint\/\" target=\"_blank\" rel=\"noreferrer noopener\">1<\/a>.<\/li>\n\n\n\n<li>For a more detailed report, use the JSON format: text<code>tflint --format=json<\/code><\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Adding Cloud Provider Plugins<\/h2>\n\n\n\n<p>To lint configurations for specific cloud providers, add the relevant plugins to your <code>.tflint.hcl<\/code> file:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>plugin \"aws\" {\n  enabled = true\n  version = \"0.24.0\"\n  source  = \"github.com\/terraform-linters\/tflint-ruleset-aws\"\n}\n\nplugin \"azurerm\" {\n  enabled = true\n  version = \"0.24.0\"\n  source  = \"github.com\/terraform-linters\/tflint-ruleset-azurerm\"\n}\n<\/code><\/pre>\n\n\n\n<p>After adding plugins, run <code>tflint --init<\/code> again to download and install them<a target=\"_blank\" rel=\"noreferrer noopener\" href=\"https:\/\/spacelift.io\/blog\/what-is-tflint\">2<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Advanced Usage<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>To run TFLint recursively in subdirectories: text<code>tflint --recursive<\/code><\/li>\n\n\n\n<li>To enable specific rules from the command line: text<code>tflint --enable-rule=aws_resource_missing_tags<\/code><\/li>\n\n\n\n<li>To disable specific rules: text<code>tflint --disable-rule=terraform_deprecated_syntax<\/code><\/li>\n\n\n\n<li>To use a custom configuration file: text<code>tflint --config=custom_tflint.hcl<\/code><\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Integrating with CI\/CD<\/h2>\n\n\n\n<p>For GitHub Actions, you can use the setup-tflint action:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>- uses: terraform-linters\/setup-tflint@v3\n  name: Setup TFLint\n- run: tflint\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Docker Usage<\/h2>\n\n\n\n<p>If you prefer using Docker, you can run TFLint without installation:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>docker run --rm -v $(pwd):\/data -t ghcr.io\/terraform-linters\/tflint\n<\/code><\/pre>\n\n\n\n<p>To download plugins and run TFLint in a single command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">text<code>docker run --rm -v $(pwd):\/data -t --entrypoint \/bin\/sh ghcr.io\/terraform-linters\/tflint -c \"tflint --init &amp;&amp; tflint\"\n<\/code><\/pre>\n\n\n\n<p>By following this tutorial, you&#8217;ll be able to effectively use TFLint to improve the quality and reliability of your Terraform code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><\/h3>\n","protected":false},"excerpt":{"rendered":"<p>Comprehensive Guide to TFLint Introduction to TFLint TFLint is an open-source Terraform linter (static analysis tool) that checks Terraform configurations for errors, potential bugs, and stylistic or best-practice violations. It&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-48686","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/48686","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=48686"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/48686\/revisions"}],"predecessor-version":[{"id":48728,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/48686\/revisions\/48728"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=48686"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=48686"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=48686"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}