<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[AkrOps Blog]]></title><description><![CDATA[Cloud, DevOps, Linux, web development and tech in general]]></description><link>https://blog.akrops.com/</link><image><url>https://blog.akrops.com/favicon.png</url><title>AkrOps Blog</title><link>https://blog.akrops.com/</link></image><generator>Ghost 5.12</generator><lastBuildDate>Sat, 11 Apr 2026 19:09:34 GMT</lastBuildDate><atom:link href="https://blog.akrops.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Cryptography crash course]]></title><description><![CDATA[Modern cryptography and its applications can be easily understood at a high level by understanding its three main mechanisms: symmetric encryption, asymmetric encryption and hashing.]]></description><link>https://blog.akrops.com/cryptography-crash-course/</link><guid isPermaLink="false">6162fd48fba2bb0001140ffd</guid><category><![CDATA[Cryptography]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Joaquín Bermúdez Castanheira]]></dc:creator><pubDate>Tue, 12 Oct 2021 13:41:33 GMT</pubDate><media:content url="https://blog.akrops.com/content/images/2022/09/mauro-sbicego-4hfpVsi-gSg-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.akrops.com/content/images/2022/09/mauro-sbicego-4hfpVsi-gSg-unsplash.jpg" alt="Cryptography crash course"><p>Modern cryptography and its applications can be easily understood at a high level by understanding its three main mechanisms: symmetric encryption, asymmetric encryption and hashing.</p><h1 id="symmetric-cryptography">Symmetric cryptography</h1><p>Let&apos;s start with symmetric-key cryptography, symmetric cryptography, or simply symmetric encryption, as this is what most of us will think of when talking about encryption. The term <strong>symmetric</strong> comes from the fact that the <strong>same key</strong> is used in order to <strong>encrypt</strong> and <strong>decrypt</strong> data.</p><p>Let&apos;s say you have a piece of sensitive information you want to keep safe. You can encrypt this information using a <strong>cipher</strong>, which is an algorithm used to perform encryption and decryption. In addition to your data you must also provide a secret key, and the cipher will process your data and output it in an encrypted format. <strong>Note</strong>: the key used in the diagram is a silly example, please avoid this type of patterns.</p><figure class="kg-card kg-image-card"><img src="https://blog.akrops.com/content/images/2021/10/image.png" class="kg-image" alt="Cryptography crash course" loading="lazy" width="2000" height="1125" srcset="https://blog.akrops.com/content/images/size/w600/2021/10/image.png 600w, https://blog.akrops.com/content/images/size/w1000/2021/10/image.png 1000w, https://blog.akrops.com/content/images/size/w1600/2021/10/image.png 1600w, https://blog.akrops.com/content/images/size/w2400/2021/10/image.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>The data provided as input is said to be in <strong>plain text</strong>, and the output of the cipher is commonly known as <strong>ciphertext</strong>. Don&apos;t be misled by these terms, as this doesn&apos;t mean you can only encrypt text files. You can encrypt any file type you can think of.</p><figure class="kg-card kg-image-card"><img src="https://blog.akrops.com/content/images/2021/10/image-1.png" class="kg-image" alt="Cryptography crash course" loading="lazy" width="2000" height="1125" srcset="https://blog.akrops.com/content/images/size/w600/2021/10/image-1.png 600w, https://blog.akrops.com/content/images/size/w1000/2021/10/image-1.png 1000w, https://blog.akrops.com/content/images/size/w1600/2021/10/image-1.png 1600w, https://blog.akrops.com/content/images/size/w2400/2021/10/image-1.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>If you have the ciphertext and the key, you can <strong>revert</strong> the process and get your data back. This process is known as <strong>decryption</strong>.</p><p>The most widely used symmetric-key cipher used nowadays is named <strong>AES</strong>, which stands for the <strong>Advanced Encryption Standard</strong>.</p><h2 id="don-t-lose-or-expose-your-key-">Don&apos;t lose or expose your key!</h2><p><strong>If you lose your key, you lose your data</strong>. You could try to brute force decryption, that is, trying out every possible combination for the key, but... for AES 256 it would take you roughly 13,689 trillion trillion trillion trillion years using 2 billion high-end computers.</p><p>This is how <strong>ransomware</strong> works: it encrypts your data and then asks you to pay for the key. If you don&apos;t pay, your data is pretty much gone.</p><p>Also, remember that <strong>anyone in possession of your key will be able to decrypt your data</strong>.</p><h2 id="ace-beatrix-and-evo">Ace, Beatrix, and Evo</h2><p>Let&apos;s say Ace wants to send Beatrix a message over an insecure channel like the Internet, but Evo has successfully performed a <strong>Man In The Middle</strong> attack and is eavesdropping on their communication.</p><figure class="kg-card kg-image-card"><img src="https://blog.akrops.com/content/images/2021/10/image-2.png" class="kg-image" alt="Cryptography crash course" loading="lazy" width="2000" height="1125" srcset="https://blog.akrops.com/content/images/size/w600/2021/10/image-2.png 600w, https://blog.akrops.com/content/images/size/w1000/2021/10/image-2.png 1000w, https://blog.akrops.com/content/images/size/w1600/2021/10/image-2.png 1600w, https://blog.akrops.com/content/images/size/w2400/2021/10/image-2.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>If the message is in plain text and Evo manages to intercept it, he will be able to read it. However, if Ace and Beatrix had previously agreed on a key, they could encrypt their messages using AES and Evo wouldn&apos;t be able to read them.</p><p>But what if they haven&apos;t performed this key exchange beforehand but they still need to achieve secrecy and privacy despite communicating over an insecure channel?</p><h1 id="asymmetric-key-or-public-key-cryptography">Asymmetric-key or public-key cryptography</h1><p>This is where <strong>asymmetric cryptography</strong> will come in handy. It&apos;s called asymmetric-key cryptography or simply asymmetric cryptography because there are <strong>two complementary keys</strong> involved: whatever you encrypt with one can only be decrypted with the other, and vice-versa.</p><p>One is commonly referred to as a <strong>public key</strong>, while the other is known as a <strong>private key</strong>. As their names imply, the public key can be freely distributed, but the private key must remain unknown to everybody but its owner. This is also why asymmetric cryptography is also commonly known as <strong>public-key cryptography</strong>.</p><p><strong>Anyone who knows your public key can send you encrypted data that only you will be able to decrypt</strong>.</p><p>The opposite is also true, that is, if you encrypt data with your private key, it can only be decrypted with your public key. This operation is known as <strong>signing</strong> and can be used as a form of <strong>authentication</strong>: since only you have access to your private key, only you could have encrypted that data, and your signature can be <strong>verified</strong> by decrypting it with your public key.</p><h2 id="back-to-abe-privacy">Back to ABE - privacy</h2><p>Back to our example. If Ace wants to send a private message to Beatrix, she can now send him her public key. She could even publish it in an online forum she and Ace might frequent, or attach it to all of her emails, which is a very common practice.</p><figure class="kg-card kg-image-card"><img src="https://blog.akrops.com/content/images/2021/10/image-6.png" class="kg-image" alt="Cryptography crash course" loading="lazy" width="1920" height="1080" srcset="https://blog.akrops.com/content/images/size/w600/2021/10/image-6.png 600w, https://blog.akrops.com/content/images/size/w1000/2021/10/image-6.png 1000w, https://blog.akrops.com/content/images/size/w1600/2021/10/image-6.png 1600w, https://blog.akrops.com/content/images/2021/10/image-6.png 1920w" sizes="(min-width: 720px) 720px"></figure><p>The key with the green background is Beatrix&apos;s public key. Evo can also intercept it, but it doesn&apos;t matter, because well... It&apos;s public after all.</p><p>Ace can now use Beatrix&apos;s public key to encrypt the message and send it to her (red padlock).</p><figure class="kg-card kg-image-card"><img src="https://blog.akrops.com/content/images/2021/10/image-7.png" class="kg-image" alt="Cryptography crash course" loading="lazy" width="1920" height="1080" srcset="https://blog.akrops.com/content/images/size/w600/2021/10/image-7.png 600w, https://blog.akrops.com/content/images/size/w1000/2021/10/image-7.png 1000w, https://blog.akrops.com/content/images/size/w1600/2021/10/image-7.png 1600w, https://blog.akrops.com/content/images/2021/10/image-7.png 1920w" sizes="(min-width: 720px) 720px"></figure><p>Since Beatrix&apos;s got the matching private key (red), she can now decrypt the message.</p><p>Evo can also intercept this message, but he can&apos;t infer anything about Beatrix&apos;s private key using her public key or Ace&apos;s ciphertext, so he can&apos;t decrypt the latter.</p><p>An extremely common use case for public-key cryptography is to exchange a key that will be used for symmetric encryption, since the latter is far more efficient than the former and can make a difference, especially when having to encrypt large pieces of information. The most common way to perform this key exchange is using the Diffie-Hellman method.</p><p>The two most common variants of public-key cryptography used nowadays are the RSA algorithm and Elliptic-curve cryptography (ECC).</p><h2 id="don-t-expose-or-lose-your-private-key-">Don&apos;t expose or lose your private key!</h2><p>Malicious users in possession of your private key will be able to decrypt anything encrypted with your public key, which was most likely private data meant for your eyes only.</p><p>They could also impersonate you since they can &quot;forge&quot; your digital signature, proving the ownership of the private key that only you are supposed to have access to.</p><p>If you think your private key might have been compromised, generate a new pair and spread the word so that everybody knows they should use your new public key and not the old one.</p><p>If you happen to lose access to your private key, naturally you will not be able to decrypt anything that was encrypted with your public key or use your digital signature anymore. This is the reason why many coins are lost forever in cryptocurrencies, and also why the first thing you&apos;re told to do when you create a software wallet or acquire a hardware wallet is to write down your seed phrase: a set of random words your private keys originate from. If you lose access to your wallet, you can recover it by using the seed phrase. Needless to say, you should keep these words somewhere safe, as anyone in possession of it will be able to steal all your funds.</p><h2 id="abe-integrity">ABE integrity</h2><p>Ace and Beatrix can now keep their communication private thanks to encryption.</p><p>However, what if Evo decides to still intercept the message and mess around with it? Even worse, what if Evo knew about the format of specific messages Ace and Beatrix exchange frequently. For example, he might know that some messages start with a bank account number, and he could alter a few bytes so that it appears to be a different number once decrypted, just to mess around with Ace and Beatrix.</p><p>Ace and Beatrix now need a way to check the <strong>integrity</strong> of their messages.</p><h1 id="hashing">Hashing</h1><p>This is where hashing can help.</p><p>A <strong>hash function</strong> takes a piece of data of any size as input and outputs a fixed-length value called <strong>digest</strong>, hash value, hash code, or simply <strong>hash</strong>. The process is commonly known as <strong>hashing</strong>.</p><figure class="kg-card kg-image-card"><img src="https://blog.akrops.com/content/images/2021/10/image-8.png" class="kg-image" alt="Cryptography crash course" loading="lazy" width="1920" height="1080" srcset="https://blog.akrops.com/content/images/size/w600/2021/10/image-8.png 600w, https://blog.akrops.com/content/images/size/w1000/2021/10/image-8.png 1000w, https://blog.akrops.com/content/images/size/w1600/2021/10/image-8.png 1600w, https://blog.akrops.com/content/images/2021/10/image-8.png 1920w" sizes="(min-width: 720px) 720px"></figure><p>Hash functions are one-way functions, in other words, they are <strong>irreversible</strong>. This means you can infer nothing from the input using the output. This is why it is considered a best practice to store <strong>passwords digests in databases</strong>, instead of the passwords themselves (as always, there are pitfalls to be avoided, but we will discuss them in another post).</p><p>There are <strong>no keys</strong> involved in this case, although the input data is sometimes referred to as the key. The output only depends on the input, so the <strong>same input</strong> will always produce the <strong>same output</strong>.</p><p>The most widely used hash algorithm nowadays is SHA-2, which stands for secure hashing algorithm version 2. The length of the output of SHA-2 can be either 224, 256, 384, or 512 bits. SHA variants are commonly referenced by their length instead of the version, e.g. SHA-256, which is the most widespread.</p><p>An interesting property of hash functions is that any tiny change in the input will cause a dramatic change in the output.</p><p>Take a look at these two SHA-256 digests for two strings that only differ in 1 byte (1 bit actually).</p><pre><code class="language-YAML">0000000000000000000000000000000000000000000000000000000000000000
827d096d92f3deeaa0e8070d79f45beb176768e57a958a1cd325f5f4b754b048

