вівторок, 28 грудня 2010 р.

Email Service for Development Needs

What's this all about?

This article covers the setup of email delivery service, suited for non-production use (like development). The important for production aspects like spam and virus checking, compatibility with legacy clients and security were intentionally not covered, though you can use this article for bootstrap setup and add all that features on top of it.

Required skills

You should feel yourself easy with Linux and Google, understand what email is (i hope you do, if not leave me your address, I'll send you a postcard), understand what IMAP, SASL, SMTP is for, being a geek in system administration  is not required.

Needed software

We will need software. Let's setup some. We will need to install exim(heavyweight version which comes with SASL support), Cyrus SASL, Cyrus IMAP and their admin tools.
grim@kepler:~$ sudo apt-get install exim4 exim4-daemon-heavy
grim@kepler:~$ sudo apt-get install sasl2-bin libsasl2-2 libsasl2-modules
grim@kepler:~$ sudo apt-get install cyrus-imapd-2.2 cyrus-admin-2.2 cyrus-clients-2.2

Basic configuration

When you're done with installation, you'll get all that preconfigured with defaults, which you want to change to suit your site.

You will find that saslauthd is disabled by default. To enable it, edit /etc/default/saslauthd and set START=yes, it's already there, you need to change the options. Also add sasldb to list of authentication mechanisms, that saslauthd daemon will use.

grim@kepler:~$ sudo vim /etc/default/saslauthd
MECHANISMS="sasldb pam"

Restart the service after that:

grim@kepler:~$ sudo /etc/init.d/saslauthd restart

Also, you will need to do basic configuration of exim MTA. This is where dpkg steps in:

grim@kepler:~$ sudo dpkg-reconfigure --priority=low exim4-config

I'll be using modular configuration in this article, so make sure you'll choose to split your configuration into small files when asked.

Binding it together

Now we're done with saslauthd and basic things, let's bind it together. First of all we need to let our MTA to use SASL. By default only users from group sasl can use SASL, so Debian-exim user, under which exim runs must be added to sasl group.

After that I'm going to create test1 user with ChangeMe1 password and finally check that exim can authenticate with SASL.

grim@kepler:~$ sudo adduser Debian-exim sasl
grim@kepler:~$ sudo saslpasswd2 -c -f /etc/sasldb2 test1
Again (for verification):

grim@kepler:~$ sudo -u Debian-exim testsaslauthd -u test1 -p ChangeMe1
0: OK "Success."

Cool! Now we're safe with OS-level stuff and can proceed with exim and Cyrus configuration, to make mail delivery actually happen.

Making delivery actually happen - Configuring exim MTA

Here we have three things to tune. First is authenticators (not quite necessary), second is router and third is transport (these two are the must).


To enable authentication of users through SASL, you will just need to uncomment the readily available authenticators, available in /etc/exim4/conf.d/auth/30_exim4-config_examples. Edit that file with editor of your taste, find and uncomment the below lines:

# Authenticate against local passwords using sasl2-bin
# Requires exim_uid to be a member of sasl group, see README.Debian.gz
  driver = plaintext
  public_name = PLAIN
  server_condition = ${if saslauthd{{$auth2}{$auth3}}{1}{0}}
  server_set_id = $auth2
  server_prompts = :
  server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}

  driver = plaintext
  public_name = LOGIN
  server_prompts = "Username:: : Password::"
  # don't send system passwords over unencrypted connections
  server_condition = ${if saslauthd{{$auth1}{$auth2}}{1}{0}}
  server_set_id = $auth1
  server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}

Note that configuring TLS is out of the scope of the current article. Maybe I'll find some time to go in depth of TLS later, but for now add the guarding macro  definition to /etc/exim4/conf.d/main/00_localmacros file.


Router and transport

Unfortunately I didn't found on the Net any readily available solutions for building mail delivery system based on SASL user database. So I've cleaned off the rust from my Perl skills and wrote the plugin for exim that can check if the user is present in sasl db. 

Download it here and put it /etc/exim4/ folder. After that's done, add the following option to your /etc/exim4/conf.d/main/00_localmacros file:

perl_startup = do '/etc/exim4/exim.pm'

The module can be tested from command line like this:

grim@kepler:~$ sudo perl -Mexim -e "check_sasldb_user test1"
Debug output is enabled
Checking sasldb for given user: test1
  test1@kepler: userPassword
User found

Now, when script is in place and confirmed to be working we should proceed with router and transport setup.

Create the file for router called /etc/exim4/conf.d/router/910_sasldb_user and put the below router definition there.

  debug_print = "R: sasldb_user for $local_part@$domain"
  condition = ${perl{check_sasldb_user}}
  driver = accept
  domains = +local_domains
  local_parts = ! root
  transport = cyrus_delivery
  cannot_route_message = Unknown user

