<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: rderik</title>
    <description>The latest articles on Forem by rderik (@rderik).</description>
    <link>https://forem.com/rderik</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F199596%2F2ff2147e-c7df-4731-9125-5d153579dd93.jpeg</url>
      <title>Forem: rderik</title>
      <link>https://forem.com/rderik</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rderik"/>
    <language>en</language>
    <item>
      <title>Directory Structure for Terraform Projects</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Sun, 01 Oct 2023 10:37:00 +0000</pubDate>
      <link>https://forem.com/rderik/directory-structure-for-terraform-projects-105c</link>
      <guid>https://forem.com/rderik/directory-structure-for-terraform-projects-105c</guid>
      <description>&lt;p&gt;Terraform doesn't concern itself with the directory structure of our project. It cares about state. We, as the users of the project, are the ones who benefit from a clean and easy-to-understand directory structure.&lt;/p&gt;

&lt;p&gt;In this post, we'll explore basic directory structures used for Terraform projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you want a more in-depth discussion about the state and directory structure relationship, you might like my guide &lt;a href="https://dev.to/guides/meditations_directory_structure_tf_projects/"&gt;Meditations on Directory Structure for Terraform Projects&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Common ways to structure your directories and files for Terraform projects

&lt;ul&gt;
&lt;li&gt;Per-project boundary&lt;/li&gt;
&lt;li&gt;Per-service boundary&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;workspaces&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common ways to structure your directories and files for Terraform projects
&lt;/h2&gt;

&lt;p&gt;There are multiple ways you can structure your code, Terraform is very flexible about it, so there is no single answer to that question. But let's look at a few commong patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Per-project boundary
&lt;/h3&gt;

&lt;p&gt;A common pattern is structuring your code using the environment as the boundary for separating resources. The directory structure looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;── basic_project
    ├── environments
    │   ├── dev
    │   │   ├── main.tf
    │   │   ├── outputs.tf
    │   │   └── variables.tf
    │   ├── prod
    │   │   ├── main.tf
    │   │   ├── outputs.tf
    │   │   └── variables.tf
    │   └── staging
    │   ├── main.tf
    │   ├── outputs.tf
    │   └── variables.tf
    ├── modules
    └── shared

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure is clean and easy to understand at a glance. If you work in a specific environment, any change you make won't affect other environments. It has a couple of drawbacks. For example, we could easily add different resources to each environment, creating drift between the environments. It is good practice to keep your environments as similar as possible, so running tests in a lower environment will reflect the effects in the same way as running them in a production environment.&lt;/p&gt;

&lt;p&gt;In a clean directory structure, the code inside the environment directories (i.e. &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;staging&lt;/code&gt; and &lt;code&gt;prod&lt;/code&gt;) are primarily to reference modules. The idea is to reduce code duplication and use the modules as the source of truth of how resources should be configured and with sensible default behaviours.&lt;/p&gt;

&lt;h3&gt;
  
  
  Per-service boundary
&lt;/h3&gt;

&lt;p&gt;When the number of resources is high, some teams break down the directory structure into smaller areas of interest. For example, split the directory structure by service. The file structure would look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;── service_A
    └── environments
        ├── dev
        │   ├── main.tf
        │   ├── outputs.tf
        │   └── variables.tf
        ├── prod
        │   ├── main.tf
        │   ├── outputs.tf
        │   └── variables.tf
        └── staging
        ├── main.tf
        ├── outputs.tf
        └── variables.tf

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are observant, you'll notice that the directory structure is basically the same as the previous one. Breaking down into smaller areas is similar to breaking it down by project. The idea stays the same: create a boundary to hold certain resources.&lt;/p&gt;

&lt;p&gt;Depending on the number of resources, the per-project structure might start causing your &lt;code&gt;plan&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; commands to take a lot of time. The reason is that Terraform has to query the AWS API to check the state of the resources it is tracking. So, a larger number of resources will lead to more API calls.&lt;/p&gt;

&lt;p&gt;There are other reasons why we might need to segregate the state:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High Number of resources, we already mentioned this&lt;/li&gt;
&lt;li&gt;Using different AWS accounts per environment&lt;/li&gt;
&lt;li&gt;Breaking state per region. Projects sometimes segregate their state per region to:

