{"id":3809,"date":"2023-07-02T13:22:09","date_gmt":"2023-07-02T13:22:09","guid":{"rendered":"https:\/\/geekmungus.co.uk\/?p=3809"},"modified":"2023-07-03T19:26:12","modified_gmt":"2023-07-03T19:26:12","slug":"using-gitlab-ci-cd-to-manage-configuration-e-g-apache2-part-2","status":"publish","type":"post","link":"https:\/\/geekmungus.co.uk\/?p=3809","title":{"rendered":"Using Gitlab CI\/CD to Manage Configuration (e.g. Apache2) \u2013 Part 2"},"content":{"rendered":"\n<p>Assuming you&#8217;ve read and followed part 1, now on part 2 we&#8217;ll get our SSH keys created, and the gitlab-runner registered with gitlab as a &#8220;runner&#8221; so we can create our pipeline.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring the SSH Keys for Gitlab-Runner<\/h2>\n\n\n\n<p>To make the local gitlab-runner on your machine have the correct keys, you need to generate them as that user. Here&#8217;s some useful links to assist you.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a rel=\"noreferrer noopener\" href=\"https:\/\/docs.gitlab.com\/ee\/ci\/ssh_keys\/\" target=\"_blank\">https:\/\/docs.gitlab.com\/ee\/ci\/ssh_keys\/<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.gitlab.com\/ee\/user\/ssh.html#generate-an-ssh-key-pair\">https:\/\/docs.gitlab.com\/ee\/user\/ssh.html#generate-an-ssh-key-pair<\/a><\/li>\n<\/ul>\n\n\n\n<p>A key thing to remember is that your keys must not have a passphrase set when created, otherwise it will prompt, but you&#8217;ll not be able to see it and your pipeline won&#8217;t run!<\/p>\n\n\n\n<p>Now in my particular example i&#8217;m going to be running the pipeline tasks under &#8220;root&#8221;, however the documentation <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.gitlab.com\/ee\/ci\/ssh_keys\/\" target=\"_blank\">https:\/\/docs.gitlab.com\/ee\/ci\/ssh_keys\/<\/a> shows you how to do this under the &#8220;gitlab-runner&#8221; user instead and also how to create key in more detail. <br>But as mentioned in our case we need to run under the &#8220;root&#8221; user, so we&#8217;ll generate a SSH keypair within &#8220;root&#8221;, so when gitlab-runner executes our pipeline and its tasks it can 1. trigger a pull of the most recent configuration from our project repository but 2. have the correct permissions to be able to execute command to say restart services like Apache2.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -s\n(now root)<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh-keygen -t rsa -b 2048<\/code><\/pre>\n\n\n\n<p>You should place the key in the default location <strong>~.ssh\/id_rsa<\/strong> and <strong>~.ssh\/id_rsa.pub<\/strong>. You can use other locations, the links above will help you with how to do that, but using different paths is beyond the scope of this document.<\/p>\n\n\n\n<p>Now we need to add the keys into gitlab, to do this firstly log on to gitlab. Click on your icon (profile) and then click, &#8220;Preferences&#8221;.<\/p>\n\n\n\n<p>Now click &#8220;SSH Keys&#8221;.<\/p>\n\n\n\n<p>Copy and paste the contents of the <strong>~.ssh\/id_rsa.pub<\/strong> file into the &#8220;key&#8221; box, and give the key a title. You can leave the expiration date as the default for now, which is 1 year. <\/p>\n\n\n\n<p><em>NOTE! Ensure you are pasting in the Public SSH key, not the private one. The private one is to be kept&#8230;.private!<\/em><\/p>\n\n\n\n<p>Once the key has been imported, let&#8217;s test you can SSH to gitlab from your machine without needing the key, you can do this with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh -T git@gitlab.com\nssh -Tvvv git@gitlab.com<\/code><\/pre>\n\n\n\n<p>Assuming all is well you&#8217;ll get a &#8220;Welcome to Gitlab!&#8221; and your username message.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setup Git and Push the Initial Configuration<\/h2>\n\n\n\n<p>Now we are ready to push our Apache configuration into our gitlab repository. So:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -s\n(now root)<\/code><\/pre>\n\n\n\n<p>Run these commands to ensure the git configuration specifies the correct user:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git config --global user.name \"Your Name\"\ngit config --global user.email \"thingy@doberry.com\"<\/code><\/pre>\n\n\n\n<p>In our case the directory is owned by root, so we need to perform these steps as root to ensure the git configuration can be created correctly. So let&#8217;s setup git and create our initial commit.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/etc\/apache2\nsudo git init --initial-branch=main\nsudo git remote add origin git@gitlab.com:tristan.self\/apache2.git\nsudo git add .\nsudo git commit -m \"Initial commit\"\nsudo git push --set-upstream origin main<\/code><\/pre>\n\n\n\n<p>Now refresh the gitlab repo, you should now see all the files have been uploaded.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Recap Where we Are<\/h2>\n\n\n\n<p>Okay, so now let&#8217;s recap where we are, we have:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Created the git repository (project).<\/li>\n\n\n\n<li>Installed the gitlab-runner on our target host.<\/li>\n\n\n\n<li>Set the gitlab-runner to run as a service.<\/li>\n\n\n\n<li>Registered the gitlab-runner with our project (repository) as a runner that the CI\/CD pipeline can use.<\/li>\n\n\n\n<li>We&#8217;ve then configured the &#8220;root&#8221; user with an SSH key, and provided that public key to gitlab as a trusted key, which means we can pull and push files into the project repository.<\/li>\n<\/ol>\n\n\n\n<p>Okay, so what&#8217;s next. Well we now have the Apache2 configuration in the repository, but we&#8217;ll not want any of this to be manual, what we want is that we can clone this repository to our normal workstation (i.e. not this server), make a change to the Apache2 configuration, commit it, then merge it and for the pipeline to start and trigger the gitlab-runner to automatically pull down the latest version of the configuration and apply it. <\/p>\n\n\n\n<p>So, let&#8217;s do that now.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring the Pipeline Files<\/h2>\n\n\n\n<p>So currently we have no CI\/CD pipeline configuration for that we need to add a <strong>.gitlab-ci.yml<\/strong> file into our repository, this file determines the pipeline configuration, and although this is a simple example the pipeline can be very complex with a number of stages, inputs, outputs etc. <\/p>\n\n\n\n<p>For this inital setup its recommended to be performing the creation of the next two files directly in the Apache2 configuration directory <strong>\/etc\/apache2<\/strong>, so you can just push it up when we&#8217;re all done (and trigger the pipeline to start for the first time).<\/p>\n\n\n\n<p>Create the following file <strong>.gitlab-ci.yml<\/strong> at the root of the repository (project) with the following contents:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>stages:\n - verify\n - deploy\n\nverify-apache2-config:\n  stage: verify\n  image: ubuntu\/apache2\n  script:\n    - echo \"Checking config\"\n    - apachectl configtest\n\nupdate-apache2-config:\n  stage: deploy\n  script:\n    - .\/deploy.sh<\/code><\/pre>\n\n\n\n<p>Let&#8217;s just explore what this file does. It defines the pipeline, so our pipeline has two stages: &#8220;verify&#8221; and &#8220;deploy&#8221;, then within each stage we have the steps that are going to be taken. <\/p>\n\n\n\n<p>In the &#8220;verify&#8221; stage it uses a Docker image to verify that the configuration is syntactically correct, if this stage was to fail (a typo in the configuration file for example), then the pipeline will stop and it won&#8217;t apply duff configuration to your server.<\/p>\n\n\n\n<p>Assuming all is well then the pipeline moves to the &#8220;deploy&#8221; stage, this quite simply tells the gitlab-runner to trigger the <strong>deploy.sh<\/strong> BASH script file, which you now need to create in the root of the repository with the following contents:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\nset -e\n\n# another quick syntax check, in situ rather than in separate CI runner\n# 'set -e' will catch errors, no need to explicitly check\n\necho \"Configuration Updated!\"\n\nuser=\"root\"\ngit_home=\/etc\/apache2\n\necho \"Updating master repository...\"\nsudo -u $user \/usr\/bin\/git --git-dir=${git_home}\/.git fetch\nsudo -u $user \/usr\/bin\/git --git-dir=${git_home}\/.git --work-tree=${git_home} pull origin main\n\necho \"Reload Apache2 Configuration\"\nsudo systemctl reload apache2<\/code><\/pre>\n\n\n\n<p>You also need to make this file executable with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chmod +x deploy.sh<\/code><\/pre>\n\n\n\n<p>Okay create, so now we have the CI\/CD configuration set within<\/p>\n\n\n\n<p>Let&#8217;s commit and push this configuration to repository, which will then trigger the first run of our pipeline!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Commit, Push and Run!<\/h2>\n\n\n\n<p>For these steps, we&#8217;ll first commit and push our CI\/CD pipeline files, then swap to look at gitlab to monitor what happens.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -s\n(now root)\n\ncd \/etc\/apache2\nsudo git add .gitlab-vi.yml\nsudo git add deploy.sh\nsudo git commit -m \"Added CI-CD files\"\nsudo git push origin main<\/code><\/pre>\n\n\n\n<p>You&#8217;ll now see the little blue clock symbol, this shows that CI\/CD has found a pipeline and has started to run it. Click on the clock symbol and we&#8217;ll inspect what is going on&#8230;.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"352\" src=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-4-1024x352.png\" alt=\"\" class=\"wp-image-3815\" srcset=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-4-1024x352.png 1024w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-4-300x103.png 300w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-4-768x264.png 768w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-4.png 1283w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>So the new files have been commited, you may want to make some random (benign) change to a configuration file, but otherwise you should now see the two stages either running or have run (depending on how quickly it scheduled and ran them).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"691\" height=\"427\" src=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-5.png\" alt=\"\" class=\"wp-image-3817\" srcset=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-5.png 691w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-5-300x185.png 300w\" sizes=\"auto, (max-width: 691px) 100vw, 691px\" \/><\/figure>\n\n\n\n<p>All appears to be fine, so let&#8217;s click on the &#8220;verify&#8221; stage. As you can see all fine, no errors in the configuration.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"569\" src=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-6-1024x569.png\" alt=\"\" class=\"wp-image-3818\" srcset=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-6-1024x569.png 1024w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-6-300x167.png 300w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-6-768x427.png 768w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-6.png 1088w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>So if we then click on the next stage (i.e. the &#8220;deploy&#8221; stage) we can then see:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"695\" src=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-8-1024x695.png\" alt=\"\" class=\"wp-image-3820\" srcset=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-8-1024x695.png 1024w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-8-300x204.png 300w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-8-768x522.png 768w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-8-305x207.png 305w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2023\/07\/image-8.png 1097w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>And again all is good, we can see the deploy.sh has been run, it has pulled down the latest copy of the repository files from gitlab and then successfully reloaded the Apache2 configuration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Bit of Troubleshooting<\/h2>\n\n\n\n<p>I had a few issues with permissions, the first time I ran the pipeline I got the following error. Stack overflow appeared to help here: <a href=\"https:\/\/stackoverflow.com\/questions\/64329037\/gitlab-shell-script-permission-denied\">https:\/\/stackoverflow.com\/questions\/64329037\/gitlab-shell-script-permission-denied<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/deploy.sh\nbash: line 127: .\/deploy.sh: Permission denied<\/code><\/pre>\n\n\n\n<p>To fix you can do this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo git update-index --chmod=+x deploy.sh\n\nsudo git commit -m \"fix\"\n\nsudo git push origin main<\/code><\/pre>\n\n\n\n<p>The CI\/CD will then re-run and you should be good!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>And that is it. We have our test web server host setup with a git repository held locally and a CI\/CD pipeline which can trigger tasks to take place on the host via the gitlab-runner.<\/p>\n\n\n\n<p>If you want to check what is going on you can tail the syslog to watch the gitlab-runner do its thing, this can be seen with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>tail -f \/var\/log\/syslog<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Additional Random Information<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo chmod g+w -R .git<\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/unsplash.com\/@ceebeesnap\" data-type=\"URL\" data-id=\"https:\/\/unsplash.com\/@ceebeesnap\">Image Attribution<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Assuming you&#8217;ve read and followed part 1, now on part 2 we&#8217;ll get our SSH keys created, and the gitlab-runner registered with gitlab as a &#8220;runner&#8221; so we can create our pipeline. Configuring the SSH Keys for Gitlab-Runner To make the local gitlab-runner on your machine have the correct keys, you need to generate them &#8230; <a title=\"Using Gitlab CI\/CD to Manage Configuration (e.g. Apache2) \u2013 Part 2\" class=\"read-more\" href=\"https:\/\/geekmungus.co.uk\/?p=3809\" aria-label=\"Read more about Using Gitlab CI\/CD to Manage Configuration (e.g. Apache2) \u2013 Part 2\">Read more<\/a><\/p>\n","protected":false},"author":4,"featured_media":3822,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[42,43],"tags":[],"class_list":["post-3809","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-git"],"_links":{"self":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/3809","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3809"}],"version-history":[{"count":6,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/3809\/revisions"}],"predecessor-version":[{"id":3825,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/3809\/revisions\/3825"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/media\/3822"}],"wp:attachment":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3809"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3809"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3809"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}