<?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"><channel><title><![CDATA[Site Reliability Engineering & DevOps | Mandela Muithi]]></title><description><![CDATA[DevOps and SRE expertise: Kubernetes, Terraform, AWS, GitOps with ArgoCD, and production-grade CI/CD pipelines. Engineering reliability at scale.]]></description><link>https://blog.mandela.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 10 May 2026 12:28:19 GMT</lastBuildDate><atom:link href="https://blog.mandela.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Simplified GeoServer Proxy Setup with Nginx]]></title><description><![CDATA[Introduction
Geoserver is an open source server for sharing geospatial data. It implements open protocols from OGC like WFS,WCS and WMS. It also supports others like WMTS by supporting use of extensions.
Nginx is an open source web server and a rever...]]></description><link>https://blog.mandela.dev/simplified-geoserver-proxy-setup-with-nginx</link><guid isPermaLink="true">https://blog.mandela.dev/simplified-geoserver-proxy-setup-with-nginx</guid><category><![CDATA[GIS]]></category><category><![CDATA[nginx]]></category><category><![CDATA[SSL]]></category><category><![CDATA[Proxy Server]]></category><dc:creator><![CDATA[Mandela Muithi]]></dc:creator><pubDate>Sat, 06 Apr 2024 21:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1712237721603/4c4b0922-e2f7-42a3-b1b6-3f110f338f95.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>Geoserver is an open source server for sharing geospatial data. It implements open protocols from OGC like WFS,WCS and WMS. It also supports others like WMTS by supporting use of extensions.</p>
<p>Nginx is an open source web server and a reverse proxy</p>
<p>In this guide I will go over how to configure geoserver to utilize nginx as a reverse proxy.</p>
<h3 id="heading-configuration">Configuration</h3>
<ul>
<li><p>To follow these steps make sure you have geoserver and nginx installed in your server. If using nginx for TSL/SSL termination make sure you are done with setting up the ssl certificates.</p>
</li>
<li><p>Acquaint yourself with nginx configuration if not familiar with it before proceeding to the step below just the basics if you have never used it before.</p>
</li>
<li><p>In the server block that has the address you intend to use, create a location block with the name geoserver and add header as shown in the code block below. If you don't use geoserver path you might get 404 errors when you try to access the proxied geoserver.</p>
<pre><code class="lang-nginx">   <span class="hljs-attribute">location</span> /geoserver {
              <span class="hljs-attribute">proxy_pass</span> http://127.0.0.1:8080/geoserver;
              <span class="hljs-attribute">proxy_set_header</span> Host <span class="hljs-variable">$host</span>;
              <span class="hljs-attribute">proxy_set_header</span> X-Real-IP <span class="hljs-variable">$remote_addr</span>;    
              <span class="hljs-attribute">proxy_set_header</span> X-Forwarded-For <span class="hljs-variable">$proxy_add_x_forwarded_for</span>;
              <span class="hljs-attribute">proxy_redirect</span> <span class="hljs-literal">off</span>;
          }
