Jekyll2017-06-16T23:56:05-07:00https://www.debuntu.org//DebuntuDebian/Ubuntu Tips and Trickschantrahttps://www.debuntu.orgHow-To: Convert a WordPress site from Multisite to Standalone install2016-01-25T23:29:20-08:002016-01-25T23:29:20-08:00https://www.debuntu.org/how-to-convert-a-wordpress-site-from-multisite-to-standalone-install<p>Since wordpress 3.0, it is possible to create a network or site by using the <em>multisite</em> feature. It allows to manage multiple wordpress websites from a single installation. Plugins, themes get installed and maintained in one place, and the individual sites can activate them.</p>
<!--more-->
<p>While multisite has its benefits, in my case, I wanted to return to a good old standalone install. I had a plan a long time ago to move multiple websites from drupal onto wordpress, but never got to it. Finally, I much prefer to handle the upgrade of 1 site on it own rather than upgrading all at the same time. While wordpress does a good job at making maintenance easy, I have been bitten a few time in the past by upgrades going bad.</p>
<p>Finally, one should also read <a href="http://codex.wordpress.org/Before_You_Create_A_Network" target="_blank">WordPress: Create A Network</a>” before going head down in setting it up.</p>
<p>Moving off a multisite install is not that straightforward, some of the resource will end up in different places, permalinks need to be fixed and some files need to be moved around.</p>
<h2 id="disclaimer">Disclaimer</h2>
<p class="notice--warning">
Before doing anything, make a backup of your site and try to run this tutorial in a VM or dev environment as you may need to adjust a few steps to fit your setup.
</p>
<p>Also, to be noted, you should not run this on a live website as this will migration will cause downtime.</p>
<p>This worked for me, but the migration is rather manual and your mileage may vary. Please follow this steps with caution!</p>
<h2 id="getting-started">Getting started</h2>
<h3 id="finding-your-site-id">Finding your site ID</h3>
<p>Now that you have a backup, you will need to find which site ID you are migrating. You can get this from visiting <em>http://example.com/wp-admin/network</em> and find the site you are migrating off.</p>
<p>In this example, I was moving site ID 2.</p>
<h2 id="database">Database</h2>
<h3 id="exporting-your-db">Exporting your DB</h3>
<p>The database table you will want to export may vary depending on the plugins you have installed and used. Here, assuming your site had ID 2 and your db <em>table_prefix</em> was set to <em>wp__, you will want to dump ALL tables starting with _wp_2_</em> along with <em>wp_usermeta</em> and <em>wp_users</em>, as they will contain the users from the multisite.</p>
<p>Here is a 1-liner that may help to get all the required data out assuming:</p>
<ul>
<li>DB name: mywordpressdb</li>
<li>DB table prefix: wp_</li>
<li>Site ID: 2</li>
</ul>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code>mysqldump -u root -p mywordpressdb <span class="k">$(</span>mysql -u root -p mywordpressdb -N -s -e <span class="s1">'show tables;'</span> | grep <span class="s1">'^wp_2_'</span><span class="k">)</span> &gt; mywordpressdb.sql
</code></pre>
</div>
<h3 id="fixing-the-db">Fixing the DB</h3>
<p>Now that we have the relevant tables, it is time to fix the content of the DB. <em>sed</em> is your friend here:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code>sed -i <span class="s1">'s#wp-content/blogs.dir/2/files#wp-content/uploads#g'</span> mywordpressdb.sql <span class="c"># Fix uploaded file locations</span>
sed -i <span class="s1">'s#wp_2_#wp_#g'</span> mywordpressdb.sql <span class="c"># fix table names</span>
sed -i <span class="s1">'s#/files/#/wp-content/uploads/#g'</span> mywordpressdb.sql <span class="c"># fix file upload permalinks</span>
</code></pre>
</div>
<p>At this stage, you should have a database backup that should allow you to restore your wordpress site in standalone mode.</p>
<h2 id="wordpress-files">WordPress files</h2>
<p>Assuming your wordpress install is in <em>/var/www/wordpress</em>, running the following command should copy the files that were uploaded while using a multisite set up to a standalone setup:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code>rsync -avz /var/www/wordpress/wp-content/blogs.dir/2/files/ /var/www/wordpress/wp-content/uploads/
rm -rf /var/www/wordpress/wp-content/blogs.dir/2/files
</code></pre>
</div>
<h2 id="importing-standalone-setup-db">Importing standalone setup DB</h2>
<p>The backup we made earlier should contain all the data we need, but to be on the safe side, we will let the wordpress installer bootstrap a new DB and then re-import the data.</p>
<h3 id="bootstrapping-the-db">Bootstrapping the DB</h3>
<p>At this stage, I assume you have a brand new DB called <em>mywordpressdb</em>. To force the wordpress installer to run, we will move <em>wp-config.php</em> in another location and we will copy it back later.</p>
<p>Accessing http://www.example.com should now trigger the wordpress installer. Go through the install steps to setup the database.</p>
<h3 id="restoring-db">Restoring DB</h3>
<p>To restore the DB from our backup, we will use the <em>mysql</em> CLI:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code>mysql -u root -p mywordpressdb < mywordpressdb.sql
</code></pre>
</div>
<h3 id="fixing-the-config">Fixing the config</h3>
<p>We now need to fix the <em>wp-config.php</em> file by removing references to multisite config. Below is an example of the constants that need to be removed from wp-config:</p>
<div class="language-diff highlighter-rouge"><pre class="highlight"><code><span class="gd">--- wordpress.old/wp-config.php 2016-01-25 17:07:24.437572380 -0500
</span><span class="gi">+++ wordpress/wp-config.php 2016-01-25 23:44:56.432183250 -0500
</span><span class="gu">@@ -119,15 +121,6 @@
</span>* in their development environments.
*/
define('WP_DEBUG', false);
<span class="gd">-define('WP_ALLOW_MULTISITE', true);
-
-define( 'MULTISITE', true );
-define( 'SUBDOMAIN_INSTALL', true );
-$base = '/';
-define( 'DOMAIN_CURRENT_SITE', 'debuntu.org' );
-define( 'PATH_CURRENT_SITE', '/' );
-define( 'SITE_ID_CURRENT_SITE', 1 );
-define( 'BLOG_ID_CURRENT_SITE', 1 );
</span>
/* That's all, stop editing! Happy blogging. */
</code></pre>
</div>
<p>Finally, we need to copy <em>wp-config.php</em> back to <em>/var/www/wordpress/</em></p>chantraSince wordpress 3.0, it is possible to create a network or site by using the multisite feature. It allows to manage multiple wordpress websites from a single installation. Plugins, themes get installed and maintained in one place, and the individual sites can activate them.How-To: Prevent SPAM with Apache’s mod security2014-11-06T06:31:30-08:002014-11-06T06:31:30-08:00https://www.debuntu.org/how-to-prevent-spam-with-apaches-mod-security<p><strong>WordPress</strong> is a great piece of software to run a blog, it is flexible, has tons of plugins are developed for it and updates are really easy to do. To fight spam comments, there is already the <strong>Akismet</strong> plugin that does a really good job.</p>
<p>While <strong>Akismet</strong> catches the spam comments and put them in a separate location, making it easy to delete them, as the number of spam grows, <strong>WordPress</strong> can take long to empty the purge the flush comments and the best option becomes to use a manual SQL query to flush them.</p>
<p>In this article, we will see how we can use <strong><a href="http://en.wikipedia.org/wiki/DNSBL" title="RBL">RBL</a></strong> to prevent spammer from posting to <strong>WordPress</strong>’s comment page and at the same time, lift a bit of load from the server.</p>
<p>While the rules work for <strong>WordPress</strong>, with a bit of modifications, it will be easy to get this setup working for any kind of blog/website.</p>
<!--more-->
<p>This setup was tested on <strong>Debian Wheezy</strong>, it is assumed that you already have a working <strong>Apache</strong> server and a working instance of <strong>WordPress</strong> running.</p>
<p>In a nutshell, what we are going to do here is to use <strong><a href="https://www.modsecurity.org/" title="ModSecurity">ModSecurity</a></strong> to inspect the web requests, and check against some <strong>RBL</strong> if the IP that attempt to post a comment is a known spammer. If it is the case, we will deny access to the page, avoiding any access to <strong>Akismet</strong> service and the database.</p>
<p><strong>RBL</strong> works by doing in DNS lookup for a special hostname, depending on the returned address, we will know if the IP is blacklisted or not. It is lightweight and subsequent calls will be faster as the DNS entry will be cached.</p>
<h2 id="installation">Installation</h2>
<p>To be able to use the <strong>RBL</strong> functionality in <strong>ModSecurity</strong>, we need at least version 2.7, <strong>Debian Wheezy</strong> ships version 2.6.6 but luckily, the <em>debian-backports</em> repository has version 2.8.0. So the first step is going to enable <a href="http://backports.debian.org/Instructions/" title="Debian backports">Debian backports</a>.</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="nb">echo</span> <span class="s2">"deb http://http.debian.net/debian wheezy-backports main"</span> > /etc/apt/sources.list.d/wheezy-backports.list
apt-get update
</code></pre>
</div>
<p>And then install <em>libapache2-mod-security2</em>:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>apt-get install libapache2-mod-security2<br /> <span class="c"># a2enmod security2</span>
</code></pre>
</div>
<h2 id="configuration">Configuration</h2>
<p>Now, edit your <em>virtual host</em> and add the following within the VirtualHost namespace:</p>
<div class="highlighter-rouge"><pre class="highlight"><code><IfModule security2_module>
SecRuleEngine On
SecRequestBodyAccess Off
SecRule REQUEST_METHOD "POST" "id:'400010',chain,drop,log,msg:'Spam host detected by zen.spamhaus.org'"
SecRule REQUEST_URI "\/wp-comments-post\.php" chain
SecRule REMOTE_ADDR "@rbl zen.spamhaus.org"
SecRule REQUEST_METHOD "POST" "id:'400011',chain,drop,log,msg:'Spam host detected by netblockbl.spamgrouper.com'"
SecRule REQUEST_URI "\/wp-comments-post\.php" chain
SecRule REMOTE_ADDR "@rbl netblockbl.spamgrouper.com"
</IfModule>
</code></pre>
</div>
<p>And finally, check that the config is correct and if it is, reload apache:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>apache2ctl -t
/etc/init.d/apache2 reload
</code></pre>
</div>
<p>What this does is to enable <strong>ModSecurity</strong> engine (<em>SecRuleEngine On</em>), to only look at the HTTP headers (<em>SecRequestBodyAccess Off</em>) and finally set the rules up. We have 2 similar rules checking 2 different <strong>DNSBL</strong>. If the first one does not match the IP, the second one may. I have found <em>zen.spamhaus.org</em> to catch most of them, and <em>netblockbl.spamgrouper.com</em> to catch some of the ones that went through.</p>
<p>We are chaining 3 rules, and if the 3 match, we will take the actions from the first rule. As a sidenote, when chaining rules, the <em><a href="https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#Actions" title="ModSecurity actions">disruptive actions</a></em> must appear in the first rule (<em>drop</em> here).</p>
<p>So, our first rule says that we want to match the <em>HTTP method</em> POST. We chain this rule and if all chained rule match, we will <em>drop</em> the request, and <em>log</em> it with a message along the line: <em>Spam host detected by _dnsbl_provider_</em>. The next rule check if the <em>URI</em> is /wp-comments-post.php, which is the page use to post comments and also get chained, finally, the third rule check that the remote IP is known to the <em>DNSRBL</em>.</p>
<p>If all 3 conditions are met, the request is dropped and does not even reach <strong>WordPress</strong>.</p>
<p>Another good <strong>DNSBL</strong> that catched IP that made it through the 2 first one is <strong><a href="http://www.projecthoneypot.org/" title="Project Honeypot">Project Honeypot</a></strong>. You need to sign up and get your <em>BL API key</em>, once you have it, you can add it to the list and fill in the key with the <em>SecHttpBlKey</em> directive as follow:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>SecHttpBlKey my_key_here
SecRule REQUEST_METHOD "POST" "id:'400012',chain,drop,log,msg:'Spam host detected by dnsbl.httpbl.org'"
SecRule REQUEST_URI "\/wp-comments-post\.php" chain
SecRule REMOTE_ADDR "@rbl dnsbl.httpbl.org"
</code></pre>
</div>
<h2 id="avoiding-too-many-lookup">Avoiding too many lookup</h2>
<p>We can improve the logic above by marking blacklisting an IP that matched against a <strong>DNSBL</strong> by blacklisting them from within <strong>ModSecurity</strong> for some time. This way, if we see an IP that we know is a spammer, we will avoid querying the DNS for no reason.</p>
<p>What we will do here, is to blacklist an IP for 7 days if we already had a match against a <strong>DNSBL</strong>. We will only do that for <em>POST</em> to the comment page (but we could be more aggressive and just blacklist against any pages.).</p>
<p>Change the rules to look like:</p>
<div class="highlighter-rouge"><pre class="highlight"><code><IfModule security2_module>
SecRuleEngine On
SecRequestBodyAccess Off
SecAction "id:400000,phase:1,initcol:IP=%{REMOTE_ADDR},pass,nolog"
SecRule IP:spam "@gt 0" "id:400001,phase:1,chain,drop,msg:'Spam host %{REMOTE_ADDR} already blacklisted'"
SecRule REQUEST_METHOD "POST" chain
SecRule REQUEST_URI "\/wp-comments-post\.php"
SecRule REQUEST_METHOD "POST" "id:'400010',chain,drop,log,msg:'Spam host detected by zen.spamhaus.org'"
SecRule REQUEST_URI "\/wp-comments-post\.php" chain
SecRule REMOTE_ADDR "@rbl zen.spamhaus.org" "setvar:IP.spam=1,expirevar:IP.spam=604800"
SecRule REQUEST_METHOD "POST" "id:'400011',chain,drop,log,msg:'Spam host detected by netblockbl.spamgrouper.com'"
SecRule REQUEST_URI "\/wp-comments-post\.php" chain
SecRule REMOTE_ADDR "@rbl netblockbl.spamgrouper.com" "setvar:IP.spam=1,expirevar:IP.spam=604800"
SecHttpBlKey my_key_here
SecRule REQUEST_METHOD "POST" "id:'400012',chain,drop,log,msg:'Spam host detected by dnsbl.httpbl.org'"
SecRule REQUEST_URI "\/wp-comments-post\.php" chain
SecRule REMOTE_ADDR "@rbl dnsbl.httpbl.org" "setvar:IP.spam=1,expirevar:IP.spam=604800"
</IfModule>
</code></pre>
</div>
<p>What is new? First, we will initialise a collection called <em>IP</em>, then, if the value of <em>IP.spam</em> is greater than 0, we will chain the rule, and drop and log the message ‘Spam host %{REMOTE_ADDR} already blacklisted’ if all other chained rule match. In the chained rules, we check that the query is POSTing to the comment page.</p>
<p>Now, when we detect a spam with a <strong>DNSBL</strong>, we set the variable <em>IP.spam</em> to 1 and make that variable expire after 7 days (604800 seconds).</p>
<h2 id="conclusion">Conclusion</h2>
<p>Using this technique, I have brought the number of comments marked as spam by Akismet down by 50x!!!. I can now let spams stack up in the spam comment list and wordpress can still delete them quickly when clicking on <em>Empty Spam</em>.</p>
<p>Not only does it make the experience more enjoyable, but by tackling the spams earlier, you save some processing resources, avoid useless writes to DB and query to <strong>Akismet</strong> along with some bandwith as the 403 page is much more lightweight then a render blog page.</p>
<p>By keeping track of known spamming IP, we can also bypass DNS queries.</p>chantraWordPress is a great piece of software to run a blog, it is flexible, has tons of plugins are developed for it and updates are really easy to do. To fight spam comments, there is already the Akismet plugin that does a really good job.
While Akismet catches the spam comments and put them in a separate location, making it easy to delete them, as the number of spam grows, WordPress can take long to empty the purge the flush comments and the best option becomes to use a manual SQL query to flush them.
In this article, we will see how we can use RBL to prevent spammer from posting to WordPress’s comment page and at the same time, lift a bit of load from the server.
While the rules work for WordPress, with a bit of modifications, it will be easy to get this setup working for any kind of blog/website.How-To: Fight SPAM with Postfix RBL2013-09-26T00:02:47-07:002013-09-26T00:02:47-07:00https://www.debuntu.org/how-to-fight-spam-with-postfix-rbl<p>Spam, spam everywhere! If you are hosting your own mail server, fighting spam can become tricky. Antispam solutions do catch a fair amount of them, but still many spam email can still make their way through.</p>
<p><strong>RBL</strong> (<em>Real-time Blackhole</em>) is a database of known spammy IPs which is accessible over DNS. Depending on the response received from the DNS server, the IP is classified as spammy or not.</p>
<p>This tutorial will show you how to set up RBL with <strong>postfix</strong>.</p>
<!--more-->
<p>We are not going to cover how to install and set up <strong>postfix</strong> here. If you do not have a working postfix setup yet, you could check <a href="/how-to-virtual-emails-accounts-with-postfix-and-dovecot/" title="How-To: Virtual Emails Accounts With Postfix And Dovecot">How-To: Virtual Emails Accounts With Postfix And Dovecot</a>.</p>
<p>Now that you have a working postfix setup, let’s talk at what we want to achieve…. Basically, the idea behind RBL is that we want to reject emails upon reception if they are coming from an IP which is known to be spammy.</br >In <strong>Postfix</strong>, this basically happens in the <em>smtpd_client_restrictions</em> config entry which resides in <em>/etc/postfix/main.cf</em> .</p>
<p>There, we will add a few <em>reject_rbl_client</em> entries that will take care of rejecting a client connection if it is blacklisted by one of the service.</p>
<div class="highlighter-rouge"><pre class="highlight"><code>smtpd_client_restrictions = permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
reject_rbl_client zen.spamhaus.org,
reject_rbl_client bl.spamcop.net,
reject_rbl_client cbl.abuseat.org,
permit
</code></pre>
</div>
<p>And finally, restart you mail server to take the new settings into account:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>/etc/init.d/postfix restart
</code></pre>
</div>
<p>Let’s go over the settings. In this case, I have chosen to use <em>zen.spamhaus.org</em> first, <em>bl.spamcop.net</em> second and finally <em>cbl.abuseat.org</em>.</p>
<p>Essentially, what is going to happen given the set of rules below, is that email sent from my network will be accepted with no checks. Same goes to authenticated users (e.g email account/password). If the email is neither sent by my network or by an email account, we reject all email which destination is not known to m, e.g no relaying (reject_unauth_destination). At that stage, the email that have not matched any of the previous rules are basically email sent to one hosted mail domain, this is where we are going to apply the RBL filter and reject emails coming from blacklisted clients.</p>
<p>If it passes all 3 RBL filters, the email will be allowed to go through…. and go through the next steps (antispam, antivirus…)</p>
<p>Using RBL is really efficient and pretty lightweight. All it take is some DNS queries and if you were going to receive a lot of spam email from the same client, this DNS entries will be cached in your (local) DNS. To get some figures on how many emails get caught through RBL, on a server that 90% of the email rejected, 98% of them are from RBL, the rest is relay being denied!</p>
<p>You can find check this list of <a href="http://en.wikipedia.org/wiki/Comparison_of_DNS_blacklists" title="DNS Blacklist services" target="blank">DNS Blacklist services</a>.</p>
<p>Enjoy your (almost) spam free email experience!</p>chantraSpam, spam everywhere! If you are hosting your own mail server, fighting spam can become tricky. Antispam solutions do catch a fair amount of them, but still many spam email can still make their way through.How-To: using Python Virtual Environments2013-09-02T23:30:49-07:002013-09-02T23:30:49-07:00https://www.debuntu.org/how-to-using-python-virtual-environments<p>A nice thing about <strong><a href="http://www.python.org/" title="Python" target="blank">Python</a></strong> is that there is tons of modules available out there. Not all those modules are readily available for your distro and even if there were, chances are that a newer release with new features is already out there.</p>
<p>You might not always want to install those modules system wide, either because there might not be any need for it, or because they could clash with the same module install via package management.</p>
<p>To answer this problem, <strong>python</strong> has a <strong>virtualenv</strong> that will let you create multiple virtual python instances within which you will be able to install whichever modules you might need. All this without requiring root pribileges.</p>
<!--more-->
<p>First, let’s install the main package for the job: <strong>virtualenv</strong>:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>sudo apt-get install python-virtualenv
</code></pre>
</div>
<p>Now we can get ready and start installing our first <strong>virtualenv</strong> environment called <em>venv</em></p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>virtualenv ~/venv
New python executable <span class="k">in </span>venv/bin/python
Installing distribute.............................................................................................................................................................................................done.
Installing pip...............done.
</code></pre>
</div>
<p>In order to get into that virtual env, we have to run the following command:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span><span class="nb">source</span> ~/venv/bin/activate
<span class="o">(</span>venv<span class="o">)</span> <span class="err">$</span>
</code></pre>
</div>
<p>At this stage, we are confined in this newly created python environment and we can start to install some packages in it. Let’s install <em>django-1.4</em>:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>pip install <span class="nv">django</span><span class="o">==</span>1.4
...
<span class="o">(</span>venv<span class="o">)</span> <span class="nv">$ </span>python -c <span class="s2">"import django; print django.get_version()"</span>
1.4
</code></pre>
</div>
<p>Now, in order to get out of this virtual environment, run:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="o">(</span>venv<span class="o">)</span> <span class="nv">$ </span>deactivate
<span class="err">$</span>
</code></pre>
</div>
<p>If you want to force the version of python to be used, you have to explicitly say it when creating the new environment. Suppose we have python3.2 binary available at <em>/usr/bin/python3.2</em>, you can create a virtual environment that will use it by using the following command line:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>virtualenv -p /usr/bin/python3.2 ~/venvpy3
<span class="gp">$ </span><span class="nb">source</span> ~/venvpy3/bin/activate
<span class="o">(</span>venvpy3<span class="o">)</span> <span class="nv">$ </span>python -V
Python 3.2.3
<span class="o">(</span>venvpy3<span class="o">)</span> <span class="nv">$ </span>deactivate
<span class="err">$</span>
</code></pre>
</div>
<p>That’s about all it takes to have an isolated python environment where you can easily <em>pip install</em> anything you like without messing with the system.</p>
<p>A separate utility <em>virtualenvwrapper</em> is available to ease the management of virtual envs, worth checking it out!</p>chantraA nice thing about Python is that there is tons of modules available out there. Not all those modules are readily available for your distro and even if there were, chances are that a newer release with new features is already out there.How-To: Automatically logout idle bash session2013-07-15T00:08:35-07:002013-07-15T00:08:35-07:00https://www.debuntu.org/how-to-automatically-logout-idle-bash-session<p>It can be useful to have a bash session automatically closing after some time. One of the obvious reason you might want this to happen is to make sure that no console is left with root access unwillingly.</p>
<p>Bash comes ready for this and can be configured to automatically terminate after waiting for activity for a given time.</p>
<!--more-->
<p>By default, <em>bash</em> will wait indefinitely for input. But, there is a way to tell <em>bash</em>, or more exactly the <em>read</em> builtin command to timeout after some time of inactivity. This has the effect, for an interactive shell, to terminate after waiting for that time.</p>
<p><strong>TMOUT</strong> is the environment variable that define that timeout.</p>
<p>In order to have this applied to ALL users on your system, you can create a file called: <em>/etc/profile.d/bash_autologout.sh</em> and add the following to it:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>export TMOUT=600
</code></pre>
</div>
<p>The next time a user will log in, they will set and export TMOUT and their shell will terminate after 10 minutes of inactivity.</p>chantraIt can be useful to have a bash session automatically closing after some time. One of the obvious reason you might want this to happen is to make sure that no console is left with root access unwillingly.How-To: WiFi roaming with wpa-supplicant2013-06-17T23:14:56-07:002013-06-17T23:14:56-07:00https://www.debuntu.org/how-to-wifi-roaming-with-wpa-supplicant<p>wpa_supplicant can be used as a roaming daemon so you can get your system to automatically connect to different network as you are going from one location to another.</p>
<p>This come in pretty handy on headless machines where you rely on network connection to be up in order to be able to access the machine.</p>
<!--more-->
<p>First, you need to make sure that you have <strong>wpasupplicant</strong> installed:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>apt-get install wpasupplicant
</code></pre>
</div>
<p>Once <strong>wpasupplicant</strong> we can go ahead and configure different networks. Go and open <em>/etc/wpa_supplicant/wpa_supplicant.conf</em>:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
# WPA-Personal (PSK)
network={
ssid="home"
scan_ssid=1
key_mgmt=WPA-PSK
psk="home_psk"
id_str="home"
}
# work network; use EAP-TLS with WPA; allow only CCMP and TKIP ciphers
network={
ssid="work"
scan_ssid=1
key_mgmt=WPA-EAP
pairwise=CCMP TKIP
group=CCMP TKIP
eap=TLS
identity="user@example.com"
ca_cert="/etc/cert/ca.pem"
client_cert="/etc/cert/user.pem"
private_key="/etc/cert/user.prv"
private_key_passwd="password"
id_str="work"
}
# non encrypted network
network={
ssid="unsecure"
scan_ssid=1
key_mgmt=NONE
id_str="unsecure"
}
</code></pre>
</div>
<p>Now that we have our different SSIDs set up, we have to configure <em>/etc/network/interfaces</em> to use wpa-supplicant in roaming mode.</p>
<p>To do that, we you need to make sure <strong>wlan0</strong> (or whichever interface name your WiFi interface maps to) is set up as follow:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp
</code></pre>
</div>
<p>With this setting, <strong>wpa-supplicant</strong> will establish a link with the access-point. Then, the OS will set up the network with <strong>DHCP</strong>.</p>
<p>As you might have seen, we have defined <em>id_str</em> for each network in <em>/etc/wpa_supplicant/wpa_supplicant.conf</em> . We can use those IDs to set up custom network settings depending on which access point we are connected to.</p>
<p>In the settings below, we will configure a static ip for <em>home</em> and <em>work</em> and we will default to <strong>DHCP</strong> for the rest.</p>
<div class="highlighter-rouge"><pre class="highlight"><code>allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
# Leave this in to default to dhcp
iface default inet dhcp
# At home, we want to have a static IP 192.168.1.2/24 with default gw 192.168.1.1
iface home inet static
address 192.168.1.2
network 255.255.255.0
gateway 192.168.1.1
# At work, we want static IP 10.0.0.10/24 with default gw 10.0.0.1
iface work inet static
address 10.0.0.20
network 255.255.255.0
gateway 10.0.0.1
</code></pre>
</div>
<p>That should be it, you can run the following as root:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>ifdown wlan0; ifup wlan0
</code></pre>
</div>
<p>And the interface should be coming up if oyu properly set up all your settings.</p>
<p>More info on setting <strong>wpa_supplicant.conf</strong> can be checked through</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code>man wpa_supplicant.conf
</code></pre>
</div>chantrawpa_supplicant can be used as a roaming daemon so you can get your system to automatically connect to different network as you are going from one location to another.How-To: Make a file Immutable/Write protected2013-06-09T23:35:57-07:002013-06-09T23:35:57-07:00https://www.debuntu.org/how-to-make-a-file-immutablewrite-protected<p>There might be time when you want to make sure that a file will be protected from accidental/automated change/deletion. While one can protect a file/directory in some ways by removing <em>write permissions</em> using standard file permission on Unix already can save you from some situations, there is more that can be done on Linux.</p>
<!--more-->
<p>The <em>e2fsprogs</em> software suite comes with a bunch of file system utilities for the ext* filesystems. Amongst them, there is the <strong>chattr</strong> that will help us <em>change attributes</em> on a Linux File system.</p>
<p>While there is numerous attributes that can be changed, for the purpose of this post, we will look at the attribute that would make our file/directory <strong>immutable</strong>, even by <em>root</em> and whichever are the Unix filesystem permissions.</p>
<p>The attribute that we will modify is <em>i</em> as in <em>immutable</em>.</p>
<h2 id="making-a-filedirectory-immutable">Making a file/directory immutable</h2>
<p>To make a file or directory immutable, we will be using the following command (considering that the file we modify is called <em>foo</em>):</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="c"># chattr +i foo</span>
</code></pre>
</div>
<p>Let’s play with 1 file and see how things go:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="c"># ls -l foo</span>
-rwxrwxrwx 1 user user 4 Jun 9 22:30 foo
<span class="c"># echo "foo" >> foo</span>
<span class="c"># chattr +i foo</span>
<span class="c"># echo "foo" >> foo</span>
-su: foo: Permission denied
<span class="c"># rm foo</span>
rm: cannot remove <span class="sb">`</span>foo<span class="s1">': Operation not permitted
</span></code></pre>
</div>
<h2 id="removing-immutable-attribute-from-a-filedirectory">Removing immutable attribute from a file/directory</h2>
<p>To remove that attribute, we need to use the <em>-i</em> version of the command:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="c"># chattr -i foo</span>
</code></pre>
</div>
<p>Now that we have remove the attribute, we can modify/remove the file:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="c"># echo "foo" >> foo</span>
<span class="c"># rm foo</span>
</code></pre>
</div>
<h2 id="checking-file-attributes">Checking file attributes</h2>
<p><strong>lsattr</strong> command can be used to verify what attributes are set on a file/directory:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>lsattr foo
----i--------e-- foo
</code></pre>
</div>
<p>There is more attributes available. To find more about it, refer to:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>man chattr
</code></pre>
</div>
<p>Do mind that some attributes are not enabled on mainline Linux kernels.</p>chantraThere might be time when you want to make sure that a file will be protected from accidental/automated change/deletion. While one can protect a file/directory in some ways by removing write permissions using standard file permission on Unix already can save you from some situations, there is more that can be done on Linux.Debian 7.0 Wheezy released2013-05-04T21:30:30-07:002013-05-04T21:30:30-07:00https://www.debuntu.org/debian-7-0-wheezy-released<p><strong>Debian 7.0</strong>, code name <strong>Wheezy</strong>, is finally released.</p>
<p>This new release of comes with some interesting new features such as <em>multiarch</em> support and tools to deploy private cloud based on <em>OpenStack</em> and <em>Xen Cloud Platform (XCP)</em>.</p>
<p>For the first time, <strong>Debian</strong> supports booting using <em>UEFI</em>.</p>
<!--more-->
<p><strong>Debian 7.0 Wheezy</strong> will be running on Linux 3.2. the <em>LAMP</em> stack will be running off <em>Apache 2.2.22</em>, <em>PHP 5.4.4</em> and <em>MySQL 5.5.30</em>.</p>
<p>On the graphical interface side, Gnome 3.4, XFCE 4.8 and KDE 4.8.4 will run your desktop. Iceweasel 10 and Icedove 10 will be your door to the internet.</p>
<p>On the virtualization side, Xen Hypervisor 4.1.4 will be running your virtual machines.</p>
<p>And much much more……</p>
<p>It is now time to get your Debian stable upgraded to <strong>Debian Wheezy</strong> and start playing with the new Debian Testing: <strong>Debian Jessie</strong>!.</p>
<p>For more information regarding this release, the official release note can be found on the <a href="http://www.debian.org/News/2013/20130504" title="Debian 7.0 Wheezy release note" target="blank">Debian 7.0 Wheezy released announcement</a>.</p>chantraDebian 7.0, code name Wheezy, is finally released.How-To: tail multiple files with multitail2013-04-28T22:13:43-07:002013-04-28T22:13:43-07:00https://www.debuntu.org/how-to-tail-multiple-files-with-multitail<p>Many times you will end up tailing multiple files simultaneously. There is a sweet linux utility called <a href="http://www.vanheusden.com/multitail/" title="multitail" target="blank"><strong>multitail</strong></a> that will let you <em>tail</em> multiple files at the same time within the same shell.</p>
<p>And not only will you be able to <em>tail</em> multiple files! You will also be able to run multiple commands and tail their outputs!</p>
<!--more-->
<p><strong>multitail</strong> allows you to tail multiple files within the same window. Outputs can be either merged together or shown in split panes either horizontally or vertically.</p>
<h2 id="installation">Installation</h2>
<p>On <em>Debian</em>, installation is pretty straightforward and only needs a bit of _apt-get_ing:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="c"># apt-get install multitail</span>
</code></pre>
</div>
<h2 id="usage">Usage</h2>
<p>There is a tons of ways to use that command. The man page is filled with different switches that can be use to better customize the output.</p>
<p>I am going to show you a few ways to use it.</p>
<p>First, let’s aggregate the output of 2 log files within the same window. This is done by using a command like:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="c"># multitail -i /var/log/daemon.log -I /var/log/auth.log</span>
</code></pre>
</div>
<p>This tells <strong>multitail</strong> to tail files <em>/var/log/daemon.log</em> and <em>/var/log/auth.log</em> and to merge the output of <em>/var/log/auth.log</em> into the first window.</p>
<p><a href="https://www.debuntu.org/wp-content/uploads/2013/04/multitail-aggregatedoutput.png"><img src="https://www.debuntu.org/wp-content/uploads/2013/04/multitail-aggregatedoutput-300x160.png" alt="Multitail merged output" title="Multitail merged output" class="align-center" height="160" sizes="(max-width: 300px) 100vw, 300px" srcset="https://www.debuntu.org/wp-content/uploads/2013/04/multitail-aggregatedoutput-150x80.png 150w, https://www.debuntu.org/wp-content/uploads/2013/04/multitail-aggregatedoutput-300x160.png 300w" width="300" /></a>
You can also have the same files’ output in 2 different panes:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="c"># multitail -i /var/log/daemon.log -i /var/log/syslog</span>
</code></pre>
</div>
<p>This will have the 2 files displayed in 2 different panes split across the horizontal axis.</p>
<p class="shell">
# multitail -s 2 -i /var/log/daemon.log -i /var/log/syslog
</p>
<p>will have the same files split across the vertical axis.</p>
<p><a href="https://www.debuntu.org/wp-content/uploads/2013/04/multitail-splitoutput.png"><img src="https://www.debuntu.org/wp-content/uploads/2013/04/multitail-splitoutput-300x160.png" alt="Multitail Split Output" title="Multitail Split Output" class="align-center" height="160" sizes="(max-width: 300px) 100vw, 300px" srcset="https://www.debuntu.org/wp-content/uploads/2013/04/multitail-splitoutput-150x80.png 150w, https://www.debuntu.org/wp-content/uploads/2013/04/multitail-splitoutput-300x160.png 300w, https://www.debuntu.org/wp-content/uploads/2013/04/multitail-splitoutput.png 809w" width="300" /></a></p>
<p>As said earlier, <strong>multitail</strong> can also tail the output of commands. In a nutshell, to do this, you will need to use <em>-l</em> in place of <em>-i</em> and <em>-L</em> instead of <em>-I</em>.</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>multitail -l <span class="s2">"ping 8.8.4.4"</span> -ec <span class="s1">'time=4[0-9]\.?[0-9]* ms'</span> -L <span class="s2">"ping 8.8.8.8"</span>
</code></pre>
</div>
<p>Will ping 8.8.4.4 and ping 8.8.8.8 simultaneously and merge the outputs within the same window. On top of that, we will highlight the chunks of output that match <em>time=4[0-9].?[0-9]* ms</em>, e.g any ping’s which RTT is between 40 and 50ms.</p>
<p><a href="https://www.debuntu.org/wp-content/uploads/2013/04/multitail-ping-same-window.png"><img src="https://www.debuntu.org/wp-content/uploads/2013/04/multitail-ping-same-window-300x165.png" alt="Multitail ping merged output" title="Multitail ping merged output" class="align-center" height="165" sizes="(max-width: 300px) 100vw, 300px" srcset="https://www.debuntu.org/wp-content/uploads/2013/04/multitail-ping-same-window-300x165.png 300w, https://www.debuntu.org/wp-content/uploads/2013/04/multitail-ping-same-window.png 805w" width="300" /></a>
There is much more possibilities offered by <strong>multitail</strong>. As always, the <em>manpage</em> is the source of truth. The developer has gathered a few example on his <a href="http://www.vanheusden.com/multitail/examples.php" title="Example page" target="blank">example page</a>.</p>chantraMany times you will end up tailing multiple files simultaneously. There is a sweet linux utility called multitail that will let you tail multiple files at the same time within the same shell.How-To: Reboot on OOM2013-04-17T00:57:39-07:002013-04-17T00:57:39-07:00https://www.debuntu.org/how-to-reboot-on-oom<p>Ever had your linux box getting <em>Out of Memory</em> (<strong>OOM</strong>)? Cleaning up after the <em>OOM killer</em> kicked in to find out that even though <em>OOM killer</em> did a decent job at trying to kill the <em>bad processes</em>, your system ends up in an unknown state and you might be better of rebooting the host to make sure it comes back up in a state that you know is safe.</p>
<!--more-->
<p><a href="https://www.debuntu.org/wp-content/uploads/2013/04/oom_reboot.png"><img src="https://www.debuntu.org/wp-content/uploads/2013/04/oom_reboot-150x83.png" alt="OOM reboot" title="Reboot on OOM" class="align-right" height="83" width="150" /></a>
This is in no way a solution to your <strong>OOM</strong> problem and you will most likely need to troubleshoot further the cause of the <strong>OOM</strong>, nonetheless, this will make sure that when the issue happens (in the middle of the night?), your system gets back on track as fast as possible.</p>
<p>If you use this solution, you really need to make sure that when your system reboots, it is actually functional!</p>
<p>Warnings been said, let see how we can make our system reboot when the <em>OOM killer</em> gets in town.</p>
<p>Well, the trick is actually to <strong>panic</strong> the kernel on <strong>OOM</strong> and to tell the system to <em>reboot</em> on <em>kernel panic</em>.</p>
<p>This is done via <em>procfs</em>. You could either echo the values in <em>/proc/sys/…</em>, but this will not be kept upon reboot, OR set the values in <em>sysctl</em> file and activate them. I will go for the later solution.</p>
<p>Create a file called <em>/etc/sysctl.d/oom_reboot.conf</em> and enter the lines below:</p>
<div class="highlighter-rouge"><pre class="highlight"><code># panic kernel on OOM
vm.panic_on_oom=1
# reboot after 10 sec on panic
kernel.panic=10
</code></pre>
</div>
<p>Then, activate the settings with:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="c"># sysctl -p /etc/sysctl.d/oom_reboot.conf</span>
vm.panic_on_oom <span class="o">=</span> 1
kernel.panic <span class="o">=</span> 10
</code></pre>
</div>
<p>And you should be good to go. You can tweak the number of seconds you want to wait before the system reboot to you need by replacing <em>10</em> with whatever value suits you.</p>
<p>If OOM killer was going to kick in again, you would get the same screen than the screenshot above.</p>
<p>If you want to confirm this works, you can run the program below on a test host (a VM on your workstation is a good candidate):</p>
<div class="language-cpp highlighter-rouge"><pre class="highlight"><code><span class="cm">/**
oom.c
allocate chunks of 10MB of memory indefinitely until you run out of memory
*/</span>
<span class="cp">#include <stdlib.h>
#include <stdio.h>
#include <string.h>
</span>
<span class="cp">#define TEN_MB 10 * 1024 * 1024
</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">){</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">b</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">TEN_MB</span><span class="p">);</span>
<span class="n">memset</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">TEN_MB</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Allocated %d MB</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="p">(</span><span class="o">++</span><span class="n">c</span> <span class="o">*</span> <span class="mi">10</span><span class="p">));</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre>
</div>
<p>Then compile with:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>gcc -o oom oom.c
</code></pre>
</div>
<p>And run it:</p>
<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>./oom
Allocated 10 MB
Allocated 20 MB
...
...
</code></pre>
</div>chantraEver had your linux box getting Out of Memory (OOM)? Cleaning up after the OOM killer kicked in to find out that even though OOM killer did a decent job at trying to kill the bad processes, your system ends up in an unknown state and you might be better of rebooting the host to make sure it comes back up in a state that you know is safe.