<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Nginx on David Hamann</title><link>https://davidhamann.de/tags/nginx/</link><description>Recent content in Nginx on David Hamann</description><generator>Hugo</generator><language>en</language><copyright>&amp;copy; David Hamann</copyright><lastBuildDate>Mon, 05 Jan 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://davidhamann.de/tags/nginx/feed.xml" rel="self" type="application/rss+xml"/><item><title>How to get rid of web server upgrade prompts when installing FileMaker Server on Ubuntu Linux</title><link>https://davidhamann.de/2026/01/05/non-interactive-filemaker-server-install-apache-nginx/</link><pubDate>Mon, 05 Jan 2026 00:00:00 +0000</pubDate><guid>https://davidhamann.de/2026/01/05/non-interactive-filemaker-server-install-apache-nginx/</guid><description>&lt;p&gt;A while back the FileMaker Server (FMS) installer for Ubuntu Linux started checking the currently installed web server versions and giving warnings and an interactive prompt (!) in case of outdated versions.&lt;/p&gt;
&lt;p&gt;This is rather annoying if you like to install/upgrade your FMS non-interactively. Using ansible, for example, your playbook would just hang and you would start wondering what&amp;rsquo;s going on.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see what is actually happening, why it&amp;rsquo;s happening, and how to solve it.&lt;/p&gt;
&lt;h2 id="what-is-happening"&gt;What is happening?&lt;/h2&gt;
&lt;p&gt;When you follow the &lt;a href="https://help.claris.com/en/server-network-install-setup-guide/content/silent-installation-linux.html"&gt;official documentation&lt;/a&gt; on &amp;ldquo;silent installations&amp;rdquo;, you could assume that setting up a &lt;a href="https://community.claris.com/en/s/article/Assisted-install-of-FileMaker-Server-17-and-later"&gt;complete&lt;/a&gt; &lt;code&gt;Assisted Install.txt&lt;/code&gt; file and using the following command is all that is necessary:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo FM_ASSISTED_INSTALL=path apt install package_path/filemaker-server-version.build-architecture.deb
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In the current and previous version (22.0.2 and 22.0.4) you will, however, eventually see something like this on stdout in the installation process:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Warning: Current nginx version($nginxVersion) is too low, it probably can lead a serious security issue! Please run the script -- NginxUpdate.sh to upgrade it to the latest version!(Ignore: If use Apache)
Do you want to continue to install? [y/n]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Non-interactively, you obviously won&amp;rsquo;t see anything and thus won&amp;rsquo;t be able to answer the prompt.&lt;/p&gt;
&lt;p&gt;More annoyingly, canceling the installer in this state will likely break the whole installation leading to &lt;code&gt;dpkg&lt;/code&gt; telling you that &lt;code&gt;filemaker-server&lt;/code&gt; has to be re-installed.&lt;/p&gt;
&lt;h2 id="why-is-it-happening"&gt;Why is it happening?&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s take a quick look at the debian package to understand why this is happening:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# unzip the installer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unzip fms_22.0.4.427_Ubuntu24_amd64.zip
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# extract the archive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ar x filemaker-server-22.0.4.427-amd64.deb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# extract the tarball&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tar xf control.tar.zst
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we have access to the control scripts we can have a look at the bash script &lt;code&gt;preinst&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In it, we see the function &lt;code&gt;checkNginxAndApacheVersion()&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;checkNginxAndApacheVersion&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; :
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$ERROR_NONE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;nginxVersion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;nginx -v 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -oP &lt;span class="s1"&gt;&amp;#39;nginx/\K[^ ]+&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;apacheVersion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;apache2 -v 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -oP &lt;span class="s1"&gt;&amp;#39;Apache/\K[^ ]+&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; dpkg --compare-versions &lt;span class="nv"&gt;$nginxVersion&lt;/span&gt; lt 1.27.0 &lt;span class="o"&gt;||&lt;/span&gt; dpkg --compare-versions &lt;span class="nv"&gt;$apacheVersion&lt;/span&gt; lt 2.4.57&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; dpkg --compare-versions &lt;span class="nv"&gt;$nginxVersion&lt;/span&gt; lt 1.27.0 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; message &lt;span class="s2"&gt;&amp;#34;Warning: Current nginx version(&lt;/span&gt;&lt;span class="nv"&gt;$nginxVersion&lt;/span&gt;&lt;span class="s2"&gt;) is too low, it probably can lead a serious security issue! Please run the script -- NginxUpdate.sh to upgrade it to the latest vers
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;ion!(Ignore: If use Apache)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; dpkg --compare-versions &lt;span class="nv"&gt;$apacheVersion&lt;/span&gt; lt 2.4.57 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; message &lt;span class="s2"&gt;&amp;#34;Warning: Current apache version(&lt;/span&gt;&lt;span class="nv"&gt;$apacheVersion&lt;/span&gt;&lt;span class="s2"&gt;) is too low, it probably can lead a serious security issue! Please run the script -- ApacheUpdate.sh to upgrade it to the latest
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;version!(Ignore: If use Nginx)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -r -p &lt;span class="s2"&gt;&amp;#34; Do you want to continue to install? [y/n]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$REPLY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;y&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$REPLY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Y&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$REPLY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;yes&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$REPLY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;YES&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$ERROR_NONE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$ERROR_INTERRUPT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; :
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can see that both nginx and Apache versions are checked against hardcoded version numbers, and if either one is lower than the target version a prompt will appear, trying to read from stdin (&lt;code&gt;read -r -p &amp;quot;...&amp;quot;&lt;/code&gt;).&lt;/p&gt;
&lt;div class="notice notice-info"&gt;
 I don&amp;rsquo;t know why they are checking for both versions and not depending on what web server is or will actually be in use.