</code></pre>
</li>
<li><p>Addressing Cross-Origin Resource Sharing (CORS) in GeoServer and Nginx</p>
<ul>
<li><p>CORS is an implementation in web browsers that allow websites served from a given domain to be able to access services from a different domain other than the one that served it. By default web browsers enforce same origin policy whereby if a website is served from domaina.com and requests a resource from domainb.com the request is blocked by the browser.</p>
</li>
<li><p>The below geoserver configuration allow CORS for all domains you can also specify for specific domains</p>
<pre><code class="lang-xml">     <span class="hljs-comment">&lt;!-- Uncomment following filter to enable CORS in Tomcat. Do not forget the second config block further down.--&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">filter</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">filter-name</span>&gt;</span>cross-origin<span class="hljs-tag">&lt;/<span class="hljs-name">filter-name</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">filter-class</span>&gt;</span>org.apache.catalina.filters.CorsFilter<span class="hljs-tag">&lt;/<span class="hljs-name">filter-class</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">init-param</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">param-name</span>&gt;</span>cors.allowed.origins<span class="hljs-tag">&lt;/<span class="hljs-name">param-name</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">param-value</span>&gt;</span>*<span class="hljs-tag">&lt;/<span class="hljs-name">param-value</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">init-param</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">init-param</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">param-name</span>&gt;</span>cors.allowed.methods<span class="hljs-tag">&lt;/<span class="hljs-name">param-name</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">param-value</span>&gt;</span>GET,POST,PUT,DELETE,HEAD,OPTIONS<span class="hljs-tag">&lt;/<span class="hljs-name">param-value</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">init-param</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">init-param</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">param-name</span>&gt;</span>cors.allowed.headers<span class="hljs-tag">&lt;/<span class="hljs-name">param-name</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">param-value</span>&gt;</span>*<span class="hljs-tag">&lt;/<span class="hljs-name">param-value</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">init-param</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">filter</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- END to Tomcat Cors filter  --&gt;</span>
</code></pre>
<pre><code class="lang-xml">   <span class="hljs-comment">&lt;!-- Uncomment following filter-mapping to enable CORS--&gt;</span>                                                                                                                 
      <span class="hljs-tag">&lt;<span class="hljs-name">filter-mapping</span>&gt;</span>                                                                                                                                                          
          <span class="hljs-tag">&lt;<span class="hljs-name">filter-name</span>&gt;</span>cross-origin<span class="hljs-tag">&lt;/<span class="hljs-name">filter-name</span>&gt;</span>                                                                                                                               
          <span class="hljs-tag">&lt;<span class="hljs-name">url-pattern</span>&gt;</span>/*<span class="hljs-tag">&lt;/<span class="hljs-name">url-pattern</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">filter-mapping</span>&gt;</span>
     <span class="hljs-comment">&lt;!--END --&gt;</span>
</code></pre>
</li>
</ul>
</li>
<li><p>Handling Cross-Site Request Forgery (CSRF) Protection</p>
<ul>
<li>Geoserver admin page employs CSRF therefore the admin page of the geoserver user interface will not work if the request does not appear to come from the origin when using a reverse proxy.</li>
</ul>
</li>
</ul>
<p>    web.xml file path</p>
<ul>
<li><pre><code class="lang-bash">    tomcat/webapps/geoserver/WEB-INF/web.xml
</code></pre>
</li>
<li><p>To allow-list your proxy with the CSRF filter you can add the code shown below in web.xml file.</p>
</li>
<li><p>Below is how you set allow list in the web.xml file</p>
<pre><code class="lang-xml">         <span class="hljs-tag">&lt;<span class="hljs-name">context-param</span>&gt;</span>                                                                                                                                                   
    <span class="hljs-tag">&lt;<span class="hljs-name">param-name</span>&gt;</span>GEOSERVER_CSRF_WHITELIST<span class="hljs-tag">&lt;/<span class="hljs-name">param-name</span>&gt;</span>                                                                                                                           
    <span class="hljs-tag">&lt;<span class="hljs-name">param-value</span>&gt;</span>replacethiswithyourdomain.com<span class="hljs-tag">&lt;/<span class="hljs-name">param-value</span>&gt;</span>                                                                                                                                
  <span class="hljs-tag">&lt;/<span class="hljs-name">context-param</span>&gt;</span>
</code></pre>
</li>
</ul>
<ul>
<li><p>The final step is to set the base url which is used by the proxy. To access the setting for base url, Click Global link in the settings section and add the value in the proxy base url text field and finally mark Use headers for Proxy URL option and save the changes.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712324703757/6f99bea6-adc9-4eb0-b963-a5c20901e362.png" alt class="image--center mx-auto" /></p>
<p>  Alternatively you can edit global.xml usually in the path shown below</p>
</li>
<li><pre><code class="lang-bash">  tomcat/webapps/geoserver/data
</code></pre>
</li>
</ul>
<p>Add the code below in the global.xml file. remember to replace https://yourdomain.com/geoserver with the your own baseUrl</p>
<ul>
<li><pre><code class="lang-xml">          <span class="hljs-tag">&lt;<span class="hljs-name">global</span>&gt;</span>
          ... 
            <span class="hljs-tag">&lt;<span class="hljs-name">settings</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">proxyBaseUrl</span>&gt;</span>https://yourdomain.com/geoserver<span class="hljs-tag">&lt;/<span class="hljs-name">proxyBaseUrl</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">useHeadersProxyURL</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">useHeadersProxyURL</span>&gt;</span>
          ...
            <span class="hljs-tag">&lt;/<span class="hljs-name">settings</span>&gt;</span>
          ...
          <span class="hljs-tag">&lt;/<span class="hljs-name">global</span>&gt;</span>
</code></pre>
</li>
</ul>
<p>To Conclude, routing geoserver services through nginx either for ssl termination or path management does not have to be a pain, following the above steps should do the trick.</p>
]]></content:encoded></item><item><title><![CDATA[Build SWI-Prolog from source code  and install it with Stow in Linux]]></title><description><![CDATA[What is  SWI-Prolog

SWI-Prolog is an implementation of the Prolog language among other implementations like:YAP,GNU Prolog and Visual Prolog.
Why Build SWI-Prolog from source
There are many reasons to build SWI-Prolog from source code to an executab...]]></description><link>https://blog.mandela.dev/build-swi-prolog-from-source-code-and-install-it-with-stow-in-linux</link><guid isPermaLink="true">https://blog.mandela.dev/build-swi-prolog-from-source-code-and-install-it-with-stow-in-linux</guid><category><![CDATA[build]]></category><category><![CDATA[Linux]]></category><category><![CDATA[languages]]></category><dc:creator><![CDATA[Mandela Muithi]]></dc:creator><pubDate>Mon, 02 May 2022 14:14:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651353632919/LgoZYIviD.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-swi-prolog">What is  SWI-Prolog</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651356872390/_AR0JUklz.png" alt="swi_proog_logo.png" />
SWI-Prolog is an implementation of the Prolog language among other implementations like:YAP,GNU Prolog and Visual Prolog.</p>
<h2 id="heading-why-build-swi-prolog-from-source">Why Build SWI-Prolog from source</h2>
<p>There are many reasons to build SWI-Prolog from source code to an executable rather than installing it from your repository of choice. Some of the reasons are:</p>
<ul>
<li>To have access to the the latest version of the software.</li>
<li>The SWI-Prolog in your Linux distribution repository and other repositories does not have the packages you need.</li>
<li>The docker distribution does not also have the packages you need.</li>
<li>To have a lightweight build with only the packages that you need.</li>
</ul>
<h2 id="heading-install-stow-in-your-machine">Install Stow in your machine</h2>
<p>Stow is a symlink(a file that contains reference to another file or directory) manager.
To install stow for 
Debian:</p>
<p><code>sudo apt install stow</code> </p>
<p>Fedora:</p>
<p><code>sudo dnf install stow</code> </p>
<p>Solus:</p>
<p><code>sudo eopkg install stow</code> </p>
<h2 id="heading-install-java-in-your-machine-optional">Install Java in your machine "Optional"</h2>
<p>If you will need to use java with Prolog make sure it is installed in your system and set its environment variable.
Run this command to check if java is install in your system:</p>
<p><code>java --version</code> </p>
<p>output should be something similar like the screenshot below</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651421498504/vu_-sy3JH.png" alt="java_version.png" /></p>
<h2 id="heading-download-source-code-from-github">Download source code from GitHub</h2>
<h3 id="heading-clone-the-repository-or-or-download-the-zipped-source">Clone the repository or or download the zipped source</h3>
<p>run the following command to clone the SWI-Prolog repository in the current directory</p>
<p>1.<code>git clone https://github.com/SWI-Prolog/swipl-devel.git</code> </p>
<p>or download and extract the zip from: 
<a target="_blank" href="https://github.com/SWI-Prolog/swipl-devel">SWI-Prolog main development repository</a>
After cloning the repository or extracting the downloaded zip open the "swipl-devel" directory in the terminal and run the following git command:</p>
<p>2.<code>git submodule update --init</code> </p>
<p>The above command initializes and updates each sub-module in the repository, including nested sub-modules if any of the sub-modules in the repository have sub-modules themselves.</p>
<h2 id="heading-installing-prerequisites-for-build">Installing prerequisites for build</h2>
<p>You can check the necessary requisites for your distribution for building SWI-Prolog from their official website in this page 
<a target="_blank" href="https://www.swi-prolog.org/build/unix.html">Getting prerequisites</a>
in the getting prerequisites section.</p>
<h2 id="heading-building">Building</h2>
<ol>
<li><p>Make a a new directory "build" inside the "swipl-devel" and move to the created directory "build", this is where the build system will be placed</p>
</li>
<li><p>Create  "stow" directory in '\usr\local' if it not there already.
2.Run the following commands</p>
</li>
</ol>
<p><code>cmake -DCMAKE_INSTALL_PREFIX=/usr/local/stow/swipl ..</code></p>
<p><code>sudo make</code></p>
<p>if you get this error after running 'sudo make' and you intend to  use jpl</p>
<p>"-- Could NOT find JNI (missing: JAVA_AWT_LIBRARY JAVA_JVM_LIBRARY JAVA_INCLUDE_PATH JAVA_INCLUDE_PATH2 JAVA_AWT_INCLUDE_PATH) 
-- Could NOT find Java (missing: Java_JAVA_EXECUTABLE Java_JAVAC_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVADOC_EXECUTABLE Development) 
"</p>
<p>make sure to have java installed and set its  home environment variable</p>
<p>eg:</p>
<pre><code><span class="hljs-built_in">export</span> JAVA_HOME=<span class="hljs-string">"/usr/local/jdk-18.0.1/"</span>
<span class="hljs-built_in">export</span> PATH=<span class="hljs-string">"<span class="hljs-variable">$PATH</span>:<span class="hljs-variable">$JAVA_HOME</span>/bin"</span>
</code></pre><p>assuming you are using openjdk files in the local folder</p>
<p>if you get this error after running 'sudo make' and you intend to  use jpl,
"-- Could NOT find JNI (missing: JAVA_JVM_LIBRARY) "</p>
<p>add the following line: 
<code>set(JAVA_JVM_LIBRARY "$Java_Home/lib/server/libjvm.so")</code> 
and replace '$Java_Home' with the directory to your java root path in the 'CMakeLists.txt' file in the 'swipl-devel' directory</p>
<p>You can ignore the above errors if you do not intend to use jpl api cmake will just skip it,
then run the following two commands:</p>
<p><code>sudo ctest -j 4</code></p>
<p><code>sudo make install</code></p>
<h2 id="heading-install-with-stow">Install with stow</h2>
<p>Move to the stow directory "/usr/local/stow"
and run the following command:</p>
<p><code>sudo stow swipl</code> </p>
<p>Now you are ready to go,to confirm that this was a success run the following command</p>
<p><code>swipl --version</code></p>
<p>the output should be something similar: 'SWI-Prolog version 8.5.10 for x86_64-linux'</p>
]]></content:encoded></item></channel></rss>