toic.org - Entries for the tag centoshttps://toic.org/blog/tags/centos/The latest entries tagged with centosen-usZinniaFri, 08 Jan 2016 14:19:45 +0000Reclaiming InnoDB ibdata unused space. https://toic.org/blog/2012/reducing-innodb-ibdata-unused-space/<p><img align='left' src="/media/filer_public/9f/70/9f70cbfc-1a4f-4885-97e1-66196ea4e805/crystal_128_kcmpartitions.png" alt="ssh" width="120" height="120" style="margin-right:20px; margin-bottom:20px;" /></p> <p>As you well know InnoDB will store its data either in one big system tablespace called ibdata or you can store it in multiple tablespaces (<a href="http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_file_per_table">innodb_file_per_table</a>). In either case InnoDB by default will not reclaim unused space gained when deleting data. Using innodb_file_per_table will separate each InnoDB table in its own .ibd file and it can be easily reclaimed by doing optimize table, using system tablespace will get you stuck since there is no real supported method for reducing you ibdata file and reclaiming unused disk space.</p> <p>One could wonder why would anyone want to have its ibdata in system tablespace? Well there are some &quot;<a class="reference external" href="http://bugs.mysql.com/bug.php?id=51325">bugs</a>&quot; (in versions prior to 5.5) and performance issues that cause mysql lock-ups when using innodb_file_per_table and doing truncate table or drop table or even drop database queries with large buffer pools. In a nutshell MySQL will do a whole buffer pool lock and scan on each of the above mentioned commands effectively stoping the entire MySQL server until it scans over the entire buffer pool for references to those dropped/truncated tables.</p> <p>When given choice and when I do know the pattern of data input to my tablespace i will chose system tablespace.</p> <p>Recently I was a victim of my own system and uncontrolled input of data to my InnoDB table space which leaved me with almost 36Gb of garbage data over one night. Naturally i truncated the data, but it left me with 37Gb ibdata file.</p> <p>So here are the steps I've taken to reduce this system tablespace.</p> <p><strong>First of all backup!</strong></p> <p>I highly recommend <a class="reference external" href="http://www.percona.com/software/percona-xtrabackup">Xtrabackup</a> from Percona for this task, yes it will require additional 37Gb of space for backup but this is by far best point in time backup for MySQL.</p> <pre class="literal-block"> innobackupex $backupdir </pre> <p>And replace the backupdir with your preferred location</p> <p>Let's create a working environment, say you have a lots of space on /home</p> <pre class="literal-block"> mkdir /home/inno-reduce cd /home/inno-reduce </pre> <p>Ok, next stop dumping all the databases that have innodb tables inside, for this I've created a small bash script a while ago..</p> <pre class="code bash literal-block"> <span class="comment">#!/bin/bash </span><span class="name variable">CWD</span><span class="operator">=</span><span class="literal string backtick">`</span><span class="name builtin">pwd</span><span class="literal string backtick">`</span> mysql -e <span class="literal string double">&quot;SELECT distinct(table_schema) FROM information_schema.TABLES where ENGINE = 'InnoDB'&quot;</span> &gt; <span class="name variable">$CWD</span>/innodb-databases.list sed <span class="literal string double">&quot;/table_schema/d&quot;</span> <span class="name variable">$CWD</span>/innodb-databases.list &gt; <span class="name variable">$CWD</span>/tmp mv <span class="name variable">$CWD</span>/tmp <span class="name variable">$CWD</span>/innodb-databases.list <span class="keyword">for</span> database in <span class="literal string backtick">`</span>cat <span class="name variable">$CWD</span>/innodb-databases.list<span class="literal string backtick">`</span><span class="punctuation">;</span> <span class="keyword">do</span> <span class="name builtin">echo</span> <span class="literal string double">&quot;dumping data from </span><span class="name variable">$database</span><span class="literal string double"> to </span><span class="name variable">$CWD</span><span class="literal string double">/</span><span class="name variable">$database</span><span class="literal string double">.sql&quot;</span> /usr/bin/mysqldump --triggers --routines <span class="name variable">$database</span> &gt; <span class="name variable">$CWD</span>/<span class="name variable">$database</span>.sql<span class="punctuation">;</span> <span class="keyword">done</span> </pre> <p>Now would be a good time to cut off any application using MySQL (for example turn off Apache, or drop the packets in firewall). Just copy and paste this code in <strong>step1-dump.sh</strong> file, make it executable and run it. It will produce a .sql dump files in your current directory (hopefully we are still on /home/inno-reduce)</p> <p>Step2 script will iterate trough that dumped data files and drop all the databases that have innodb tables inside.</p> <pre class="code bash literal-block"> <span class="comment">#!/bin/bash </span><span class="name variable">CWD</span><span class="operator">=</span><span class="literal string backtick">`</span><span class="name builtin">pwd</span><span class="literal string backtick">`</span> <span class="keyword">for</span> database in <span class="literal string backtick">`</span>ls <span class="name variable">$CWD</span>/*.sql<span class="punctuation">|</span>awk -F<span class="literal string single">'/'</span> <span class="literal string single">'{print $NF}'</span><span class="punctuation">|</span>cut -d. -f1<span class="literal string backtick">`</span><span class="punctuation">;</span> <span class="keyword">do</span> <span class="name builtin">echo</span> <span class="literal string double">&quot;droping database </span><span class="name variable">$database</span><span class="literal string double">&quot;</span> mysqladmin drop <span class="name variable">$database</span> <span class="keyword">done</span> </pre> <p>Again just copy and paste this code in <strong>step2-drop.sh</strong>, make it executable and run it. At this point There shouldn't be any InnoDB tables in MySQL server.</p> <p>Now, it is a good time to shutdown your MySQL service and rm ibdata file. On typical CentOS system this would be done with</p> <pre class="literal-block"> service mysqld stop rm -f /var/lib/mysql/ibdata1 </pre> <p>If you are not running CentOS and default MySQL install or if you have ibdata file on some other path… please adjust the above. Starting MySQL service at this point would &quot;regenerate&quot; ibdata file with its smallest size increment as defined in my.cnf lets do so:</p> <pre class="literal-block"> service mysqld start </pre> <p>And now for the third script</p> <pre class="code bash literal-block"> <span class="comment">#!/bin/bash </span><span class="name variable">CWD</span><span class="operator">=</span><span class="literal string backtick">`</span><span class="name builtin">pwd</span><span class="literal string backtick">`</span> <span class="keyword">for</span> database in <span class="literal string backtick">`</span>ls <span class="name variable">$CWD</span>/*.sql<span class="punctuation">|</span>awk -F<span class="literal string single">'/'</span> <span class="literal string single">'{print $NF}'</span><span class="punctuation">|</span>cut -d. -f1<span class="literal string backtick">`</span><span class="punctuation">;</span> <span class="keyword">do</span> mysqladmin create <span class="name variable">$database</span> mysql <span class="name variable">$database</span> &lt; <span class="name variable">$CWD</span>/<span class="name variable">$database</span>.sql <span class="keyword">done</span> </pre> <p>As before copy and paste this script into <strong>step3-import.sh</strong> (remember to place this file at the same directory as other two, and dumps), make it executable and run it.</p> <p>Voila! your data is back in, ibdata reduced and MySQL up&amp;running.</p> <p>Remember to restore any access to your MySQL service (starting Apache, clearing firewall drops, etc..)</p> [email protected] (branko)Tue, 04 Dec 2012 23:05:56 +0000https://toic.org/blog/2012/reducing-innodb-ibdata-unused-space/ServicesWsgi on cPanel improved https://toic.org/blog/2011/wsgi-on-cpanel-improved/<p>There is a long time now from my original post on running Django with python 2.6 on cPanel based servers, and as time passed there was some issues while deploying Django in such a way. So I decided to post another post with some updates regarding deployment of any python based scripts trough mod_wsgi and cPanel.</p> <p><strong>What's changed since last post?</strong></p> <ul> <li><p class="first">There is a fix for easy_apache rebuilds, retaining the mod_wsgi and not braking rebuild process</p> </li> <li><p class="first">There was some additions in virtualhost include files, enabling python app to run as a user, not nobody</p> </li> <li><p class="first">A fix for cpanel's shell fork bomb protection while running python aps as a user and not nobody</p> </li> <li><p class="first">Some minor changes regarding media handling, so it get's included in virtualhost includes and not by eating up user's subdomains</p> </li> <li><p class="first">And of course python and Django version updates</p> <blockquote> <p>Disclaimer at the beginning, this setup works for me on latest RELESE cPanel build, running on top of CentOS 5.5. I'm posting this as a way how I managed to get it working, so this shouldn't be considered as a official way of running Django or any other python app on cPanell servers. Although, as per my last post &lt;a href=&quot;/blog/2010/django-on-cpanel-with-python2-6-virtualenv-and-mod_wsgi/&quot;&gt;Django on cpanel with python2.6, virtualenv and mod_wsgi&lt;/a&gt; lot's of people are reporting this is working for them also, and this version of deployment guide will bring some more enhancements.</p> </blockquote> </li> </ul> <div class="section" id="installing-python-and-dependencies"> <h1>Installing python and dependencies</h1> <pre class="literal-block"> mkdir /usr/src/python2.7 &amp;&amp; cd /usr/src/python2.7 </pre> <p>again, if you need sqlite, now is the time to install it.</p> <pre class="code bash literal-block"> wget http://www.sqlite.org/sqlite-autoconf-3070500.tar.gz tar zxvf sqlite-autoconf-3070500.tar.gz <span class="name builtin">cd </span>sqlite-autoconf-3070500 ./configure make make install </pre> <p>Since CentOS 5.5 is still running python 2.4 and if you don't wish to brake your system you should install your python 2.7 in alternate location:</p> <pre class="code bash literal-block"> <span class="name builtin">cd</span> /usr/src/python2.7/ wget http://www.python.org/ftp/python/2.7.1/Python-2.7.1.tgz tar zxvf Python-2.7.1.tgz <span class="name builtin">cd </span>Python-2.7.1 ./configure --prefix<span class="operator">=</span>/opt/python2.7 --with-threads --enable-shared ./configure --help make make install </pre> <p>This will install python 2.7 in <strong>/opt/python2.7</strong> directory. To make any use of this alternate install we must do the following:</p> <pre class="code bash literal-block"> ln -s /opt/python2.7/bin/python /usr/bin/python2.7 <span class="name builtin">echo</span> <span class="literal string single">'/opt/python2.7/lib'</span>&gt;&gt; /etc/ld.so.conf.d/opt-python2.7.conf ldconfig </pre> <p>It will make a symbolic link in your path and instruct the system where to find libs for this alternate python install.</p> <p>Now is a good time to check if everything is working as it should</p> <pre class="code python literal-block"> <span class="name">root</span><span class="name decorator">&#64;toy2</span> <span class="punctuation">[</span><span class="operator">/</span><span class="name">usr</span><span class="operator">/</span><span class="name">src</span><span class="operator">/</span><span class="name">python2</span><span class="operator">.</span><span class="literal number integer">7</span><span class="punctuation">]</span><span class="comment"># /usr/bin/python2.7</span> <span class="name">Python</span> <span class="literal number float">2.7</span><span class="operator">.</span><span class="literal number integer">1</span> <span class="punctuation">(</span><span class="name">r271</span><span class="punctuation">:</span><span class="literal number integer">86832</span><span class="punctuation">,</span> <span class="name">Mar</span> <span class="literal number integer">26</span> <span class="literal number integer">2011</span><span class="punctuation">,</span> <span class="literal number integer">22</span><span class="punctuation">:</span><span class="literal number integer">31</span><span class="punctuation">:</span><span class="literal number integer">33</span><span class="punctuation">)</span> <span class="punctuation">[</span><span class="name">GCC</span> <span class="literal number float">4.1</span><span class="operator">.</span><span class="literal number integer">2</span> <span class="literal number integer">20080704</span> <span class="punctuation">(</span><span class="name">Red</span> <span class="name">Hat</span> <span class="literal number float">4.1</span><span class="operator">.</span><span class="literal number integer">2</span><span class="operator">-</span><span class="literal number integer">48</span><span class="punctuation">)]</span> <span class="name">on</span> <span class="name">linux2</span> <span class="name">Type</span> <span class="literal string">&quot;help&quot;</span><span class="punctuation">,</span> <span class="literal string">&quot;copyright&quot;</span><span class="punctuation">,</span> <span class="literal string">&quot;credits&quot;</span> <span class="operator word">or</span> <span class="literal string">&quot;license&quot;</span> <span class="keyword">for</span> <span class="name">more</span> <span class="name">information</span><span class="operator">.</span> <span class="operator">&gt;&gt;&gt;</span> <span class="keyword namespace">import</span> <span class="name namespace">sqlite3</span> <span class="operator">&gt;&gt;&gt;</span> </pre> <p><strong>Type CTRL+D to exit.</strong></p> <p>Next thing to do is installation of python-setup tools:</p> <pre class="code bash literal-block"> /usr/bin/python2.7 <span class="name builtin">cd</span> /usr/src/python2.7/ wget http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg sh setuptools-0.6c11-py2.7.egg --prefix<span class="operator">=</span>/opt/python2.7 </pre> <p>In this tutorial, I'm skipping the installation of mysql for python since you will have to install it per user basis in their virtual environments. All we need to do next is to install virtualenv to our python 2.7 so we can distribute them to our users</p> <pre class="literal-block"> cd /opt/python2.7/bin/ ./easy_install virtualenv </pre> </div> <div class="section" id="mod-wsgi-installation"> <h1>mod_wsgi installation</h1> <pre class="code bash literal-block"> <span class="name builtin">cd</span> /opt/python2.7/lib/python2.7/config/ ln -s ../../libpython2.7.so . <span class="name builtin">cd</span> /usr/src/python2.7/ wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz tar zxvf mod_wsgi-3.3.tar.gz <span class="name builtin">cd </span>mod_wsgi-3.3 ./configure --with-python<span class="operator">=</span>/opt/python2.7/bin/python make make install </pre> <p>Now this will install mod_wsgi.so file in /usr/local/apache/modules folder, as I experienced during cPanel easy_apache rebuilds it will completely empty this folder, thus any virtualhost includes relying on mod_wsgi will fail and easy_apache will not be able to properly rebuild your httpd.conf file and whole apache or php upgrade you were running will fail and revert back to last good state.</p> <p>To avoid this we will now copy the mod_wsgi to different folder:</p> <pre class="literal-block"> mkdir /usr/local/apache/extramodules mv /usr/local/apache/modules/mod_wsgi.so /usr/local/apache/extramodules/ </pre> <p><strong>Note that this wsgi module is built with python 2.7 and will not work with any other version.</strong> If for some strange reason later on you try to run any given python application with system's default python2.4 it will not work.</p> <p>Anyways, all we need to do next is to include mod_wsgi into the apache configuration:</p> <pre class="literal-block"> nano /usr/local/apache/conf/includes/pre_virtualhost_global.conf </pre> <p>and paste:</p> <pre class="literal-block"> LoadModule wsgi_module /usr/local/apache/extramodules/mod_wsgi.so AddHandler wsgi-script .wsgi </pre> <p>Now do configtest:</p> <pre class="literal-block"> root&#64;toy2 [~]# service httpd configtest Syntax OK </pre> <p>If you get <strong>Syntax OK</strong> at the end, you can safely restart your apache:</p> <pre class="literal-block"> /scripts/restartsrv httpd </pre> <p>This is it, our apache can now serve python apps like Django, pylons, etc...</p> </div> <div class="section" id="setting-up-django-projects"> <h1>Setting up Django projects</h1> <p>Just like in my <a class="reference external" href="/blog/2010/django-on-cpanel-with-python2-6-virtualenv-and-mod_wsgi/">previous post</a> I'll use '<strong>[username]</strong>' for cpanel username reference and '<strong>[domain]</strong>' for that user's domain. To match your needs you will have to replace those where appropriate.</p> <p>We will quickly setup user's virtualenv, be aware though some of the python packages requires compile rights, and most of the cPanel setups I've seen so far are forbidding compiler access to their users. You can either make an permanent exception for this user, or you can instruct your user to contact you whenever he needs to install some package that requires compile rights (PIL, mysql...).</p> <p>To enable compile rights for that specific user you can find that user in WHM <strong>WHM-&gt;Compiler Access-&gt;Allow specific users to use the compilers</strong> or if you don't like to exit the shell you can do it like this:</p> <pre class="literal-block"> gpasswd -a [username] compiler </pre> <p>to remove it, use the same path in WHM and in shell:</p> <pre class="literal-block"> gpasswd -d [username] compiler </pre> <p>For now, lets add this user to the compiler group since we will be installing some python packages for him in the start. Also you will have to enable your user a normal login shell, let's first check what shell this user has.</p> <pre class="literal-block"> cat /etc/passwd |grep [username] </pre> <p>it should return something like this:</p> <pre class="literal-block"> [username]:x:928:923::/home/[username]:/usr/local/cpanel/bin/jailshell </pre> <p>This user has jailshell enabled to change that into normal shell do this:</p> <pre class="literal-block"> usermod -s /bin/bash [username] </pre> <p>If it's already bash, don't change it. You can also do this via <strong>WHM-&gt; Manage Shell Access.</strong></p> <p>So let's finaly create a virtualenv for our user:</p> <pre class="code bash literal-block"> <span class="name builtin">cd</span> /home/<span class="operator">[</span>username<span class="operator">]</span> /opt/python2.7/bin/virtualenv --no-site-packages --distribute virtualenv chown -R <span class="operator">[</span>username<span class="operator">]</span>.<span class="operator">[</span>username<span class="operator">]</span> virtualenv </pre> <p>this will create a new directory <strong>/home/[username]/virtualenv</strong> with our new virtual python environment for our user. From this point on we will do everything as the user and not root, until told otherwise.</p> <pre class="literal-block"> su [username] source virtualenv/bin/activate </pre> <p>And the promt will change to something like this:</p> <pre class="literal-block"> (virtualenv)[username]&#64;[domain] [~]# </pre> <p>that way we know we are loged in as user and we are using his virtualenv. Now let's install Django in this users environment, simply enter:</p> <pre class="literal-block"> easy_install django </pre> <p>Now is also a good time to install additional python site-packages like mysql and PIL.</p> <pre class="literal-block"> easy_install pil easy_install mysql-python </pre> <p>So we have the django installed inside the users virtualenv, all we have to do now is start one of the instance. It's probably the best practice to keep django sites outside of public_html folders on cpanel servers. So we will do (<strong>still as a user</strong>)</p> <pre class="code bash literal-block"> <span class="name builtin">cd </span>mkdir djangosites <span class="name builtin">cd </span>djangosites django-admin.py startproject <span class="operator">[</span>projectname<span class="operator">]</span> </pre> <p>So by now we should have a directory structure like this:</p> <pre class="literal-block"> /home/[username]/virtualenv &lt; - python virtual environment /home/[username]/djangosites &lt;- django sites folder /home/[username]/djangosites/[projectname] &lt;- django project </pre> <p>Create the wsgi script for that project, usualy <strong>[projectname].wsgi</strong> in django sites folder</p> <pre class="literal-block"> nano /home/[username]/djangosites/[projectname].wsgi </pre> <p>and paste the following code:</p> <pre class="code python literal-block"> <span class="keyword namespace">import</span> <span class="name namespace">sys</span> <span class="keyword namespace">import</span> <span class="name namespace">site</span> <span class="keyword namespace">import</span> <span class="name namespace">os</span> <span class="name">vepath</span> <span class="operator">=</span> <span class="literal string">'/home/[username]/virtualenv/lib/python2.7/site-packages'</span> <span class="name">prev_sys_path</span> <span class="operator">=</span> <span class="name builtin">list</span><span class="punctuation">(</span><span class="name">sys</span><span class="operator">.</span><span class="name">path</span><span class="punctuation">)</span> <span class="name">site</span><span class="operator">.</span><span class="name">addsitedir</span><span class="punctuation">(</span><span class="name">vepath</span><span class="punctuation">)</span> <span class="name">sys</span><span class="operator">.</span><span class="name">path</span><span class="operator">.</span><span class="name">append</span><span class="punctuation">(</span><span class="literal string">'/home/[username]/djangosites'</span><span class="punctuation">)</span> <span class="name">new_sys_path</span> <span class="operator">=</span> <span class="punctuation">[</span><span class="name">p</span> <span class="keyword">for</span> <span class="name">p</span> <span class="operator word">in</span> <span class="name">sys</span><span class="operator">.</span><span class="name">path</span> <span class="keyword">if</span> <span class="name">p</span> <span class="operator word">not</span> <span class="operator word">in</span> <span class="name">prev_sys_path</span><span class="punctuation">]</span> <span class="keyword">for</span> <span class="name">item</span> <span class="operator word">in</span> <span class="name">new_sys_path</span><span class="punctuation">:</span> <span class="name">sys</span><span class="operator">.</span><span class="name">path</span><span class="operator">.</span><span class="name">remove</span><span class="punctuation">(</span><span class="name">item</span><span class="punctuation">)</span> <span class="name">sys</span><span class="operator">.</span><span class="name">path</span><span class="punctuation">[:</span><span class="literal number integer">0</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="name">new_sys_path</span> <span class="keyword namespace">from</span> <span class="name namespace">django.core.handlers.wsgi</span> <span class="keyword namespace">import</span> <span class="name">WSGIHandler</span> <span class="name">os</span><span class="operator">.</span><span class="name">environ</span><span class="punctuation">[</span><span class="literal string">'DJANGO_SETTINGS_MODULE'</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="literal string">'[projectname].settings'</span> <span class="name">application</span> <span class="operator">=</span> <span class="name">WSGIHandler</span><span class="punctuation">()</span> </pre> <p>give the scripts execute permissions:</p> <pre class="literal-block"> chmod +x /home/[username]/djangosites/[projectname].wsgi </pre> <p>and exit user login with:</p> <pre class="literal-block"> exit </pre> <p>now you will have your <strong>root propmt</strong> at the shell:</p> <pre class="literal-block"> root&#64;servername [/home/username]# </pre> <p><strong>If you have decided so, now is the good time to disable the compiler access for this user.</strong></p> <p>create the apache include folder for that virtualhost:</p> <pre class="literal-block"> mkdir -p /usr/local/apache/conf/userdata/std/2/[username]/[domain]/ nano /usr/local/apache/conf/userdata/std/2/[username]/[domain]/django.conf </pre> <p>and add:</p> <pre class="code apacheconf literal-block"> <span class="name tag">&lt;ifmodule</span> <span class="literal string">mod_wsgi.c</span><span class="name tag">&gt;</span> <span class="name builtin">WSGIScriptAlias</span> / <span class="literal string other">/home/</span>[username]/djangosites/[projectname].wsgi <span class="name builtin">WSGIDaemonProcess</span> [projectname] <span class="keyword">user</span>=[username] <span class="keyword">group</span>=[username] processes=5 threads=15 display-name=%{GROUP} <span class="name builtin">WSGIProcessGroup</span> [projectname] <span class="name builtin">WSGIApplicationGroup</span> %{GLOBAL} <span class="name tag">&lt;/ifmodule&gt;</span> </pre> <p>Ok, so this will create a processgroup for this specific django projects with 5 processes each 15 threads with our user's uid and gid. This is great since we have isolated this user to his own application pool and his own home path, also we are enforcing user quotas since if we omit &quot;user=[username] group=[username]&quot; from WSGIDaemonProcess the deamon process will run ass apache user nobody, and all files made/uploaded via this application will not count into this user's quota. They will also make lot's of problems if the user don't grant global write permissions on some folders. Just like mod_php and php_suexec.</p> </div> <div class="section" id="shell-fork-bomb-exception"> <h1>Shell fork bomb exception</h1> <p>On the other hand, running 5 processes each with 15 threads (you can customize this ofcourse), will hit the defaults ulimits enforced by cPanels shell fork bomb protection (if enabled). You could either disable the protection, or you can make a little adjustments to its logic so that you can make exceptions per user allowing them a bit more freedom but still not unlimited.</p> <p>I have found this method somewhere on cPanel forums (I can't seem to find the exact post right now, but I will update this post when I find it), anyways with little patching of profile, limits and bashrc you can create a list of users that have a slightly higher limits, so our django users won't run into any memory or fork limits normally enforced by <strong>fork bomb protection</strong>.</p> <p>I've created a little tarball with installer scripts for patched fork bomb logic, I advise you to check the files prior to installing them. Script will make a copies of your original files, to the same destination with .orig suffixes.</p> <pre class="code bash literal-block"> <span class="name builtin">cd</span> /usr/src/ wget https://toic.org/files/django/forkbomb.tar.gz tar zxvf forkbomb.tar.gz <span class="name builtin">cd </span>forkbomb ./install.sh </pre> <p>Now all you have to do is put one username per line in <strong>/etc/profile.exclude</strong></p> <p>Each user in that line will have slightly bigger ulimits</p> </div> <div class="section" id="back-to-the-django"> <h1>Back to the Django</h1> <p>Let's also make admin media paths and media folder paths</p> <div class="system-message"> <p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">&lt;string&gt;</tt>, line 323)</p> Literal block expected; none found.</div> <p>mkdir /home/[username]/djangosites/[projectname]/media nano /usr/local/apache/conf/userdata/std/2/[username]/[domain]/django-media.conf</p> <p>and add.</p> <pre class="code apacheconf literal-block"> <span class="name builtin">Alias</span> <span class="literal string other">/admin_media/</span> <span class="literal string other">/home/</span>[username]/virtualenv/lib/python2.7/site-packages/Django-1.2.4-py2.7.egg/django/contrib/admin/media/ <span class="name tag">&lt;Directory</span> <span class="literal string">/home/[username]/virtualenv/lib/python2.7/site-packages/Django-1.2.4-py2.7.egg/django/contrib/admin/media</span><span class="name tag">&gt;</span> <span class="name builtin">Order</span> deny,allow <span class="name builtin">Allow</span> from <span class="keyword">all</span> <span class="name tag">&lt;/Directory&gt;</span> <span class="name builtin">Alias</span> <span class="literal string other">/media/</span> <span class="literal string other">/home/</span>[username]/djangosites/[projectname]/media/ <span class="name tag">&lt;Directory</span> <span class="literal string">/home/[username]/djangosites/[projectname]/media</span><span class="name tag">&gt;</span> <span class="name builtin">Order</span> deny,allow <span class="name builtin">Allow</span> from <span class="keyword">all</span> <span class="name tag">&lt;/Directory&gt;</span> </pre> <p>Just replace your python version, django version and username and projectname in paths. This will create [domain]/media - for site media and [domain]/admin_media/ for admin media</p> <p>Now verify those apache include files and rebuild apache conf:</p> <pre class="literal-block"> /scripts/verify_vhost_includes /scripts/rebuildhttpdconf </pre> <p>As always you can make subdomains for your media files, you will just need to update your [projectname]/settings.py</p> <p>And that's it, hope you enjoy your django installation</p> </div> [email protected] (branko)Sun, 27 Mar 2011 20:01:02 +0000https://toic.org/blog/2011/wsgi-on-cpanel-improved/CodingLinuxTutorialsDjango on cpanel with python2.6, virtualenv and mod_wsgi https://toic.org/blog/2010/django-on-cpanel-with-python2-6-virtualenv-and-mod_wsgi/<p><img align='left' src="/media/filer_public/47/a4/47a4abec-d7e5-4beb-b61e-cb2688d0dc02/umltopython.png" alt="ssh" style="padding-top: 20px; margin-right:20px; margin-bottom: 20px;" /><br />Here is the simple to follow step by step tutorial on howto run latest Django on cpanel powered servers with python 2.6, virtual env and mod_wsgi.<br />If you are running cPanel on your server it's most probably a rhel or centos distro, and those will have by default python2.4 installed. You can't just overwrite your python2.4 as many of the system utilities are depended on the python2.4 So what we will do is install an alternate python 2.6 and setup our server to run Django instances with python2.6</p> <p>First of all let's make a folder where we will download all those source packages</p> <div class="section" id="installing-python-and-dependencies"> <h1>Installing python and dependencies</h1> <pre class="literal-block"> mkdir -p /usr/src/python26 &amp;&amp; cd /usr/src/python26 </pre> <p>Next, we have to download and install sqlite3 dependency. It's not needed if your Django instances will not run sqlite databases, but on a safe side it's better to install it than not.</p> <pre class="code bash literal-block"> wget http://www.sqlite.org/sqlite-amalgamation-3.6.4.tar.gz tar zxvf sqlite-amalgamation-3.6.4.tar.gz <span class="name builtin">cd </span>sqlite-3.6.4 ./configure make make install </pre> <p>If all went well it's time to install python 2.6 as alternate install.</p> <pre class="code bash literal-block"> <span class="name builtin">cd</span> /usr/src/python26 wget http://www.python.org/ftp/python/2.6.5/Python-2.6.5.tgz tar zxvf Python-2.6.5.tgz <span class="name builtin">cd </span>Python-2.6.5 ./configure --prefix<span class="operator">=</span>/opt/python2.6 --with-threads --enable-shared make make install </pre> <p>This will install python 2.6 in <strong>/opt/python2.6</strong> and will not interfere with system python install. Let's make a symbolic link to our newly installed python:</p> <pre class="literal-block"> ln -s /opt/python2.6/bin/python /usr/bin/python2.6&lt; </pre> <p>Also we must instruct our system where it should find the libs for new python.</p> <pre class="code bash literal-block"> <span class="name builtin">echo</span> <span class="literal string single">'/opt/python2.6/lib'</span> &gt;&gt; /etc/ld.so.conf.d/opt-python2.6.conf ldconfig </pre> <p>You shoud check if your new python install is working as it should:</p> <pre class="code python literal-block"> <span class="operator">/</span><span class="name">usr</span><span class="operator">/</span><span class="name builtin">bin</span><span class="operator">/</span><span class="name">python2</span><span class="operator">.</span><span class="literal number integer">6</span> <span class="name">Python</span> <span class="literal number float">2.6</span><span class="operator">.</span><span class="literal number integer">5</span> <span class="punctuation">(</span><span class="name">r265</span><span class="punctuation">:</span><span class="literal number integer">79063</span><span class="punctuation">,</span> <span class="name">Jul</span> <span class="literal number integer">15</span> <span class="literal number integer">2010</span><span class="punctuation">,</span> <span class="literal number integer">16</span><span class="punctuation">:</span><span class="literal number integer">55</span><span class="punctuation">:</span><span class="literal number integer">23</span><span class="punctuation">)</span> <span class="punctuation">[</span><span class="name">GCC</span> <span class="literal number float">4.1</span><span class="operator">.</span><span class="literal number integer">2</span> <span class="literal number integer">20080704</span> <span class="punctuation">(</span><span class="name">Red</span> <span class="name">Hat</span> <span class="literal number float">4.1</span><span class="operator">.</span><span class="literal number integer">2</span><span class="operator">-</span><span class="literal number integer">48</span><span class="punctuation">)]</span> <span class="name">on</span> <span class="name">linux2</span> <span class="name">Type</span> <span class="literal string">&quot;help&quot;</span><span class="punctuation">,</span> <span class="literal string">&quot;copyright&quot;</span><span class="punctuation">,</span> <span class="literal string">&quot;credits&quot;</span> <span class="operator word">or</span> <span class="literal string">&quot;license&quot;</span> <span class="keyword">for</span> <span class="name">more</span> <span class="name">information</span><span class="operator">.</span> <span class="operator">&gt;&gt;&gt;</span> </pre> <p>Type <strong>CTRL+D</strong> to exit. Next thing to do is installation of python-setup tools:</p> <pre class="code bash literal-block"> <span class="name builtin">cd</span> /usr/src/python26 wget http://pypi.python.org/packages/2.6/s/setuptools/setuptools-0.6c11-py2.6.egg sh setuptools-0.6c11-py2.6.egg --prefix<span class="operator">=</span>/opt/python2.6 </pre> <p>Make sure to define the prefix on where your new python 2.6 installation is residing. We should make a temporary alias for new python as it will be needed for installation of python mysql package:</p> <pre class="literal-block"> alias python=&quot;/opt/python2.6/bin/python&quot; </pre> <p>Let's check if everything is working ok:</p> <pre class="code python literal-block"> <span class="name">python</span> <span class="name">Python</span> <span class="literal number float">2.6</span><span class="operator">.</span><span class="literal number integer">5</span> <span class="punctuation">(</span><span class="name">r265</span><span class="punctuation">:</span><span class="literal number integer">79063</span><span class="punctuation">,</span> <span class="name">Jul</span> <span class="literal number integer">15</span> <span class="literal number integer">2010</span><span class="punctuation">,</span> <span class="literal number integer">16</span><span class="punctuation">:</span><span class="literal number integer">55</span><span class="punctuation">:</span><span class="literal number integer">23</span><span class="punctuation">)</span> <span class="punctuation">[</span><span class="name">GCC</span> <span class="literal number float">4.1</span><span class="operator">.</span><span class="literal number integer">2</span> <span class="literal number integer">20080704</span> <span class="punctuation">(</span><span class="name">Red</span> <span class="name">Hat</span> <span class="literal number float">4.1</span><span class="operator">.</span><span class="literal number integer">2</span><span class="operator">-</span><span class="literal number integer">48</span><span class="punctuation">)]</span> <span class="name">on</span> <span class="name">linux2</span> <span class="name">Type</span> <span class="literal string">&quot;help&quot;</span><span class="punctuation">,</span> <span class="literal string">&quot;copyright&quot;</span><span class="punctuation">,</span> <span class="literal string">&quot;credits&quot;</span> <span class="operator word">or</span> <span class="literal string">&quot;license&quot;</span> <span class="keyword">for</span> <span class="name">more</span> <span class="name">information</span><span class="operator">.</span> <span class="operator">&gt;&gt;&gt;</span> <span class="name">CTRL</span> <span class="operator">+</span> <span class="name">D</span> </pre> <p>So next in line is mysql for python:</p> <pre class="code bash literal-block"> <span class="name builtin">cd</span> /usr/src/python26 wget http://netcologne.dl.sourceforge.net/project/mysql-python/mysql-python/1.2.3/MySQL-python-1.2.3.tar.gz tar zxvf MySQL-python-1.2.3.tar.gz <span class="name builtin">cd </span>MySQL-python-1.2.3 python setup.py build python setup.py install </pre> <p>Again let's verify the install:</p> <pre class="code python literal-block"> <span class="name">cd</span> <span class="operator">/</span><span class="name">usr</span><span class="operator">/</span><span class="name">src</span><span class="operator">/</span><span class="name">python26</span> <span class="name">python</span> <span class="name">Python</span> <span class="literal number float">2.6</span><span class="operator">.</span><span class="literal number integer">5</span> <span class="punctuation">(</span><span class="name">r265</span><span class="punctuation">:</span><span class="literal number integer">79063</span><span class="punctuation">,</span> <span class="name">Jul</span> <span class="literal number integer">15</span> <span class="literal number integer">2010</span><span class="punctuation">,</span> <span class="literal number integer">17</span><span class="punctuation">:</span><span class="literal number integer">57</span><span class="punctuation">:</span><span class="literal number integer">29</span><span class="punctuation">)</span> <span class="punctuation">[</span><span class="name">GCC</span> <span class="literal number float">4.1</span><span class="operator">.</span><span class="literal number integer">2</span> <span class="literal number integer">20080704</span> <span class="punctuation">(</span><span class="name">Red</span> <span class="name">Hat</span> <span class="literal number float">4.1</span><span class="operator">.</span><span class="literal number integer">2</span><span class="operator">-</span><span class="literal number integer">48</span><span class="punctuation">)]</span> <span class="name">on</span> <span class="name">linux2</span> <span class="name">Type</span> <span class="literal string">&quot;help&quot;</span><span class="punctuation">,</span> <span class="literal string">&quot;copyright&quot;</span><span class="punctuation">,</span> <span class="literal string">&quot;credits&quot;</span> <span class="operator word">or</span> <span class="literal string">&quot;license&quot;</span> <span class="keyword">for</span> <span class="name">more</span> <span class="name">information</span><span class="operator">.</span> <span class="operator">&gt;&gt;&gt;</span> <span class="keyword namespace">import</span> <span class="name namespace">sqlite3</span> <span class="operator">&gt;&gt;&gt;</span> <span class="keyword namespace">import</span> <span class="name namespace">MySQLdb</span> <span class="operator">&gt;&gt;&gt;</span> <span class="name">CTRL</span> <span class="operator">+</span> <span class="name">D</span> </pre> <p>It shouldn't return any errors while issuing import statements. Ok for the end let's install the virtualenv so we can create a virtual python enviroment for each user and his Django instances</p> <pre class="code bash literal-block"> <span class="name builtin">cd</span> /opt/python2.6/bin ./easy_install virtualenv </pre> <p>And here we conclude the python instalation. Next order of business is mod_wsgi</p> </div> <div class="section" id="mod-wsgi-installation"> <h1>mod_wsgi installation</h1> <pre class="code bash literal-block"> <span class="name builtin">cd</span> /opt/python2.6/lib/python2.6/config/ ln -s ../../libpython2.6.so . <span class="name builtin">cd</span> /usr/src/python26 wget http://modwsgi.googlecode.com/files/mod_wsgi-3.2.tar.gz tar zxvf mod_wsgi-3.2.tar.gz <span class="name builtin">cd </span>mod_wsgi-3.2 ./configure –with-python<span class="operator">=</span>/opt/python2.6/bin/python make make install </pre> <p>This will install mod_wsgi in <strong>/usr/local/apache/modules/mod_wsgi.so</strong> Note that this wsgi module is built with python 2.6 and will not work with any other version. All we have to do now is add the mod_wsgi in our apache conf. You can do that on cpanel servers via WHM. Log into <strong>WHM</strong> , click on <strong>Apache Configuration</strong> then <strong>Include Editor</strong> then <strong>Pre-Virtualhost</strong> Include and select <strong>All versions</strong> Paste this:</p> <pre class="literal-block"> LoadModule wsgi_module /usr/local/apache/modules/mod_wsgi.so AddHandler wsgi-script .wsgi </pre> <p>** Save and restart apache.** And that's it. Our apache is now ready to serve python scripts via mod_wsgi Now all we have to do is install some Django instances for our user.</p> </div> <div class="section" id="setting-up-django-projects"> <h1>Setting up Django projects</h1> <p>I'll use '<strong>[username]</strong> ' for cpanel username reference and '<strong>[domain]</strong> ' for that user's domain. To match your needs you will have to replace those where appropriate. First of all you will have to decide if you will do empty virtual environments so that the user can decide what python site-packages will he use or will you preinstall some packages so that user can only update his virtualenv with packages that are missing. If you are choosing the first method user will have to have compile rights under security setting of cpanel WHM otherwise he will not be able to install packages as python mysql, PIL and some others. If you choose the former method you can preinstall those packages systemwide for our alternate python install, but whenever you update those packages all virtual environments will be updated with them. It's a matter of personal preference. I for myself rather like the clean virtualenv, and before delivering it to the client you as root preinstall in his virtualenv those packages requiring gcc rights. So let's create a virtualenv for our user:</p> <pre class="code bash literal-block"> <span class="name builtin">cd</span> /home/<span class="operator">[</span>username<span class="operator">]</span> /opt/python2.6/bin/virtualenv --no-site-packages --distribute virtualenv chown -R <span class="operator">[</span>username<span class="operator">]</span>.<span class="operator">[</span>username<span class="operator">]</span> virtualenv </pre> <p>this will create a new directory __ /home/[username]/virtualenv __ with our new virtual python environment for our user. You will have to enable normal shell for this user, let's first check what shell this user has.</p> <pre class="literal-block"> cat /etc/passwd |grep [username] </pre> <p>it should return something like this:</p> <pre class="literal-block"> [username]:x:928:923::/home/[username]:/usr/local/cpanel/bin/jailshell </pre> <p>This user has jailshell enabled to change that into normal shell do this:</p> <pre class="literal-block"> usermod -s /bin/bash [username] </pre> <p>You can also do this via <strong>WHM-&gt; Manage Shell Access.</strong> From this point on we will do everything as the user and not root, until told otherwise.</p> <pre class="literal-block"> su [username] source virtualenv/bin/activate </pre> <p>And the promt will change to something like this:</p> <pre class="literal-block"> (virtualenv)[username]&#64;[domain] [~]# </pre> <p>that way we know we are loged in as user and we are using his virtualenv. Now let's install Django in this users environment, simply enter:</p> <pre class="literal-block"> easy_install django </pre> <p>Now is also a good time to install additional python site-packages like mysql and PIL. First temporarily enable compilers for this user via <strong>WHM-&gt;Compiler Access-&gt;Allow specific users to use the compilers</strong> do the modules install with:</p> <pre class="literal-block"> easy_install [module_name] </pre> <p><strong>disable the compiler access afterwards</strong></p> <p>So we have the django installed inside the users virtualenv, all we have to do now is start one of the instance. It's probably the best practice to keep django sites outside of public_html folders on cpanel servers. So we will do (<strong>still as a user</strong>)</p> <pre class="literal-block"> cd mkdir djangosites cd djangosites django-admin.py startproject [projectname] </pre> <p>So by now we should have a directory structure like this:</p> <pre class="literal-block"> /home/[username]/virtualenv &lt; - python virtual environment /home/[username]/djangosites &lt;- django sites folder /home/[username]/djangosites/[projectname] &lt;- django project </pre> <p>Create the wsgi script for that project, usualy <strong>[projectname].wsgi</strong> in django sites folder</p> <pre class="literal-block"> nano /home/[username]/djangosites/[projectname].wsgi </pre> <p>and paste the following code:</p> <pre class="code python literal-block"> <span class="keyword namespace">import</span> <span class="name namespace">sys</span> <span class="keyword namespace">import</span> <span class="name namespace">site</span> <span class="keyword namespace">import</span> <span class="name namespace">os</span> <span class="name">vepath</span> <span class="operator">=</span> <span class="literal string">'/home/[username]/virtualenv/lib/python2.6/site-packages'</span> <span class="name">prev_sys_path</span> <span class="operator">=</span> <span class="name builtin">list</span><span class="punctuation">(</span><span class="name">sys</span><span class="operator">.</span><span class="name">path</span><span class="punctuation">)</span> <span class="name">site</span><span class="operator">.</span><span class="name">addsitedir</span><span class="punctuation">(</span><span class="name">vepath</span><span class="punctuation">)</span> <span class="name">sys</span><span class="operator">.</span><span class="name">path</span><span class="operator">.</span><span class="name">append</span><span class="punctuation">(</span><span class="literal string">'/home/[username]/djangosites'</span><span class="punctuation">)</span> <span class="name">new_sys_path</span> <span class="operator">=</span> <span class="punctuation">[</span><span class="name">p</span> <span class="keyword">for</span> <span class="name">p</span> <span class="operator word">in</span> <span class="name">sys</span><span class="operator">.</span><span class="name">path</span> <span class="keyword">if</span> <span class="name">p</span> <span class="operator word">not</span> <span class="operator word">in</span> <span class="name">prev_sys_path</span><span class="punctuation">]</span> <span class="keyword">for</span> <span class="name">item</span> <span class="operator word">in</span> <span class="name">new_sys_path</span><span class="punctuation">:</span> <span class="name">sys</span><span class="operator">.</span><span class="name">path</span><span class="operator">.</span><span class="name">remove</span><span class="punctuation">(</span><span class="name">item</span><span class="punctuation">)</span> <span class="name">sys</span><span class="operator">.</span><span class="name">path</span><span class="punctuation">[:</span><span class="literal number integer">0</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="name">new_sys_path</span> <span class="keyword namespace">from</span> <span class="name namespace">django.core.handlers.wsgi</span> <span class="keyword namespace">import</span> <span class="name">WSGIHandler</span> <span class="name">os</span><span class="operator">.</span><span class="name">environ</span><span class="punctuation">[</span><span class="literal string">'DJANGO_SETTINGS_MODULE'</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="literal string">'[projectname].settings'</span> <span class="name">application</span> <span class="operator">=</span> <span class="name">WSGIHandler</span><span class="punctuation">()</span> </pre> <p>give the scripts execute permissions:</p> <pre class="literal-block"> chmod +x /home/[username]/djangosites/[projectname].wsgi </pre> <p>and exit user login with:</p> <pre class="literal-block"> exit </pre> <p>now you will have your <strong>root propmt</strong> at the shell:</p> <pre class="literal-block"> root&#64;servername [/home/username]# </pre> <p>create the apache include folder for that virtualhost:</p> <pre class="literal-block"> mkdir -p /usr/local/apache/conf/userdata/std/2/[username]/[domain]/ nano /usr/local/apache/conf/userdata/std/2/[username]/[domain]/django.conf </pre> <p>and add:</p> <pre class="code apacheconf literal-block"> <span class="name tag">&lt;ifmodule</span> <span class="literal string">mod_wsgi.c</span><span class="name tag">&gt;</span> <span class="name builtin">WSGIScriptAlias</span> / <span class="literal string other">/home/</span>[username]/djangosites/[projectname].wsgi <span class="name builtin">WSGIDaemonProcess</span> [username] processes=7 threads=1 display-name=%{GROUP} <span class="name builtin">WSGIProcessGroup</span> [username] <span class="name builtin">WSGIApplicationGroup</span> %{GLOBAL} <span class="name tag">&lt;/ifmodule&gt;</span> </pre> <p>edit the virtualhost entry for that domain:</p> <pre class="literal-block"> nano /usr/local/apache/conf/httpd.conf </pre> <p>and in that virtualhost add:</p> <pre class="literal-block"> Include &quot;/usr/local/apache/conf/userdata/std/2/[username]/[domain]/*.conf&quot; </pre> <p>save &amp; exit</p> <p><strong>test the apache configuration prior to reload:</strong></p> <pre class="literal-block"> service httpd configtest </pre> <p>Should say syntax OK at the end, if so reload the apache:</p> <pre class="literal-block"> /scripts/restartsrv_httpd </pre> <p>And voila, you have your django instance up&amp; running You can now add via User's cpanel media subdomain for django media files, and define the path to the subdomain root in setings.py media root can live inside public_html folder. You can also create additional subdomain for admin media and copy the admin media content to that subdoman. For example: admin-media.[domain]:</p> <pre class="literal-block"> cp -r /home/[username]/virtualenv/lib/python2.6/site-packages/Django-1.2.1-py2.6.egg/django/contrib/admin/media/* /home/[username]/public_html/admin-media/ </pre> </div> [email protected] (branko)Sat, 14 Aug 2010 19:59:44 +0000https://toic.org/blog/2010/django-on-cpanel-with-python2-6-virtualenv-and-mod_wsgi/CodingLinuxTutorialsMunin centralized monitoring on Centos https://toic.org/blog/2009/munin-centralized-monitoring-on-centos/<p>Munin is a great tool for performance graphing your servers, by default it will graph resources on localhost, however if you wish to monitor multiple servers from single location, then you must deploy a central Munin server.</p> <p>Having central graphs mean you can have central hub of data about performance of your systems. This can later be better presented, viewed and analyzed, </p> <p>Let's begin setting up a central server</p> <p>To get things started we will need one server for centralized graphs. For start this can be a low budget dedicated server or a small vps, if you have large amount of monitored nodes, and large amout of metrics on them, then you will probably want to invest in better disks. Updating huge amounts of rrd files and regenerating html an graphs can be disk IO intensive with large instalations.</p> <div class="section" id="installing-munin"> <h1>Installing munin</h1> <p>This will be a minimal install for a central munin server. I'm using a small vps with minimal centos 5 install.</p> <p>First let's setup elrepo:</p> <pre class="literal-block"> rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-3.noarch.rpm </pre> <p>Now we need to install munin and munin-node (if you wish to monitor this host as well):</p> <pre class="literal-block"> yum install -y munin munin-node </pre> <p>by default munin will put its html files into <strong>/var/www/html/munin</strong> folder If you wish to move that to another place, now is your time. For the sake of simplicity I'll just leave it where it is. Of course we will need apache to access munin html files, so if you don't have apache installed do:</p> <pre class="literal-block"> yum install -y httpd </pre> <p>now start the apache:</p> <pre class="literal-block"> service httpd start </pre> <p>If you left everything as it is munin html should be available at: <a class="reference external" href="http://yourhostname.com/munin/">http://yourhostname.com/munin/</a> You may notice that there is nothing there yet, just wait until we configure all other hosts. start the munin-node on this host (if you installed it):</p> <pre class="literal-block"> service munin-node start </pre> <p>Make sure your cron is runing:</p> <pre class="literal-block"> service crond status </pre> <p>and let's go configure those other hosts.</p> </div> <div class="section" id="installing-munin-node"> <h1>Installing munin-node</h1> <div class="section" id="installing-on-cpanel"> <h2>Installing on cPanel</h2> <p>Since lot's of my servers to monitor are with cPanel installed there is an easy way to install munin.</p> <p>Login to your <strong>whm</strong> go to: <strong>Manage plugins</strong>, now find <strong>Munin</strong>, click a check box, scroll down and click save. After the munin is installed it should appear in your <strong>whm</strong> at the bottom of the navigation. Go and check up if the munin is installed correctly.</p> <p>Installing trough cPanel will install munin-node and munin, you can disable the munin graphing later if you like.</p> </div> <div class="section" id="installing-on-non-cpanel"> <h2>Installing on non cPanel</h2> <p>We can install munin on Centos trough Elrepo. first we will setup elrepo:</p> <pre class="literal-block"> rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-3.noarch.rpm </pre> <p>and then install a munin-node:</p> <pre class="literal-block"> yum install -y munin-node </pre> <p>voila... let's configure nodes on remote servers now.</p> </div> </div> <div class="section" id="configuring-munin-node-on-remote-hosts"> <h1>Configuring munin-node on remote hosts</h1> <p>For both cPanel and non-cPanel servers all we need to do is add allowed host in munin-node.conf:</p> <pre class="literal-block"> nano /etc/munin/munin-node.conf </pre> <p>add at the end of the file:</p> <pre class="literal-block"> allow ^192\.168\.0\.20$ </pre> <p>where 192.168.0.20 is the IP address of you central munin server. restart the munin-node:</p> <pre class="literal-block"> service munin-node restart </pre> <p>If you have firewall installed on that host (and I hope you do), allow the incoming tcp port 4949 for the IP of the central node.</p> <p>In <a class="reference external" href="http://www.configserver.com/cp/csf.html">csf</a> add the following line:</p> <pre class="literal-block"> tcp:in:d=4949:s=192.168.0.20 </pre> <p>to your <strong>/etc/csf/csf.allow</strong> file</p> <p>or just run:</p> <pre class="literal-block"> iptables -A INPUT -p tcp -s 192.168.0.2 --dport 4949 -m state --state NEW,ESTABLISHED -j ACCEPT </pre> <p>Modify this to your firewall, and don't forget to replace 192.168.0.20 with your munin server IP. Now everything should be ready for data collection from central server</p> </div> <div class="section" id="configuring-munin-server"> <h1>Configuring munin server</h1> <p>We need to configure munin conf file on our central server to collect data from remote servers:</p> <pre class="literal-block"> nano /etc/munin/munin.conf </pre> <p>If you didn't change any locations of html files and munin datastore you realy don't need to change that in the conf file.</p> <p>What we are interested with are the host sections. You will notice there is configuration for our localhost You can change its name now, leave the address field as it is.</p> <p>To add up a new host just add:</p> <pre class="literal-block"> [myhost.mydomain.com] address 192.168.0.10 use_host_name yes </pre> <p>change the 192.168.0.10 with the IP of the server you wish to monitor. you can now add as many host you like. Make sure that you have enabled outgoing connections on tcp port 4949 on your central munin server. After a while the first results should start to appear.</p> </div> <div class="section" id="configuring-multi-host-display-graphs"> <h1>Configuring multi host display graphs</h1> <p>The real benefit of having all the host graphs and data on one place is you can easily make multi host graphs and compare the loads on the servers. This could help you grasp a bigger picture of individual server workloads and give you an idea what to improve and how to load balance between the machines.</p> <p>Here is one of the example graphs, showing apache request per second. If the machines were the same hardware configuration that would give indications that some of the machines have higher hit rate and we would need to rewrite our load balancing.</p> <p>We could do the same thing with load graphs and see which servers have the spikes, and distribute the workload on some less loaded servers.</p> <img alt="/media/filer_public/00/62/00627fe5-be95-4a9f-bb98-fc5979a0b320/munin1.png" src="/media/filer_public/00/62/00627fe5-be95-4a9f-bb98-fc5979a0b320/munin1.png" /> <img alt="/media/filer_public/37/24/37244bfb-ece6-4bb3-b152-b2d4bc0d6d6d/munin2.png" src="/media/filer_public/37/24/37244bfb-ece6-4bb3-b152-b2d4bc0d6d6d/munin2.png" /> <p><strong>So how do we configure this?</strong></p> <p>First you need to find out rrd's name of the data you wish to put on the graph.</p> <p>for example apache accesses per second:</p> <pre class="literal-block"> cd /var/lib/munin/yourdomain.com </pre> <p><strong>ls -lh</strong> in the directory and you will find out what data is available to munin. in case of the apache accesses data we will have few files named:</p> <blockquote>hostname.domainname.com-<span style="color: red;">apache_accesses-accesses80</span>-d.rrd hostname2.domainname.com-<span style="color: red;">apache_accesses-accesses80</span>-d.rrd</blockquote><p>what we are interested with are those fields (marked in red) after the domain name separated by dash. Ok let's write a conf in munin.conf for this two hosts:</p> <pre class="literal-block"> nano /etc/munin/munin.conf </pre> <p>Go under the host definitions in your conf file and add:</p> <blockquote><strong>[domainname.com;Totals] <span style="color: green;">update no</span> <span style="color: blue;">apacheaccess</span>.graph_title Apache access side by side <span style="color: blue;">apacheaccess</span>.graph_order hostname=hostname.domainname.com:<span style="color: red;">apache_accesses.accesses80</span> hostname1=hostname1.domainname.com.com:<span style="color: red;">apache_accesses.accesses80</span></strong></blockquote><p>Notice the red lines, they are the same as rrd filenames red parts we saw earlier, just replace dash with dot. Green text is to disable updates for this domain declaration since updates are already done at the host declaration in the conf file. Blue is the graph representation name, followed by title in the first line and data in second.</p> <p>This way you can make all the side by side graphs for all the data munin collected in rrd files. After the changes wait for a next munin update and enjoy the graphs</p> </div> [email protected] (branko)Fri, 09 Oct 2009 19:56:24 +0000https://toic.org/blog/2009/munin-centralized-monitoring-on-centos/MonitoringFirewalling xen bridge https://toic.org/blog/2009/firewalling-xen-bridge/<p>Occasionally you will wish to block certain ports to your DomUs from Dom0. By default you wish to allow any traffic from and to DomU but for some security considerations, I found it to be wise to block some ports to and from my clients DomUs. One such port range is for example IRC. Although it can be routed trough alternate ports, most of automated malicious scripts use default ones. It's quite handy to block them so they ain't able to contact home.</p> <p>As said by default Xen bridge is open for all traffic from and to DomUs. It's up to DomU admin to firewall their own virtual machine. Unfortunately some just forget to do the proper securing of the system, and as a result you get compromised DomU contacting various botnets, and executing all kind of nasty stuff.</p> <p>To prevent this we can make a firewall rules in DomU that will by default block some traffic. Since I'm using bridged network, firwalling must be done on bridge. I found <a class="reference external" href="http://www.shorewall.net/Xen.html">this</a> great article on shorewall manuals explaining how to setup bridged network firewall. I installed it and tested it on 32bit Centos 5.2, but it should work on any system.</p> <p>Fist of all you will need to <a class="reference external" href="http://shorewall.net/download.htm">download</a> and install latest shorewall.</p> <p>As stated in documentation link above, you must enable bridge support in shorewall.conf:</p> <pre class="literal-block"> nano /etc/shorewall/shorewall.conf </pre> <p>Set:</p> <pre class="literal-block"> BRIDGING=Yes </pre> <p>Now we have to edit our firewall zones:</p> <pre class="literal-block"> nano /etc/shorewall/zones </pre> <p>It should look something like this:</p> <pre class="literal-block"> #ZONE TYPE OPTIONS IN OUT # OPTIONS OPTIONS fw &nbsp; &nbsp;firewall dom0 ipv4 domU ipv4 net ipv4 #LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE </pre> <p>Next thing to do is to define network interfaces, we will be dealing with two network interfaces: virtualized eth0 and bridge:</p> <pre class="literal-block"> nano /etc/shorewall/interfaces </pre> <p>And the file should look like this:</p> <pre class="literal-block"> #ZONE INTERFACE &nbsp; &nbsp;BROADCAST &nbsp; &nbsp;OPTIONS - &nbsp; &nbsp;xenbr0 - dhcp net eth0 detect dhcp #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE </pre> <p>Next stop, hosts file:</p> <pre class="literal-block"> nano /etc/shorewall/hosts </pre> <p>And the file should look like this:</p> <pre class="literal-block"> #ZONE HOST(S) OPTIONS dom0 xenbr0:vif0.0 domU xenbr0:vif+ &nbsp; &nbsp; routeback net xenbr0:peth0 #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS LINE -- DO NOT REMOVE </pre> <p>Now let's make some policies in our firewall:</p> <pre class="literal-block"> nano /etc/shorewall/policy </pre> <p>And the file should look like this:</p> <pre class="literal-block"> #SOURCE DEST POLICY LOG LIMIT: CONNLIMIT: # LEVEL BURST MASK fw &nbsp; &nbsp;all ACCEPT all fw &nbsp; &nbsp;ACCEPT info dom0 all ACCEPT all dom0 ACCEPT info domU all ACCEPT all domU &nbsp; &nbsp; ACCEPT net net NONE all all REJECT info #LAST LINE -- DO NOT REMOVE </pre> <p>This will by default allow any traffic through the bridge. You can also specify DROP policy for your Dom0 and then open necessary ports in rules file. Note that the fw and dom0 are the same but they both need to be declared in policy and rules file. So... for now, this does not block IRC traffic as we started to do, all we need to do now is to setup the rules file:</p> <pre class="literal-block"> nano /etc/shorewall/rules </pre> <p>And the file should look like this:</p> <pre class="literal-block"> #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT &nbsp; &nbsp;TIME PORT PORT(S) DEST LIMIT GROUP #irc REJECT net domU tcp 6660:6669 REJECT domU net tcp 6660:6669 #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE </pre> <p>After adding this, it will block all incoming and outgoing traffic from port range 6660 to 6669 for all DomUs. If you wish to add an exception to one DomU you can simply edit the rules file and insert the exception above the REJECT:</p> <pre class="literal-block"> #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT &nbsp; &nbsp;TIME PORT PORT(S) DEST LIMIT GROUP #DomU exceptions ACCEPT net domU:192.168.0.10 &nbsp; &nbsp;tcp 6660:6669 ACCEPT domU:192.168.0.10 &nbsp; &nbsp;net tcp 6660:6669 #DomU restrictions #irc REJECT net domU tcp 6660:6669 REJECT domU net tcp 6660:6669 #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE </pre> <p>This way only the DomU with ip 192.168.0.10 will have unblocked IRC ports. Although the above config should work it didn't for me. Centos 5.2 by default comes with:</p> <pre class="literal-block"> net.bridge.bridge-nf-call-iptables = 0 </pre> <p>so no bridge firewalling is actually done. To enable this edit your sysctl.conf file:</p> <pre class="literal-block"> nano /etc/sysctl.conf </pre> <p>and append:</p> <pre class="literal-block"> net.bridge.bridge-nf-call-iptables = 1 </pre> <p>now run:</p> <pre class="literal-block"> sysctl -p </pre> <p>And the bridged firewall for your DomUs should work now.</p> [email protected] (branko)Sun, 19 Apr 2009 19:52:29 +0000https://toic.org/blog/2009/firewalling-xen-bridge/VirtualizationMultiple network interfaces in Xen https://toic.org/blog/2008/multiple-network-interfaces-in-xen/<p>By default xen tools comes with only one network interface enabled for your dom0 and domU machines. So what if you want to add some more? It's actually very simple.</p> <p>All you need to do is run:</p> <p>/etc/xen/scripts/network-bridge start vifnum=1 netdev=eth1 bridge=xenbr1</p> <p>This will effectively create one extra xenbr attached to eth1 interface. You can repeat the above command for all your interfaces, and you can stop them in the same manner, just replace start with stop.</p> <p></p> <p>To enable this automatically you can create file named, multi-network-bridge:</p> <pre class="literal-block"> vim /etc/xen/scripts/multi-network-bridge </pre> <p>paste this:</p> <pre class="literal-block"> #!/bin/sh /etc/xen/scripts/network-bridge $&#64; vifnum=0 netdev=eth0 bridge=xenbr0 /etc/xen/scripts/network-bridge $&#64; vifnum=1 netdev=eth1 bridge=xenbr1 </pre> <p>Of course you can add up as many interfaces you like in this script. After you have added your interfaces, you need to edit xend-config.spx file:</p> <pre class="literal-block"> vim /etc/xen/xend-config.spx </pre> <p>Find a line defining network script, it should by default look like this:</p> <pre class="literal-block"> (network-script network-bridge) </pre> <p>Edit it so it contains your newly created multi network bridge script. In my case it should look like:</p> <pre class="literal-block"> (network-script multi-network-bridge) </pre> <p>All you need to do now is restart xend service:</p> <pre class="literal-block"> /etc/init.d/xend restart </pre> <p>New network bridge named xenbr1 should be available now.</p> <p><strong>How can I add up another network bridge to my domU machine?</strong></p> <p>It's pretty simple actually, you already have defined <strong>vif</strong> statements for current network interface, all you need to do now is edit that domU config file, precisely <strong>vif</strong> line and add up another xenbr interface.</p> <p>For example, if my domU vif line looks like this:</p> <pre class="literal-block"> vif = ['ip=xx.xxx.167.4, vifname=vifbran0, rate = 10000KB/s, bridge=xenbr0'] </pre> <p>with another xenbr interface it should look like this:</p> <pre class="literal-block"> vif = ['ip=89.201.167.4, vifname=vifbran0, rate = 10000KB/s, bridge=xenbr0', 'ip=192.168.1.10, vifname=vifbran1, rate = 10000KB/s, bridge=xenbr1'] </pre> <p>Also if you wish to use <a class="reference external" href="/blog/2008/09/22/preventing-ip-conflicts-in-xen/">ip conflict prevention</a> you must add additional mac section in vif configuration. Restart your domU and voila, another network interface is present</p> [email protected] (branko)Mon, 06 Oct 2008 19:44:41 +0000https://toic.org/blog/2008/multiple-network-interfaces-in-xen/LinuxVirtualizationPreventing ip conflicts in xen https://toic.org/blog/2008/preventing-ip-conflicts-xen/<p>Lately I was playing with stock xen kernel and virtualization, and I came across one relatively big problem. Let’s say I want to share my guest machines to, let’s say clients. You must give them root… because that’s whats VPS-es all all about, having root access to OS without having to purchase expensive hardware. Having that in mind they are by default untrusted and unpredictable, they can do god knows what in there!</p> <p>So what caught my eye?</p> <p>By default xen, and available management tools, don’t really have a way of sorting out IP conflicts in bridged mode. Basically you have bunch of scripts that will provision VPS alongside with IP address. Looking at the conf files you have vif and IP declarations in vm_xen.conf file. <br /></p> <p>But what is really preventing clients from entering:</p> <pre class="literal-block"> ifconfig eth0 xxx.xxx.xxx.xxx </pre> <p>where xxx is ip of some super important server in same netmask?</p> <p>Luckily, I came across this problem while still in testing, here’s what I found and came up with after 3 days intensive googling.</p> <p>Xen supports IP declaration in <strong>vif</strong> statment of domU config file like this:</p> <pre class="literal-block"> vif = ['ip=xxx.xxx.xxx.xxx, more parametars here....'] </pre> <p>Also you can declare multiple IP's by simply putting space between them, like this:</p> <pre class="literal-block"> vif = ['ip=xxx.xxx.xxx.xx1 xxx.xxx.xxx.xx2, more parametars here....'] </pre> <p>For the purpose of IP conflict prevention make sure you declare unique mac address in vif section to.</p> <p>So what does this IP thingy in <strong>vif</strong> do? Absolutely nothing (at least not yet)!</p> <p>Next step is to install ebtables (<a class="reference external" href="http://ebtables.sourceforge.net/">http://ebtables.sourceforge.net/</a>) on your distro. Then all we need to do is patch up a vif-bridge script located in /etc/xen/scripts/</p> <p>So here’s the diff:</p> <pre class="literal-block"> --- vif-bridge-org 2008-07-30 21:26:16.000000000 +0200 +++ vif-bridge 2008-07-30 21:30:59.000000000 +0200 &#64;&#64; -57,15 +57,35 &#64;&#64; online) setup_bridge_port &quot;$vif&quot; add_to_bridge &quot;$bridge&quot; &quot;$vif&quot; - ;; - + ebtables -N $vif + ebtables -P $vif DROP + ebtables -A INPUT -i $vif -j $vif + ebtables -A FORWARD -i $vif -j $vif + ebtables -A $vif -p ARP --arp-opcode 1 -j ACCEPT + + if [ ! -z &quot;$ip&quot; ] + then + for oneip in $ip + do + ebtables -A $vif -p IPv4 --ip-src $oneip -j ACCEPT + ebtables -A $vif -p IPv4 --ip-dst $oneip -j ACCEPT + ebtables -A $vif -p ARP --arp-opcode 2 --arp-ip-src $oneip -j ACCEPT + done + ebtables -A $vif --log-prefix=&quot;arp-drop&quot; --log-arp -j DROP + fi + ;; + offline) do_without_error brctl delif &quot;$bridge&quot; &quot;$vif&quot; do_without_error ifconfig &quot;$vif&quot; down - ;; + do_without_error ebtables -D INPUT -i $vif -j $vif + do_without_error ebtables -D FORWARD -i $vif -j $vif + do_without_error ebtables -F $vif + do_without_error ebtables -X $vif + ;; esac-handle_iptable +#handle_iptable log debug &quot;Successful vif-bridge $command for $vif, bridge $bridge.&quot; if [ &quot;$command&quot; == &quot;online&quot; ] </pre> <p>Asuming you use bridging scripts this effectively restricts IP address(es) from &quot;vif = ['ip=xxx.xxx.xxx.xxx']&quot; list to <strong>mac</strong> addresses in <strong>vif</strong> list. Restrictoins are done while booting up VPS and removed when powering it off. This way untrusted user is limited only to IP addresses defined in xen guest conf file. Trying to change existing IP address into another IP on network will only render that machine unresponsive.</p> [email protected] (branko)Mon, 22 Sep 2008 19:07:40 +0000https://toic.org/blog/2008/preventing-ip-conflicts-xen/LinuxVirtualization