0000000000000000000000000000000000000000000000000000000000000001
f774fbb3f4cc0777bc80b6e86e6bf5ab70e2875ecc4c8cf102840d801a9a74ab</code></pre><p>This mechanism allows us to check if there&apos;s been any change in our data, which could be caused by an error, or by a malicious actor like Evo.</p><h2 id="back-to-abe-integrity">Back to ABE - integrity</h2><p>Now that we have hashing, Ace can provide proof of integrity to Beatrix.</p><p>But is it enough with computing the hash of the message and sending it along? You might have already seen the problem with this approach: Evo can simply alter the message and recompute the hash, before forwarding it to Beatrix.</p><p>What Ace can do now, just like Beatrix did, is generating his own asymmetric key pair. Now, instead of just sending the digest of his message along, he can <strong>sign it</strong>, i.e. encrypt it with his private key. All Beatrix needs in order to verify this signature is Ace&apos;s public key.</p><p>You might also be thinking: anyone with access to the public key, including Evo, can still check the value of the hash now. Indeed, he could, and he could even recompute it, but he can&apos;t <strong>sign</strong> it, because he doesn&apos;t have Ace&apos;s <strong>private key</strong>. In other words, he can&apos;t break this <strong>authentication </strong>mechanism.</p><p>Evo could now start flipping bits like a maniac before forwarding the message to Beatrix, but thanks to these mechanisms she would realize that the channel has been compromised and would warn Ace.</p><p>Ace could have also signed the message itself by encrypting it with his private key, but it&apos;s a far more common practice to sign a digest instead, and there are two main reasons for this:</p><ul><li>As discussed, it provides proof of <strong>integrity</strong>.</li><li>It&apos;s far more <strong>efficient</strong>, as it&apos;s much faster to compute a hash and then sign it than using asymmetric cryptography to encrypt a file or message that could be massive when compared to the short and fixed length of a hash.</li></ul><h1 id="cryptography-mechanisms-and-security-properties-recap">Cryptography mechanisms and security properties - recap</h1><ul><li>Thanks to symmetric and asymmetric <strong>encryption</strong>, Ace and Beatrix have achieved <strong>privacy</strong>.</li><li>Thanks to <strong>hashing</strong>, they have achieved <strong>integrity</strong>.</li><li>Thanks to public-key cryptography, in particular the <strong>signing</strong> and <strong>verifying</strong> operations, they have achieved <strong>authentication</strong>, i.e. the message is authentic and there&apos;s proof of its source or origin.</li><li>They have also achieved <strong>non-repudiation</strong> (short for non-repudiation of origin). In this case, Ace won&apos;t be able to deny that he was the author of the message.</li></ul>]]></content:encoded></item><item><title><![CDATA[Resource targetting in Terraform - getting rid of that pesky blocker]]></title><description><![CDATA[Terraform allows us to target particular resources. This can be extremely useful to remove blockers, e.g. when some deletion protection in a resource is preventing us from taking down an entire project.]]></description><link>https://blog.akrops.com/resource-targetting-in-terraform-getting-rid-of-that/</link><guid isPermaLink="false">601d9ef5a234b900016cf466</guid><category><![CDATA[Terraform]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Joaquín Bermúdez Castanheira]]></dc:creator><pubDate>Sat, 06 Feb 2021 00:26:50 GMT</pubDate><media:content url="https://blog.akrops.com/content/images/2022/09/engin-akyurt-bPiuY2ZSlvU-unsplash-1.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.akrops.com/content/images/2022/09/engin-akyurt-bPiuY2ZSlvU-unsplash-1.jpg" alt="Resource targetting in Terraform - getting rid of that pesky blocker"><p>Picture the following scenario:</p>
<ul>
<li>A software project has reached the end of its lifecycle and you want to take it down, destroying all of the AWS infrastructure that you have provisioned using Terraform.</li>
<li>This set of resources includes an RDS instance.</li>
<li>You run <code>terraform destroy</code> and, after double checking the mass destruction plan, you push the red button.</li>
<li>Destruction begins and you observe in ecstasy as the logs go by.</li>
<li>Your hysterical evil laugh is abruptly interrupted by the following message:<br>
<code>Error: DB Instance FinalSnapshotIdentifier is required when a final snapshot is required</code></li>
</ul>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.akrops.com/content/images/2021/02/nani.gif" class="kg-image" alt="Resource targetting in Terraform - getting rid of that pesky blocker" loading="lazy" width="498" height="278"></figure><p></p><p>To make things worse, the instance has prevented the destruction of all of the resources upon which it depended: the VPC and its subnets, security groups, etc.</p><p>Two things can happen now:</p><!--kg-card-begin: markdown--><p>a) In a mix of cold sweat, extreme relief and silly laughter, you realize you actually needed a final snapshot... In this case you would add this to your <code>aws_db_instance</code> resource:<br>
<code>final_snapshot_identifier = &quot;nyse_stonks_final_snapshot&quot;</code></p>
<p>b) You don&apos;t care about the darn thing or you already have a proper backup, so instead:<br>
<code>skip_final_snapshot = true</code></p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>No matter which path you choose, here comes the paradox: you now need to apply these changes in order to be able to destroy the remaining resources. But, of course, if you simply run <code>terraform apply</code>, you are going to create again all the resources you have already destroyed...</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.akrops.com/content/images/2021/02/confused1.gif" class="kg-image" alt="Resource targetting in Terraform - getting rid of that pesky blocker" loading="lazy" width="504" height="322"></figure><p></p><p>Good news is: you can actually apply changes to a single resource by first targetting it.</p><!--kg-card-begin: markdown--><p>We can first check what resources are still there and identify the RDS instance by running <code>terraform state list</code>. Your list might look similar to this one:</p>
<pre><code class="language-javascript">aws_db_instance.nyse_stonks_db
aws_db_subnet_group.nyse_stonks_db
aws_security_group.nyse_stonks_db
module.vpc.aws_subnet.private[0]
module.vpc.aws_subnet.private[1]
module.vpc.aws_subnet.private[2]
module.vpc.aws_vpc.this[0]
</code></pre>
<p>Terraform allows us not only to save our plan into a file, but to target specific resources as well, so let&apos;s do both:<br>
<code>terraform plan -target aws_db_instance.nyse_stonks_db -out evil.plan</code></p>
<p>As expected, there will be a single change in this plan, e.g.</p>
<pre><code class="language-javascript">~ resource &quot;aws_db_instance&quot; &quot;nyse_stonks_db&quot; {
    ...
  ~ skip_final_snapshot                   = false -&gt; true
    ...
}
</code></pre>
<p>Let&apos;s proceed to apply the plan by running:<br>
<code>terraform apply evil.plan</code></p>
<p>Don&apos;t forget to remove the plan unless you have a pattern under .gitignore, or it might accidentally end up under version control (it happened to a friend of mine).</p>
<p>And finally, if you are still <strong>148% sure</strong> that you want to destroy everything:<br>
<code>terraform destroy -auto-approve</code></p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.akrops.com/content/images/2021/02/nuke.gif" class="kg-image" alt="Resource targetting in Terraform - getting rid of that pesky blocker" loading="lazy" width="320" height="179"></figure><p>Observe with immense joy as you have finally managed to destroy all the things.</p><p>Another typical case where this approach can be useful is in case you forget to remove the deletion protection on EC2 instances, ALBs, etc.</p>]]></content:encoded></item><item><title><![CDATA[An overview of systemd]]></title><description><![CDATA[Systemd is a Linux init system and software suite developed mainly as an effort to standardize the Linux init system.]]></description><link>https://blog.akrops.com/introduction-to-systemd/</link><guid isPermaLink="false">5fe65eeaa234b900016cec09</guid><category><![CDATA[Linux]]></category><category><![CDATA[Sysadmin]]></category><dc:creator><![CDATA[Joaquín Bermúdez Castanheira]]></dc:creator><pubDate>Wed, 30 Dec 2020 15:52:46 GMT</pubDate><media:content url="https://blog.akrops.com/content/images/2022/09/arthur-mazi-6148mnVnY-s-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.akrops.com/content/images/2022/09/arthur-mazi-6148mnVnY-s-unsplash.jpg" alt="An overview of systemd"><p>Systemd is a Linux init system and software suite developed mainly as an effort to <strong>standardize the Linux init system. </strong>It has effectively replaced others like <a href="https://wiki.archlinux.org/index.php/SysVinit">SysV init</a> or <a href="https://en.wikipedia.org/wiki/Upstart_(software)">upstart</a> in most distros, although it keeps a very high degree of backwards compatibility with the former. It has been adopted by most Linux distributions since 2015.</p><h2 id="what-is-an-init-system">What is an init system?</h2><p>An init (short for <em>initialization</em>) system or process is the first process started by the Linux kernel during boot, bringing up and maintaining <a href="https://en.wikipedia.org/wiki/User_space">userspace</a> services. Systemd shares a few traits with most init systems:</p><ul><li>Since it&apos;s the first process to start, it bears the process identifier (PID) 1.</li><li>It has no parent process. This is denoted with a parent PID (PPID) of 0.</li><li>It will continue to run until the system is shut down.</li><li>It is the common ancestor for every process.</li><li>It automatically adopts all orphaned processes.</li></ul><p>The kernel thread daemon, kthreadd, has in most cases PID 2 and is usually the only process other than systemd that has no parent. All kernel threads are forked from this process.</p><!--kg-card-begin: markdown--><p>Separate instances of systemd are started for logged-in users to start their services. That is why if you start going down the tree, i.e. towards the root (init) or looking for the parent of each process, you will most likely hit a process whose command looks something like <code>/lib/systemd/systemd --user</code> and in most cases this will be a direct child of the actual init process with PID 1.</p>
<p>The standard init process can actually be replaced with some other binary (e.g. <code>/bin/bash</code>) via the kernel init argument, but this is meant to be a temporary change in order to do some troubleshooting (or hacking ;) ) and of course it will deprive the user or sysadmin from every service offered by it.</p>
<!--kg-card-end: markdown--><h2 id="why-is-systemd-so-hated-by-many">Why is systemd so hated by many?</h2><p>Even though to the eyes of most Linux users and system administrators it is essentially a new standardized init process, it provides utilities for a wide array of tasks including device management, login management, network connection management, and event logging (the init component is actually known as the system and service manager). This goes against one of the fundamental principles of the <a href="https://en.wikipedia.org/wiki/Unix_philosophy">Unix philosophy</a>: &quot;Make each program do one thing well&quot;.</p><p>Despite the fact that systemd is actually a software suite rather than a single application, many consider it to be bloated. For example, systemd has its own UEFI boot manager called <a href="https://wiki.archlinux.org/index.php/Systemd-boot">systemd-boot</a>, but most distributions keep using <a href="https://www.gnu.org/software/grub/">GRUB</a> instead and will most likely continue to do so.</p><p>In any case, usage of all the components of the suite is by no means mandatory and every Linux user can choose which ones to use.</p><h2 id="units">Units</h2><p>Units represent resources managed by systemd. Each unit can declare required or optional dependencies on other units in the system, ensuring that at least all of its required dependencies are up and running before starting it.</p><p>Units don&apos;t have to be exclusively services, and despite the core component of systemd being an init system, it&apos;s not mandatory for all units managed by systemd to be started at boot.</p><h4 id="unit-files-and-their-locations">Unit files and their locations</h4><p>In order to create a unit, you only need to create a text file describing its configuration. Unit files are commonly found under three different locations:</p><!--kg-card-begin: markdown--><ul>
<li><code>/lib/systemd/system</code>: units managed by packages or the OS.</li>
<li><code>/etc/systemd/system</code>: these are usually managed by the sysadmin and can override unit files under <code>/lib</code> (this is the most appropriate place for making changes).</li>
<li><code>/run/systemd/system</code>: non-persistent runtime modifications (remember a filesystem of type tmpfs is mounted under /run).</li>
</ul>
<!--kg-card-end: markdown--><h4 id="naming-convention">Naming convention</h4><p>Unit files are named following a &quot;name.type&quot; convention, e.g.</p><!--kg-card-begin: markdown--><ul>
<li><code>docker.service</code>: the docker service unit.</li>
<li><code>ssh.socket</code>: a unit of type socket for accepting ssh connections.</li>
<li><code>reboot.target</code>: the reboot target-type unit (more on targets later).</li>
</ul>
<!--kg-card-end: markdown--><p>These are the three most common types of units, but there are several others like device, mount, swap, path, timer, etc.</p><h4 id="anatomy-of-a-unit-file">Anatomy of a unit file</h4><p>Unit files are organized in sections denoted by square brackets, e.g. [Section]. The [Unit] section is common to every unit file, and others like [Service] are specific to a type of unit. Sections contain directives in the form Key=Value.</p><p>Let&apos;s analyze the sections and their directives in a standard unit file for the Nginx web server and reverse proxy:</p><!--kg-card-begin: markdown--><pre><code>[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target
</code></pre>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>The <strong>Unit</strong> section is generally used for defining metadata for the unit and defining its relationship with other units.</p>
<ul>
<li>Description: a short description of the unit, usually including its name.</li>
<li>Documentation: it can reference one or more man pages instead of a url if there are any available.</li>
<li>After: this unit should be started after all the units referenced in this directive. This does not imply dependency and such must be defined through either the <code>Requires</code>, <code>Wants</code> or <code>BindsTo</code> directives.</li>
<li>Wants: establishes a dependency on the units listed here. Unlike <code>Requires</code>, which is more strict, this unit will continue to function if its dependencies are not found or fail to start. <code>Wants</code> is recommended instead of <code>Requires</code>.</li>
</ul>
<p>The <strong>Service</strong> section is unique and mandatory for all units of type service.</p>
<ul>
<li>Type: specifies the type of service according to the behavior of its process. In this case, <code>forking</code> means that the service forks into a child process, the parent exits and the child continues to run as the service main process.</li>
<li>PIDFile: a path referring to the PID file of the service used in combination with <code>Type=forking</code> so that systemd can reliably identify the main process of the service (whose PID will be stored in the MAINPID environment variable and used later by <code>ExecReload</code> and <code>ExecStop</code> in this case).</li>
<li>ExecStart: the command to be executed when the service starts. In this case we can see that it is of course the Nginx binary and that the default configuration file is provided with the -c option.</li>
<li>ExecReload: commands to execute to trigger a configuration reload in the service. In this case, the unit is configured to send a SIGHUP signal, which by convention is often used to let know a process that it should re-read its configuration.</li>
<li>ExecStop: as you&apos;ve probably guessed, the command to execute in order to stop the service (by sending a SIGTERM to it).</li>
</ul>
<p>The <strong>Install</strong> section is optional and is used to define the behavior or a unit if it is enabled or disabled. Enabling a unit marks it to be automatically started at boot. In essence, this is accomplished by latching the unit in question onto another unit to be started at boot (in this case referencing the multi-user target via the WantedBy directive).</p>
<ul>
<li>WantedBy: this can be seen as the Wants &quot;reverse&quot; directive. It causes a dependency of type Wants= to be added from the listed unit to the current unit. In this case, since Nginx service is enabled, it&apos;s &quot;wanted by&quot; the multi-user target.</li>
</ul>
<!--kg-card-end: markdown--><h2 id="targets">Targets</h2><p>As we have already seen, targets are a type of unit. According to systemd&apos;s man pages:</p><blockquote>A unit configuration file whose name ends in &quot;<code>.target</code>&quot; encodes information about a target unit of systemd, which is used for grouping units and as well-known synchronization points during start-up.<br>Target units do not offer any additional functionality on top of the generic functionality provided by units. They exist merely to group units via dependencies (useful as boot targets), and to establish standardized names for synchronization points used in dependencies between units. Among other things, target units are a more flexible replacement for SysV runlevels in the classic SysV init system.</blockquote><p>In other words, targets can be seen as groups of units, and they are &quot;reached&quot; when all of these units have started successfully. There is an equivalent target for every classic SysV runlevel. These are actually symlinks and can be examined by running<br><code>ls -l /lib/systemd/system | grep &apos;.target$&apos; | grep runlevel</code></p><!--kg-card-begin: markdown--><pre><code>runlevel0.target -&gt; poweroff.target
runlevel1.target -&gt; rescue.target
runlevel2.target -&gt; multi-user.target
runlevel3.target -&gt; multi-user.target
runlevel4.target -&gt; multi-user.target
runlevel5.target -&gt; graphical.target
runlevel6.target -&gt; reboot.target
</code></pre>
<!--kg-card-end: markdown--><p>If you are developing your own service, you can even write your own target so that any other services relying on it can know when it&apos;s &quot;online&quot;, i.e. when all of its dependencies have been fulfilled, e.g. it might depend on network-online.target and postgresql.service. The most common naming pattern for this would be myservice-online.target.</p><h2 id="systemctl">Systemctl</h2><p>The final important piece of the puzzle is systemctl, the systemd system and service manager control. It can be seen as a CLI to interact with systemd.</p><!--kg-card-begin: markdown--><p>As specified in its man pages, its syntax goes along<br>
<code>systemctl [OPTIONS...] COMMAND [UNIT...]</code></p>
<p>So if you want to check the overall status of the system, you can run:<br>
<code>systemctl status</code></p>
<p>If you want to check the status of the sshd service in particular:<br>
<code>systemctl status sshd.service</code></p>
<p>You can also check if targets have been reached:<br>
<code>systemctl status multi-user.target</code></p>
<p>As mentioned before, systemd keeps a high degree of compatibility with the classic SysV init. If you check the location of the <code>init</code> command under a system managed by systemd (<code>/sbin/init</code>), you will see that it is actually a symlink to <code>/lib/systemd/systemd</code>. If you want to enter runlevel 6, i.e. rebooting your machine, these four commands would be equivalent:</p>
<pre><code>reboot            # /sbin/reboot -&gt; /bin/systemctl*
init 6            # /sbin/init -&gt; /lib/systemd/systemd*
systemctl reboot  # reboot is available as a systemctl command
systemctl isolate reboot.target  # targets can be &quot;isolated&quot;
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>