<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>Practical System Administration</title>
	<atom:link href="https://thepracticalsysadmin.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://thepracticalsysadmin.com</link>
	<description></description>
	<lastBuildDate>Tue, 01 Dec 2020 14:26:10 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2.9</generator>
<site xmlns="com-wordpress:feed-additions:1">116720332</site>	<item>
		<title>Create Windows Server 2019 AMIs using Packer</title>
		<link>https://thepracticalsysadmin.com/create-windows-server-2019-amis-using-packer/</link>
					<comments>https://thepracticalsysadmin.com/create-windows-server-2019-amis-using-packer/#comments</comments>
		
		<dc:creator><![CDATA[Josh Reichardt]]></dc:creator>
		<pubDate>Tue, 01 Dec 2020 14:26:10 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://thepracticalsysadmin.com/?p=37158</guid>

					<description><![CDATA[<p>There are quite a few blog posts out there detailing this, but none of them seem to be up to date for use with the HCL style syntax, introduced in Packer 1.5, which has a number of advantages over using the original JSON syntax, namely that it is much more human friendly, flexible, and easy [&#8230;]</p>
<p>The post <a href="https://thepracticalsysadmin.com/create-windows-server-2019-amis-using-packer/" target="_blank">Create Windows Server 2019 AMIs using Packer</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></description>
										<content:encoded><![CDATA[<!-- Easy Plugin for AdSense V8.67 -->
<!-- [leadin: 1 urCount: 1 urMax: 0] -->
<div class="ezAdsense adsense adsense-leadin" style="text-align:left;margin:12px;"><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Responsive text only -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-5253421968934617"
     data-ad-slot="3887571415"
     data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script></div>
<!-- Easy Plugin for AdSense V8.67 -->

<figure class="wp-block-image size-large"><img decoding="async" width="648" height="365" src="https://i1.wp.com/thepracticalsysadmin.com/wp-content/uploads/2020/11/packer1.jpg?resize=648%2C365&#038;ssl=1" alt="" class="wp-image-37161" data-recalc-dims="1"/></figure>



<p>There are quite a few blog posts out there detailing this, but none of them seem to be up to date for use with the HCL style syntax, introduced in Packer 1.5, which has a <a href="https://github.com/hashicorp/hcl#why" target="_blank" rel="noreferrer noopener">number of advantages</a> over using the original JSON syntax, namely that it is much more human friendly, flexible, and easy to work with.</p>



<p>So in this post I will share a very quick and dirty example packer configuration that uses the HCL syntax to create, provision and upload a Windows server AMI to AWS.</p>



<p>You&#8217;ll need the following <strong>bootstrap_win.txt</strong> file in place in order for Packer to be able to provision the server using PowerShell commands over WinRM.</p>



<pre class="wp-block-code"><code>&lt;powershell>

write-output "Running User Data Script"
write-host "(host) Running User Data Script"

Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force -ErrorAction Ignore

# Don't set this before Set-ExecutionPolicy as it throws an error
$ErrorActionPreference = "stop"

# Remove HTTP listener
Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse

# Create a self-signed certificate to let ssl work
$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer"
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force

# WinRM
write-output "Setting up WinRM"
write-host "(host) setting up WinRM"

cmd.exe /c winrm quickconfig -q
cmd.exe /c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}'
cmd.exe /c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}'
cmd.exe /c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{CredSSP="true"}'
cmd.exe /c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`"5986`";Hostname=`"packer`";CertificateThumbprint=`"$($Cert.Thumbprint)`"}"
cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes
cmd.exe /c netsh firewall add portopening TCP 5986 "Port 5986"
cmd.exe /c net stop winrm
cmd.exe /c sc config winrm start= auto
cmd.exe /c net start winrm

&lt;/powershell></code></pre>



<p>Here is what the full Packer HCL configuration looks like.</p>



<pre class="wp-block-code"><code>variable "aws_region" {
  type    = string
  default = "us-west-2"
}

variable "instance_type" {
  type    = string
  default = "t3.medium"
}

variable "subnet_id" {
  type = string
}

variable "vpc_id" {
  type = string
}

variable "ami_users" {
  type = string
}

source "amazon-ebs" "windows_server" {
  ami_description             = "A custom Windows Server AMI"
  ami_name                    = "windows-example"
  ami_users                   = &#91;"${var.ami_users}"]
  associate_public_ip_address = true
  communicator                = "winrm"
  instance_type               = "${var.instance_type}"
  region                      = "${var.aws_region}"
  force_deregister            = true
  force_delete_snapshot       = true
  source_ami_filter {
    filters = {
      architecture        = "x86_64"
      name                = "Windows_Server-2019-English-Full-ContainersLatest-*"
      root-device-type    = "ebs"
      virtualization-type = "hvm"
    }
    most_recent = true
    owners      = &#91;"801119661308"]
  }
  subnet_id      = "${var.subnet_id}"
  user_data_file = "./bootstrap_win.txt"
  vpc_id         = "${var.vpc_id}"
  winrm_insecure = true
  winrm_port     = 5986
  winrm_use_ssl  = true
  winrm_username = "Administrator"
}

build {
  sources = &#91;"source.amazon-ebs.windows_server"]

  # Extra configuration
  provisioner "file" {
    destination = "C:\\ProgramData\\someconfig.txt"
    source      = "./myconfig.txt"
  }

  provisioner "powershell" {
    # Reinitialize the server to generate a random password on first boot
    inline = &#91;
      "C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\SendWindowsIsReady.ps1 -Schedule",
      "C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule",
      "C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\SysprepInstance.ps1 -NoShutdown"
    ]
  }
}</code></pre>



<p>Notice the two provisioners. The first enables a way for you to inject local configurations into the image before baking it, useful for adding extra configurations. The second is specific to AWS Windows Server images but essentially allows the machine to act like it is being booted for the first time, using the SendWindowsIsReady.ps1, InitializeInstance.ps1 and SysprepInstance.ps1 scripts. These scripts are important pieces to ensuring that this AMI can be created and started the exact same way every time.</p>



<p>Some of the configuration options may not be necessary so you will need to play around with the configuration to make it suit your needs. For example, you may want to create a unique image on every build, which can be done using timestamps. If you use unique identifiers, the force_deregister and force_delete_snapshot options can be omitted. </p>



<p>Likewise, since this Packer image is specific to Windows, it uses a number of winrn_ options, which would be replaced by ssh_ options if this were being provisioned for Linux.</p>



<p>One other trick that I found to be helpful was setting some of these variables on the fly via a script. You can use PKR_VAR_&lt;var> via shell to set some environment variables. This is especially useful when the configuration needs to be shared across different environments for things that change, e.g. vpc_id and subnet_id.</p><p>The post <a href="https://thepracticalsysadmin.com/create-windows-server-2019-amis-using-packer/" target="_blank">Create Windows Server 2019 AMIs using Packer</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://thepracticalsysadmin.com/create-windows-server-2019-amis-using-packer/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">37158</post-id>	</item>
		<item>
		<title>Immutable WordPress Installations with Kubernetes</title>
		<link>https://thepracticalsysadmin.com/immutable-wordpress-installations-with-kubernetes/</link>
					<comments>https://thepracticalsysadmin.com/immutable-wordpress-installations-with-kubernetes/#comments</comments>
		
		<dc:creator><![CDATA[Josh Reichardt]]></dc:creator>
		<pubDate>Mon, 19 Oct 2020 14:47:48 +0000</pubDate>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Wordpress]]></category>
		<guid isPermaLink="false">https://thepracticalsysadmin.com/?p=37146</guid>

					<description><![CDATA[<p>In this post I will describe some of the interesting discoveries I have made for a recent side project I have been working on, which include a few nice discoveries to automate and manage WordPress deployments with Kubernetes. Automating WordPress I am very happy with the patterns that have emerged from this project. One thing [&#8230;]</p>
<p>The post <a href="https://thepracticalsysadmin.com/immutable-wordpress-installations-with-kubernetes/" target="_blank">Immutable WordPress Installations with Kubernetes</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="648" height="220" src="https://i0.wp.com/thepracticalsysadmin.com/wp-content/uploads/2020/10/wp2.png?resize=648%2C220&#038;ssl=1" alt="wordpress on kubernetes" class="wp-image-37153" data-recalc-dims="1"/></figure>



<p>In this post I will describe some of the interesting discoveries I have made for a recent side project I have been working on, which include a few nice discoveries to automate and manage WordPress deployments with Kubernetes.</p>



<p><strong>Automating WordPress</strong></p>



<p>I am very happy with the patterns that have emerged from this project. One thing that I have always struggled with (I&#8217;m sure others have as well) in the world of WP has been finding a good way to create completely reproducible and immutable code and configurations. For example, managing plugins and themes has been a painful experience because WP was designed back in  a time before configuration as code and infrastructure as code. Due to this different paradigm, WP is usually stood up once, then managed via it </p>



<p>Tools have evolved since then and a perfect example of one of the bridges between the old and new way is the <a href="https://wp-cli.org/" target="_blank" rel="noreferrer noopener" title="wp-cli">wp-cli</a>. The wp-cli is basically a way to automate all kinds of things you would otherwise do in the UI. For example, wp-cli provides a way to manage plugin and themes, which as I mentioned has been notoriously difficult to do in the past.</p>



<p>The next step forward is the combination of a tool called <a href="https://roots.io/bedrock/" title="https://roots.io/bedrock/" target="_blank" rel="noreferrer noopener">bedrock</a> and its accompanying way of modifying it and building your own Docker image. The roots/bedrock method provides the wp-cli in the build scripts so if needed, you can automate tasks using extra entrypoint scripts and/or wp-cli commands, which is just a nice extra touch and shows that the maintainers of the project are putting a lot of effort into it.</p>



<p>A few other bells and whistles include a way to build custom plugins into Docker images for portability rather than relying on some external persistent storage solution which can quickly add overhead and complexity to a project, as well as modern tools like PHP <a href="https://getcomposer.org/" title="https://getcomposer.org/" target="_blank" rel="noreferrer noopener">Composer</a> and <a href="https://wpackagist.org/" title="https://wpackagist.org/">Packagist</a> which provide a way to install packages (Composer) and a way to manage WP plugins via the Composer package manager (packagist).</p>



<pre class="wp-block-preformatted"><strong>Sidenote</strong>

There are several other ways of deploying WP into Kubernetes, unfortunately most of these methods do not address multitenancy. If multitenancy is needed, a much more complicated approach is needed involving either NFS or some other many -&gt; many volume mapping.</pre>



<p><strong>Deploying with Kubernetes</strong></p>



<p>The tricky part to all of this is the fact that I was unable to find any examples of others using Kubernetes to deploy bedrock managed Docker containers. There is a docker-compose.yaml file in the repo that works perfectly well, but the next step beyond that doesn&#8217;t seem to be a topic that has been covered much.</p>



<p>Luckily it is mostly straight forward to bring the docker-compose configuration into Kubernetes, there are just a few minor adjustments that need to be made. The below link should provide the basic scaffolding needed to bring bedrock into a Kubernetes cluster. This method will even expose a way to create and manage WP multisite, another notoriously difficult aspect of WP to manage.</p>



<p><a href="https://gist.github.com/jmreicha/aae3ce024c13be1c561189946f1a0efc">https://gist.github.com/jmreicha/aae3ce024c13be1c561189946f1a0efc</a></p>



<p>There are a couple of things to note with this configuration. You will need build/maintain your own Docker image based off the roots/bedrock repo linked above. You will also need to have some knowledge of Kubernetes and a working Kubernetes cluster in place. The configuration will require certificates, and DNS so <strong>cert-manager</strong> and <strong>external-dns</strong> will most likely need to be deployed into the cluster.</p>



<p>Finally, in the configuration the password, domain (example.com), environment variables for configuring the database and Docker image will need to be updated to reflect your own environment. This method assumes that the WordPress database has already been split out to another location, <em>so will require the Kubernetes cluster to be able to communicate with wherever the database is hosted.</em></p>



<p>To see some of the magic, change the number of replicas in the Kubernetes manifest configuration from 1 to 2, and you should be able to see a new, completely identical container come up with all the correct configurations and code and start taking traffic.</p>



<p><strong>Conclusion</strong></p>



<p>Switching to the immutable infrastructure approach with WP nets a big win. By adopting these new methods and workflows you can control everything with code, which removes the need for manually managing WP instances and instead allows you to create workflows and pipelines to do all of the heavy lifting.</p>



<p>These benefits include much more visibility in controlling changes, because now Git becomes the central source of truth which allows you to get a better picture of the what, when and why than any other system I have found. This new paradigm also enables the use of Continuous Integration as it is intended &#8211; the automatic builds and deploys because of Docker and Kubernetes integrations producing immutable artifacts (Docker), and deployments (Kubernetes manifests) create a clean and simple way to manage the aspects of running the WordPress site.</p>
 <!-- Easy Plugin for AdSense Unfiltered [count: 2 is not less than 2] --><p>The post <a href="https://thepracticalsysadmin.com/immutable-wordpress-installations-with-kubernetes/" target="_blank">Immutable WordPress Installations with Kubernetes</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://thepracticalsysadmin.com/immutable-wordpress-installations-with-kubernetes/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">37146</post-id>	</item>
		<item>
		<title>Terraform Testing Tools</title>
		<link>https://thepracticalsysadmin.com/terraform-testing-tools/</link>
					<comments>https://thepracticalsysadmin.com/terraform-testing-tools/#comments</comments>
		
		<dc:creator><![CDATA[Josh Reichardt]]></dc:creator>
		<pubDate>Sat, 27 Jun 2020 14:03:47 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://thepracticalsysadmin.com/?p=37111</guid>

					<description><![CDATA[<p>What begins with &#8220;T&#8221;? I have been thinking about various ways of testing infrastructure and resources lately and have been having a difficult time parsing out the various tools that are available. This post is meant to be a reference for &#8220;finding the right tool for the right job&#8221; as part of testing various infrastructures. [&#8230;]</p>
<p>The post <a href="https://thepracticalsysadmin.com/terraform-testing-tools/" target="_blank">Terraform Testing Tools</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img decoding="async" loading="lazy" src="https://i1.wp.com/thepracticalsysadmin.com/wp-content/uploads/2020/06/terraform-test1.png?resize=196%2C255&#038;ssl=1" alt="terraform testing tools" class="wp-image-37139" width="196" height="255" data-recalc-dims="1" /></figure></div>



<p>What begins with &#8220;T&#8221;? I have been thinking about various ways of testing infrastructure and resources lately and have been having a difficult time parsing out the various tools that are available. This post is meant to be a reference for &#8220;finding the right tool for the right job&#8221; as part of testing various infrastructures.</p>



<p>Often times when you start talking about testing, you will hear about the testing pyramid, which is described along with some other interesting aspects of testing Terraform in <a aria-label="this blog post (opens in a new tab)" class="aioseop-link" href="https://medium.com/deliveredtechnologies/unit-testing-terraform-e592a5c3777f" target="_blank" rel="noreferrer noopener">this blog post</a>, it covers a lot of the pitfalls and gotchas you might run into.</p>



<p>My aim originally was to find a good tool for unit testing Terraform and as part of that adventure have uncovered a number of other interesting projects, that while not directly applicable, could be very useful for a number of different testing scenarios. Read the above blog post for more info but suffice to say, unit testing (the bottom layer of the testing pyramid) is quite difficult to do with Infrastructure as Code and Terraform and at this point is mostly not a solved problem.</p>



<p>Here is the list of tools that I uncovered in my research. Please let me know if there are any missing.</p>



<p><a aria-label="Terratest (opens in a new tab)" class="aioseop-link" href="https://github.com/gruntwork-io/terratest" target="_blank" rel="noreferrer noopener">Terratest</a></p>



<p>Terratest is written and maintained by the folks at Terragrunt and it provides a comprehensive testing experience for deploying Infrastructure as Code, testing that it works as expected and then tears down the IaC when it is finished. From what I can tell this is probably the most comprehensive testing tool out there, still doesn&#8217;t cover unit tests, but is a great way to ensure things are working end to end.</p>



<p><a href="https://github.com/newcontext-oss/kitchen-terraform" target="_blank" aria-label="Kitchen-Terraform (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">Kitchen-Terraform</a></p>



<p>Follows the BDD philosophy and spins up, tests and spins down various Terraform resources. Works in a similar fashion to Terratest to bring up the environment, test and then tear things down.</p>



<p><a aria-label="serverspec (opens in a new tab)" href="https://serverspec.org/" target="_blank" rel="noreferrer noopener" class="aioseop-link">serverspec</a></p>



<p>This testing tool is one of the original tools I ran across when originally mulling over the idea of unit testing infrastructure back in the days when configuration management tools like Chef, Puppet and Salt ruled the earth.</p>



<p><a href="https://www.inspec.io/docs/reference/resources/#aws-resources" target="_blank" aria-label="inspec (aws-resources) (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">inspec (aws-resources)</a></p>



<p>Very similiar to awspec, this tool provides a framework for testing various AWS resources. This one is nice because it uses inspec to build on and so it has a lot of extra capabilities.</p>



<p><a aria-label="awspec (opens in a new tab)" href="https://github.com/k1LoW/awspec" target="_blank" rel="noreferrer noopener" class="aioseop-link">awspec</a></p>



<p>Very similar to the other &#8220;spec&#8221; tools, awspec is built in the same style as serverspec/inspec and provides a very nice interface for testing various <a aria-label="AWS resource types (opens in a new tab)" href="https://github.com/k1LoW/awspec/blob/master/doc/resource_types.md" target="_blank" rel="noreferrer noopener" class="aioseop-link">AWS resource types</a>. Since it is modeled after serverspec, you will need to deal with Ruby.</p>



<p><a aria-label="Testinfra (opens in a new tab)" href="https://testinfra.readthedocs.io/en/latest/" target="_blank" rel="noreferrer noopener" class="aioseop-link">Testinfra</a></p>



<p>Another Python based unit testing style framework. This tools varies from Terraform Validate in that it mainly focuses on testing the lower level server and OS, but it does have integration for testing a number of other things.</p>



<p><a href="https://github.com/eerkunt/terraform-compliance" target="_blank" aria-label="terraform-compliance (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">terraform-compliance</a></p>



<p>A nice tool for testing (and enforcing Terraform compliance rules).</p>



<p><a aria-label="terraform_validate (opens in a new tab)" href="https://github.com/elmundio87/terraform_validate" target="_blank" rel="noreferrer noopener" class="aioseop-link">Terraform Validate</a></p>



<p> This is a nice tool for expressing various test conditions as compliance, especially if you are already familiar with Python and its testing landscape. This tool parses configs using pyhcl and allows you to write familiar unittest style tests for Terraform configurations.</p>



<p><a aria-label="Pulumi (opens in a new tab)" href="https://www.pulumi.com/blog/unit-test-infrastructure/" target="_blank" rel="noreferrer noopener" class="aioseop-link">Pulumi</a></p>



<p>This one is a bit of a wild card but could prove interesting to some readers. Pulumi provides direct integration into your language of choice (Python for me) to enable you to write pulumi code using language native unit tests. Obviously Pulumi isn&#8217;t Terraform but I had to mention it here because there is a significant amount of crossover between the tools.</p>
 <!-- Easy Plugin for AdSense Unfiltered [count: 2 is not less than 2] --><p>The post <a href="https://thepracticalsysadmin.com/terraform-testing-tools/" target="_blank">Terraform Testing Tools</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://thepracticalsysadmin.com/terraform-testing-tools/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">37111</post-id>	</item>
		<item>
		<title>Exploring Linux Terminals</title>
		<link>https://thepracticalsysadmin.com/exploring-linux-terminals/</link>
					<comments>https://thepracticalsysadmin.com/exploring-linux-terminals/#comments</comments>
		
		<dc:creator><![CDATA[Josh Reichardt]]></dc:creator>
		<pubDate>Wed, 13 May 2020 03:43:43 +0000</pubDate>
				<category><![CDATA[Command Line]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">https://thepracticalsysadmin.com/?p=37128</guid>

					<description><![CDATA[<p>I have been experimenting with Linux on a recently acquired Lenovo X1 Carbon and as part of the process I have been exploring and testing out various productivity tools, including terminal emulators. The first thing I discovered in this process is that there&#8217;s a lot of terminals out there. And they&#8217;re all slightly different, and [&#8230;]</p>
<p>The post <a href="https://thepracticalsysadmin.com/exploring-linux-terminals/" target="_blank">Exploring Linux Terminals</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img decoding="async" loading="lazy" src="https://i1.wp.com/thepracticalsysadmin.com/wp-content/uploads/2020/05/iconfinder_terminal_285695.png?resize=350%2C350&#038;ssl=1" alt="" class="wp-image-37131" width="350" height="350" data-recalc-dims="1" /></figure></div>



<p>I have been experimenting with Linux on a recently acquired Lenovo X1 Carbon and as part of the process I have been exploring and testing out various productivity tools, including terminal emulators.</p>



<p>The first thing I discovered in this process is that there&#8217;s a lot of terminals out there.  And they&#8217;re all slightly different, and in my experience, almost none of them were able to do all of the tweaks I like.</p>



<p>Here is the list of terminals I have tested out (so far).</p>



<ul><li><a aria-label="Alacritty (opens in a new tab)" href="https://github.com/alacritty/alacritty" target="_blank" rel="noreferrer noopener" class="aioseop-link">Alacritty</a></li><li><a aria-label="Gnome Terminal (opens in a new tab)" href="https://help.gnome.org/users/gnome-terminal/stable/overview.html.en" target="_blank" rel="noreferrer noopener" class="aioseop-link">Gnome Terminal</a></li><li><a aria-label="Kitty (opens in a new tab)" href="https://sw.kovidgoyal.net/kitty/" target="_blank" rel="noreferrer noopener" class="aioseop-link">Kitty</a></li><li><a href="https://st.suckless.org/" target="_blank" aria-label="Simple Terminal (ST) (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">Simple Terminal (ST)</a></li><li><a aria-label="Terminator (opens in a new tab)" href="https://terminator-gtk3.readthedocs.io/en/latest/" target="_blank" rel="noreferrer noopener" class="aioseop-link">Terminator</a></li><li><a aria-label="Termite (opens in a new tab)" href="https://wiki.archlinux.org/index.php/Termite" target="_blank" rel="noreferrer noopener" class="aioseop-link">Termite</a></li><li><a aria-label="Tilix (opens in a new tab)" href="https://gnunn1.github.io/tilix-web/" target="_blank" rel="noreferrer noopener" class="aioseop-link">Tilix</a></li><li><a aria-label="urxvt (opens in a new tab)" href="https://wiki.archlinux.org/index.php/Rxvt-unicode" target="_blank" rel="noreferrer noopener" class="aioseop-link">urxvt</a></li></ul>



<p>As you can see, that is a bunch of terminals. To keep things short, in my exploration and testing, the best 3 I found were as follows.</p>



<p><strong>Alacritty &#8211; 3rd</strong></p>



<p>It is fast, defaults are great, works perfectly with the tiling window managers. This one would would probably have been first on the list if it was able to provide a <a href="https://github.com/alacritty/alacritty/issues/302" target="_blank" aria-label="blinking cursor (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">blinking cursor</a> but as I found with many of the options there seemed to almost always be a gotcha.</p>



<p>A few high points for this terminal, written in Rust, it uses the GPU to offload rendering, cross platform, and maybe my favorite feature, the configuration file is yaml based. Docs are also good and the community is really taking off so I have a strong feeling this one will continue improving.</p>



<p><strong>urxvt &#8211; 2nd</strong></p>



<p>The biggest problem with this terminal for me is that it is painful to configure. There are no preferences configured out of the box, which to some is preferred, but also, digging through old blog posts and perl scripts is not how I like to spend my time.</p>



<p>This terminal is second on the list  because it was the only other terminal that was able to do all of the small little tweaks and adjustments that suit my preferences. And it is fast and light weight, which are good things.</p>



<p>Here is the <a href="https://github.com/jmreicha/configs/blob/master/config/urxvt/.Xdefaults" target="_blank" aria-label="configuration I ended up with (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">configuration I ended up with</a> if interested.</p>



<p><strong>Kitty &#8211; 1st</strong></p>



<p>This terminal was a clear winner. It was able to do all of my custom tweaks and settings and because it has nice defaults I only needed to add about 10 lines of extra configuration.</p>



<p>This terminal has a lot of other stuff going for it. It is written in Rust, which makes it fast, it uses the GPU to offload rendering, which also makes it fast, easy to configure, and for the most part just works. Only gotcha I found was that I needed to explicitly turn on copy to selection in my configuration, but that was easy.</p>



<p>Here is the <a href="https://github.com/jmreicha/configs/blob/master/config/kitty/kitty.conf" target="_blank" aria-label="configuration I ended up with (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">configuration I ended up with</a> if interested.</p>



<p><strong>Conclusion</strong></p>



<p>I plan on keeping this list updated to some extent as I find more Terminals to try out. As you can see, there are many different options and seem to be more and more all the time.</p>



<p>Your experience may differ so obviously take these musings with a pinch of salt, and please do look through the various options and try things out to see if they will work for you. That said, I do think I have a specific enough use case that these recommendations should be helpful in guiding most users.</p>



<p>Here is the <a href="https://github.com/jmreicha/configs" target="_blank" aria-label="repo with all of my various configurations (opens in a new tab)" rel="noreferrer noopener" class="aioseop-link">repo with all of my various configurations</a> if you want to check something out. There were a few terminal configs that didn&#8217;t end up there just because they were too minimal or I didn&#8217;t like them.</p>
 <!-- Easy Plugin for AdSense Unfiltered [count: 2 is not less than 2] --><p>The post <a href="https://thepracticalsysadmin.com/exploring-linux-terminals/" target="_blank">Exploring Linux Terminals</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://thepracticalsysadmin.com/exploring-linux-terminals/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">37128</post-id>	</item>
		<item>
		<title>Idempotent Shell Scripts with Terraform</title>
		<link>https://thepracticalsysadmin.com/idempotent-shell-scripts-with-terraform/</link>
					<comments>https://thepracticalsysadmin.com/idempotent-shell-scripts-with-terraform/#comments</comments>
		
		<dc:creator><![CDATA[Josh Reichardt]]></dc:creator>
		<pubDate>Sun, 22 Mar 2020 20:11:19 +0000</pubDate>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Terraform]]></category>
		<guid isPermaLink="false">https://thepracticalsysadmin.com/?p=37096</guid>

					<description><![CDATA[<p>One challenge when dealing with Terraform is keeping things clean and repeatable. My current favorite approach to accomplish this task using shell scripts is by using a combination of null_resources and triggers to control when scripts should be updated. These controls combined with Terraform provisioners and template_files provide a nice flexible way to deal with [&#8230;]</p>
<p>The post <a href="https://thepracticalsysadmin.com/idempotent-shell-scripts-with-terraform/" target="_blank">Idempotent Shell Scripts with Terraform</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="wp-block-image"><figure class="aligncenter is-resized"><img decoding="async" loading="lazy" src="https://i1.wp.com/thepracticalsysadmin.com/wp-content/uploads/2020/03/terraform1.png?resize=267%2C267&#038;ssl=1" alt="" class="wp-image-37105" width="267" height="267" data-recalc-dims="1" /></figure></div>



<p>One challenge when dealing with Terraform is keeping things clean and repeatable. My current favorite approach to accomplish this task using shell scripts is by using a combination of <em><a rel="noreferrer noopener" aria-label="null_resources (opens in a new tab)" href="https://www.terraform.io/docs/providers/null/resource.html" target="_blank">null_resources</a></em> and <em>triggers</em> to control when scripts should be updated. These controls combined with Terraform <a rel="noreferrer noopener" aria-label="provisioners (opens in a new tab)" href="https://www.terraform.io/docs/provisioners/index.html" target="_blank">provisioners</a> and <a rel="noreferrer noopener" aria-label="emplate_files (opens in a new tab)" href="https://www.terraform.io/docs/providers/template/d/file.html" target="_blank">template_files</a> provide a nice flexible way to deal with otherwise potentially messy scripts.</p>



<p>I like to provide more than one trigger so that they can be recomputed when either a variable that gets passed into the script changes, or, the script itself changes. This trick is handy when you need to bend Terraform into doing something that it usually doesn&#8217;t handle, like some startup or bootstrap process.</p>



<p>Below is the full example with templated scripts and triggers in Terraform v0.11.  The same logic should also work with Terraform v0.12 with minimal changes. </p>



<pre class="wp-block-code"><code>data "template_file" "cool_script" {
  template = "${file("${path.module}/script.sh")}"

  vars {
    my_cool_var = "${var.my_cool_var}"
  }
}

resource "null_resource" "script" {

  # Trigger when the script when variables change
  triggers = {
    my_trigger = "${var.my_cool_var}"
    script_sha = "${sha256(file("${path.module}/script.sh"))}"
  }

  provisioner "local-exec" {
    command   = "${data.template_file.cool_script.rendered}"
    interpreter = ["/bin/bash", "-c"]
  }
}</code></pre>



<p>You can provide as many variables to the <strong>template_file</strong> as the script needs and any time those get updated, the <strong>null_resource</strong> will pick these changes up and update/rerun your script for you.  Notice that the provisioner in the null_resource is basically set up to call bash against the rendered script that we created, using the values in the vars.</p>



<p>If you call the script again, nothing should change because we already computed the SHA of the rendered script and told Terraform to keep track of that state. The below example is a simple way for telling Terraform to keep track of changes to the script/template.</p>



<pre class="wp-block-code"><code>script_sha = "${sha256(file("${path.module}/script.sh"))}"</code></pre>



<p>Once the script is updated, the next time the script gets called, its values and output should update accordingly. Likewise, since we are also using a var as a trigger, when that changes the script will also be updated.</p>



<p>Terraform is flexible enough to allow us to do things like this because often times there are situations and edge cases where Terraform can&#8217;t really perform some actions.  The above example is a common workaround for provisioning resources that either don&#8217;t have an API that Terraform can tap into, or are just tasks that are only handled via some startup or bootstrap script/process.</p>
 <!-- Easy Plugin for AdSense Unfiltered [count: 2 is not less than 2] --><p>The post <a href="https://thepracticalsysadmin.com/idempotent-shell-scripts-with-terraform/" target="_blank">Idempotent Shell Scripts with Terraform</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://thepracticalsysadmin.com/idempotent-shell-scripts-with-terraform/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">37096</post-id>	</item>
		<item>
		<title>Bash Quick Substitution</title>
		<link>https://thepracticalsysadmin.com/bash-quick-substitution/</link>
					<comments>https://thepracticalsysadmin.com/bash-quick-substitution/#comments</comments>
		
		<dc:creator><![CDATA[Josh Reichardt]]></dc:creator>
		<pubDate>Sun, 16 Feb 2020 18:36:04 +0000</pubDate>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Command Line]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<guid isPermaLink="false">https://thepracticalsysadmin.com/?p=37089</guid>

					<description><![CDATA[<p>One thing that I love about bash is that there is never a shortage of new tips and tricks to learn. I have been using bash for over 10 years now and just stumbled on this little trick. This one (as the title implies) allows you to quickly substitute a string into the previous command [&#8230;]</p>
<p>The post <a href="https://thepracticalsysadmin.com/bash-quick-substitution/" target="_blank">Bash Quick Substitution</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="wp-block-image"><figure class="aligncenter is-resized"><img decoding="async" loading="lazy" src="https://i1.wp.com/thepracticalsysadmin.com/wp-content/uploads/2020/02/bigbrain2.jpg?resize=505%2C490&#038;ssl=1" alt="big brain" class="wp-image-37094" width="505" height="490" data-recalc-dims="1" /><figcaption>Big Brain Time</figcaption></figure></div>



<p>One thing that I love about bash is that there is never a shortage of new tips and tricks to learn.  I have been using bash for over 10 years now and just stumbled on this little trick.</p>



<p>This one (as the title implies) allows you to quickly substitute a string into the previous command and rerun the command with the substitution.</p>



<p>Quick substitution is officially part of the <a rel="noreferrer noopener" aria-label="Bash Event Designators (opens in a new tab)" href="https://www.gnu.org/software/bash/manual/html_node/Event-Designators.html" target="_blank">Bash Event Designators</a> mechanism and is a great way to fix a typo from a previous command.  Below is an example.</p>



<pre class="wp-block-code"><code># Simple example to highlight substitutions
echo foo

# This will replace the string "foo" with "bar" and rerun the last command
^foo^bar</code></pre>



<p>This shorthand notation is great for most use cases, with the exception of needing to replace multiple instances of a given string.  Luckily that is easily addressed with the Event Designators expanded substitution syntax, shown below.</p>



<pre class="wp-block-code"><code># This will substitute ALL occurrences of foo in the previous command
!!:gs/foo/bar/

# Slightly different syntax allows you to do the same thing in ZSH
^foo^bar^:G</code></pre>



<p>The syntax is slightly more complicated in the first example but should be familiar enough to anyone that has used sed and/or vim substitutions, and the second example is almost identical to the shorthand substitution.</p>



<p><strong>fc</strong></p>



<p>Taking things one step further, we can actually edit the previous command to fix anything more than a typo of different argument.  fc is actually a bash builtin function so it is available almost everywhere.</p>



<p>fc is especially useful for dealing with very long, complicated commands.</p>



<pre class="wp-block-code"><code># Oops, we messed this up
echo fobarr | grep bar

# To fix it, just open the above in your default editor
fc

# when you write and quit the file it will put the contents into your current command</code></pre>



<p>There are many <a rel="noreferrer noopener" aria-label="great tutorials (opens in a new tab)" href="https://shapeshed.com/unix-fc/" target="_blank">great tutorials</a> available so I would recommend looking around to see all the options and get more ideas.</p>
 <!-- Easy Plugin for AdSense Unfiltered [count: 2 is not less than 2] --><p>The post <a href="https://thepracticalsysadmin.com/bash-quick-substitution/" target="_blank">Bash Quick Substitution</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://thepracticalsysadmin.com/bash-quick-substitution/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">37089</post-id>	</item>
		<item>
		<title>Untangling CLI Text Processing Tools</title>
		<link>https://thepracticalsysadmin.com/untangling-various-text-processing-cli-tools/</link>
					<comments>https://thepracticalsysadmin.com/untangling-various-text-processing-cli-tools/#comments</comments>
		
		<dc:creator><![CDATA[Josh Reichardt]]></dc:creator>
		<pubDate>Sun, 02 Feb 2020 17:23:35 +0000</pubDate>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Command Line]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripting]]></category>
		<guid isPermaLink="false">https://thepracticalsysadmin.com/?p=37064</guid>

					<description><![CDATA[<p>Update (2/7/2020): Added jc The landscape of command line driver text manipulation and processing tools is somewhat large and confusing, with more and more tools emerging all the time. Because I am having trouble keeping them all in my head, I decided to make a little reference guide to help remember which tool to choose [&#8230;]</p>
<p>The post <a href="https://thepracticalsysadmin.com/untangling-various-text-processing-cli-tools/" target="_blank">Untangling CLI Text Processing Tools</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-image"><img decoding="async" loading="lazy" width="648" height="432" src="https://i1.wp.com/thepracticalsysadmin.com/wp-content/uploads/2020/01/tangle1.jpg?resize=648%2C432&#038;ssl=1" alt="" class="wp-image-37077" data-recalc-dims="1"/></figure>



<p><strong>Update (2/7/2020):</strong> Added jc</p>



<p>The landscape of command line driver text manipulation and processing tools is somewhat large and confusing, with more and more tools emerging all the time.  Because I am having trouble keeping them all in my head, I decided to make a little reference guide to help remember which tool to choose for the correct task at hand.</p>



<ul><li>jq</li><li>jc</li><li>yq (both python and go versions)</li><li>oq</li><li>xq</li><li>hq</li><li>jk</li><li>ytt</li><li>configula</li><li>jsonnet</li><li>sed (for everything else)</li></ul>



<p><a rel="noreferrer noopener" aria-label="jq (opens in a new tab)" href="https://stedolan.github.io/jq/" target="_blank"><strong>jq</strong></a></p>



<p>Reach for jq first when you need to do any kind of processing with JSON files.</p>



<p>From the website, &#8220;jq is like <code>sed</code> for JSON data &#8211; you can use it to slice and filter and map and transform structured data with the same ease that <code>sed</code>, <code>awk</code>, <code>grep</code> and friends let you play with text.&#8221;</p>



<pre class="wp-block-code"><code>sudo apt-get install jq
# or
brew install jq

# consume json and output as unchanged json
curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.'</code></pre>



<p><strong><a href="https://github.com/kellyjonbrazil/jc" target="_blank" rel="noreferrer noopener" aria-label="jc (opens in a new tab)">jc</a></strong></p>



<p>This project looks very interesting and is a refreshing thing to see in the Linux world.  JC is basically a way to create structured objects (ala PowerShell) as JSON output from running various Linux commands.  And from the GitHub repo, &#8221; This tool serializes the output of popular gnu linux command line tools and file types to structured JSON output. This allows piping of output to tools like jq&#8221;.</p>



<p>Transforming data into structured objects can massively simplify interacting with them by pairing the output with jq to interact with.</p>



<pre class="wp-block-code"><code>pip3 install --upgrade jc
df | jc --df -p
[
  {
    "filesystem": "devtmpfs",
    "1k_blocks": 1918816,
    "used": 0,
    "available": 1918816,
    "use_percent": 0,
    "mounted_on": "/dev"
  },
  {
    "filesystem": "tmpfs",
    "1k_blocks": 1930664,
    "used": 0,
    "available": 1930664,
    "use_percent": 0,
    "mounted_on": "/dev/shm"
  },
  ...
]</code></pre>



<p><strong>yq</strong> (<a rel="noreferrer noopener" aria-label="Python (opens in a new tab)" href="https://github.com/kislyuk/yq" target="_blank">Python</a>) (<a rel="noreferrer noopener" aria-label="Go (opens in a new tab)" href="https://github.com/mikefarah/yq" target="_blank">Go</a>)</p>



<p>This tool can be confusing because there is both a Python version and a Go version.  On top of that, the Python version includes its own version of xq, which is different than the standalone xq tool.</p>



<p>The main differences between the Python and Go version is that the Python version can deal with both yaml and xml while the Go version is meant to be used as a command line tool to deal with only yaml.</p>



<pre class="wp-block-code"><code>pip install yq
cat input.yml | yq -y .foo.bar</code></pre>



<p><strong><a rel="noreferrer noopener" aria-label="oq (opens in a new tab)" href="https://blacksmoke16.github.io/oq/" target="_blank">oq</a></strong></p>



<p>From the website, oq is &#8220;A performant, portable&nbsp;<a rel="noreferrer noopener" href="https://github.com/stedolan/jq/" target="_blank">jq</a>&nbsp;wrapper thats facilitates the consumption and output of formats other than JSON; using&nbsp;<code>jq</code>&nbsp;filters to transform the data&#8221;.</p>



<p>The claim to fame that oq has is that it is very similar to jq but works better with other data formats, including xml and yaml.  For example, you can read in some xml (and others), apply some filters, and output to yaml (and others).  This flexibility makes oq a good option if you need to deal with different data formats oustide of JSON.</p>



<pre class="wp-block-code"><code>snap install oq
# or
brew tap blacksmoke16/tap &amp;&amp; brew install oq

# consume json and output xml
echo '{"name": "Jim"}' | oq -o xml .</code></pre>



<p><strong><a href="https://github.com/kislyuk/yq" target="_blank" rel="noreferrer noopener" aria-label="xq (opens in a new tab)">xq</a></strong></p>



<p>From the Github page, &#8220;Apply XPath expressions to XML, like&nbsp;<code>jq</code>&nbsp;does for JSONPath and JSON&#8221;.</p>



<p>The coolest use case I have found for xq so far is taking in an xml file and outputting it into a json file, which surprising I haven&#8217;t found another tool that can do this (oc authors say there are plans to do this in the future).  The simplest example is to curl a page, pipe it through xq to change it to json and then pipe it again and use jq to manipulate the data.</p>



<pre class="wp-block-code"><code>pip install yq
curl -s https://mysite.xml | xq .</code></pre>



<p><a rel="noreferrer noopener" aria-label="hq (opens in a new tab)" href="https://github.com/rbwinslow/hq" target="_blank">hq</a></p>



<p>Like xq (and jq) but for html parsing.  This tool is handy for manipulating html in the same way you would xml or json.</p>



<pre class="wp-block-code"><code>pip install hq
cat /path/to/file.html | hq '`Hello, ${/html/head/title}!`'</code></pre>



<p><strong><a href="https://jkcfg.github.io" target="_blank" rel="noreferrer noopener" aria-label="jk (opens in a new tab)">jk</a></strong></p>



<p>This is a newer tool, with a slightly different approach aimed at helping to automate configurations, especially for things like Kubernetes but should work with most structured data.</p>



<p>This tool works with json, yaml and hcl and can be used in conjunction with Javascript, making it an interesting option.</p>



<pre class="wp-block-code"><code>curl -Lo jk https://github.com/jkcfg/jk/releases/download/0.3.1/jk-darwin-amd64
chmod +x jk
sudo mv jk /usr/local/bin/

// alice.js
const alice = {
  name: 'Alice',
  beverage: 'Club-Mate',
  monitors: 2,
  languages: [
    'python',
    'haskell',
    'c++',
    '68k assembly', // Alice is cool like that!
  ],
};

// Instruct to write the alice object as a YAML file.
export default [
  { value: alice, file: `developers/${alice.name.toLowerCase()}.yaml` },
];

jk generate -v alice.js</code></pre>



<p><a rel="noreferrer noopener" aria-label="ytt (opens in a new tab)" href="https://github.com/k14s/ytt" target="_blank"><strong>ytt</strong></a></p>



<p>This is basically a simplified templating language that only intends to deal with yaml.  The approach the authors took was to create yaml templates and sanbdox/embed Python into the templating engine, allowing users to call on the power of Python inside of their templates.</p>



<p>The easiest way to play around with ytt if you don&#8217;t want to clone the repo is to try out the <a href="https://get-ytt.io/" target="_blank" rel="noreferrer noopener" aria-label="online playground (opens in a new tab)">online playground</a>.</p>



<pre class="wp-block-code"><code>curl -Lo ytt https://github.com/k14s/ytt/releases/download/v0.25.0/ytt-darwin-amd64
chmod +x ytt
sudo mv ytt /usr/local/bin/

https://github.com/k14s/ytt.git &amp;&amp; cd ytt
ytt -f examples/playground/example-demo/</code></pre>



<p><strong><a rel="noreferrer noopener" aria-label="Configula (opens in a new tab)" href="https://github.com/brendandburns/configula" target="_blank">configula</a></strong></p>



<p>From the GitHub page, &#8221; Configula is a configuration generation language and processor. It&#8217;s goal is to make the programmatic definition of declarative configuration easy and intuitive&#8221;.</p>



<p>Similar in some ways to ytt, but instead of embedding Python into the yaml template file, you create a .py file and then render the py file into yaml using the Configula command line tool.</p>



<pre class="wp-block-code"><code>git clone https://github.com/brendandburns/configula
cd configula

# tiny.py
# Define a YAML object where the 'foo' field has the value of evaluating 1 + 2 (e.g. 3)
my_obj = foo: !~ 1 + 2
my_obj.render()

./configula examples/tiny.py</code></pre>



<p><a rel="noreferrer noopener" aria-label="jsonnet (opens in a new tab)" href="https://jsonnet.org/learning/tutorial.html" target="_blank"><strong>jsonnet</strong></a></p>



<p>Jsonnet bills itself as a &#8220;data templating language for app and tool developers&#8221;.  This tool was originally created by folks working at Google, and has been around for quite some time now.  For some reason always seems to fly underneath the radar but it is super powerful.</p>



<p>This tool is a superset of JSON and allows you to add conditionals, loops and other functions available as part of its standard library.  Jsonnet can render itself into json and yaml output.</p>



<pre class="wp-block-code"><code>pip install jsonnet
# or
brew install jsonnet

// example.jsonnet
{
  person1: {
    name: "Alice",
    welcome: "Hello " + self.name + "!",
  },
  person2: self.person1 { name: "Bob" },
}

jsonnet -S example.jsonnet</code></pre>



<p><strong><a href="https://www.gnu.org/software/sed/manual/sed.html" target="_blank" rel="noreferrer noopener" aria-label="sed (opens in a new tab)">sed</a></strong></p>



<p>For (pretty much) everything else, there is Sed.  Sed, short for stream editor, has been around forever and is basically a Swiss army knife for manipulating text, and if you have been using *nix for any length of time you have more than likely come across this tool before.  From their docs, Sed is &#8220;a stream editor is used to perform basic text transformations on an input stream&#8221;.</p>



<p>The odds are good that Sed will likely do what you&#8217;re looking for if you can&#8217;t use one of the aforementioned tools.</p>
 <!-- Easy Plugin for AdSense Unfiltered [count: 2 is not less than 2] --><p>The post <a href="https://thepracticalsysadmin.com/untangling-various-text-processing-cli-tools/" target="_blank">Untangling CLI Text Processing Tools</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://thepracticalsysadmin.com/untangling-various-text-processing-cli-tools/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">37064</post-id>	</item>
		<item>
		<title>Automatically set Terraform environment variables</title>
		<link>https://thepracticalsysadmin.com/automatically-set-terraform-environment-variables/</link>
					<comments>https://thepracticalsysadmin.com/automatically-set-terraform-environment-variables/#comments</comments>
		
		<dc:creator><![CDATA[Josh Reichardt]]></dc:creator>
		<pubDate>Sun, 22 Dec 2019 20:15:55 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://thepracticalsysadmin.com/?p=37050</guid>

					<description><![CDATA[<p>If you have spent any time managing infrastructure you have probably run into the issue of needing to set environment variables in order to connect to various resources. For example, the AWS Terraform provider allows you to automatically source local environment variables, which solves the issue of placing secrets in places they should be, ie. [&#8230;]</p>
<p>The post <a href="https://thepracticalsysadmin.com/automatically-set-terraform-environment-variables/" target="_blank">Automatically set Terraform environment variables</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="wp-block-image"><figure class="alignleft is-resized"><img decoding="async" loading="lazy" src="https://i0.wp.com/thepracticalsysadmin.com/wp-content/uploads/2019/12/linuxdir1.png?resize=243%2C243&#038;ssl=1" alt="automatically load environment variables" class="wp-image-37058" width="243" height="243" data-recalc-dims="1" /></figure></div>



<p>If you have spent any time managing infrastructure you have probably run into the issue of needing to set environment variables in order to connect to various resources.</p>



<p>For example, the <a rel="noreferrer noopener" aria-label="AWS Terraform provider (opens in a new tab)" href="https://www.terraform.io/docs/providers/aws/index.html#environment-variables" target="_blank">AWS Terraform provider</a> allows you to automatically source local environment variables, which solves the issue of placing secrets in places they should be, ie. writing the keys into configurations or state.  This use case is pretty straight forward, you can just set the environment variables once and everything will be able to connect.</p>



<p>The problem arises when environments need to be changed frequently or other configurations requiring secrets or tokens to connect to other resources need to be changed.</p>



<p>There are various tools available to solve the issue of managing and storing secrets for connecting to AWS including <a rel="noreferrer noopener" aria-label="aws-vault (opens in a new tab)" href="https://github.com/99designs/aws-vault" target="_blank">aws-vault</a> and <a rel="noreferrer noopener" aria-label="aws-env (opens in a new tab)" href="https://github.com/Droplr/aws-env" target="_blank">aws-env</a>.  The main issue is that these tools are opinionated and only work with AWS and aren&#8217;t designed to work with Terraform.</p>



<p>Of course this problem isn&#8217;t specific to Terraform, but the solution I have discovered using <a rel="noreferrer noopener" aria-label="ondir (opens in a new tab)" href="https://github.com/alecthomas/ondir" target="_blank">ondir</a> is generic enough that it can be applied to Terraform as well as any other task that involves setting up environment variables or running shell commands whenever a specific directory is changed to or left.</p>



<p>With that said, the ondir tool in combination with <a rel="noreferrer noopener" aria-label="Terragrunt (opens in a new tab)" href="https://github.com/gruntwork-io/terragrunt" target="_blank">Terragrunt</a>, gives you a set of tools that vastly improves the Terraform experience.  There is a lot of Terragrunt reference material already so I won&#8217;t discuss it much here.  The real power of my solution comes from combining ondir with Terragrunt to enhance how you use Terraform.</p>



<p><strong>Note:</strong> Before getting into more details of ondir, it is worth mentioning that there are several other similar tools, the most well known of which is called <a rel="noreferrer noopener" aria-label="direnv (opens in a new tab)" href="https://github.com/direnv/direnv" target="_blank">direnv</a>.  Direnv provides a few other features and a nice library for completing actions so it is definitely work checking out if you are not looking for a solution specific to Terraform/Terragrunt.  Other tools in the space include autoenv, smartcd and a few others.</p>



<p>Direnv should technically work to solve the problem, but when managing and maintaining large infrastructures, I have found it to be more tedious and cumbersome to manage.</p>



<p><strong>Ondir</strong></p>



<p>From the Github page, Ondir is <em><strong>a small program to automate tasks specific to certain directories</strong></em><strong>,</strong> so isn&#8217;t designed specifically to set environment variables but makes a perfect fit doing so.</p>



<p>Install ondir</p>



<pre class="wp-block-code"><code># OSX
brew install ondir
# Ubuntu
apt install ondir</code></pre>



<p>Configure ondir</p>



<p>After installing, add the following lines to your ~/.zshrc (or <a rel="noreferrer noopener" aria-label="these lines (opens in a new tab)" href="https://github.com/alecthomas/ondir/blob/master/scripts.sh" target="_blank">these lines</a> if you are using bash) and restart your shell.</p>



<pre class="wp-block-code"><code>val_ondir() {
  eval "`ondir \"$OLDPWD\" \"$PWD\"`"
}
chpwd_functions=( eval_ondir $chpwd_functions )</code></pre>



<p>Ondir leverages an <strong>~/.ondirrc</strong> file to configure the tool.  This file basically consists of enter and leave directives for performing actions when specific directories are entered and left.  To make this tool useful with Terragrunt, I have setup a simple example below for exporting a database password given a path that gets switched into (if the path ends in stage/database), which is defined in the ~/.ondirrc file.  One very nice feature of ondir is that it allows regular expressions to be used to define the enter/leave directives, which makes allows for complex paths to be defined.</p>



<pre class="wp-block-code"><code>enter .+(stage\/database)
    echo "Setting database password"
    export TF_VAR_db_password=mypassword
leave .+(stage\/database)
    unset TF_VAR_db_password</code></pre>



<p>With this logic, the shell should automatically export a database password for Terraform to use whenever you switch to the directory ending in stage/database.</p>



<pre class="wp-block-code"><code>cd ~/project/path/to/stage/database
# Check your environment for the variable
env | grep TF_VAR
TF_VAR_db_password=mypassword

cd ~
# When you leave the directory it should get unset
env | grep TF_VAR</code></pre>



<p>In a slightly more complicated example, you may have a databases.sh script containing more logic for setting up or exporting variables or otherwise setting up environments.</p>



<pre class="wp-block-code"><code>#!/usr/bin/env bash

db_env=$(pwd | awk -F '/' '{print $(NF-1)"/"$NF}')

if [[ "$db_env" == "stage/database" ]]; then
    # do stuff
    export TF_VAR_db_password="mypassword"

else [[ "$db_env" == "prod/database" ]]; then
    # do other stuff
    export TF_VAR_db_password="myotherpassword"
fi</code></pre>



<p><strong>Conclusion</strong></p>



<p>That&#8217;s pretty much.  Now you can automatically set environment variables for Terraform to use, based on the directory we are currently and no longer need to worry about setting and unsetting environment variables manually.</p>



<p>I HIGHLY recommend checking out direnv as well.  It offers slightly different functionality, and some neat features which in some cases may actually be better for specific tasks than ondir.  For example, the <a rel="noreferrer noopener" aria-label="direnv stdlib (opens in a new tab)" href="https://direnv.net/man/direnv-stdlib.1.html" target="_blank">direnv stdlib</a> has some great helpers to help configure environments cleanly.</p>



<p>For me, using ondir for managing my Terragrunt configs and direnv for managing other projects makes the most sense.</p>
 <!-- Easy Plugin for AdSense Unfiltered [count: 2 is not less than 2] --><p>The post <a href="https://thepracticalsysadmin.com/automatically-set-terraform-environment-variables/" target="_blank">Automatically set Terraform environment variables</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://thepracticalsysadmin.com/automatically-set-terraform-environment-variables/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">37050</post-id>	</item>
		<item>
		<title>Testing for Deprecated Kubernetes APIs</title>
		<link>https://thepracticalsysadmin.com/testing-for-deprecated-kubernetes-apis/</link>
					<comments>https://thepracticalsysadmin.com/testing-for-deprecated-kubernetes-apis/#comments</comments>
		
		<dc:creator><![CDATA[Josh Reichardt]]></dc:creator>
		<pubDate>Mon, 11 Nov 2019 05:17:18 +0000</pubDate>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Command Line]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Kubectl]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Security]]></category>
		<guid isPermaLink="false">https://thepracticalsysadmin.com/?p=37039</guid>

					<description><![CDATA[<p>Kubernetes API changes are coming up and I wanted to make a quick blog post to highlight what this means and show a few of things I have discovered to deal with the changes. First, there have been some relevant announcements regarding the changes and deprecations recently. The first being the API Depractions in 1.16 [&#8230;]</p>
<p>The post <a href="https://thepracticalsysadmin.com/testing-for-deprecated-kubernetes-apis/" target="_blank">Testing for Deprecated Kubernetes APIs</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Kubernetes API changes are coming up and I wanted to make a quick blog post to highlight what this means and show a few of things I have discovered to deal with the changes.</p>



<p>First, there have been some relevant announcements regarding the changes and deprecations recently.  The first being the <a rel="noreferrer noopener" aria-label="API Depractions in 1.16 (opens in a new tab)" href="https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/" target="_blank">API Depractions in 1.16</a> announcement, which describes the changes to the API and some of the things to look at and do to fix problems </p>



<p>The next post is the <a rel="noreferrer noopener" aria-label="Kubernetes 1.16 release (opens in a new tab)" href="https://kubernetes.io/blog/2019/09/18/kubernetes-1-16-release-announcement/" target="_blank">Kubernetes 1.16 release</a> announcement, which contains a section &#8220;Significant Changes to the Kubernetes API&#8221; that references the deprecation post.</p>



<p>Another excellent resource for learning about how Kubernetes deprecations work is the <a rel="noreferrer noopener" href="https://kubernetes.io/docs/reference/using-api/deprecation-policy/" target="_blank">API deprecation documentation</a>, highlighted in the deprecation post, but not widely shared.</p>



<p>In my opinion, the Kubernetes community really dropped the ball in terms of communicating these changes and missed an opportunity to describe and discuss the problems that these changes will create.  I understand that the community is gigantic and it would be impossible to cover every case, but to me, the few blog posts describing the changes and not much other official communication or guides for how to handle and fix the impending problems is a little bit underwhelming.</p>



<p>The average user probably doesn&#8217;t pay attention to these blog posts, and there are a lot of old Helm charts out in the wild still, so I&#8217;m confident that the incoming changes will create headaches and table flips when people start upgrading.  As an example, if you have an old API defined and running in a pre 1.16 cluster, and upgrade without fixing the API version first, APPS IN YOUR CLUSTER WILL BREAK.  The good news is that new clusters won&#8217;t allow the old API versions, making errors easier to see and deal with.</p>



<p><strong>Testing for and fixing deprecated APIs</strong></p>



<p>With that mini rant out of the way, there is a simple but effective way to test your existing configurations for API compatibility.</p>



<p>Conftest is a nice little tool that helps write tests against structured configuration data, using the Rego language using <a rel="noreferrer noopener" aria-label="Open Policy Agent (opens in a new tab)" href="https://www.openpolicyagent.org/docs/latest/" target="_blank">Open Policy Agent</a> (OPA).  Conftest works with many file types including JSON, TOML and HCL, which makes it a great choice for testing a variety of different configurations, but is especially useful for testing Kubernetes YAML configurations.</p>



<p>To get started, install <a rel="noreferrer noopener" href="https://github.com/instrumenta/conftest" target="_blank">conftest</a>.</p>



<pre class="wp-block-code"><code>wget https://github.com/instrumenta/conftest/releases/download/v0.15.0/conftest_0.15.0_Linux_x86_64.tar.gz
tar xzf conftest_0.15.0_Linux_x86_64.tar.gz
sudo mv conftest /usr/local/bin</code></pre>



<p>Then we can use the handy policy provided by the <a rel="noreferrer noopener" aria-label="deprek8 (opens in a new tab)" href="https://github.com/naquada/deprek8" target="_blank">deprek8</a> repo to validate the API versions.</p>



<pre class="wp-block-preformatted">curl https://raw.githubusercontent.com/naquada/deprek8/master/policy/deprek8.rego &gt; deprek8.rego
conftest test -p deprek8.rego sample/manifest.yaml</pre>



<p>Here&#8217;s what a FAIL condition might look like according to what is defined in the rego policy file for an outdated API version.</p>



<pre class="wp-block-code"><code>FAIL - sample/manifest.yaml - Deployment/my-deployment: API extensions/v1beta1 for Deployment is no longer served by default, use apps/v1 instead.</code></pre>



<p>The Rego policy is what actually defines the behavior that Conftest will display and as you can see, it found an issue with the Deployment object defined in the test manifest.</p>



<p>Below is the Rego policy that causes Conftest to spit out the FAILure message.  The syntax is clean and easy to follow, so writing and adjusting policies is easy.</p>



<pre class="wp-block-code"><code>_deny = msg {
  resources := ["DaemonSet", "Deployment", "ReplicaSet"]
  input.apiVersion == "extensions/v1beta1"
  input.kind == resources[_]
  msg := sprintf("%s/%s: API extensions/v1beta1 for %s is no longer served by default, use apps/v1 instead.", [input.kind, input.metadata.name, input.kind])
}</code></pre>



<p>Once you know what is wrong with the configuration, you can use the <strong>kubectl convert</strong> subcommand to fix up the existing deprecated API objects.  Again, attempting to create objects using deprecated APIs in 1.16 will be rejected automatically by Kubernetes, so you will only need to deal with converting existing objects in old clusters being upgraded.</p>



<p>From the above error, we know the object type (Deployment) and the version (extensions/v1beta1).  With this information we can run the convert command to fix the object.</p>



<pre class="wp-block-code"><code># General syntax
kubectl convert -f &lt;file> --output-version &lt;group>/&lt;version>

# The --output-version flag allows specifying the API version to upgrade to 
kubectl convert -f sample/manifest.yaml  --output-version apps/v1

# Omitting the --output-version flag will convert to the latest version
kubectl convert -f sample/manifest.yaml</code></pre>



<p>After the existing objects have been converted and any manifest files have been updated you should be safe to upgrade Kubernetes.</p>



<p><strong>Bonus</strong></p>



<p>There was a fantastic episode of TGIK awhile back called <a rel="noreferrer noopener" aria-label="Kubernetes API Removal and You (opens in a new tab)" href="https://github.com/vmware-tanzu/tgik/tree/master/episodes/084" target="_blank">Kubernetes API Removal and You</a> that describes in great detail what all of the deprections mean and how to fix them &#8211; definitely worth a watch if you have the time.</p>



<p><strong>Conclusion</strong></p>



<p>OPA and testing configurations using tools like conftest and Rego policies is a great way to harden and help standardize configurations.  Taken a step further, these configuration testing tools can be extended to test all sorts of other things.</p>



<p>Conftest looks especially promising because of the number of file types that it understands.  There is a lot of potential here for doing things like unit testing Kubernetes configuration files and other things like Terraform configs.</p>



<p>I haven&#8217;t written any Rego policies yet but the language looks pretty straight forward and easy to deal with.  I think that as configurations continue to evolve, tools like Conftest (OPA), <a href="https://github.com/instrumenta/kubeval" target="_blank" rel="noreferrer noopener" aria-label="Kubeval (opens in a new tab)">Kubeval</a> and <a rel="noreferrer noopener" aria-label="Kustomize (opens in a new tab)" href="https://github.com/kubernetes-sigs/kustomize" target="_blank">Kustomize</a> will gain more traction and help simplify some of the complexities of Kubernetes.</p>
 <!-- Easy Plugin for AdSense Unfiltered [count: 2 is not less than 2] --><p>The post <a href="https://thepracticalsysadmin.com/testing-for-deprecated-kubernetes-apis/" target="_blank">Testing for Deprecated Kubernetes APIs</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://thepracticalsysadmin.com/testing-for-deprecated-kubernetes-apis/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">37039</post-id>	</item>
		<item>
		<title>Quickly securing local secrets</title>
		<link>https://thepracticalsysadmin.com/quickly-securing-local-secrets/</link>
					<comments>https://thepracticalsysadmin.com/quickly-securing-local-secrets/#comments</comments>
		
		<dc:creator><![CDATA[Josh Reichardt]]></dc:creator>
		<pubDate>Sun, 15 Sep 2019 19:05:54 +0000</pubDate>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Command Line]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<guid isPermaLink="false">https://thepracticalsysadmin.com/?p=37017</guid>

					<description><![CDATA[<p>One thing I have run into recently and have been thinking about a little bit lately, is a simple way to hide environment variables that contain sensitive information. For example, when working in a local environment, if you need access to a secret like an oauth token or some authentication method to an API, the [&#8230;]</p>
<p>The post <a href="https://thepracticalsysadmin.com/quickly-securing-local-secrets/" target="_blank">Quickly securing local secrets</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>One thing I have run into recently and have been thinking about a little bit lately, is a simple way to hide environment variables that contain sensitive information.  For example, when working in a local environment, if you need access to a secret like an oauth token or some authentication method to an API, the first inclination is usually to just hard code the secret contents into your local bash/zsh profile so that it can be read anytime you need access to it.  This method obviously will work but if the filesystem itself isn&#8217;t encrypted, the secret can easily be leaked and for a small amount of effort I believe I have found an effective way of shrinking the visibility of these secrets.</p>



<p>Inspired by the <a rel="noreferrer noopener" aria-label="aws-vault (opens in a new tab)" href="https://github.com/99designs/aws-vault" target="_blank">aws-vault</a> tool which is a simple but secure way of storing local AWS credentials in environment variables using a local password store, in this post I will show you a quick and dirty way to add an extra layer of security to your (other) local environment by injecting sensitive secrets stored in an encrypted location (password store) into your local terminal.  This method works for both OSX and Linux and is just a few lines of configuration and examples for both OSes are shown below.</p>



<p>In OSX the keychain is a good starting place for storing and retrieving secrets and in Linux the combination of GPG and <a rel="noreferrer noopener" aria-label="the standard unix password manager (opens in a new tab)" href="https://www.passwordstore.org/" target="_blank">the standard unix password manager</a> &#8220;pass&#8221; work well together.  Pass also works on OSX if you aren&#8217;t a fan of keychain.</p>



<p>Below are steps for storing and retrieving local secrets using the Linux pass tool.  There are installation instructions and full documentation for how to use the tool in the link above.  It should also be noted that the system needs to have GPG installed in order to write and read secrets.</p>



<p>One you have GPG configured, create the password store.  I am skipping most of the GPG configuration because there is a lot to know, the command below should be enough to get things started.  If you already have GPG set up and configured you can skip the setup.</p>



<p>Set up GPG and pass.</p>



<pre class="wp-block-code"><code>gpg2 --full-gen-key # follow prompts to create a gpg store with defaults
pass init &lt;email> # use the same email address used with gpg
pass git init # optionally set pass up as a git repo</code></pre>



<p>To create/edit a secret.</p>



<pre class="wp-block-code"><code>#pass insert/edit &lt;secret>
pass insert mysecret
pass edit mysecret</code></pre>



<p>Pass allows for hierarchies but in the example we are just going to put the secret at the top level.  The command above will open the default editor.  After closing the editor, the password will be written to an encrypted file in ~/.password-store.  Once you have added the password you can show the contents of the newly added secret.</p>



<p>To read a secret into the terminal.</p>



<pre class="wp-block-code"><code>#pass show &lt;secret>
pass show mysecret</code></pre>



<p>You can also quickly list all of your secrets.</p>



<pre class="wp-block-code"><code>pass ls</code></pre>



<p>Now that we have a created secret, we can write a little bash function to pull out the contents of the password and export them as an environment variable when the shell gets sourced.  Put the following snippet into your ~/.bashrc, ~/.zshrc or ~/.bashprofile to read secrets.</p>



<pre class="wp-block-code"><code>get_password () {
  pass show "$1"
}</code></pre>



<p>A similar result can be achieved in OSX using the &#8220;security&#8221; command line tool.</p>



<pre class="wp-block-code"><code>get_password () {
  security find-generic-password -ga "$1" -w
}</code></pre>



<p>In your shell configuration file you can simply export the result of calling the get_password() function into an environment variable.</p>



<pre class="wp-block-code"><code>export MYSECRET="$(get_password mysecret)"</code></pre>



<p>Source the shell profile to pickup the new changes.  After that, you should now see the contents of the secret inside an environment variable in your terminal.</p>



<pre class="wp-block-code"><code>source ~/.bashrc
env | grep MYSECRET</code></pre>



<p><strong>Conclusion</strong></p>



<p>Obviously this isn&#8217;t a perfect way to secure your environment since the secret is available to anyone who is able to connect to this user so make sure you practice good security in as many other ways as possible.</p>



<p>What this method does do though is cuts down the amount of sensitive information that can be gleaned from a user account by ensuring that shell secrets are encrypted at rest and unavailable as clear text.</p>
 <!-- Easy Plugin for AdSense Unfiltered [count: 2 is not less than 2] --><p>The post <a href="https://thepracticalsysadmin.com/quickly-securing-local-secrets/" target="_blank">Quickly securing local secrets</a> first appeared on <a href="https://thepracticalsysadmin.com/" target="_blank">Practical System Administration</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://thepracticalsysadmin.com/quickly-securing-local-secrets/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">37017</post-id>	</item>
	</channel>
</rss>