&lt;/div&gt;

&lt;p&gt;If we trace the calls to the function, we see a little further up that the check only takes place under certain conditions:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;isLicenseAccepted&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;		&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt; -eq &lt;span class="nv"&gt;$ERROR_NONE&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$SECURITY_CHECK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So where is &lt;code&gt;$SECURITY_CHECK&lt;/code&gt; coming from?&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s actually read from the &lt;code&gt;Assisted Install.txt&lt;/code&gt; file in &lt;code&gt;readAssistedInstallInfo()&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$fileValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; cut -d &lt;span class="s2"&gt;&amp;#34;=&amp;#34;&lt;/span&gt; -f &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; xargs&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; cut -d &lt;span class="s2"&gt;&amp;#34;=&amp;#34;&lt;/span&gt; -f 2&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; in
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Security Check&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; in
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;True&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;yes&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Yes&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;SECURITY_CHECK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; * &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;SECURITY_CHECK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Essentially, this means we can jump over this interactive prompt by setting &lt;code&gt;Security Check=0&lt;/code&gt; in our &lt;code&gt;Assisted Install.txt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Looking at the documentation of assisted installs, there&amp;rsquo;s unfortunately no mention of this flag: &lt;a href="https://community.claris.com/en/s/article/Assisted-install-of-FileMaker-Server-17-and-later"&gt;Assisted install of Claris FileMaker Server&lt;/a&gt; (at the time of this writing).&lt;/p&gt;
&lt;p&gt;Once I found the flag name, I researched a bit more and eventually found that it&amp;rsquo;s actually officially documented – just somewhere else (oh, well). Look at &amp;ldquo;Linux: Show the Apache and Nginx update warnings&amp;rdquo; here: &lt;a href="https://help.claris.com/en/server-network-install-setup-guide/content/customize-personalization-file.html"&gt;Customize the personalization file&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="the-solution"&gt;The solution&lt;/h2&gt;
&lt;p&gt;After this little detour into the installer, the solution is quite simple:&lt;/p&gt;
&lt;p&gt;Set &lt;code&gt;Security Check=0&lt;/code&gt; if you don&amp;rsquo;t want to be prompted.&lt;/p&gt;
&lt;p&gt;Alternatively, make sure to upgrade your web server versions (unfortunately both nginx and Apache) to the indicated version first, and then run your non-interactive install.&lt;/p&gt;
&lt;p&gt;You can find the upgrade scripts in the package as well; they are called: &lt;code&gt;NginxUpdate.sh&lt;/code&gt; and &lt;code&gt;ApacheUpdate.sh&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I hope this saves someone else a little bit of digging :-)&lt;/p&gt;</description></item><item><title>nginx alias misconfiguration allowing path traversal</title><link>https://davidhamann.de/2022/08/14/nginx-alias-traversal/</link><pubDate>Sun, 14 Aug 2022 00:00:00 +0000</pubDate><guid>https://davidhamann.de/2022/08/14/nginx-alias-traversal/</guid><description>&lt;p&gt;I recently came across an nginx server that had a vulnerable alias configuration which allowed anyone to read files outside the intended directory. In the following post I will describe the misconfiguration and provide demo files so that you can experiment with it yourself.&lt;/p&gt;
&lt;div class="notice notice-info"&gt;
 The general issue was originally highlighted a few years ago in a BlackHat presentation (&lt;a href="https://i.blackhat.com/us-18/Wed-August-8/us-18-Orange-Tsai-Breaking-Parser-Logic-Take-Your-Path-Normalization-Off-And-Pop-0days-Out-2.pdf"&gt;Breaking Parser Logic!, Orange Tsai&lt;/a&gt;) and apparantly first shown even earlier. While the linked presentation only has a couple of slides on this particular issue it&amp;rsquo;s worth checking out in full.
&lt;/div&gt;

&lt;h2 id="the-docker-setup"&gt;The docker setup&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s say we have a PHP application that should be served through nginx. To quickly get things running we configure our setup via the following &lt;code&gt;docker-compose.yml&lt;/code&gt; file:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;version: &amp;#34;3.7&amp;#34;

