<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Service on blog.iankulin.com</title><link>https://blog.iankulin.com/tags/service/</link><description>Recent content in Service on blog.iankulin.com</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Sat, 30 Sep 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.iankulin.com/tags/service/index.xml" rel="self" type="application/rss+xml"/><item><title>Installing service with Ansible</title><link>https://blog.iankulin.com/installing-service-with-ansible/</link><pubDate>Sat, 30 Sep 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/installing-service-with-ansible/</guid><description>&lt;p&gt;Having written my little monitoring endpoint in Go, it needs pushed out to all my servers and VM&amp;rsquo;s. Clearly this is a job for Ansible which I&amp;rsquo;ve already &lt;a href="https://blog.iankulin.com/ansible-with-secrets/"&gt;dabbled my toes in&lt;/a&gt;. Before we get onto doing that though, we need to have a think about how to make it a service.&lt;/p&gt;
&lt;h3 id="linux-services"&gt;Linux Services&lt;/h3&gt;
&lt;p&gt;A service in Linux is just a program, but one that&amp;rsquo;s usually required to be running all the time to provide some piece of functionality. The &amp;ldquo;program&amp;rdquo; can be any executable, but to allow systemd to manage it, we need to tell it a bit about what we want in a &lt;code&gt;.service&lt;/code&gt; file. This file is used by &lt;code&gt;systemd&lt;/code&gt; to know how to manage the service. They can get quite complex, but here&amp;rsquo;s the simple one for &lt;code&gt;vitals-glimpse&lt;/code&gt; - my little monitoring API endpoint.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-08-19-at-11.23.21-am.png" alt="[Unit]
Description=Memory and Disk statistics server on port 10321
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/vitals-glimpse
[Install]
WantedBy=default.target"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ExecStart&lt;/code&gt; is just saying what executable file is to be run. In this case it&amp;rsquo;s my compiled Go program. It&amp;rsquo;s a whopping 6MB so I&amp;rsquo;m assuming it&amp;rsquo;s all statically linked and standalone, so to run it we just copy it into &lt;code&gt;/usr/local/bin&lt;/code&gt; and run it from there.&lt;/p&gt;
&lt;p&gt;The two lines mentioning &lt;code&gt;.target&lt;/code&gt;s might not be obvious. These refer to the different times things happen in the machine startup sequence. &lt;code&gt;After=network.target&lt;/code&gt; means &amp;ldquo;don&amp;rsquo;t start this until the network is up and running&amp;rdquo;. You can see how it would be pointless to start a server that&amp;rsquo;s listening on a network port before networking is live. &lt;code&gt;default.target&lt;/code&gt; is just the system state when everything is going and ready for the users to interact with things, so when we specify &lt;code&gt;WantedBy=default.target&lt;/code&gt; we&amp;rsquo;re just saying &amp;ldquo;this service needs to be running by the time we are ready for user interactions&amp;rdquo;.&lt;/p&gt;
&lt;h3 id="installation"&gt;Installation&lt;/h3&gt;
&lt;p&gt;I already have my hosts file listing every machine, and an encrypted vault for my secrets (we&amp;rsquo;ve discussed those before), so the installation Ansible playbook just needs to copy the executable file into place in &lt;code&gt;/usr/local/bin&lt;/code&gt;, mark it as executable, copy the service file into place, and then start the service.&lt;/p&gt;
&lt;p&gt;If the files are already up to date and we don&amp;rsquo;t copy anything, then there&amp;rsquo;s no need touch the service, but if we have copied a new file, then we want to restart the service to pick up the change. Here&amp;rsquo;s how that all looks.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; Install vitals&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;glimpse to a Debian based server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# ansible-playbook vg-install.yml --ask-vault-pass &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vars_files&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;./&lt;/span&gt;vault&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;yml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hosts&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; vm100&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;dockhost
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; become&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tasks&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; Copy service file
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ansible&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;builtin&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;copy&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; src&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; files&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;vitals&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;glimpse&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;service
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dest&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;etc&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;systemd&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;system&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;vitals&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;glimpse&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;service
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; notify&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; Restart vitals&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;glimpse
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; Copy executable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ansible&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;builtin&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;copy&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; src&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; files&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;vitals&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;glimpse
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dest&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;usr&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;local&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;bin&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;vitals&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;glimpse
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mode&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#39;0755&amp;#39;&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Set the executable permissions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; notify&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; Restart vitals&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;glimpse
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; handlers&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; Restart vitals&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;glimpse
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ansible&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;builtin&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;service&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; vitals&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;glimpse
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; state&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; restarted
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; enabled&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; yes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The first thing to know is that I have a hosts inventory file in my Ansible config, and &lt;code&gt;vm100-dockhost&lt;/code&gt; is just one of those hosts. The sudo credentials for that host are in the &lt;code&gt;vault.yml&lt;/code&gt; file mentioned in the code as &lt;code&gt;vars_file&lt;/code&gt;. I&amp;rsquo;ve started putting the command I need to run each playbook in a comment in the file so I don&amp;rsquo;t have to remember them, the command for this one: &lt;code&gt;ansible-playbook vg-install.yml --ask-vault-pass&lt;/code&gt; tells Ansible to run this playbook, and ask me for the password to decrypt the vault file.&lt;/p&gt;
&lt;p&gt;The if/then mechanism to only do something based on something earlier happening in Ansible is usually achieved with notify/handles. We put the declarative block which is optionally executed in the &lt;code&gt;handlers:&lt;/code&gt; block. The name of this block (in the case above it is &lt;code&gt;Restart vitals-glimpse&lt;/code&gt;) is specified with the &lt;code&gt;notify&lt;/code&gt; key. If either of the files are copied in, then the notify flag is set and the service is restarted.&lt;/p&gt;</description></item></channel></rss>