<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jim Carter, Author at Dogsbody Technology</title>
	<atom:link href="https://www.dogsbody.com/blog/author/jimcarter/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>Linux managed services &#38; consulting for ambitious web agencies and SaaS companies</description>
	<lastBuildDate>Mon, 09 Aug 2021 10:04:38 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.3</generator>
	<item>
		<title>How to set-up fail2ban for a WordPress site</title>
		<link>https://www.dogsbody.com/blog/how-to-set-up-fail2ban-for-a-wordpress-site/?pk_campaign=feed&#038;pk_kwd=how-to-set-up-fail2ban-for-a-wordpress-site</link>
					<comments>https://www.dogsbody.com/blog/how-to-set-up-fail2ban-for-a-wordpress-site/?pk_campaign=feed&#038;pk_kwd=how-to-set-up-fail2ban-for-a-wordpress-site#comments</comments>
		
		<dc:creator><![CDATA[Jim Carter]]></dc:creator>
		<pubDate>Mon, 09 Aug 2021 10:04:38 +0000</pubDate>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://www.dogsbody.com/?p=27537</guid>

					<description><![CDATA[<p>What is Fail2ban Fail2ban is a tool which you can use to reduce the impact of attacks on your servers. Typically you configure it to monitor a log file for suspicious activity.  Then once the activity crosses a threshold you can have it take an action, such as block the source IP address in your [&#8230;]<img src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fhow-to-set-up-fail2ban-for-a-wordpress-site%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dhow-to-set-up-fail2ban-for-a-wordpress-site&amp;action_name=How%20to%20set-up%20fail2ban%20for%20a%20WordPress%20site&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /></p>
<p>The post <a href="https://www.dogsbody.com/blog/how-to-set-up-fail2ban-for-a-wordpress-site/?pk_campaign=feed&#038;pk_kwd=how-to-set-up-fail2ban-for-a-wordpress-site">How to set-up fail2ban for a WordPress site</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>What is Fail2ban</h2>
<p>Fail2ban is a tool which you can use to reduce the impact of attacks on your servers. Typically you configure it to monitor a log file for suspicious activity.  Then once the activity crosses a threshold you can have it take an action, such as block the source IP address in your firewall.  It&#8217;s a good way to stop attacks early but doesn&#8217;t entirely prevent them.</p>
<h2>Why use it to protect WordPress</h2>
<p>Due to it&#8217;s popularity, WordPress is often the target of automated attacks.  We often see bruteforce attacks targeting xmlrpc.php or wp-login.php, these rely on making a huge number of requests in the hope that one will eventually be successful.  Using strong passwords, especially for accounts with admin access is important to reduce the risk from attacks.  Fail2ban can be used to slow attackers down.  This helps for two reasons: it makes them less likely to succeed; it reduces the load on the server caused by processing these requests.</p>
<h3>Other options</h3>
<ul>
<li>Using an external <a href="https://www.dogsbody.com/blog/security-and-the-cloud/">Web Application Firewall</a> (WAF) such as <a href="https://sucuri.net/">Sucuri</a> or <a href="https://www.cloudflare.com/">Cloudflare</a>.</li>
<li>Using webserver configuration options to limit requests such as <a href="https://nginx.org/r/limit_req">limit_req</a> in Nginx.</li>
<li>WordPress security plugins such as <a href="https://www.wordfence.com/">Wordfence</a>.</li>
</ul>
<p>Blocking an attack as far upstream as possible is always advantageous to save resources so we would typically favour a Web Application Firewall or Webserver configuration over using fail2ban or a WordPress plugin however every site, server and customer is different so it will depend on the exact configuration used and required.</p>
<h2>Install &amp; config fail2ban (for Ubuntu)</h2>
<pre>sudo apt-get install fail2ban</pre>
<p>Fail2ban works by having a jail file which references the log file, a filter and an action.  By default fail2ban will protect sshd.  If you are restricting SSH access in another way then you might want to turn this off.  You can do so by creating the following as /etc/fail2ban/jail.local</p>
<pre>[sshd]
enabled = false</pre>
<p>Fail2ban doesn&#8217;t come with a filter for WordPress.  I&#8217;d like to credit <a href="https://osric.com/chris/accidental-developer/2019/07/block-wordpress-scanners-fail2ban/">these</a> <a href="https://blog.rimuhosting.com/2016/11/02/using-fail2ban-on-wordpress-wp-login-php-and-xmlrpc-php/">two</a> articles for providing a good starting point.  We see requests to &#8216;//xmlrpc.php&#8217; (note the double slashes) fairly frequently so tweaked the below to also flag them.  As this is detecting any requests to wp-login/xmlrpc it will flag legitimate admin users when they login etc.  We&#8217;ll look to account for this with the jail configuration.</p>
<p>You can create the filter as /etc/fail2ban/filter.d/wordpress.conf</p>
<pre>[Definition]
failregex = ^&lt;HOST&gt; .* "(GET|POST) /+wp-login.php
            ^&lt;HOST&gt; .* "(GET|POST) /+xmlrpc.php</pre>
<p>The jail file has most of the configuration options:</p>
<ul>
<li>logpath, in this case the path to your Apache access log</li>
<li>action, adjust this if you&#8217;re using a different firewall or want to be sent email instead, you can see available options in /etc/fail2ban/action.d/</li>
<li>maxretry, the number of requests within findtime seconds to ban after</li>
<li>bantime, the number of seconds to ban for, with this action how long they&#8217;re blocked in iptables</li>
</ul>
<p>As mentioned, the filter will catch both malicious and legitimate users.  We&#8217;re configuring maxrety fairly high and bantime relatively low to minimise the probability and impact if we do block a legitimate user.  Whilst this allows attackers to make roughly one request every ten seconds this is a fraction of what they&#8217;d make without fail2ban.</p>
<p>You can create the jail file as /etc/fail2ban/jail.d/wordpress.conf</p>
<pre>[wordpress]
enabled = true
port = http,https
filter = wordpress
action = iptables-multiport[name=wordpress, port="http,https", protocol=tcp]
logpath = /var/log/apache2/all-sites-access.log
maxretry = 12
findtime = 120
bantime = 120
</pre>
<p>Restart fail2ban to load in your new config</p>
<pre>sudo systemctl restart fail2ban</pre>
<h2>Checking your fail2ban set-up</h2>
<p>Show the jails</p>
<pre>sudo fail2ban-client status
</pre>
<p>Show info about the WordPress jail</p>
<pre>sudo fail2ban-client status wordpress
</pre>
<p>List the f2b-wordpress iptables chain (this will be created the first time fail2ban blocks an IP and contain blocked IPs)</p>
<pre>sudo iptables -v -n -L f2b-wordpress
sudo ip6tables -v -n -L f2b-wordpress
</pre>
<p>View the log to see any IPs banned or flagged</p>
<pre>sudo less /var/log/fail2ban.log
</pre>
<p>&nbsp;</p>
<p><em>Feature <a href="https://www.flickr.com/photos/grungepunk/5802444017/" target="_blank" rel="noopener noreferrer">image</a> by <a href="https://www.flickr.com/photos/grungepunk/" target="_blank" rel="noopener noreferrer">Jussie D.Brito</a></em><em> licensed <a href="https://creativecommons.org/licenses/by-sa/2.0/" target="_blank" rel="noopener noreferrer">CC BY-SA 2.0</a></em>.</p>
<img decoding="async" src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fhow-to-set-up-fail2ban-for-a-wordpress-site%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dhow-to-set-up-fail2ban-for-a-wordpress-site&amp;action_name=How%20to%20set-up%20fail2ban%20for%20a%20WordPress%20site&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /><p>The post <a href="https://www.dogsbody.com/blog/how-to-set-up-fail2ban-for-a-wordpress-site/?pk_campaign=feed&#038;pk_kwd=how-to-set-up-fail2ban-for-a-wordpress-site">How to set-up fail2ban for a WordPress site</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dogsbody.com/blog/how-to-set-up-fail2ban-for-a-wordpress-site/?pk_campaign=feed&#038;pk_kwd=how-to-set-up-fail2ban-for-a-wordpress-site/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>NGINX &#8211; Optimising Redirects</title>
		<link>https://www.dogsbody.com/blog/nginx-optimising-redirects/?pk_campaign=feed&#038;pk_kwd=nginx-optimising-redirects</link>
					<comments>https://www.dogsbody.com/blog/nginx-optimising-redirects/?pk_campaign=feed&#038;pk_kwd=nginx-optimising-redirects#comments</comments>
		
		<dc:creator><![CDATA[Jim Carter]]></dc:creator>
		<pubDate>Mon, 14 Sep 2020 09:26:51 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[NGINX]]></category>
		<guid isPermaLink="false">https://www.dogsbody.com/?p=22150</guid>

					<description><![CDATA[<p>We&#8217;re a big user of NGINX as you can probably imagine. It&#8217;s been fascinating to see it&#8217;s growth over the last 10 years and we love it&#8217;s quick adoption of new standards. Optimisations are always important, especially at scale; we&#8217;re always looking for the cleanest way to do things and redirects are definitely one of [&#8230;]<img src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fnginx-optimising-redirects%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dnginx-optimising-redirects&amp;action_name=NGINX%20%26%238211%3B%20Optimising%20Redirects&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /></p>
<p>The post <a href="https://www.dogsbody.com/blog/nginx-optimising-redirects/?pk_campaign=feed&#038;pk_kwd=nginx-optimising-redirects">NGINX &#8211; Optimising Redirects</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>We&#8217;re a big user of NGINX as you can probably imagine. It&#8217;s been fascinating to see it&#8217;s growth over the last 10 years and we love it&#8217;s quick adoption of new standards.</p>
<p>Optimisations are always important, especially at scale; we&#8217;re always looking for the cleanest way to do things and redirects are definitely one of the easiest and quickest wins.</p>
<p>Redirects are used when you want to send users to a different URL based on the requested page.  Some popular reasons to do this are:</p>
<ul>
<li>Redirect users from a short memorable URI to a corresponding page</li>
<li>Keep old URLs working after migrating from one bit of software to another</li>
<li>Redirect discontinued product pages (returning 404s) to the most closely related page</li>
</ul>
<p>Redirects can typically be done in using <code>rewrite</code> or  <code>return</code> with the addition of <code>map</code> for large arrays of redirects. Lets look at the differences&#8230;.</p>
<h2>Using &#8216;rewrite&#8217; for redirects</h2>
<p>Rewrite isn&#8217;t all bad, it&#8217;s very powerful but with that comes a large CPU overhead as it uses regex by default.</p>
<p>Consider the following rule to redirect browsers accessing an image to a separate subdomain; perhaps a CDN&#8230;</p>
<pre>rewrite ^/images/(*.jpg)$ http://static.example.com/$1 permanent;</pre>
<h2><strong>Using &#8216;return&#8217; for redirects<br />
</strong></h2>
<p>A redirect is as simple as returning a HTTP status code so why not do just that with the <code>return</code> option.</p>
<p>If you have to redirect an entire site to a new URL then it can be simply done with&#8230;</p>
<pre><span class="k">server</span> <span class="p">{</span>
    <span class="kn">server_name</span> <span class="s">oldsite.example.com</span><span class="p">;</span>
    <span class="kn">return</span> <span class="mi">301</span> <span class="nv">$scheme://newsite.example.com$request_uri</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">server</span> <span class="p">{</span>
    <span class="kn">server_name</span> <span class="nv">newsite</span>.<span class="s">example.com</span><span class="p">;</span>
    <span class="c1"># [...]</span>
<span class="p">}</span></pre>
<p>&#8230; remember that http and https configs can easily be separated to allow the http site to only forward on requests ensuring that it&#8217;s impossible for anyone to access your site insecurely&#8230;</p>
<pre><span class="k">server</span> <span class="p">{
</span>    listen 80;
    <span class="kn">server_name</span> <span class="s">www.example.com</span><span class="p">;</span>
    <span class="kn">return</span> <span class="mi">301</span> https<span class="nv">://www.example.com$request_uri</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">server</span> <span class="p">{
    listen 443;</span>
    <span class="kn">server_name</span> www.<span class="s">example.com</span><span class="p">;</span>
    <span class="c1"># [...]</span>
<span class="p">}</span></pre>
<h2>Using &#8216;map&#8217; for redirects</h2>
<p>If you&#8217;ve only got a handful of redirects then using rewrite to do this isn&#8217;t a big deal.  Once you&#8217;re talking about hundreds or thousands of redirects it&#8217;s worth looking to use a <a href="https://nginx.org/en/docs/http/ngx_http_map_module.html#map">map</a>.</p>
<p>Here&#8217;s an example configuration using a map and return directive to set-up two redirects.</p>
<p>Depending on how many URLs you&#8217;re redirecting you&#8217;ll need a different value for map_hash_bucket_size.  I&#8217;d stick with powers of 2, a config test (nginx -t) will warn you if your value is too small.<br />
<code>$uri</code> is an <a href="https://nginx.org/en/docs/varindex.html">NGINX variable</a>.<br />
<code>$new_uri</code> is the new variable that we&#8217;re creating, if you&#8217;ve got multiple sites you&#8217;ll need to use different variable names.</p>
<pre>map_hash_bucket_size 128;
map $uri $new_uri {
    /test-to-rewrite /test-rewritten;
    /test2-to-rewrite /test2-rewritten;
}

server {
    server_name <span class="s">example.com</span><span class="p">;</span>
    if ($new_uri) {
        return 301 $new_uri;
    }
#...
}</pre>
<p>For reference, here&#8217;s the equivalent syntax using rewrite.</p>
<pre>server {
    server_name <span class="s">example.com</span><span class="p">;</span>
    rewrite ^/test-to-rewrite$ /test-rewritten permanent;
    rewrite ^/test2-to-rewrite$ /test2-rewritten permanent;
#...
}</pre>
<h2>Testing map performance</h2>
<p>Before testing this my expectation was that there would be a cross over point after which using a map was beneficial.  What I found was that a map is suitable for any number of redirects but it&#8217;s not until you have a large number that it&#8217;s essential.</p>
<h3>Test conditions</h3>
<ul>
<li>Ubuntu 18.04 on a AWS c5.large</li>
<li>nginx v1.18.0</li>
<li>Used ApacheBench to make 10k local requests with 500 concurrent connections</li>
</ul>
<p>I ran each test 3 times and used the average in the numbers below.  I was measuring:</p>
<ul>
<li>Time taken to complete all of the requests</li>
<li>Memory usage with NGINX stopped, running and running after the test</li>
</ul>
<p>I&#8217;m happy this can show the relationship between the number of redirects and the performance differences between a map and rewrite.  Though it won&#8217;t represent your exact set-up.</p>
<h3>Single redirect</h3>
<p>The first thing I tested using both the rewrite and map configuration was a single redirect.</p>
<p>The time to complete these requests was comparable.  Both round to 0.42s with the map being a few hundredths of a second slower.  I believe this is within the errors of my testing.  The memory usage of running NGINX was too close to separate, fluctuating between 3-6M.</p>
<h3>Large (83k) redirects</h3>
<p>After that I tested what I&#8217;d consider the other extreme.  I pulled 83k lines out of the dictionary file and set-up redirects for them.  I ran the test against multiple different words.  This shows how the number of preceding redirects affects the time to complete the requests.</p>
<ul>
<li>Abdomen &#8211; which appears early in my redirects had comparable times (the average over the 3 test runs is actually identical)</li>
<li>Absentee &#8211; the 250th redirect took 0.66s with rewrite rules and 0.42s with the map</li>
<li>Animated &#8211; the 2500th redirect took 4.43s with rewrite rules and 0.42s with the map</li>
<li>Evangelising &#8211; the 25000th redirect took 27.86s with rewrite rules and 0.42s with the map</li>
<li>Zing &#8211; which appears late in my redirects took 57.54s with rewrite rules and 0.42s with the map</li>
<li>The 404 page I was testing &#8211; this represents load times of any small static page below the redirects in the config, it took 56.89s with rewrite rules and 0.43s with the map</li>
</ul>
<p><img fetchpriority="high" decoding="async" class="aligncenter wp-image-23406 size-full" src="https://www.dogsbody.com/wp-content/uploads/83k_redirects-1.png" alt="Graph showing response time for various redirects" width="700" height="500" srcset="https://www.dogsbody.com/wp-content/uploads/83k_redirects-1.png 700w, https://www.dogsbody.com/wp-content/uploads/83k_redirects-1-300x214.png 300w, https://www.dogsbody.com/wp-content/uploads/83k_redirects-1-260x185.png 260w" sizes="(max-width: 700px) 100vw, 700px" /></p>
<p>The time to process each different redirect was effectively constant when using a map.  Using rewrite the time to process a redirect is proportional to the number of rewrite rules before it.</p>
<p>Memory usage was also noticeably different.  I found that the increase due to running NGINX was ~16M for the map and ~66M for the rewrites.  After the test had run this increased by a few megabytes to ~19M and ~68M.</p>
<h3>250 redirects</h3>
<p>I wanted to check if the sheer number of rewrites was slowing things down.  I cut the config down to just the first 250 redirects.  This significantly reduced memory usage.  The time taken for requests to the Absentee redirect was negligibly different from when there were 83k redirects.</p>
<h3>Fewer requests</h3>
<p>I ran an extra test with 100 requests (rather than 10k) and 5 concurrent connections (rather than 500).  This is also a closer approximation to a single user accessing a webpage.  The time taken to access the Zing redirect was 0.55s (rather than 57.65s).  I&#8217;m happy that this shows the time for a single request is effectively constant.</p>
<h2>Conclusion</h2>
<p>For a large number of redirects a map is both faster and more memory efficient.  For a small number of redirects either rewrite or using a map is acceptable.  Since there&#8217;s no discernible disadvantage to a map and you may need to add more redirects in the future I&#8217;d use a map when possible.</p>
<p><a href="https://www.dogsbody.com/contact/">Give us a shout</a> if we can help you with your NGINX setup.</p>
<p>&nbsp;</p>
<p><em>Feature <a href="https://www.flickr.com/photos/43021516@N06/8045602124/" target="_blank" rel="noopener noreferrer">image</a> by <a href="https://www.flickr.com/photos/43021516@N06/" target="_blank" rel="noopener noreferrer">Special Collections Toronto Public Library</a></em><em> licensed <a href="https://creativecommons.org/licenses/by-sa/2.0/" target="_blank" rel="noopener noreferrer">CC BY-SA 2.0</a></em>.</p>
<img decoding="async" src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fnginx-optimising-redirects%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dnginx-optimising-redirects&amp;action_name=NGINX%20%26%238211%3B%20Optimising%20Redirects&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /><p>The post <a href="https://www.dogsbody.com/blog/nginx-optimising-redirects/?pk_campaign=feed&#038;pk_kwd=nginx-optimising-redirects">NGINX &#8211; Optimising Redirects</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dogsbody.com/blog/nginx-optimising-redirects/?pk_campaign=feed&#038;pk_kwd=nginx-optimising-redirects/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>A short guide to MySQL database optimization</title>
		<link>https://www.dogsbody.com/blog/mysql-database-optimization/?pk_campaign=feed&#038;pk_kwd=mysql-database-optimization</link>
					<comments>https://www.dogsbody.com/blog/mysql-database-optimization/?pk_campaign=feed&#038;pk_kwd=mysql-database-optimization#respond</comments>
		
		<dc:creator><![CDATA[Jim Carter]]></dc:creator>
		<pubDate>Tue, 09 Jun 2020 09:10:05 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[MySQL]]></category>
		<guid isPermaLink="false">https://www.dogsbody.com/?p=16760</guid>

					<description><![CDATA[<p>MySQL is a very popular open source database, but many install it and forget about it. Spending a little time on MySQL database optimization can reap huge returns &#8230; In this article, I want to show you a couple of the first places you should head, when you need to pinpoint bottlenecks or tweak the [&#8230;]<img src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fmysql-database-optimization%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dmysql-database-optimization&amp;action_name=A%20short%20guide%20to%20MySQL%20database%20optimization&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /></p>
<p>The post <a href="https://www.dogsbody.com/blog/mysql-database-optimization/?pk_campaign=feed&#038;pk_kwd=mysql-database-optimization">A short guide to MySQL database optimization</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>MySQL is a very popular open source database, but many install it and forget about it. Spending a little time on MySQL database optimization can reap huge returns &#8230;</p>
<p>In this article, I want to show you a couple of the first places you should head, when you need to pinpoint bottlenecks or tweak the MySQL configuration.</p>
<h2>MySQL slow log</h2>
<p>The slow log, will log any queries that take longer than a given number of seconds.</p>
<p>This can help you to identify poorly written or demanding queries.  You can then refactor them or use concepts like &#8220;indexes&#8221; to speed them up.</p>
<p>It&#8217;s often helpful to start with a high &#8220;long query time&#8221;, to just flag up the longest queries and then gradually reduce it, as you deal with each one in turn.</p>
<p>To enable the slow log, create the following /etc/mysql/mysql.conf.d/mycustomconfigs.cnf or add the following lines to your my.conf file&#8230;</p>
<pre>[mysqld]
slow_query_log=true
long_query_time=1
slow-query-log-file=/var/log/mysql/mysql-slow</pre>
<p>&#8230; then restart MySQL, to load in the new values.</p>
<h3>Improve the query</h3>
<p>Once you&#8217;ve found a slow query, it&#8217;s worth considering if there is a simpler way to get the same information.</p>
<p>If you can improve the performance of the query you might be able to skip looking into why the old one was slow.</p>
<h3>Explain/Describe</h3>
<p>If you&#8217;re still looking to improve your query, we need to dig into how MySQL is actually running the query and why it&#8217;s slow.  This will give us a better idea how to fix it.</p>
<p>For these examples I ran a few basic queries against this <a href="https://github.com/datacharmer/test_db" target="_blank" rel="noopener noreferrer">auto generated employee data</a>.</p>
<p>Let&#8217;s suppose your slow query is:</p>
<pre>SELECT AVG(hire_date) FROM employees WHERE emp_no IN (SELECT emp_no FROM dept_manager)</pre>
<p>To see how it will be executed, prefix it with EXPLAIN:</p>
<pre>mysql&gt; EXPLAIN SELECT AVG(hire_date) FROM employees WHERE emp_no IN (SELECT emp_no FROM dept_manager);
+----+-------------+--------------+------------+--------+---------------+---------+---------+-------------------------------+------+----------+------------------------+
| id | select_type | table        | partitions | type   | possible_keys | key     | key_len | ref                           | rows | filtered | Extra                  |
+----+-------------+--------------+------------+--------+---------------+---------+---------+-------------------------------+------+----------+------------------------+
| 1  | SIMPLE      | dept_manager | NULL       | index  | PRIMARY       | PRIMARY | 8       | NULL                          | 24   | 100.00   | Using index; LooseScan |
| 1  | SIMPLE      | employees    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | employees.dept_manager.emp_no | 1    | 100.00   | NULL                   |
+----+-------------+--------------+------------+--------+---------------+---------+---------+-------------------------------+------+----------+------------------------+
2 rows in set, 1 warning (0.00 sec)

</pre>
<p>It&#8217;s worth having a quick look at the documentation on the <a href="https://dev.mysql.com/doc/refman/8.0/en/explain-output.html#explain-output-columns" target="_blank" rel="noopener noreferrer">output format</a>.  Three of the columns to check are:</p>
<ul>
<li>key &#8211; is the index that will be used, the one you&#8217;d expect?</li>
<li>rows &#8211; is the number of rows to be examined as low as possible?</li>
<li>filtered &#8211; is the percentage of results being filtered as high as possible?</li>
</ul>
<p>Suppose we&#8217;re regularly making the following query:</p>
<pre>SELECT * FROM employees WHERE gender = 'M'</pre>
<p>This has <a href="https://dev.mysql.com/doc/refman/8.0/en/explain-output.html#jointype_all" target="_blank" rel="noopener noreferrer">type: ALL</a> meaning that all rows in the table will be scanned.</p>
<p>It therefore makes sense here to add an index.</p>
<p>After doing so, the type changes to <a href="https://dev.mysql.com/doc/refman/8.0/en/explain-output.html#jointype_ref" target="_blank" rel="noopener noreferrer">ref</a> &#8211; MySQL can simply return the rows matching the index rather than checking every row.</p>
<p>As you&#8217;d expect this halves the number of rows:</p>
<pre>mysql&gt; EXPLAIN SELECT * FROM employees WHERE gender = 'M';
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered  | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| 1  | SIMPLE      | employees | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 299025 | 50.00    | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql&gt; CREATE INDEX gender ON employees(gender);
Query OK, 0 rows affected (0.97 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql&gt; EXPLAIN SELECT * FROM employees WHERE gender = 'M';
+----+-------------+-----------+------------+------+---------------+--------+---------+-------+--------+----------+-------+
| id | select_type | table     | partitions | type | possible_keys | key    | key_len | ref   | rows   | filtered | Extra |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------+--------+----------+-------+
| 1  | SIMPLE      | employees | NULL       | ref  | gender        | gender | 1       | const | 149512 | 100.00   | NULL  |
+----+-------------+-----------+------------+------+---------------+--------+---------+-------+--------+----------+-------+
1 row in set, 1 warning (0.01 sec)</pre>
<h2>Third Party Tools</h2>
<p>I should mention, that there are a bunch of tools that can help you find bottlenecks and really hone your MySQL database optimization techniques.</p>
<p>For websites written in PHP, we&#8217;re big fans of <a href="https://newrelic.com/products/application-monitoring" target="_blank" rel="noopener noreferrer">New Relic APM.</a> This tool will allow you to sort pages based on their load time.  You can then dig deeper into whether the application code or database queries have the most room for improvement.</p>
<p>Once you&#8217;ve narrowed things down, you can start implementing improvements.</p>
<p>It&#8217;s worth having a search for other application monitoring providers to see if tools such as <a href="https://www.datadoghq.com/" target="_blank" rel="noopener noreferrer">Datadog</a> or <a href="https://www.dynatrace.com/" target="_blank" rel="noopener noreferrer">DynaTrace</a> better suit you.</p>
<h2>MySQL Tuner</h2>
<p>MySQL Tuner is a tool which looks at a database&#8217;s usage patterns to suggest configuration improvements.  Make sure you run it on a live system, that has been running for at least 24 hours.  Otherwise it won&#8217;t have access to enough data to make relevant recommendations.</p>
<p>Before you <a href="https://github.com/major/MySQLTuner-perl#downloadinstallation" target="_blank" rel="noopener noreferrer">download</a> and <a href="https://github.com/major/MySQLTuner-perl#specific-usage" target="_blank" rel="noopener noreferrer">use</a> the tool I&#8217;ll echo it&#8217;s warning:</p>
<div class="update__flowed">
<div class="update__indent">
<blockquote><p>It is extremely important for you to fully understand each change you make to a MySQL database server. If you don&#8217;t understand portions of the script&#8217;s output, or if you don&#8217;t understand the recommendations, you should consult a knowledgeable DBA or system administrator that you trust. Always test your changes on staging environments, and always keep in mind that improvements in one area can negatively affect MySQL in other areas.</p></blockquote>
</div>
</div>
<p>Once you run MySQL Tuner, it will login to the database, read a bunch of metrics and print out some recommendations.</p>
<p>It&#8217;s worth grouping the related ones and reading up on any you haven&#8217;t come across.  After that you can test out changes in your staging environment.</p>
<p>One common improvement is to set skip-name-resolve.  This saves a little bit of time on each connection by not performing DNS lookups.  Before you do this make sure you aren&#8217;t using DNS in any of your grant statements (you&#8217;re just using IP addresses or localhost).</p>
<h2>Your friendly SysAdmins</h2>
<p>Of course, we are also here to help and regularly advise customers on changes that can be made to their infrastructure.</p>
<p><a href="https://www.dogsbody.com/contact/" rel="noopener noreferrer">Give us a shout</a> if you think we can help you too.</p>
<p>&nbsp;</p>
<p><em>Feature <a href="https://www.flickr.com/photos/leermakers/24110617213/" target="_blank" rel="noopener noreferrer">image</a> by <a href="https://www.flickr.com/photos/leermakers" target="_blank" rel="noopener noreferrer">Joris Leermakers</a></em><em> licensed <a href="https://creativecommons.org/licenses/by-sa/2.0/" target="_blank" rel="noopener noreferrer">CC BY-SA 2.0</a></em>.</p>
<img loading="lazy" decoding="async" src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fmysql-database-optimization%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dmysql-database-optimization&amp;action_name=A%20short%20guide%20to%20MySQL%20database%20optimization&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /><p>The post <a href="https://www.dogsbody.com/blog/mysql-database-optimization/?pk_campaign=feed&#038;pk_kwd=mysql-database-optimization">A short guide to MySQL database optimization</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dogsbody.com/blog/mysql-database-optimization/?pk_campaign=feed&#038;pk_kwd=mysql-database-optimization/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Removing support for TLS 1.0 and TLS 1.1</title>
		<link>https://www.dogsbody.com/blog/removing-support-for-tls-1-0-and-tls-1-1/?pk_campaign=feed&#038;pk_kwd=removing-support-for-tls-1-0-and-tls-1-1</link>
					<comments>https://www.dogsbody.com/blog/removing-support-for-tls-1-0-and-tls-1-1/?pk_campaign=feed&#038;pk_kwd=removing-support-for-tls-1-0-and-tls-1-1#respond</comments>
		
		<dc:creator><![CDATA[Jim Carter]]></dc:creator>
		<pubDate>Tue, 19 May 2020 09:51:39 +0000</pubDate>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[Maintenance]]></category>
		<guid isPermaLink="false">https://www.dogsbody.com/?p=20695</guid>

					<description><![CDATA[<p>TL;DR For security reasons, it is best practice to disable TLS 1.0 and TLS 1.1, but before you do this you may need to weigh up the risks to traffic from old browsers. After disabling TLS 1.0 and TLS 1.1 any visitors using old browsers won&#8217;t be able to access your site.  If you are [&#8230;]<img src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fremoving-support-for-tls-1-0-and-tls-1-1%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dremoving-support-for-tls-1-0-and-tls-1-1&amp;action_name=Removing%20support%20for%20TLS%201.0%20and%20TLS%201.1&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /></p>
<p>The post <a href="https://www.dogsbody.com/blog/removing-support-for-tls-1-0-and-tls-1-1/?pk_campaign=feed&#038;pk_kwd=removing-support-for-tls-1-0-and-tls-1-1">Removing support for TLS 1.0 and TLS 1.1</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>TL;DR</h2>
<p>For security reasons, it is best practice to disable TLS 1.0 and TLS 1.1, but before you do this you may need to weigh up the risks to traffic from old browsers.</p>
<p>After disabling TLS 1.0 and TLS 1.1 any visitors using old browsers won&#8217;t be able to access your site.  If you are accepting credit card payments through your website then your customers security is more important but if you have a public information site then this may not be the case.</p>
<h2>Don&#8217;t I always want the best security?</h2>
<p>Please don&#8217;t get us wrong. We are NOT advocating blindly reducing security. This post is very much a response to customers that come to us wanting changes that will break their sites in order to get a perfect score or tick a compliance box. We can usually come up with a best of both worlds once we show the exact implications of the change.</p>
<h2>What&#8217;s the fuss about?</h2>
<p class="p-rich_text_section">GlobalSign&#8217;s <a href="https://www.globalsign.com/en/blog/disable-tls-10-and-all-ssl-versions">What&#8217;s Behind the Change?</a> paragraph sums this up nicely:</p>
<blockquote>
<p class="c-mrkdwn__pre" data-stringify-type="pre">Various vulnerabilities over the past few years (e.g., BEAST, POODLE, DROWN…we love a good acronym, don&#8217;t we?) have had industry experts recommending disabling all versions of SSL and TLS 1.0 for a while now. PCI Compliance was another driving factor. On June 30, 2018, the PCI Data Security Standard (DSS) required that all websites needed to be on TLS 1.1 or higher in order to comply.</p>
</blockquote>
<p>The <a href="https://www.rfc-editor.org/rfc/rfc7525.html">RFC 7525</a> from 2015 stipulates that implementations should not use TLS 1.0 or TLS 1.1:</p>
<pre class="newpage">   o  Implementations SHOULD NOT negotiate TLS version 1.0 [<a title="&quot;The TLS Protocol Version 1.0&quot;" href="https://www.rfc-editor.org/rfc/rfc2246">RFC2246</a>];
      the only exception is when no higher version is available in the
      negotiation.
      Rationale: TLS 1.0 (published in 1999) does not support many
      modern, strong cipher suites.  In addition, TLS 1.0 lacks a per-
      record Initialization Vector (IV) for CBC-based cipher suites and
      does not warn against common padding errors.
   o  Implementations SHOULD NOT negotiate TLS version 1.1 [<a title="&quot;The Transport Layer Security (TLS) Protocol Version 1.1&quot;" href="https://www.rfc-editor.org/rfc/rfc4346">RFC4346</a>];
      the only exception is when no higher version is available in the
      negotiation.
      Rationale: TLS 1.1 (published in 2006) is a security improvement
      over TLS 1.0 but still does not support certain stronger cipher
      suites.</pre>
<p class="c-mrkdwn__pre" data-stringify-type="pre">Qualys SSL Labs have <a href="https://blog.qualys.com/ssllabs/2018/11/19/grade-change-for-tls-1-0-and-tls-1-1-protocols">reduced their grading for servers which support TLS 1.0 or TLS 1.1</a></p>
<h2>Assessing the risk</h2>
<p>Who won&#8217;t be able to access my website if I disable TLS 1.0 or TLS 1.1? Generally speaking browsers before 2013 will have trouble.  Most popular clients affected are old Android phones and old versions of Windows with Internet Explorer 10.  For the exact Android versions and other affected clients this is a <a href="https://caniuse.com/#feat=tls1-2">nice breakdown</a>.  As you&#8217;d expect the number of visitors with these old clients will vary according to your user base.  It&#8217;s best you check your site&#8217;s analytics to inform your decision.</p>
<p>Again, you can take into account how important encryption is for your website.  For example, at the time of writing it&#8217;s interesting to note that paypal.com has removed support for TLS 1.0 &amp; 1.1 whilst google.com has not.</p>
<h2>Summary</h2>
<p>So what does this mean?  Lets give some examples&#8230;</p>
<p><strong>If security is important to you</strong>; perhaps you have an e-commerce site taking payments or you are a IT consultancy like ourselves where people wish to share private information. You must disable old SSL/TLS protocols so that the only way people can communicate with your site is as secure as possible.</p>
<p><strong>If accessibility is important to you</strong>; perhaps you are trying to share public information, be it a marketing or public resources site. It maybe worth supporting old protocols to allow your message to be shared as wide as possible.</p>
<p>Remember; it maybe typically called a sales &#8220;funnel&#8221; but traffic doesn&#8217;t have to end up in just one place. Users not supporting the right levels of security can be redirected to alternative pages where they can be contacted in other ways.  Why lose a sale when you don&#8217;t have to!</p>
<p>&nbsp;</p>
<p>We&#8217;ve intentionally painted with broad strokes in this blog post.  We&#8217;re happy to give specific advice if you <a href="https://www.dogsbody.com/contact/">contact us</a> and feel free to leave a comment <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<img loading="lazy" decoding="async" src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fremoving-support-for-tls-1-0-and-tls-1-1%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dremoving-support-for-tls-1-0-and-tls-1-1&amp;action_name=Removing%20support%20for%20TLS%201.0%20and%20TLS%201.1&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /><p>The post <a href="https://www.dogsbody.com/blog/removing-support-for-tls-1-0-and-tls-1-1/?pk_campaign=feed&#038;pk_kwd=removing-support-for-tls-1-0-and-tls-1-1">Removing support for TLS 1.0 and TLS 1.1</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dogsbody.com/blog/removing-support-for-tls-1-0-and-tls-1-1/?pk_campaign=feed&#038;pk_kwd=removing-support-for-tls-1-0-and-tls-1-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Exploring character encoding types</title>
		<link>https://www.dogsbody.com/blog/character-encoding-types/?pk_campaign=feed&#038;pk_kwd=character-encoding-types</link>
					<comments>https://www.dogsbody.com/blog/character-encoding-types/?pk_campaign=feed&#038;pk_kwd=character-encoding-types#respond</comments>
		
		<dc:creator><![CDATA[Jim Carter]]></dc:creator>
		<pubDate>Fri, 06 Mar 2020 11:45:27 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">https://www.dogsbody.com/?p=12205</guid>

					<description><![CDATA[<p>Morse code was first used to transfer information in the 1840&#8217;s.  As you&#8217;re probably aware, it uses a series of dots and dashes to represent each character. Computers need a way to represent characters in binary form &#8211; as a series of ones and zeros &#8211; equivalent to the dots and dashes used by Morse [&#8230;]<img src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fcharacter-encoding-types%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dcharacter-encoding-types&amp;action_name=Exploring%20character%20encoding%20types&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /></p>
<p>The post <a href="https://www.dogsbody.com/blog/character-encoding-types/?pk_campaign=feed&#038;pk_kwd=character-encoding-types">Exploring character encoding types</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Morse code was first used to transfer information in the 1840&#8217;s.  As you&#8217;re probably aware, it uses a series of dots and dashes to represent each character.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-18099" src="https://www.dogsbody.com/wp-content/uploads/2019-11-27_11h32_06.png" alt="" width="928" height="447" srcset="https://www.dogsbody.com/wp-content/uploads/2019-11-27_11h32_06.png 928w, https://www.dogsbody.com/wp-content/uploads/2019-11-27_11h32_06-300x145.png 300w, https://www.dogsbody.com/wp-content/uploads/2019-11-27_11h32_06-768x370.png 768w, https://www.dogsbody.com/wp-content/uploads/2019-11-27_11h32_06-705x340.png 705w" sizes="auto, (max-width: 928px) 100vw, 928px" /></p>
<p>Computers need a way to represent characters in binary form &#8211; as a series of ones and zeros &#8211; equivalent to the dots and dashes used by Morse code.</p>
<h2>ASCII</h2>
<p>A widely used way for computers to encode information, is <a href="https://en.wikipedia.org/wiki/ASCII" target="_blank" rel="noopener noreferrer">ASCII</a> (American Standard Code for Information Interchange), created in the 1960&#8217;s.</p>
<p>ASCII defines a string of seven ones and zeros that represent the letters A-Z, upper and lowercase as well as numbers 0-9 and common symbols. 128 characters in total.</p>
<h2>8 bit encoding</h2>
<p>As you&#8217;d expect, ASCII is well suited for use in America, however it&#8217;s missing many characters that are frequently used in other countries.</p>
<p>For example, it doesn&#8217;t include characters like é or £ &amp; €.</p>
<p>Due to ASCII&#8217;s popularity, it&#8217;s been used as a base to create many different encodings.  All these different encodings add an extra eighth bit, doubling the possible number of characters and using the additional space for characters used by differing groups &#8230;</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/ISO/IEC_8859-1" target="_blank" rel="noopener noreferrer">Latin 1</a> &#8211; Adds Western Europe and Americas (Afrikaans, Danish, Dutch, Finnish, French, German, Icelandic, Irish, Italian, Norwegian, Spanish and Swedish) characters.</li>
<li>Latin 2 &#8211; Adds Latin-written Slavic and Central European (Czech, Hungarian, Polish, Romanian, Croatian, Slovak, Slovene) characters.</li>
<li>Latin 3 &#8211; Adds Esperanto, Galician, Maltese, and Turkish characters.</li>
<li>Latin 4 &#8211; Adds Scandinavia/Baltic, Estonian, Latvian, and Lithuanian characters (is an incomplete predecessor of Latin 6).</li>
<li>Cyrillic &#8211; Adds Bulgarian, Byelorussian, Macedonian, Russian, Serbian and Ukrainian characters.</li>
<li>Arabic &#8211; Adds Non-accented Arabic characters.</li>
<li>Modern Greek &#8211; Adds Greek characters.</li>
<li>Hebrew &#8211; Adds Non-accented Hebrew characters.</li>
<li>Latin 5 &#8211; Same as Latin 1 except for Turkish instead of Icelandic characters</li>
<li>Latin 6 &#8211; Adds Lappish/Nordic/Eskimo languages. Adds the last Inuit (Greenlandic) and Sami (Lappish) letters that were missing in Latin 4 to cover the entire Nordic area characters.</li>
<li>etc.</li>
</ul>
<p>All of this still doesn&#8217;t give global coverage though! There&#8217;s also an issue due to the inability of using different encodings on a single document, should you ever need to use characters from different character sets.</p>
<p>We need an alternative &#8230;</p>
<h2>Unicode</h2>
<p><a href="https://en.wikipedia.org/wiki/Unicode" target="_blank" rel="noopener noreferrer">Unicode</a> seeks to unify all the characters into one set.</p>
<p>This simplifies communication, as everyone can use a shared character set and doesn&#8217;t need to convert between them.</p>
<p>Unicode allows for over a million characters!</p>
<p>One of the most popular ways to encode Unicode, is as UTF-8.  UTF-8 has a variable width. Depending on the character used to encode, either 8, 16, 24 or 32 bits are used.</p>
<p>For characters in the ASCII character set, only 8 bits need to be used.</p>
<p>Another way to encode Unicode is UTF-32, which always uses 32 bit. This fixed width is simpler, but causes it to often use significantly more space than UTF-8.</p>
<h2>Emoji</h2>
<p>You probably don&#8217;t need telling, but Emoji are picture characters.</p>
<p>For a long time, knowledge workers have created smiley faces and more complex emoticons using symbols.</p>
<p>To take this a step further, emoji provide a wealth of characters.</p>
<p>The data transferred is always the same, but the pictures used differ between different platforms. Depending on the device, you&#8217;re viewing this, our smiley face emoji, ?, will look different.</p>
<p>The popularity of emoji has actually helped push Unicode support, which includes emoji as part of its character set.</p>
<p>I&#8217;ve pulled out a few recently added ones and you can see more <a href="https://unicode.org/emoji/charts/emoji-versions.html" target="_blank" rel="noopener noreferrer">on the Unicode website</a>.</p>
<p>U+1F996 added in 2017 &#8211; T-Rex ?<br />
U+1F99C added in 2018 &#8211; Parrot ?<br />
U+1F9A5 added in 2019 &#8211; Sloth ?</p>
<p>&nbsp;</p>
<p><em>Feature <a href="https://www.flickr.com/photos/photommo/26099344353/in/photolist-FLiXMK-nSaEFf-uoi4j9-L5QBVA-GZQgmz-Avj6Mt-XqXeoA-qvpTK8-qvoyrx-zzJGyT-ppRsus-5Dvmuw-arXM4A-6mGAdS-JNT3ov-Af21j9-GDTjt3-2dFMMXw-FHhw8P-G9cQ2Z-7ugtzu-a8iWWp-ritzL1-212HcbX-TGDSp3-2d8C3mp-GczgVf-MpebKV-5WZgAA-25kU2KK-MwyW3F-MwyYXP-soPXJg-GFJidj-GZQk4z-MZsjvY-2432Dpa-5Zc1Db-Xn1DLF-8fJRca-P4hjYh-GXyqv1-Ro9wDn-24GK5SL-oar9MP-embGzB-Xm4UYk-24mEi3Z-X1AnJo-6yDAP9" target="_blank" rel="noopener noreferrer">image</a> by <a href="https://www.flickr.com/photos/photommo/" target="_blank" rel="noopener noreferrer">Thomas</a></em><em> licensed <a href="https://creativecommons.org/licenses/by-sa/2.0/" target="_blank" rel="noopener noreferrer">CC BY-SA 2.0</a></em>.</p>
<img loading="lazy" decoding="async" src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fcharacter-encoding-types%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dcharacter-encoding-types&amp;action_name=Exploring%20character%20encoding%20types&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /><p>The post <a href="https://www.dogsbody.com/blog/character-encoding-types/?pk_campaign=feed&#038;pk_kwd=character-encoding-types">Exploring character encoding types</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dogsbody.com/blog/character-encoding-types/?pk_campaign=feed&#038;pk_kwd=character-encoding-types/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python 2 will go end of life on 01 Jan 2020</title>
		<link>https://www.dogsbody.com/blog/python-2-will-go-end-of-life-on-01-jan-2020/?pk_campaign=feed&#038;pk_kwd=python-2-will-go-end-of-life-on-01-jan-2020</link>
					<comments>https://www.dogsbody.com/blog/python-2-will-go-end-of-life-on-01-jan-2020/?pk_campaign=feed&#038;pk_kwd=python-2-will-go-end-of-life-on-01-jan-2020#respond</comments>
		
		<dc:creator><![CDATA[Jim Carter]]></dc:creator>
		<pubDate>Mon, 09 Sep 2019 13:43:57 +0000</pubDate>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[EOL]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://www.dogsbody.com/?p=13984</guid>

					<description><![CDATA[<p>Quick Public Safety Announcement, Python 2.7 goes end of life 01 Jan 2020.  This is the end of the road for Python 2.x &#8211; there won&#8217;t be a version 2.8. This means any Python code that&#8217;s still on 2.x needs updating to Python 3.  Any code that isn&#8217;t moved over won&#8217;t receive security updates so [&#8230;]<img src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fpython-2-will-go-end-of-life-on-01-jan-2020%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dpython-2-will-go-end-of-life-on-01-jan-2020&amp;action_name=Python%202%20will%20go%20end%20of%20life%20on%2001%20Jan%202020&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /></p>
<p>The post <a href="https://www.dogsbody.com/blog/python-2-will-go-end-of-life-on-01-jan-2020/?pk_campaign=feed&#038;pk_kwd=python-2-will-go-end-of-life-on-01-jan-2020">Python 2 will go end of life on 01 Jan 2020</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Quick Public Safety Announcement, Python 2.7 goes <a href="https://www.python.org/dev/peps/pep-0373/">end of life 01 Jan 2020</a>.  This is the end of the road for Python 2.x &#8211; there won&#8217;t be a version 2.8.</p>
<p>This means any Python code that&#8217;s still on 2.x needs updating to Python 3.  Any code that isn&#8217;t moved over won&#8217;t receive security updates so will inevitably become insecure.</p>
<h2>Identify your code</h2>
<p>If you&#8217;ve got a lot of code it&#8217;s worth taking the time to check what&#8217;s where and which version of Python it&#8217;s using.</p>
<p>Python 3 was released at the end of 2008.  Adoption has been slow, a factor has been that all of your dependencies need to support Python 3 before you can.  Now that we&#8217;re over 10 years down the road this is much less likely to be an issue.</p>
<p>You can start off by checking code that has been written more recently.  Hopefully this will have been written for Python 3.  A survey by JetBrains shows that between 2017 and 2018 the number of developers that mostly used Python 2 fell from <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#python-3-adoption">25%</a> to just <a href="https://www.jetbrains.com/research/python-developers-survey-2018/#python-3-adoption">16%</a>.  It&#8217;s also interesting to note the divide between use cases.  Data science having better adoption than both web and dev-ops.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-14906 aligncenter" src="https://www.dogsbody.com/wp-content/uploads/python_adoption_2018.png" alt="" width="454" height="250" srcset="https://www.dogsbody.com/wp-content/uploads/python_adoption_2018.png 454w, https://www.dogsbody.com/wp-content/uploads/python_adoption_2018-300x165.png 300w, https://www.dogsbody.com/wp-content/uploads/python_adoption_2018-450x248.png 450w" sizes="auto, (max-width: 454px) 100vw, 454px" /></p>
<h2>Don&#8217;t forget old code</h2>
<p>Unfortunately the numbers above are for code that developers are writing now.  We&#8217;re also concerned with code that was written many years ago and hasn&#8217;t recently had any major changes.  Looking at the number of packages downloaded instead of what developers are mostly using gives a <a href="https://www.ncsc.gov.uk/blog-post/time-to-shed-python-2">different picture</a>.  The numbers are closer to 50/50 with the trend between data science and dev-ops still clear.  TensorFlow is most often downloaded for Python 3 whilst botocore is heavily Python 2.  <a href="http://boto.cloudhackers.com/en/latest/">Boto</a> is heavily used in API access to cloud providers such as AWS.</p>
<p>If all of your recent code is Python 3 it&#8217;s worth having a good dig around for places old code might be hiding.</p>
<h2>What are the steps to update to Python 3?</h2>
<ul>
<li>The first step to update code is to make sure any packages you&#8217;re using support Python 3.  A tool such as <a href="https://pypi.org/project/caniusepython3/">caniusepython3</a> should show you where the issues are.</li>
<li>After that depending on the complexity of your code you can update it by hand or use a tool such as <a class="reference external" href="http://python-future.org/automatic_conversion.html">Futurize</a> to help with the conversion .</li>
</ul>
<p>A key part of smoothly updating is to have a good testing process so you can quickly find and fix the bits that unexpectedly break.  See the <a href="https://docs.python.org/3/howto/pyporting.html">porting guide</a> for more info.</p>
<p>&nbsp;</p>
<p><em>Feature image by <a href="https://www.flickr.com/photos/mpaulmd/">See1,Do1,Teach1</a> licensed <a href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a>.</em></p>
<img loading="lazy" decoding="async" src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fpython-2-will-go-end-of-life-on-01-jan-2020%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dpython-2-will-go-end-of-life-on-01-jan-2020&amp;action_name=Python%202%20will%20go%20end%20of%20life%20on%2001%20Jan%202020&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /><p>The post <a href="https://www.dogsbody.com/blog/python-2-will-go-end-of-life-on-01-jan-2020/?pk_campaign=feed&#038;pk_kwd=python-2-will-go-end-of-life-on-01-jan-2020">Python 2 will go end of life on 01 Jan 2020</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dogsbody.com/blog/python-2-will-go-end-of-life-on-01-jan-2020/?pk_campaign=feed&#038;pk_kwd=python-2-will-go-end-of-life-on-01-jan-2020/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Tripwire &#8211; How and Why</title>
		<link>https://www.dogsbody.com/blog/tripwire-how-and-why/?pk_campaign=feed&#038;pk_kwd=tripwire-how-and-why</link>
					<comments>https://www.dogsbody.com/blog/tripwire-how-and-why/?pk_campaign=feed&#038;pk_kwd=tripwire-how-and-why#respond</comments>
		
		<dc:creator><![CDATA[Jim Carter]]></dc:creator>
		<pubDate>Tue, 09 Apr 2019 10:35:21 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[Security]]></category>
		<guid isPermaLink="false">https://www.dogsbody.com/?p=10744</guid>

					<description><![CDATA[<p>Open Source Tripwire is a powerful tool to have access to.  Tripwire is used by the MOD to monitor systems.  The tool is based on code contributed by Tripwire &#8211; a company that provide security products and solutions.  If you need to ensure the integrity of your filesystem Tripwire could be the perfect tool for [&#8230;]<img src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Ftripwire-how-and-why%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dtripwire-how-and-why&amp;action_name=Tripwire%20%26%238211%3B%20How%20and%20Why&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /></p>
<p>The post <a href="https://www.dogsbody.com/blog/tripwire-how-and-why/?pk_campaign=feed&#038;pk_kwd=tripwire-how-and-why">Tripwire &#8211; How and Why</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://github.com/Tripwire/tripwire-open-source">Open Source Tripwire</a> is a powerful tool to have access to.  Tripwire is used by the MOD to monitor systems.  The tool is based on code contributed by <a href="https://www.tripwire.com/">Tripwire</a> &#8211; a company that provide security products and solutions.  If you need to ensure the integrity of your filesystem Tripwire could be the perfect tool for you.</p>
<h2>What is Tripwire</h2>
<p>Open Source Tripwire is a popular host based intrusion detection system (IDS).  It is used to monitor filesystems and alert when changes occur.  This allows you to detect intrusions or unexpected changes and respond accordingly.  Tripwire has great flexibility over which files and directories you choose to monitor which you specify in a policy file.</p>
<h2>How does it work</h2>
<p>Tripwire keeps a database of file and directory meta data.  Tripwire can then be ran regularly to report on any changes.</p>
<p>If you install Tripwire from Ubuntu&#8217;s repo as per the instructions below a daily cron will be set-up to send you an email report.  The general view with alerting is that no news is good news.  Due to the nature of Tripwire it&#8217;s useful to receive the daily email, that way you&#8217;ll notice if Tripwire gets disabled.</p>
<h2>Before we start</h2>
<p>Before setting up Tripwire please check the following:</p>
<ul>
<li>You&#8217;ve configured email on your server.  If not you&#8217;ll need to do that first, we&#8217;ve got a <a href="https://www.dogsbody.com/blog/root-email-notifications-with-postfix">guide</a>.</li>
<li>You&#8217;re manually patching your server.  Make sure you don&#8217;t have unattended upgrades running (<a href="https://www.dogsbody.com/blog/how-to-set-up-unattended-upgrades">see the manual updates section</a>) as unless you&#8217;re co-ordinating Tripwire with your patching process it will be hard for you to distinguish between expected and unexpected changes.</li>
<li>You&#8217;re prepared to put some extra time into maintaining this system for the benefit of knowing when your files change.</li>
</ul>
<h2>Installation on Ubuntu</h2>
<pre>sudo apt-get update
sudo apt-get install tripwire</pre>
<p>You&#8217;ll be prompted to create your site and local keys, make sure you record them in your <a href="https://www.dogsbody.com/blog/password-managers-what-how-and-why/">password manager</a>.</p>
<p>In your preferred editor open /etc/tripwire/twpol.txt</p>
<p>The changes you make here are based on what you&#8217;re looking to monitor, the default config has good coverage of system files but is unlikely to be monitoring your website files if that&#8217;s something you wanted to do.  For example, I&#8217;ve needed to remove /proc and some of the files in /root that haven&#8217;t existed on systems I&#8217;ve been monitoring.</p>
<p>Then create the signed policy file and then the database:</p>
<pre>sudo twadmin --create-polfile /etc/tripwire/twpol.txt
sudo tripwire --init</pre>
<p>At this point it&#8217;s worth running a check. You&#8217;ll want to make sure it has no errors.</p>
<pre>sudo tripwire --check</pre>
<p>Finally I&#8217;d manually run the daily cron to check the email comes through to you.</p>
<pre>sudo /etc/cron.daily/tripwire</pre>
<h2>Day to day usage</h2>
<h3>Changing files</h3>
<p>After you make changes to your system you&#8217;ll need to run a report to check what tripwire sees have changed.</p>
<pre>sudo tripwire --check</pre>
<p>You can then update the signed database.  This will open up the report allowing you to check you&#8217;re happy with the changes before exiting.</p>
<pre>sudo tripwire --update -r /var/lib/tripwire/report/$HOSTNAME-yyyyMMdd-HHmmss.twr</pre>
<p>You&#8217;ll need your local key in order to update the database.</p>
<h3>Changing policy</h3>
<p>If you decide you&#8217;d like to monitor or exclude some more files you can update /etc/tripwire/twpol.txt.  If you&#8217;re monitoring this file you&#8217;ll need to update the database as per the above section.  After that you can update the signed policy file (you&#8217;ll need your site and local keys for this).</p>
<pre>sudo tripwire --update-policy /etc/tripwire/twpol.txt
</pre>
<p>&nbsp;</p>
<p>As you can see tripwire can be an amazingly powerful tool in any security arsenal.  We use it as part of <a href="https://www.dogsbody.com/in-life-support/server-management-and-monitoring/">our maintenance plans</a> and encourage others to do the same.</p>
<p>&nbsp;</p>
<p><em>Feature image by <a href="https://www.flickr.com/photos/nathalie-photos" target="_blank" rel="noopener noreferrer">Nathalie</a> licensed <a title="Creative Commons BY-SA 2.0" href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a>.</em></p>
<img loading="lazy" decoding="async" src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Ftripwire-how-and-why%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dtripwire-how-and-why&amp;action_name=Tripwire%20%26%238211%3B%20How%20and%20Why&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /><p>The post <a href="https://www.dogsbody.com/blog/tripwire-how-and-why/?pk_campaign=feed&#038;pk_kwd=tripwire-how-and-why">Tripwire &#8211; How and Why</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dogsbody.com/blog/tripwire-how-and-why/?pk_campaign=feed&#038;pk_kwd=tripwire-how-and-why/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>What are Status Pages?</title>
		<link>https://www.dogsbody.com/blog/what-are-status-pages/?pk_campaign=feed&#038;pk_kwd=what-are-status-pages</link>
					<comments>https://www.dogsbody.com/blog/what-are-status-pages/?pk_campaign=feed&#038;pk_kwd=what-are-status-pages#comments</comments>
		
		<dc:creator><![CDATA[Jim Carter]]></dc:creator>
		<pubDate>Tue, 05 Feb 2019 11:30:27 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[monitoring]]></category>
		<guid isPermaLink="false">https://www.dogsbody.com/?p=10384</guid>

					<description><![CDATA[<p>A status pages allows a supplier of a service to let their customers know about outages and issues with their service.  They can be used to show planned maintenance and can hook into e-mail or other update methods but typically they are a website firstly.  Status pages are great; they make things easier for everyone [&#8230;]<img src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fwhat-are-status-pages%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dwhat-are-status-pages&amp;action_name=What%20are%20Status%20Pages%3F&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /></p>
<p>The post <a href="https://www.dogsbody.com/blog/what-are-status-pages/?pk_campaign=feed&#038;pk_kwd=what-are-status-pages">What are Status Pages?</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>A status pages allows a supplier of a service to let their customers know about outages and issues with their service.  They can be used to show planned maintenance and can hook into e-mail or other update methods but typically they are a website firstly.  Status pages are great; they make things easier for everyone and save time.  If you think you&#8217;re having an issue related to a provider you can quickly look at their status page to see if they&#8217;re already aware of it before deciding whether or not to contact them.  If they have already acknowledged the problem it also means you don&#8217;t need to spend time working out what has changed at your end.</p>
<h2>We have one</h2>
<p>Our status page <a href="https://status.dogsbody.com/?utm_source=blog_10384">status.dogsbody.com</a>, has been running for quite a while. We suggest our customer use it as your first point of call when you spot something odd.  If you&#8217;ve got your own server(s) that we maintain, we&#8217;ll contact you directly if we start seeing issues.  The status page covers the below&#8230;</p>
<h4>Support &#8211; methods we usually communicate with you</h4>
<ul>
<li>Email</li>
<li>Telephone</li>
<li>Slack</li>
</ul>
<h4>Hosting &#8211; our shared hosting servers</h4>
<ul>
<li>Indigo (our WordPress only hosting)</li>
<li>Purple (our general purpose hosting)</li>
<li>Violet (our cPanel hosting)</li>
</ul>
<p>When we schedule maintenance or have issues we&#8217;ll update you via the status page.  If you are an Indigo or Purple customer and want to be notified of issues or maintenance go ahead and <a href="https://status.dogsbody.com/subscribe?utm_source=blog_10384&amp;utm_campaign=subscribe">subscribe</a>.</p>
<h2>You want one</h2>
<p>Having an (up to date) status page improves your users experience.  It gives them a quick way to find out what&#8217;s going on.  This means they&#8217;ll be have a better understanding and (usually) more tolerant of issues you&#8217;re already dealing with.</p>
<p>Having a status page is likely to cut down on the number of similar questions you get if you have an outage.  We&#8217;ve been really happy with the self-hosted open source software we&#8217;re using &#8211; <a href="https://cachethq.io/">Cachet</a>.  We wanted to make sure our status page doesn&#8217;t go down at the same time as our other services.  So we&#8217;ve used a different server provider to our main infrastructure.  If you want to avoid worrying about that sort of thing, we&#8217;ve seen a lot of people are using <a href="https://www.statuspage.io/">statuspage.io</a> and <a href="https://status.io/">status.io</a>.</p>
<p><em>Feature image background by </em><a class="owner-name truncate no-outline" title="Go to Wolfgang.W. 's photostream" href="https://www.flickr.com/photos/cuxclipper1/" data-track="attributionNameClick">Wolfgang.W.</a> <em>licensed </em><em><a title="Creative Commons BY-SA 2.0" href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a>.</em></p>
<img loading="lazy" decoding="async" src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fwhat-are-status-pages%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dwhat-are-status-pages&amp;action_name=What%20are%20Status%20Pages%3F&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /><p>The post <a href="https://www.dogsbody.com/blog/what-are-status-pages/?pk_campaign=feed&#038;pk_kwd=what-are-status-pages">What are Status Pages?</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dogsbody.com/blog/what-are-status-pages/?pk_campaign=feed&#038;pk_kwd=what-are-status-pages/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Hackathon &#8211; Image Recognition Slackbot</title>
		<link>https://www.dogsbody.com/blog/hackathon-image-recognition-slackbot/?pk_campaign=feed&#038;pk_kwd=hackathon-image-recognition-slackbot</link>
					<comments>https://www.dogsbody.com/blog/hackathon-image-recognition-slackbot/?pk_campaign=feed&#038;pk_kwd=hackathon-image-recognition-slackbot#respond</comments>
		
		<dc:creator><![CDATA[Jim Carter]]></dc:creator>
		<pubDate>Tue, 27 Nov 2018 11:33:46 +0000</pubDate>
				<category><![CDATA[Activities]]></category>
		<category><![CDATA[Hackathon]]></category>
		<guid isPermaLink="false">https://www.dogsbody.com/?p=9841</guid>

					<description><![CDATA[<p>Our internal hackathons give us extra opportunities to play with software and carry out quick projects we can&#8217;t usually justify sinking time into. A while ago we built our Slackbot, it&#8217;s a bit of fun, from providing inspirational quotes to tracking who&#8217;s made the most cups of tea. It&#8217;s well on it&#8217;s way to doing [&#8230;]<img src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fhackathon-image-recognition-slackbot%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dhackathon-image-recognition-slackbot&amp;action_name=Hackathon%20%26%238211%3B%20Image%20Recognition%20Slackbot&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /></p>
<p>The post <a href="https://www.dogsbody.com/blog/hackathon-image-recognition-slackbot/?pk_campaign=feed&#038;pk_kwd=hackathon-image-recognition-slackbot">Hackathon &#8211; Image Recognition Slackbot</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Our <a href="https://www.dogsbody.com/blog/introducing-dogsbody-internal-hackathons/">internal hackathons</a> give us extra opportunities to play with software and carry out quick projects we can&#8217;t usually justify sinking time into.</p>
<p>A while ago we built our <a href="https://github.com/dogsbodytech/extensible-slackbot">Slackbot</a>, it&#8217;s a bit of fun, from providing inspirational quotes to tracking who&#8217;s made the most cups of tea. It&#8217;s well on it&#8217;s way to doing everything you never wanted.</p>
<h2><img loading="lazy" decoding="async" class="alignnone size-full wp-image-9842" src="https://www.dogsbody.com/wp-content/uploads/quote.png" alt="" width="581" height="169" srcset="https://www.dogsbody.com/wp-content/uploads/quote.png 581w, https://www.dogsbody.com/wp-content/uploads/quote-300x87.png 300w, https://www.dogsbody.com/wp-content/uploads/quote-450x131.png 450w" sizes="auto, (max-width: 581px) 100vw, 581px" /></h2>
<h2>The Problem</h2>
<p>DogsBOT reacts to discussions regarding lunch. Initially this was with ? emoji. Since we don&#8217;t eat spaghetti every day I switched it to the ? emoji but this also became routine.  What we needed was a less predictable, more intelligent reaction.  My criteria for this was:</p>
<ul>
<li>Linked to the current weekly menu</li>
<li>Some element of chance</li>
</ul>
<h2>A <em>Solution</em></h2>
<p>The canteen menu for the week is available as a PDF on the site intranet. It was an easy choice to use it as the source for DogsBOT&#8217;s lunch reactions.  As there are multiple options each day DogsBOT would be able to pick one for today at random.</p>
<p>With that decided we just needed to convert the PDF of the menu to text.  Given my bias to use python, a quick google indicated PyPDF2 would be the perfect tool. Unfortunately the menu turned out to be almost entirely images.  All I was able to pull out was the title and a bunch of meta data.  I needed to switch to an image recognition tool.</p>
<p>For the image recognition I wanted to run the code locally so ignored the various cloud solutions.  This still left a lot of choice of software.  I found this <a href="https://medium.freecodecamp.org/getting-started-with-tesseract-part-i-2a6a6b1cf75e">guide</a> which did everything I was looking for using OpenCV (to clean up the image) and Tesseract (to pull out the text).</p>
<p>Now I&#8217;d got the text, I needed to work out which day the food would be served on. I was starting to run out of time so I set-up a quick loop.  It assumes each item is from the day of the week it most recently passed.  Happy that this was mostly working so I moved on to converting the food to emoji.  I did this by attempting to convert each word to an emoji and using the ones that were successful.  In hindsight I would have been better off selecting reactions based on shortnames in this <a href="https://github.com/iamcal/emoji-data">data</a> as Slack reactions use them rather than emoji.</p>
<h2>Conclusion</h2>
<p>The new improved lunch plugin mostly works.  I had fun playing with PyPDF2, ImageMagick, OpenCV and Tesseract as well as learning a little more about how Slack reactions work.</p>
<p>Tesseract is impressively good.   Given that I&#8217;d been planning to just pull the text out of the PDF I didn&#8217;t spend huge amount of time comparing it with the <a href="https://en.wikipedia.org/wiki/Comparison_of_optical_character_recognition_software">alternatives</a> since it did everything I needed.  If spent more time on this I&#8217;d like to spend more time tweaking the OpenCV commands to work with different lower quality images.</p>
<h2>More hackathons</h2>
<p>Whether we&#8217;re <a href="https://www.dogsbody.com/blog/five-go-on-a-hacking-weekend/">fitting out a storm trooper </a>or <a href="https://www.dogsbody.com/blog/emf-camp-2018-a-field-full-of-nerds/">camping in a field</a> we all love spending a day out doing <a href="https://www.dogsbody.com/blog/category/activities/">something different</a>.  For our next hackathon we&#8217;re planning to try and break in to our internal servers.  If you&#8217;ve got any hackathons lined up you think we&#8217;re missing out on let us know in the comments.</p>
<img loading="lazy" decoding="async" src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fhackathon-image-recognition-slackbot%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dhackathon-image-recognition-slackbot&amp;action_name=Hackathon%20%26%238211%3B%20Image%20Recognition%20Slackbot&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /><p>The post <a href="https://www.dogsbody.com/blog/hackathon-image-recognition-slackbot/?pk_campaign=feed&#038;pk_kwd=hackathon-image-recognition-slackbot">Hackathon &#8211; Image Recognition Slackbot</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dogsbody.com/blog/hackathon-image-recognition-slackbot/?pk_campaign=feed&#038;pk_kwd=hackathon-image-recognition-slackbot/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PHP 5.6 will go end of life on 31 Dec 2018</title>
		<link>https://www.dogsbody.com/blog/php-5-6-will-go-end-of-life-on-31-dec-2018/?pk_campaign=feed&#038;pk_kwd=php-5-6-will-go-end-of-life-on-31-dec-2018</link>
					<comments>https://www.dogsbody.com/blog/php-5-6-will-go-end-of-life-on-31-dec-2018/?pk_campaign=feed&#038;pk_kwd=php-5-6-will-go-end-of-life-on-31-dec-2018#respond</comments>
		
		<dc:creator><![CDATA[Jim Carter]]></dc:creator>
		<pubDate>Tue, 02 Oct 2018 10:41:51 +0000</pubDate>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[EOL]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://www.dogsbody.com/?p=8629</guid>

					<description><![CDATA[<p>Quick Public Safety Announcement, PHP 5.6 goes end of life (EOL) on the 31 December 2018.  This means that known security flaws will no longer be being fixed so any sites you have running on it will become vulnerable, hence it is important you update them to a newer version. We recommend updating to the [&#8230;]<img src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fphp-5-6-will-go-end-of-life-on-31-dec-2018%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dphp-5-6-will-go-end-of-life-on-31-dec-2018&amp;action_name=PHP%205.6%20will%20go%20end%20of%20life%20on%2031%20Dec%202018&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /></p>
<p>The post <a href="https://www.dogsbody.com/blog/php-5-6-will-go-end-of-life-on-31-dec-2018/?pk_campaign=feed&#038;pk_kwd=php-5-6-will-go-end-of-life-on-31-dec-2018">PHP 5.6 will go end of life on 31 Dec 2018</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></description>
										<content:encoded><![CDATA[<header class="entry-content-header"></header>
<div class="entry-content">
<p>Quick Public Safety Announcement, PHP 5.6 goes <a href="http://php.net/supported-versions.php">end of life (EOL) on the 31 December 2018</a>.  This means that known security flaws will no longer be being fixed so any sites you have running on it will become vulnerable, hence it is important you update them to a newer version.</p>
<p>We recommend updating to the latest stable version (at the time of writing this is PHP 7.2).  As this is a major upgrade you will want to test your site on the new version and may need to get your developers to update some code before moving over.</p>
<p>If you&#8217;re unsure if you are affected or want a hand upgrading? <a href="https://www.dogsbody.com/contact/">Get in touch</a>!</p>
<p><img decoding="async" src="https://seld.be/images/composer-2018-01.png" /></p>
<p>Everyone loves a good graph and <a href="https://seld.be/notes/php-versions-stats-2018-1-edition">Jordi Boggiano</a> has provided this great overview of the PHP versions out there in the wild!</p>
</div>
<p>Feature image by <a href="https://www.flickr.com/photos/mpaulmd/">See1,Do1,Teach1</a> licensed <a href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a>.</p>
<img loading="lazy" decoding="async" src="https://analytics.dogsbody.com/piwik.php?idsite=1&amp;rec=1&amp;url=https%3A%2F%2Fwww.dogsbody.com%2Fblog%2Fphp-5-6-will-go-end-of-life-on-31-dec-2018%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dphp-5-6-will-go-end-of-life-on-31-dec-2018&amp;action_name=PHP%205.6%20will%20go%20end%20of%20life%20on%2031%20Dec%202018&amp;urlref=https%3A%2F%2Fwww.dogsbody.com%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" /><p>The post <a href="https://www.dogsbody.com/blog/php-5-6-will-go-end-of-life-on-31-dec-2018/?pk_campaign=feed&#038;pk_kwd=php-5-6-will-go-end-of-life-on-31-dec-2018">PHP 5.6 will go end of life on 31 Dec 2018</a> appeared first on <a href="https://www.dogsbody.com">Dogsbody Technology</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dogsbody.com/blog/php-5-6-will-go-end-of-life-on-31-dec-2018/?pk_campaign=feed&#038;pk_kwd=php-5-6-will-go-end-of-life-on-31-dec-2018/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: www.dogsbody.com @ 2026-08-12 14:42:25 by W3 Total Cache
-->