&lt;ul&gt;
&lt;li&gt;Reduce blast radius if a region is down&lt;/li&gt;
&lt;li&gt;Deployment strategies that would prefer to only deploy to certain regions for testing, i.e. canary deployments
&amp;lt;!-- vim-markdown-toc Redcarpet --&amp;gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;workspaces&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Another common alternative for the per-project directory structure is using &lt;code&gt;workspaces&lt;/code&gt;. This structure maintains the same code for all environments, reducing the possibility of differences between environments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;── single_code_multiple_var
    ├── infra
    │   ├── main.tf
    │   ├── provider.tf
    │   ├── outputs.tf
    │  └── variables.tf
    ├─── environments
    │   ├── env.dev.tfvars
    │   ├── env.staging.tfvars
    │  └── env.prod.tfvars
    └── modules

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are still cases where we would like different behaviours per environment. For example, using smaller instance types for lower-level environments and larger instance types for production. To reflect that difference, we use different values in &lt;code&gt;tfvars&lt;/code&gt; files that will capture the differences. This directory structure and workflow are OK if you are OK with having the same backend for all the workspaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  backend "s3" { &amp;lt;--- we can't use variable interpolation, so we can't do the following
    region = "${local.env[var.enviroment]}"
    bucket = "rderik-tfstate-${var.environment}"
    key = "${var.environment}/tfstate/terraform.tfstate"
    dynamodb_table = "rderik-tfstate-${var.environment}"
    encrypt = true
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If, for some reason, we need to use a different backend per environment, then we have to solve the problem with the &lt;code&gt;backend&lt;/code&gt;, which has its own set of peculiarities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The directory structure that we end up using for our project is highly dependent on how we want to manage the state of our project. Consider if you want to keep one state per project, service, region, etc. The key to deciding which directory structure to use in your project is for you to understand the relationship between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;State&lt;/li&gt;
&lt;li&gt;Directory structure&lt;/li&gt;
&lt;li&gt;Backend&lt;/li&gt;
&lt;li&gt;Module versions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you clearly understand how you want to handle those aspects of your project, it'll be easier to choose the directory structure that will make your life easier. But don't worry too much about it. It is OK to start with one structure and later understand that you have outgrown that structure and migrate out of it. Believing you'll have all the answers from the beginning is a common mistake.&lt;/p&gt;

&lt;p&gt;Software projects are iterative. You keep growing and you keep adapting that is the nature of our work.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
    </item>
    <item>
      <title>How to set up a new Terraform project using S3 backend and DynamoDB locking</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Sat, 08 Oct 2022 12:34:00 +0000</pubDate>
      <link>https://forem.com/rderik/how-to-set-up-a-new-terraform-project-using-s3-backend-and-dynamodb-locking-19mg</link>
      <guid>https://forem.com/rderik/how-to-set-up-a-new-terraform-project-using-s3-backend-and-dynamodb-locking-19mg</guid>
      <description>&lt;p&gt;Sometimes it feels easier to work on complex and challenging tasks with our tools. We forget how to do the simple initial steps for a project. The reason for this is that we lack practice starting projects. If you work for a company, you'll probably set up your Infrastructure as Code (IaC) once and then iterate for it. Unless you work on a consultancy or start projects just for fun, you might forget the initial steps to set up a project.&lt;/p&gt;

&lt;p&gt;This post is about setting up a Terraform project storing the TFState using an S3 bucket and using DynamoDB as our lock mechanism to help prevent issues when two people are working on the same infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you are interested in learning more about how to set up the directory structure for your Terraform project, you might find my guide, &lt;a href="https://rderik.com/guides/meditations_directory_structure_tf_projects"&gt;Meditations on Directory Structure for Terraform Projects&lt;/a&gt;, useful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The chicken and egg problem of setting up resources before the state&lt;/li&gt;
&lt;li&gt;Creating the resources storing the state locally&lt;/li&gt;
&lt;li&gt;Set up our backend to use S3 and DynamoDB&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The chicken and egg problem of setting up resources before the state
&lt;/h2&gt;

&lt;p&gt;It should be a straightforward process to start a Terraform project. Set the state to be stored in an S3 bucket and DynamoDB to keep the lock. But the problem begins when we realise that those resources, the S3 bucket and the DynamoDB table, won't be tracked by Terraform. We would also like to keep track of those resources in our IaC; we don't want them to be an exception. So what do you do? Do you create them manually and then later import them? While I believe you could do that, there might be a better way.&lt;/p&gt;

&lt;p&gt;First, create the resources using the local state, then migrate the state to S3 and DynamoDB. That is a simple idea, so let's do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the resources storing the state locally
&lt;/h2&gt;

&lt;p&gt;Using the following code, let's define the initial template for creating the S3 bucket and the DynamoDB table. We will create a bucket called &lt;code&gt;my-terraform-state&lt;/code&gt; and a table called &lt;code&gt;my-terraform-lock&lt;/code&gt;. You can name yours however works for you. Create a file named &lt;code&gt;main.tf&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  region = "us-west-1"
}