services:
 web:
 image: nginx:alpine
 ports:
 - 8081:80
 networks:
 - internal
 volumes:
 - ./webapp:/var/www/webapp
 - ./nginx.conf:/etc/nginx/conf.d/default.conf
 depends_on:
 - php

 php:
 image: php:fpm-alpine
 volumes:
 - ./webapp:/var/www/webapp
 networks:
 - internal

networks:
 internal:
 driver: bridge
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We have two services, &lt;code&gt;web&lt;/code&gt; (nginx) and &lt;code&gt;php&lt;/code&gt;, mount our php source code and &lt;code&gt;nginx.conf&lt;/code&gt; and have the services on the same &lt;code&gt;internal&lt;/code&gt; network.&lt;/p&gt;
&lt;p&gt;Our directory structure will look like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;.
├── docker-compose.yml
├── nginx.conf
└── webapp
 ├── app
 │   ├── db.php
 │   └── webroot
 │   └── index.php
 └── static
 └── sample.png
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="the-nginx-config"&gt;The nginx config&lt;/h2&gt;
&lt;p&gt;Our &lt;code&gt;nginx.conf&lt;/code&gt; file will be a fairly simple and standard-looking one which already has the issue baked in (can you see it?):&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;server {
 server_name _;

 root /var/www/webapp/app/webroot;
 index index.php index.html index.htm;

 access_log /var/log/nginx/php-access.log;
 error_log /var/log/nginx/php-error.log;

 location /assets {
 alias /var/www/webapp/static/;
 }

 location / {
 try_files $uri $uri/ /index.php?$query_string;
 location ~ \.php$ {
 include fastcgi_params;
 fastcgi_pass php:9000;
 fastcgi_index index.php;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="the-web-app"&gt;The web app&lt;/h2&gt;
&lt;p&gt;Our demo web app is really just for demonstration purposes and doesn&amp;rsquo;t do anything useful.&lt;/p&gt;
&lt;p&gt;We have &lt;code&gt;webapp/app/db.php&lt;/code&gt; (to have a file outside of the webroot that contains some credentials):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;appuser&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$pass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;secret&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;PDO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mysql:host=localhost;dbname=test&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$pass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then our &lt;code&gt;index.php&lt;/code&gt; in the webroot folder to show an intended output of the PHP application:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Here is the webroot&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="launch-the-application-and-see-the-issue"&gt;Launch the application and see the issue&lt;/h2&gt;
&lt;p&gt;Now that we have all necessary demo files set up, we can launch our containers:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;docker-compose up --build
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Going to &lt;code&gt;http://127.0.0.1:8081&lt;/code&gt; should now return &lt;code&gt;Here is the webroot&lt;/code&gt;, which is the output of &lt;code&gt;index.php&lt;/code&gt; in the webroot folder.&lt;/p&gt;
&lt;p&gt;As seen in the above nginx config we also have an &lt;code&gt;/assets&lt;/code&gt; location pointing to the &lt;code&gt;/static&lt;/code&gt; directory. Navigating to &lt;code&gt;http://127.0.0.1:8081/assets/sample.png&lt;/code&gt; gives us the sample image, as expected.&lt;/p&gt;
&lt;p&gt;So what&amp;rsquo;s the issue?&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;/assets&lt;/code&gt; location directive has no trailing slash and nginx will thus only match &lt;code&gt;/assets&lt;/code&gt; and then append whatever is in the request to the final destination path.&lt;/p&gt;
&lt;p&gt;If we open &lt;code&gt;http://127.0.0.1:8081/assets../app/db.php&lt;/code&gt; we can force a directory traversal and access files in a directory one level down. For our demo app this means we can access the source code of &lt;code&gt;db.php&lt;/code&gt;, a sensitive file outside of the webroot. Here, &lt;code&gt;/assets../app/db.php&lt;/code&gt; effectively becomes &lt;code&gt;/var/www/webapp/static/../app/db.php&lt;/code&gt;.&lt;/p&gt;
&lt;div class="notice notice-info"&gt;
 Note that attempts to force &amp;ldquo;regular&amp;rdquo; directory traversals in a requested path, as in &lt;code&gt;/../&lt;/code&gt;, are obviously prevented by default.
&lt;/div&gt;

&lt;p&gt;&lt;img alt="nginx slash traversal" loading="lazy" src="https://davidhamann.de/images/nginx_alias_traversal.png"&gt;&lt;/p&gt;
&lt;p&gt;While we could of course prevent the PHP source code from being returned vs. evaluated, this would not change the fact that we could still access other files one directory down – for example something like &lt;code&gt;/assets../app/.env&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The fix here is to make sure to always set the full path in the location directive, as in &lt;code&gt;location /assets/&lt;/code&gt; (note the trailing slash).&lt;/p&gt;
&lt;h2 id="the-files"&gt;The files&lt;/h2&gt;
&lt;p&gt;You can access the demo files via this &lt;a href="https://gist.github.com/davidhamann/f589b434071bb7e2a1502643d1dcd8fb"&gt;GitHub gist&lt;/a&gt;.&lt;/p&gt;</description></item></channel></rss>