Create the file for transport called /etc/exim4/conf.d/transport/30_cyrus_imapd and put the below transport definition there

  driver = pipe
  command = /usr/sbin/cyrdeliver $local_part
  user = cyrus
  group = mail
  message_prefix =
  message_suffix =

After all these changes we are ready to update exim configuration and restart it.

grim@kepler:~$ sudo update-exim4.conf
grim@kepler:~$ sudo /etc/init.d/exim4 restart

To check if that worked, you can test the delivery using -bt option like this:

grim@kepler:/etc/exim4$ exim -bt test1
R: system_aliases for test1@kepler.linuxgears.org
R: sasldb_user for test1@kepler.linuxgears.org
  router = sasldb_user, transport = cyrus_delivery

Making delivery actually happen - Configuring Cyrus IMAP

Again we need to make sure cyrus user is in sasl group, so /etc/sasldb2 is readable by Cyrus apps.

grim@kepler:~$ sudo adduser cyrus sasl

Then make sure that the user cyrus is in the admins: line in /etc/imapd.conf.

# Uncomment the following and add the space-separated users who
# have admin rights for all services.
admins: cyrus

Restart cyrus with

grim@kepler:/etc/exim4$ sudo /etc/init.d/cyrus2.2 restart

One last thing is setting up the password for cyrus user. Use saslpasswd2 tool, just like above for test1 user:

grim@kepler:/etc/exim4$ sudo saslpasswd2 -c cyrus

Now you can adminsiter imap mailboxes. Run cyradm to connect to cyrus daemon:

cyradm -u cyrus localhost
Enter the password when asked and create a mailbox for your first user.

localhost> cm user.test1
localhost> quit


Finally test the availability of your service through direct SMTP session to the host.

grim@blackbox:~$ telnet kepler 25
Connected to kepler.linuxgears.org.
Escape character is '^]'.
220 kepler ESMTP Exim 4.71 Sun, 26 Dec 2010 22:51:08 +0200
EHLO snuke
250-kepler Hello 77-52-53-233.dialup.umc.net.ua []
250-SIZE 52428800
250 HELP
MAIL FROM: <oleksiy.khilkevich@gmail.com>
250 OK
RCPT TO: <test1@kepler.linuxgears.org>
250 Accepted
354 Enter message, ending with "." on a line by itself
From: Oleksiy
To: Test1

250 OK id=1PWxad-0002LE-Jfa
Connection closed by foreign host.

And you may want to test your IMAP server works
 with imtest

grim@blackbox:~$ imtest -a test1 -w ChangeMe1 localhost
S: * OK kepler Cyrus IMAP4 v2.2.13-Debian-2.2.13-19 server ready
S: C01 OK Completed
S: + bm9uY2U9InNjcjFvYkZkYnc5b05aeDNBcVJOKzNRaTVDY0NEVjBJOE1MYmFtVGwwdW89IixyZWFsbT0ia2VwbGVyIixxb3A9ImF1dGgsYXV0aC1pbnQsYXV0aC1jb25mIixjaXBoZXI9InJjNC00MCxyYzQtNTYscmM0LGRlcywzZGVzIixtYXhidWY9NDA5NixjaGFyc2V0PXV0Zi04LGFsZ29yaXRobT1tZDUtc2Vzcw==
C: dXNlcm5hbWU9InRlc3QxIixyZWFsbT0ia2VwbGVyIixub25jZT0ic2NyMW9iRmRidzlvTlp4M0FxUk4rM1FpNUNjQ0RWMEk4TUxiYW1UbDB1bz0iLGNub25jZT0iUnBPVGliTXBCNjU2ek10d0tycmhnNDJQRm1HN01KQ3FuOXVOUVVjYTRvVT0iLG5jPTAwMDAwMDAxLHFvcD1hdXRoLWNvbmYsY2lwaGVyPXJjNCxtYXhidWY9MTAyNCxkaWdlc3QtdXJpPSJpbWFwL2xvY2FsaG9zdCIscmVzcG9uc2U9MTFmODhmNTkxMzQ4MWUxOTMyMzgwN2RjZTQxNDlhYmU=
S: + cnNwYXV0aD1kMDc4YjM2MDc1NDRkNTJmYjZiYTBlNmQwMWJhYjliNg==
S: A01 OK Success (privacy protection)

Security strength factor: 128
Connection closed.

Now you can tell it is working.

Webmail setup

Now, when we have the delivery chain configured, the next thing is to install some webmail system, so you can view the incoming messages easy way.

If you are just as poor as me, you'll probably have only one dedicated server available, and if you are just as itchy for experiments as me, you'd probably already have some services on it, like web server and app server. If that is the case, the ports 80 and 8080 are most probably to be busy or will be busy in the near future. In addition to that, I didn't want to mess with other sites, I wanted this all thing to be kind of separate, so I could easily change it or switch it on/off without much impact.