#terraform {
# backend "s3" {
# region = "us-west-1"
# bucket = "my-terraform-state"
# key = "global/tfstate/terraform.tfstate"
# dynamodb_table = "my-terraform-lock"
# encrypt = true
# }
#}

resource "aws_s3_bucket" "my-terraform-state" {
  bucket = "my-terraform-state"
  acl = "private"
}

resource "aws_dynamodb_table" "my-terraform-lock" {
  name = "my-terraform-lock"
  billing_mode = "PAY_PER_REQUEST"
  hash_key = "LockID"
  attribute {
    name = "LockID"
    type = "S"
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll notice that there is some commented-out code. We usually would use that to tell Terraform to keep the state in S3 and to use DynamoDB for locking. We will use that code, but not just now.&lt;/p&gt;

&lt;p&gt;With our &lt;code&gt;main.tf&lt;/code&gt; file created, we can run &lt;code&gt;terraform init&lt;/code&gt;, this will create the state locally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform init

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the state, we can apply the template and create the bucket and table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform apply

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect, we now have the table and table created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up our backend to use S3 and DynamoDB
&lt;/h2&gt;

&lt;p&gt;Now we remove the comments on the code that defines our backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  backend "s3" {
    region = "us-west-1"
    bucket = "my-terraform-state"
    key = "global/tfstate/terraform.tfstate"
    dynamodb_table = "my-terraform-lock"
    encrypt = true
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save &lt;code&gt;main.tf&lt;/code&gt; and run terraform init again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform init

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it, you are ready!&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This was a short and simple post, but I hope it is useful. I've had this question before, and it is nice to have a quick article to point to instead of trying to remember how I did it the first time.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Creating network applications in macOS</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Mon, 14 Sep 2020 12:51:13 +0000</pubDate>
      <link>https://forem.com/rderik/creating-network-applications-in-macos-3cj</link>
      <guid>https://forem.com/rderik/creating-network-applications-in-macos-3cj</guid>
      <description>&lt;p&gt;I finally completed my "macOS network programming in Swift" guide. You can get it from &lt;a href="https://rderik.com/guides/"&gt;my site&lt;/a&gt;. The guide covers how to use the following libraries and frameworks to build network applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;BSD Sockets&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Network.framework&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;SwiotNIO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have a look and share with anyone that might find it useful. The guides on my site are free, but if you want to support me, you can pay anything you want.&lt;/p&gt;

&lt;p&gt;Here's the link:&lt;br&gt;
&lt;a href="https://rderik.com/guides/"&gt;rderik.com - Guides&lt;/a&gt;&lt;/p&gt;

</description>
      <category>swift</category>
    </item>
    <item>
      <title>Using SwiftNIO to build a simple Server</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Thu, 20 Aug 2020 21:12:01 +0000</pubDate>
      <link>https://forem.com/rderik/using-swiftnio-to-build-a-simple-server-e77</link>
      <guid>https://forem.com/rderik/using-swiftnio-to-build-a-simple-server-e77</guid>
      <description>&lt;p&gt;If you haven't heard about &lt;a href="https://github.com/apple/swift-nio"&gt;SwiftNIO&lt;/a&gt;, it is a framework with the primary purpose of building network applications. It takes a lot of the responsibility for the network code of your application so you can focus on the application code.&lt;/p&gt;

&lt;p&gt;If you are interested in Server-Side Swift, you might find this post interesting:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rderik.com/blog/understanding-swiftnio-by-building-a-text-modifying-server/"&gt;Understanding SwiftNIO by building a text modifying server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback is welcomed.&lt;/p&gt;

</description>
      <category>swift</category>
    </item>
    <item>
      <title>Building a text-based clock using Swift</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Thu, 06 Aug 2020 21:22:38 +0000</pubDate>
      <link>https://forem.com/rderik/building-a-text-based-clock-using-swift-277j</link>
      <guid>https://forem.com/rderik/building-a-text-based-clock-using-swift-277j</guid>
      <description>&lt;p&gt;If you are looking for a fun project to get into command-line tools development, I think you'll enjoy this article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rderik.com/blog/building-a-text-based-application-using-swift-and-ncurses/"&gt;https://rderik.com/blog/building-a-text-based-application-using-swift-and-ncurses/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It uses the C &lt;code&gt;ncurses(3)&lt;/code&gt; library via &lt;code&gt;SwiftCursesTerm&lt;/code&gt; to create a clock modelled as a 7-segment display.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--egpoPVmE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e1vtxootoz5erle9pjsl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--egpoPVmE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e1vtxootoz5erle9pjsl.png" alt="text-based clock application"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope you like it.&lt;/p&gt;

</description>
      <category>swift</category>
    </item>
    <item>
      <title>A command-line tool to create your GitHub profile using a template</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Tue, 21 Jul 2020 18:26:21 +0000</pubDate>
      <link>https://forem.com/rderik/a-command-line-tool-to-create-your-github-profile-using-a-template-1ci3</link>
      <guid>https://forem.com/rderik/a-command-line-tool-to-create-your-github-profile-using-a-template-1ci3</guid>
      <description>&lt;p&gt;As you might have noticed, you can now create a &lt;a href="https://dev.to/web/design-github-profile-using-readme-md-8al"&gt;GitHub profile&lt;/a&gt; by creating a repository with the same name as your GitHub username. I wanted to add content that changes often, but I didn't want to do it manually. So I created &lt;a href="https://github.com/rderik/octoprofile"&gt;Octoprofile&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Octoprofile is a small command-line tool that allows you to build your GitHub Profile using a template, and you can extend the template by using plugins. The plugin system is quite simple, but that's the point, anyone can extend it and create their own plugins.&lt;/p&gt;

&lt;p&gt;The tool is open-source, and the point is to help others. If you are a beginner and want to contribute, I think this project is an excellent place to start.&lt;/p&gt;

&lt;p&gt;Ok, I hope it is helpful. Here is the link to the GitHub repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rderik/octoprofile"&gt;https://github.com/rderik/octoprofile&lt;/a&gt;&lt;/p&gt;

</description>
      <category>swift</category>
      <category>commandline</category>
      <category>github</category>
    </item>
    <item>
      <title>Generating a table of contents with anchors for markdown - Vim plugin</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Mon, 20 Jul 2020 12:30:39 +0000</pubDate>
      <link>https://forem.com/rderik/generating-a-table-of-contents-with-anchors-for-markdown-vim-plugin-15ba</link>
      <guid>https://forem.com/rderik/generating-a-table-of-contents-with-anchors-for-markdown-vim-plugin-15ba</guid>
      <description>&lt;p&gt;I use vim as my editor and markdown to write the articles for my site. I think that the articles are easier to navigate when they have a table of contents.&lt;/p&gt;

&lt;p&gt;Adding a table of contents was easy. Many plugins accomplish this. But I couldn't find a plugin that also added the anchors. And adding the anchors was a very tedious process. So I modified the &lt;a href="https://github.com/mzlogin/vim-markdown-toc"&gt;vim-markdown-toc&lt;/a&gt; plugin to add the anchors.&lt;/p&gt;

&lt;p&gt;If you are looking to do the same, I  wrote a short post on how to do it with my modified version of the plugin. You can read about it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rderik.com/notes/generate-table-of-contents-with-anchors-for-markdown-file-vim-plugin/"&gt;https://rderik.com/notes/generate-table-of-contents-with-anchors-for-markdown-file-vim-plugin/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope you find it useful.&lt;/p&gt;

</description>
      <category>vim</category>
      <category>markdown</category>
      <category>plugin</category>
    </item>
    <item>
      <title>Creating a composable command-line tool using the Swift Argument Parser</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Thu, 09 Jul 2020 12:07:52 +0000</pubDate>
      <link>https://forem.com/rderik/creating-a-composable-command-line-tool-using-the-swift-argument-parser-190f</link>
      <guid>https://forem.com/rderik/creating-a-composable-command-line-tool-using-the-swift-argument-parser-190f</guid>
      <description>&lt;p&gt;Most of us make use of command-line tools that are composable, like &lt;code&gt;sed(1)&lt;/code&gt;, &lt;code&gt;grep(1)&lt;/code&gt;, &lt;code&gt;sort(1)&lt;/code&gt;. Not all tools use the same conventions for working with input from the standard input(STDIN). But it's certainly handy when they do.&lt;/p&gt;

&lt;p&gt;Apple &lt;a href="https://swift.org/blog/argument-parser/"&gt;announced on February 2020&lt;/a&gt; the &lt;a href="https://github.com/apple/swift-argument-parser"&gt;Swift Argument Parser&lt;/a&gt;. It provides an easy to use parsing capability, and their &lt;a href="https://github.com/apple/swift-argument-parser/tree/master/Documentation"&gt;documentation&lt;/a&gt;is good. But as many examples on the Internet about building command-line tools, they focus on self-contained applications.&lt;/p&gt;

&lt;p&gt;I thought it might be useful to show how to create a composable command-line tool. A composable command-line tool allows you to create a workflow between different tools. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Name:*"&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.txt | &lt;span class="nb"&gt;sort&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are using two tools here &lt;code&gt;grep(1)&lt;/code&gt;(To search for the pattern &lt;code&gt;Name:*&lt;/code&gt; on all files with a &lt;code&gt;.txt&lt;/code&gt; extension) and &lt;code&gt;sort(1)&lt;/code&gt;. Each of the commands can be used on their own, but when we put them together, we can create complex workflows that easily solve our problem. The idea is redirecting the Standard Output(STDOUT) of one command and use it as the Standard Input(STDIN) of the second command using a pipe &lt;code&gt;|&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we want to make our command-line tool composable, we would like to support the following cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the tool is called without any parameters it'll try to read from the STDIN.&lt;/li&gt;
&lt;li&gt;If the tool's last argument is a single dash (&lt;code&gt;-&lt;/code&gt;) read from the STDIN.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same way as &lt;code&gt;sort(1)&lt;/code&gt; or other Unix command-line tools work. &lt;/p&gt;

&lt;p&gt;we can call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;file.txt | &lt;span class="nb"&gt;sort&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or we can call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sort &lt;/span&gt;file.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are interested in how to build a command-line tool that is composable using the Swift Argument Parser, you might find the following post interesting:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rderik.com/blog/understanding-the-swift-argument-parser-and-working-with-stdin/"&gt;https://rderik.com/blog/understanding-the-swift-argument-parser-and-working-with-stdin/&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;As always, feedback is welcomed.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>commandline</category>
      <category>tools</category>
    </item>
    <item>
      <title>Jails &amp; VNET a Guide</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Fri, 19 Jun 2020 21:41:30 +0000</pubDate>
      <link>https://forem.com/rderik/jails-vnet-a-guide-3a2n</link>
      <guid>https://forem.com/rderik/jails-vnet-a-guide-3a2n</guid>
      <description>&lt;p&gt;I was working with jails in FreeBSD and wanted to model the infrastructure using jails and virtual networks. This project led me through a learning journey on how to use vnets and jails. Vnets were useful for jail isolation at the network level.&lt;/p&gt;

&lt;p&gt;I ended up writing a guide for anyone that needs it. If you are interested, you can get the guide here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rderik.com/guides/"&gt;https://rderik.com/guides/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get the guide in different formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ePub&lt;/li&gt;
&lt;li&gt;Mobi&lt;/li&gt;
&lt;li&gt;PDF&lt;/li&gt;
&lt;li&gt;Plain text&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also include the source code. The plain text is handy when you would like to copy any command in the examples.&lt;/p&gt;

&lt;p&gt;The guide is free, but if you would like to support my work, you can pay anything you want. In any case, I hope you find it useful.&lt;/p&gt;

</description>
      <category>freebsd</category>
      <category>jail</category>
      <category>virtualnetwork</category>
      <category>virtualization</category>
    </item>
    <item>
      <title>Deciding on a FreeBSD partition schema</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Mon, 01 Jun 2020 23:09:16 +0000</pubDate>
      <link>https://forem.com/rderik/deciding-on-a-freebsd-partition-schema-2lia</link>
      <guid>https://forem.com/rderik/deciding-on-a-freebsd-partition-schema-2lia</guid>
      <description>&lt;p&gt;Lately, I've been playing around with FreeBSD. I remembered the first few times I had to partition a disk a long time ago. I spent a lot of time researching what other people did and talking with friends about it. &lt;/p&gt;

&lt;p&gt;It is not a complicated process, but because I didn't do it often, I had to re-learn what I've done every time. Now I'm mostly using ZF which kind of makes partitioning a single disk not necessary. But I wanted to write down my notes on partitioning a disk using UFS if I had to do it again.&lt;/p&gt;

&lt;p&gt;I'm following the advice in &lt;a href="https://nostarch.com/absfreebsd3"&gt;Absolute FreeBSD, 3rd edition&lt;/a&gt;, and create the following partitions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;efi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;swap&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dump&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/tmp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/var&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/usr&lt;/code&gt; (I'm keeping my &lt;code&gt;home&lt;/code&gt; directory under &lt;code&gt;/usr&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I believe that is a solid "classic" partitioning schema that I find useful and clean. And from this base, and depending on the system I'm deploying, I'll add new partitions. For example, a partition for &lt;code&gt;/database&lt;/code&gt; if I'm running a server dedicated to PostgreSQL.&lt;/p&gt;

&lt;p&gt;Anyhow, if you are interested in more detail here is the link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rderik.com/notes/notes-on-freebsd-ufs-partition-schema/"&gt;https://rderik.com/notes/notes-on-freebsd-ufs-partition-schema/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would also recommend the book &lt;a href="https://nostarch.com/absfreebsd3"&gt;Absolute FreeBSD, 3rd edition&lt;/a&gt;, quite enjoyable. I learned a lot from it.&lt;/p&gt;

</description>
      <category>freebsd</category>
      <category>disks</category>
      <category>partitions</category>
      <category>ufs</category>
    </item>
    <item>
      <title>Using a simple Bash script to increase your iOS bundle version</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Tue, 26 May 2020 14:42:47 +0000</pubDate>
      <link>https://forem.com/rderik/using-a-simple-bash-script-to-increase-your-ios-bundle-version-6fg</link>
      <guid>https://forem.com/rderik/using-a-simple-bash-script-to-increase-your-ios-bundle-version-6fg</guid>
      <description>&lt;p&gt;Last week I got a message from someone using a tool I created for myself called &lt;code&gt;XCIncreaseBuildVersion&lt;/code&gt;. I created this script that increases the bundle version in preparation for uploading my app to App Store Connect. &lt;/p&gt;

&lt;p&gt;It's always satisfying to see your tools help someone. &lt;/p&gt;

&lt;p&gt;The script searches the &lt;code&gt;Info.plist&lt;/code&gt; files and increases the build version number using &lt;code&gt;plutil(1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you are interested in the tool you can find it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rderik/xcibversion/"&gt;https://github.com/rderik/xcibversion/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to check the whole article that explains the logic behind the automation of the process, and how to upload the &lt;code&gt;xarchive&lt;/code&gt; to App Store Connect, you can find it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rderik.com/blog/automating-build-and-testflight-upload-for-simple-ios-apps/"&gt;https://rderik.com/blog/automating-build-and-testflight-upload-for-simple-ios-apps/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Who knows, maybe it can also help you in your CI/CD pipeline.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>devops</category>
      <category>bash</category>
      <category>commandline</category>
    </item>
    <item>
      <title>Record your terminal session using the `script`command.</title>
      <dc:creator>rderik</dc:creator>
      <pubDate>Mon, 25 May 2020 22:34:43 +0000</pubDate>
      <link>https://forem.com/rderik/record-your-terminal-session-using-the-script-command-g1i</link>
      <guid>https://forem.com/rderik/record-your-terminal-session-using-the-script-command-g1i</guid>
      <description>&lt;p&gt;I've been in the situation where I ran a script that behaved weirdly and would love to be able to "replay" what I did to figure out what went wrong. A useful command for those cases is &lt;code&gt;script(1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;script&lt;/code&gt; command (&lt;a href="https://en.wikipedia.org/wiki/Script_(Unix)"&gt;introduced in 1979&lt;/a&gt;) allows you to record a terminal session to a file. You can later check and reference that file to analyse it as you please. Or maybe record your terminal as a demo.&lt;/p&gt;

&lt;p&gt;As with any other Unix command, the power comes from your creativity on how to use it. You can use &lt;code&gt;script&lt;/code&gt; to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Record a demo.&lt;/li&gt;
&lt;li&gt;Capture output.&lt;/li&gt;
&lt;li&gt;Record session to report a bug.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can try it just by typing &lt;code&gt;script&lt;/code&gt; in your terminal. It opens up a new shell that will be recorded. By default, the session is saved in a file named &lt;code&gt;typescript&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;script
% &lt;span class="nb"&gt;ls&lt;/span&gt;
% &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then view the capture by using &lt;code&gt;cat(1)&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are interested in more detail, here are my notes on how to use it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rderik.com/notes/using-the-script-command-to-record-a-terminal-session/"&gt;https://rderik.com/notes/using-the-script-command-to-record-a-terminal-session/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bash</category>
      <category>terminal</category>
      <category>commandline</category>
    </item>
  </channel>
</rss>
