Automate Your Initial OS Setup
Tags: programming, bash, os, terminal
Published: 2020-03-22 10:25:49

---
title: Automate Your Initial OS Setup
published: true
description: Learn how to automate the manual process of installing software and dealing with common settings & configurations each time you reinstall your OS
tags: programming,bash,os,terminal
cover_image:  https://pmihaylov.com/wp-content/uploads/2020/03/star-wars-r2-d2-2085831-1-scaled-e1584872725803.jpg
canonical_url: https://pmihaylov.com/automate-os-setup
---
<!-- wp:paragraph -->
<p>There was a time in my life when a huge part of my time was spent reinstalling my Linux OS. Wonder why?</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Well, the first time you install Linux, they warn you to never run <code>rm- rf /</code> as this would delete your entire system. Fair enough, that's simple to follow.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>What they don't tell you is that you have another million ways to effectively do the same thing with commands which seem harmless at first glance.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>However, there were some benefit form my misfortunes. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>What irritated me the most was installing all the software I use from scratch every single time. I often forgot to install one or two programs I use and had to do it on the fly once I actually needed them which was very disturbing.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Hence, I came up with the idea to create a script which would automate this process via a single command. Every time I reinstall my OS, I simply run the script, go get myself a coffee and once I'm back, I have my OS all setup with what I need.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>If you're in a situation where you often have to do this yourself, read on.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Also, be aware that this guide is specific to installing Linux and Mac OS. You could probably apply the same concept in Windows, but I only speak <code>bash</code>, not <code>bat</code>. </p>
<!-- /wp:paragraph -->

<!-- wp:more -->
<!--more-->
<!-- /wp:more -->

<!-- wp:heading -->
<h2>Bash to the rescue</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Now, there are tools out there specifically designed to achieve this. For example, you have <a href="https://puppet.com/">Puppet</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Additionally, you could create docker images which have your setup bundled in an image. You could also use <a href="https://www.archlinux.org/">Arch Linux</a>, which has a package manager enabling you to automate this more reliably, so I've been told.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>But, I'm a simple man. I like simple tools. Hence, I've encapsulated this entire convoluted process in a single bash script.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>You can find my entire OS setup script <a href="https://github.com/preslavmihaylov/default-setups">here</a>. Nowadays, I have two different versions - one for Ubuntu and one for Mac.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>But, to get started yourself, here's what you have to do:</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Reinstall your OS</li><li>Create a new empty script &amp; add it to some kind of a repo (e.g. in Github)</li><li>Every time you install a new program or enable some setting, add a line for that in the script</li><li>Over time, when your needs or setup changes, keep your script up to date</li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>That's really the gist of it.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The important thing is to keep your script up to date, otherwise, you might abandon it altogether and stick to the old cumbersome ways of installing stuff manually.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>What follows is a set of tips &amp; tricks to have in mind</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Automate your settings as well</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Apart from enumerating all the software you need in <code>sudo apt-get install</code> lines, you can also add any additional settings not related to software install that you might need.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>For example, I need Bulgarian Phonetic installed on my Ubuntu, which is not there by default, hence I've figured out how to do it from the terminal and added it to my script. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>I no longer have to google "add keyboard mapping ubuntu" every time I reinstall the OS.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The good part is that most of these settings, especially in Linux, are totally scriptable. They often have GUI ways to do it (e.g. Go to Settings -&gt; Keyboard -&gt; ..., etc) but I always search for the terminal one-liners in order to add it to the script.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>When the settings aren't scriptable...</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>There might be times when there isn't an alternative to setting something up via the GUI. Or at least, Google isn't helpful enough to show you how to do it in sensible time.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>For these cases, I still suggest to "automate" them, but not via a script, but via written instructions in your <code>README.md</code> which you have to manually follow.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This is a bit cumbersome, but still better than trying to rediscover how to setup something every time you reinstall the OS.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Here's an example from my <a href="https://github.com/preslavmihaylov/default-setups/tree/master/mac">Mac setup</a>: </p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":1002,"sizeSlug":"large"} -->
<figure class="wp-block-image size-large"><img src="https://i2.wp.com/pmihaylov.com/wp-content/uploads/2020/03/image.png?fit=676%2C650&amp;ssl=1" alt="" class="wp-image-1002"/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>I've found this to be more common for Mac, since most answers in stackoverflow regarding how to setup something are via a GUI interface, which sucks.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>I'm pretty sure there is a way to achieve all these settings via the terminal, but I've decided not to invest too much time in finding them out. However, if you happen to know how to do it, then feel free to open a pull request, it would be much appreciated. :)</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Store a repo of common configurations</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>In addition to automating the settings and software you need, if you rely on software like <a href="https://pmihaylov.com/vim-better-developer/">vim</a>, tmux or anything else which has some convoluted configuration, I suggest creating a separate repo for storing your configurations.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Getting it "installed" can be part of your OS setup script. This is exactly what I've done with my <a href="https://github.com/preslavmihaylov/dotfiles">dotfiles</a> repo. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In it,  I keep my latest vim configuration, along with some auxiliary configs for tmux and various plugins.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Due to this, after I run my setup script, not only do I have all my necessary software installed, but I also have my vim setup with my favorite plugins and configuration the way I like it.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Tired of installing the same software all the time? Tired of setting up vim every time you get a new laptop or reinstall your OS?</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Well, now you have your solution - automate the process. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Here's how in a nutshell:</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Create a script</li><li>Add your installations + settings + common configurations</li><li>Repeat step 2 infinitely</li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Once you do this, you will escape the insidious process of setting up everything from scratch all the time.</p>
<!-- /wp:paragraph -->