That's why we're gonna setup separate Apache virtual host on port 81.

For webmail software I've chosen RoundCube (http://roundcube.net/) which is quite nice and easy to deploy and what's more important can work with SQLite as a backend DB.

First we'll install all dependencies RC requires:

grim@kepler:~$ sudo apt-get install apache2 libapache2-mod-php5 sqlite php5-sqlite php5-mcrypt php5-intl

Next is to create new Apache virtual host. To do that add below lines to /etc/apache2/ports.conf

NameVirtualHost *:81
Listen 81

Next go to /etc/apache2/sites-available and copy file called default to default-81.

grim@kepler:~$ cd /etc/apache2/sites-available/
grim@kepler:/etc/apache2/sites-available$ sudo cp default default-81

Edit the file, and change the virtual host configuration to refer to the port 81.
You may also want to change DocumentRoot and some other options. As for me I've left most of the file intact and changed below lines: 

<VirtualHost *:81>
    DocumentRoot /srv/www-81
    <Directory /srv/www-81/>
    ErrorLog /var/log/apache2/error-default-81.log
    CustomLog /var/log/apache2/access-default-81.log combined

Now we are ok to enable the virtual host. Do it with command:

grim@kepler:~$ sudo a2ensite default-81

Check the configuration for errors and restart the web server.

grim@kepler:~$ apache2ctl -S
apache2: Could not reliably determine the server's fully qualified domain name, using for ServerName
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
*:81                   is a NameVirtualHost
         default server (/etc/apache2/sites-enabled/default-81:1)
         port 81 namevhost (/etc/apache2/sites-enabled/default-81:1)
*:80                   is a NameVirtualHost
         default server (/etc/apache2/sites-enabled/000-default:1)
         port 80 namevhost (/etc/apache2/sites-enabled/000-default:1)
Syntax OK
grim@kepler:~$ sudo /etc/init.d/apache2 graceful

You can try access the site at port 81(for my case that'd be http://kepler:81/)

I'll not be covering installation of RoundCube here, as there is already really self-explanatory article at http://wiki.kartbuilding.net/index.php/Roundcube, if you'll find any problems with adapting it for your installation, feel free to ask for help.

So as a final goal you should have http://<your-host>:81/roundcube/ showing the RC login page.

Great, now I've done all this long, so what do I have?

Now you have the working mail service, were you can easily add/remove users, send/receive emails on behalf of them and watch that emails through web interface.


I didn't covered the Cyrus IMAP and SASL usage in this install. If you find troubles using it, feel free to ask in comments, or send me the mail.


[1] https://help.ubuntu.com/8.04/serverguide/C/exim4.html
[2] http://www.exim.org/exim-html-current/doc/html/spec_html/ch12.html
[3] http://flakey.info/mailserver/
[4] http://www.exim.org/docs.html

субота, 18 грудня 2010 р.

Remove MBR from hard drive

Say you want to wipe Linux from the hard drive and you don't want reinstall the Windows you had there. You delete the Linux partitions, but chances are that you had bootloader, either LILO or GRUB installed in MBR. Since you will delete / and /boot, you don't have valid bootloader anymore and you don't need it at all.

What you want is to install default MBR on the disk.

From Linux you can do this by filling MBR bytes on disk with zeroes.

# dd if=/dev/null of=/dev/sdX bs=446 count=1

четвер, 16 грудня 2010 р.


Забрал сегодня iPod! Полный фейл вышел с первым впечатлением, так как винды под рукой не оказалось, на ноуте была бубунта. Пришлось кусая локти и снося дружеский сарказм, терпеть, пока не пришел домой. Сейчас качаю iTunes и пускаю слюну на завтрашний день, когда буду крутым айтишником, в старой куртке и потертых джинсах, зато блять с айподом.

У меня теперь всегда с собой зеркало и 160 гиг музона :)

субота, 11 грудня 2010 р.

Мысль и чувства

Дочитал сегодня Германа Гессе "Нарцисс и Гольдмунд". Замечательное произведение о жизненном пути человека как о познании себя и бытия, отвлеченное от религиозных предрассудков.

Вкратце, есть два способа познания мира: чувственный и мыслительный. Нарциссс и Гольдмунд - два друга, две крайности этих восприятий: Нарцисс - мыслитель и аскет, познающий с помошью абстракций, формул и логического вывода, Голдьмунд - человек искусства, познающий мир и себя с помощью чувств и образов. Дух мыслителя и дух художника.

Книга описывает в основном жизнь Гольдмунда и заканчивается его кончиной, Гессе явно хотел показать именно чувственную сторону, хотя создалось впечатление, что сам Гессе есть как раз человеком-мыслителем, то есть Нарциссом. При этом концовка, да и сюжет, говорит о том, что сам Гессе превозносил чувственный путь над логическим. Странное впечатление, учитывая, что Гессе - писатель, а не ученый. Из краткой биографии из Википедии видно, что его судьба больше напоминает судьбу Гольдмунда, так что это лишь мое мнение.

Мне же интересно было наблюдать, как поднимаются один за другим множество моих теперешних переживаний, кажеться Гессе ставил себе те же вопросы в свое время, что и я.

Главное, что запомнилось - это кристаллизация различия между чувством и мыслью. Когда дочитал до половины, уже не мог на мир смотреть как раньше, а когда дочитал, то почувствовал один из тех моментов, когда в душе уравновесились две противоположности, найден ответ на еще один вопрос. 

Вообще ответ я нашел уже давно, но прочувствовал его по-настоящему только сейчас. И чувство такое, как будто я сам себя обокрал, не пользовался чем-то, что дано мне с самого начала.

субота, 4 грудня 2010 р.

Деактивація фізичного тому LVM

Треба було сьогодні на одному з вінчаків, що використовувався повністю як фізичний том для LVM, створити розділи. При цьому дані повинні бути збережені (1.2 тбайти, купа кльових фільмів, музики і древнього хламу який я боюся видалити :])

Маю дві групи томів на двох жорстких дисках. Необхідно звільнити один з них (/dev/sdc).

root@blackbox:/home# pvs
  PV         VG        Fmt  Attr PSize   PFree 
  /dev/dm-3            lvm2 --   100.00g 100.00g
  /dev/dm-4            lvm2 --   282.17g 282.17g
  /dev/sda4  blackbox  lvm2 a-   502.17g      0
  /dev/sdb             lvm2 --   596.17g 596.17g
  /dev/sdc   datastore lvm2 a-     1.82t 679.02g
  /dev/sde             lvm2 --   298.09g 298.09g

Щоб зберегти інфу, я нашкріб де тільки міг вінчестерів та вільного місця, і маю загалом 1.2 тбайти в резерві для копіювання даних з фізичного тому.

Додаю нові фізичні томи до групи datastore.

root@blackbox:/home# vgextend datastore /dev/dm-3 /dev/dm-4 /dev/sdb /dev/sde
  Volume group "datastore" successfully extended
root@blackbox:/home# pvs
  PV         VG        Fmt  Attr PSize   PFree 
  /dev/dm-3  datastore lvm2 a-   100.00g 100.00g
  /dev/dm-4  datastore lvm2 a-   282.16g 282.16g
  /dev/sda4  blackbox  lvm2 a-   502.17g      0
  /dev/sdb   datastore lvm2 a-   596.17g 596.17g
  /dev/sdc   datastore lvm2 a-     1.82t 679.02g
  /dev/sde   datastore lvm2 a-   298.09g 298.09g

Після чого звільняємо фізичний том

root@blackbox:/home# pvmove -v -i 30 /dev/sdc
    Finding volume group "datastore"
  Detected pvmove in progress for /dev/sdc
    Found volume group "datastore"
    Found volume group "datastore"
    Found volume group "datastore"
    Checking progress every 30 seconds
  /dev/sdc: Moved: 1.0%
  /dev/sdc: Moved: 1.3%

Після чого я йду заварювати чай і ставлю на перегляд фільм з того самого тому, який зараз переміщується :)

понеділок, 22 листопада 2010 р.

Наступний тиждень

Останні кілька днів...
Майже написав свй парсер MIME-типу multipart/form-data. Покрив його
тестами, - мок-фреймворки та й взагалі TDD - це кул. Коли придумуєш нові тести, сам знаходиш зроблені помилки, а детальне покриття часто дає досить точну причину баги.

Попрактикувався з EasyMock, JUnit, InputStream'ами. Пригадав динамічне прграмування та алгоритм пошуку зразка в послідовності. Розібрався, як завантажують файли в інтернети.

Все це паралельно з переглядом "Міміно", "Кін-дза-дза!" та інших класичних радянських фільмів.

Наступний тиждень буде присвячений вивченню java.util.concurrent.*, технології веб-сервісів, та повторенню JDBC, доробці парсера мультипартових даних, практиці в JSP.

Придумайте мені гарну ідею з використанням усіх трьох.

До речі, JSP, мені здається, важкуватий, як для вивчення, через купу стандартів та історичних причин у синтаксис, так і через відсутність необхідних API, у тому числі для завантаження файлів. На PHP завантаження файла складає 5 рядків коду, а на чистому JSP перевищує 30, і не універсальне.

Перескочив з Eclipse на IDEA, набагато приємніше писати код. Основна причина переходу - у Eclipse хрєновєнький контент-ассіст і валідація коду часто лагає. В Ідеї помітив теж маленьку  проблему з підсвіткою JSP, але в цілому набагато якісніша IDE.