Home Network Setup, Part 5

Ok,

This is the fifth part of my guide on how to setup a home network. If you’ve only just dropped in I’d recommend you have a quick read over parts 1, 2, 3 & 4. Throughout this guide I’ve exclusively used CentOS4 and I’ve assumed it’s a basic clean install.

I cover the following topics in this part:

  • POP3/IMAP Server
  • Outbound SMTP Server
  • Local mail pull
  • Web based mail access
  • Dynamic Virtualhost Access

Telesto in my case is a VPS but it will be based on a CentOS 4 installation. Consequently, these instructions should work fine on a normal server. I won’t be running through HOW to setup OpenVZ, that’s a topic for a seperate HOWTO. 🙂

IMAP/POP3 Server
First off we install the Dovecot POP3/IMAP server. Dovecot apparently has the best performance of all the Maildir compatible IMAP servers and uses indexing to allow for fast retrieval of messages. With 50,000 messages stored in my IMAP box it’s fairly essential I use an efficient IMAP server. Hopefully this will suffice or I’ll have to switch back to Courier IMAP (what I use on my current Mail Server). So, onto business:

[root@telesto ~]# yum install dovecot
Setting up Install Process
Setting up repositories
centos4-base 100% |=========================| 1.1 kB 00:00
centos4-updates-released 100% |=========================| 951 B 00:00
Reading repository metadata in from local files
Parsing package install arguments
Resolving Dependencies
–> Populating transaction set with selected packages. Please wait.
—> Downloading header for dovecot to pack into transaction set.
dovecot-0.99.11-2.EL4.1.i 100% |=========================| 13 kB 00:00
—> Package dovecot.i386 0:0.99.11-2.EL4.1 set to be updated
–> Running transaction check
–> Processing Dependency: libpq.so.3 for package: dovecot
–> Processing Dependency: libmysqlclient.so.14 for package: dovecot
–> Restarting Dependency Resolution with new changes.
–> Populating transaction set with selected packages. Please wait.
—> Downloading header for mysql to pack into transaction set.
mysql-4.1.12-3.RHEL4.1.i3 100% |=========================| 35 kB 00:00
—> Package mysql.i386 0:4.1.12-3.RHEL4.1 set to be updated
—> Downloading header for postgresql-libs to pack into transaction set.
postgresql-libs-7.4.8-1.R 100% |=========================| 11 kB 00:00
—> Package postgresql-libs.i386 0:7.4.8-1.RHEL4.1 set to be updated
–> Running transaction check
–> Processing Dependency: perl(DBI) for package: mysql
–> Restarting Dependency Resolution with new changes.
–> Populating transaction set with selected packages. Please wait.
—> Downloading header for perl-DBI to pack into transaction set.
perl-DBI-1.40-8.i386.rpm 100% |=========================| 11 kB 00:00
—> Package perl-DBI.i386 0:1.40-8 set to be updated
–> Running transaction check

Dependencies Resolved

=============================================================================
Package Arch Version Repository Size
=============================================================================
Installing:
dovecot i386 0.99.11-2.EL4.1 centos4-base 601 k
Installing for dependencies:
mysql i386 4.1.12-3.RHEL4.1 centos4-base 2.8 M
perl-DBI i386 1.40-8 centos4-base 466 k
postgresql-libs i386 7.4.8-1.RHEL4.1 centos4-base 144 k

Transaction Summary
=============================================================================
Install 4 Package(s)
Update 0 Package(s)
Remove 0 Package(s)
Total download size: 4.0 M
Is this ok [y/N]: y
Downloading Packages:
(1/4): dovecot-0.99.11-2. 100% |=========================| 601 kB 00:04
(2/4): mysql-4.1.12-3.RHE 100% |=========================| 2.8 MB 00:18
(3/4): postgresql-libs-7. 100% |=========================| 144 kB 00:00
(4/4): perl-DBI-1.40-8.i3 100% |=========================| 466 kB 00:02
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
Installing: perl-DBI ######################### [1/4]
Installing: mysql ######################### [2/4]
Installing: postgresql-libs ######################### [3/4]
Installing: dovecot ######################### [4/4]

Installed: dovecot.i386 0:0.99.11-2.EL4.1
Dependency Installed: mysql.i386 0:4.1.12-3.RHEL4.1 perl-DBI.i386 0:1.40-8 postgresql-libs.i386 0:7.4.8-1.RHEL4.1
Complete!

So, now we have the base Dovecot files installed.

[root@telesto ~]# chkconfig –level 345 dovecot on
[root@telesto ~]# service dovecot start
Starting Dovecot Imap: [ OK ]
[root@telesto ~]#

Now I want to do some quick modifications to the Dovecot configuration. Consequently, I make the following changes to /etc/dovecot.conf:

protocols = imap imaps pop3 pop3s
default_mail_env = maildir:/home/%u/.Maildir

Now I also setup our shared home directories from Tethys (using an NFS export) and coupled it with NIS authentication. That means that Dovecot will be able to use our central home directories & authentication database.

Getmail Setup

To avoid lost mail due to our MTA segfaulting or not being started I prefer to use Getmail. From the Freshmeat.net description:

getmail is intended as a simple, secure, and reliable replacement for fetchmail. It retrieves email (either all messages, or only unread messages) from one or more POP3, SPDS, or IMAP4 servers (with or without SSL) for one or more email accounts, and reliably delivers into qmail-style Maildirs, mboxrd files, or through external MDAs (command deliveries) specified on a per-account basis. getmail also has excellent support for domain (multidrop) mailboxes, including delivering messages to different users or destinations based on the envelope recipient address.

So we proceed to build and install Getmail:

[root@telesto ~]# wget http://pyropus.ca/software/getmail/old-versions/getmail-4.5.3.tar.gz
–09:47:16– http://pyropus.ca/software/getmail/old-versions/getmail-4.5.3.tar.gz
=> `getmail-4.5.3.tar.gz’
Resolving pyropus.ca… 70.64.38.253
Connecting to pyropus.ca|70.64.38.253|:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 137,589 (134K) [application/x-tar]

100%[=================================================================================================================>] 137,589 –.–K/s

09:47:16 (11.47 MB/s) – `getmail-4.5.3.tar.gz’ saved [137589/137589]

[root@telesto ~]# tar -zxf getmail-4.5.3.tar.gz
[root@telesto ~]# cd getmail-4.5.3
[root@telesto getmail-4.5.3]# python setup.py build
running build
running build_py
creating build
creating build/lib
creating build/lib/getmailcore
copying getmailcore/message.py -> build/lib/getmailcore
copying getmailcore/_pop3ssl.py -> build/lib/getmailcore
copying getmailcore/filters.py -> build/lib/getmailcore
copying getmailcore/logging.py -> build/lib/getmailcore
copying getmailcore/destinations.py -> build/lib/getmailcore
copying getmailcore/__init__.py -> build/lib/getmailcore
copying getmailcore/retrievers.py -> build/lib/getmailcore
copying getmailcore/utilities.py -> build/lib/getmailcore
copying getmailcore/exceptions.py -> build/lib/getmailcore
copying getmailcore/_retrieverbases.py -> build/lib/getmailcore
copying getmailcore/baseclasses.py -> build/lib/getmailcore
copying getmailcore/constants.py -> build/lib/getmailcore
running build_scripts
creating build/scripts-2.3
copying and adjusting getmail -> build/scripts-2.3
copying and adjusting getmail_fetch -> build/scripts-2.3
copying and adjusting getmail_maildir -> build/scripts-2.3
copying and adjusting getmail_mbox -> build/scripts-2.3
changing mode of build/scripts-2.3/getmail from 644 to 755
changing mode of build/scripts-2.3/getmail_fetch from 644 to 755
changing mode of build/scripts-2.3/getmail_maildir from 644 to 755
changing mode of build/scripts-2.3/getmail_mbox from 644 to 755
[root@telesto getmail-4.5.3]# python setup.py install
running install
running build
running build_py
running build_scripts
running install_lib
running install_scripts
copying build/scripts-2.3/getmail -> /usr/bin
copying build/scripts-2.3/getmail_fetch -> /usr/bin
copying build/scripts-2.3/getmail_maildir -> /usr/bin
copying build/scripts-2.3/getmail_mbox -> /usr/bin
changing mode of /usr/bin/getmail to 755
changing mode of /usr/bin/getmail_fetch to 755
changing mode of /usr/bin/getmail_maildir to 755
changing mode of /usr/bin/getmail_mbox to 755
running install_data
[root@telesto getmail-4.5.3]#

Next we login as one of our Mail users:

[stuart@telesto ~]$ mkdir -p .Maildir/cur
[stuart@telesto ~]$ mkdir -p .Maildir/new
[stuart@telesto ~]$ mkdir -p .Maildir/tmp

I’ve then created the following contents for getmail configuration (1 file per server to pull from):

~/.getmail/getmailrc-serverpeak.com

[retriever]
type = SimplePOP3SSLRetriever
server = mail.serverpeak.com
username = stuart@serverpeak.com
password = password

[destination]
type = Maildir
path = ~/.Maildir/

Multiple occurances of these files will need to be created for each POP3 server you wish to check and deliver for. To run getmail using these multiple files I run the following command:

[stuart@telesto ~]$ getmail -rgetmailrc-UQ -rgetmailrc-iinet -rgetmailrc-serverpeak.com
getmail version 4.5.3
Copyright (C) 1998-2006 Charles Cazabon. Licensed under the GNU GPL version 2.
SimplePOP3Retriever:s4027706@student.uq.edu.au:110:
0 messages retrieved, 0 skipped
SimplePOP3Retriever:seekbrain@iinet.net.au@mail.iinet.net.au:110:
0 messages retrieved, 0 skipped
SimplePOP3SSLRetriever:stuart@serverpeak.com:995:
msg 1/2 (4297 bytes) delivered, deleted
msg 2/2 (21000 bytes) delivered, deleted
2 messages retrieved, 0 skipped
[stuart@telesto ~]$

These files are loaded from ~/.getmail so make sure you place your config there. 🙂
Now the easiest way to automate this is to place a crontab running getmail. Which I do, piping output to /dev/null:

[stuart@telesto ~]$ crontab -l
0-59/5 * * * * /usr/bin/getmail -rgetmailrc-UQ -rgetmailrc-iinet -rgetmailrc-serverpeak.com &> /dev/null
[stuart@telesto ~]$

So now we have a local mailbox with IMAP access. I then proceed to do the same for the other user (sally) as she wants to get her mail too! 🙂

SMTP Smart Host

I only use a local SMTP server for smart host relaying of mail to our upstream MTA. Consequently, using exim (which comes stock with CentOS4) will suffice. I personally preference Qmail for larger setups but it’s overkill for our purposes.

Install exim via yum:

[root@telesto ~]# yum install exim
Setting up Install Process
Setting up repositories
centos4-base 100% |=========================| 1.1 kB 00:00
centos4-updates-released 100% |=========================| 951 B 00:00
Reading repository metadata in from local files
Parsing package install arguments
Resolving Dependencies
–> Populating transaction set with selected packages. Please wait.
—> Downloading header for exim to pack into transaction set.
exim-4.43-1.RHEL4.5.i386. 100% |=========================| 21 kB 00:00
—> Package exim.i386 0:4.43-1.RHEL4.5 set to be updated
–> Running transaction check

Dependencies Resolved

=============================================================================
Package Arch Version Repository Size
=============================================================================
Installing:
exim i386 4.43-1.RHEL4.5 centos4-base 1.5 M

Transaction Summary
=============================================================================
Install 1 Package(s)
Update 0 Package(s)
Remove 0 Package(s)
Total download size: 1.5 M
Is this ok [y/N]: y
Downloading Packages:
(1/1): exim-4.43-1.RHEL4. 100% |=========================| 1.5 MB 00:10
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
Installing: exim ######################### [1/1]

Installed: exim.i386 0:4.43-1.RHEL4.5
Complete!

Next we make a few changes to exim.conf to allow relaying FROM the local network and to forward mail VIA our upstream:

/etc/exim/exim.conf:

hostlist relay_from_hosts = 127.0.0.1 : 192.168.50.0/24 : 192.168.128.0/24

Just after the “begin routers” option I added:

route_append:
driver = manualroute
domains = *
transport = remote_smtp
route_data = “mail.iinet.net.au byname”

I then disable sendmail, stop sendmail, enable exim & start exim:

[root@telesto exim]# service sendmail stop
Shutting down sendmail: [ OK ]
Shutting down sm-client: [ OK ]
[root@telesto exim]# chkconfig –level 2345 sendmail off
[root@telesto exim]# chkconfig –level 2345 exim on
[root@telesto exim]# service exim restart
Shutting down exim: [ OK ]
Starting exim: [ OK ]
[root@telesto exim]#

I can then test these settings and track via the mail log:

2006-02-12 11:51:36 1F86Om-0006Az-4l <= sally@serverpeak.com H=([192.168.50.100]) [192.168.50.100] P=esmtp S=496 id=1139708945.11338.2.camel@laptop.seekbrain.com 2006-02-12 11:51:37 1F86Om-0006Az-4l => stuart@serverpeak.com R=route_append T=remote_smtp H=mail.iinet.net.au [203.0.178.192]
2006-02-12 11:51:37 1F86Om-0006Az-4l Completed

Cool eh!?

Webmail Access

Now, the big question is, should I use Horde or Squirrelmail here. I kind of prefer Horde since it has a lot of cool features but by the same token Squirrelmail is fast loading which, for remote access, is advantageous. With this in mind, coupled with the fact that Sally is familiar with Squirrelmail made me decide on it.

Lucky for us it’s also shipped as part of CentOS (thanks to Redhat):

[root@telesto ~]# yum install squirrelmail
Setting up Install Process
Setting up repositories
centos4-base 100% |=========================| 1.1 kB 00:00
centos4-updates-released 100% |=========================| 951 B 00:00
Reading repository metadata in from local files
Parsing package install arguments
Resolving Dependencies
–> Populating transaction set with selected packages. Please wait.
—> Package squirrelmail.noarch 0:1.4.3a-12.EL4.centos4 set to be updated
–> Running transaction check
–> Processing Dependency: php >= 4.0.4 for package: squirrelmail
–> Processing Dependency: aspell for package: squirrelmail
–> Restarting Dependency Resolution with new changes.
–> Populating transaction set with selected packages. Please wait.
—> Package aspell.i386 12:0.50.5-3.fc3 set to be updated
—> Package php.i386 0:4.3.9-3.9 set to be updated
–> Running transaction check
–> Processing Dependency: php-pear for package: php
–> Processing Dependency: aspell-en for package: aspell
–> Restarting Dependency Resolution with new changes.
–> Populating transaction set with selected packages. Please wait.
—> Package php-pear.i386 0:4.3.9-3.9 set to be updated
—> Package aspell-en.i386 50:0.51-11 set to be updated
–> Running transaction check

Dependencies Resolved

=============================================================================
Package Arch Version Repository Size
=============================================================================
Installing:
squirrelmail noarch 1.4.3a-12.EL4.centos4 centos4-base 3.2 M
Installing for dependencies:
aspell i386 12:0.50.5-3.fc3 centos4-base 314 k
aspell-en i386 50:0.51-11 centos4-base 1.9 M
php i386 4.3.9-3.9 centos4-updates-released 1.3 M
php-pear i386 4.3.9-3.9 centos4-updates-released 265 k

Transaction Summary
=============================================================================
Install 5 Package(s)
Update 0 Package(s)
Remove 0 Package(s)
Total download size: 7.0 M
Is this ok [y/N]: y
Downloading Packages:
(1/5): squirrelmail-1.4.3 100% |=========================| 3.2 MB 00:22
(2/5): php-pear-4.3.9-3.9 100% |=========================| 265 kB 00:02
(3/5): aspell-0.50.5-3.fc 100% |=========================| 314 kB 00:03
(4/5): aspell-en-0.51-11. 100% |=========================| 1.9 MB 00:14
(5/5): php-4.3.9-3.9.i386 100% |=========================| 1.3 MB 00:09
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
Installing: aspell ######################### [1/5]
Installing: php ######################### [2/5]
Installing: squirrelmail ######################### [3/5]
Installing: php-pear ######################### [4/5]
Installing: aspell-en ######################### [5/5]

Installed: squirrelmail.noarch 0:1.4.3a-12.EL4.centos4
Dependency Installed: aspell.i386 12:0.50.5-3.fc3 aspell-en.i386 50:0.51-11 php.i386 0:4.3.9-3.9 php-pear.i386 0:4.3.9-3.9
Complete!
[root@telesto ~]#

Next we do some basic configuration of Squirrelmail using it’s config utility from /usr/share/squirrelmail/config. We run it by simply typing “perl conf.pl”. I made the following changes:

(1) -> (1) Organization Name: Seekbrain
(2) -> (3) Sendmail or SMTP: SMTP
(2) -> (A) Update IMAP Settings
(8) -> Server Software: other
(9) -> Delimiter: detect
(3) -> (1) Default Folder Prefix: none

I then type “S” to save the settings then Q to quit.

I then modified /etc/httpd/conf/httpd.conf so Squirrelmail is the default page to load regardless of it’s accessible host:

DocumentRoot “/usr/share/squirrelmail”

So, now if I goto http://telesto.seekbrain.com I get Squirrelmail. I can login and access the same mailstore as my standard desktops. 🙂

But what about accessing our Webmail abroad?

External Webmail Access

Now, it’s possible to simply forward inbound requests to port 80 to our Mail server and be done. But what about if you want to host multiple “sites” on our plain ol’ little dynamic ADSL connection? Introducing, mod_proxy, this great module means we can setup all our VirtualHosts on our gateway and have them handle all requests before passing them on to our REAL server.

So, on Dione I first install Apache:

[root@dione ~]# yum install httpd
Setting up Install Process
Setting up repositories
update 100% |=========================| 951 B 00:00
base 100% |=========================| 1.1 kB –:–
addons 100% |=========================| 951 B –:–
extras 100% |=========================| 1.1 kB 00:00
Reading repository metadata in from local files
primary.xml.gz 100% |=========================| 55 kB 00:01
update : ################################################## 137/137
Added 2 new packages, deleted 0 old in 0.60 seconds
primary.xml.gz 100% |=========================| 29 kB 00:01
extras : ################################################## 125/125
Added 1 new packages, deleted 0 old in 0.40 seconds
Parsing package install arguments
Resolving Dependencies
–> Populating transaction set with selected packages. Please wait.
—> Downloading header for httpd to pack into transaction set.
httpd-2.0.52-22.ent.cento 100% |=========================| 62 kB 00:01
—> Package httpd.i386 0:2.0.52-22.ent.centos4 set to be updated
–> Running transaction check
–> Processing Dependency: apr >= 0.9.4-24.2 for package: httpd
–> Processing Dependency: httpd-suexec for package: httpd
–> Processing Dependency: libaprutil-0.so.0 for package: httpd
–> Processing Dependency: libapr-0.so.0 for package: httpd
–> Restarting Dependency Resolution with new changes.
–> Populating transaction set with selected packages. Please wait.
—> Downloading header for apr-util to pack into transaction set.
apr-util-0.9.4-21.i386.rp 100% |=========================| 5.2 kB 00:04
—> Package apr-util.i386 0:0.9.4-21 set to be updated
—> Downloading header for httpd-suexec to pack into transaction set.
httpd-suexec-2.0.52-22.en 100% |=========================| 21 kB 00:01
—> Package httpd-suexec.i386 0:2.0.52-22.ent.centos4 set to be updated
—> Downloading header for apr to pack into transaction set.
apr-0.9.4-24.5.i386.rpm 100% |=========================| 7.4 kB 00:00
—> Package apr.i386 0:0.9.4-24.5 set to be updated
–> Running transaction check

Dependencies Resolved

=============================================================================
Package Arch Version Repository Size
=============================================================================
Installing:
httpd i386 2.0.52-22.ent.centos4 update 887 k
Installing for dependencies:
apr i386 0.9.4-24.5 base 88 k
apr-util i386 0.9.4-21 base 51 k
httpd-suexec i386 2.0.52-22.ent.centos4 update 28 k

Transaction Summary
=============================================================================
Install 4 Package(s)
Update 0 Package(s)
Remove 0 Package(s)
Total download size: 1.0 M
Is this ok [y/N]: y
Downloading Packages:
(1/4): httpd-2.0.52-22.en 100% |=========================| 887 kB 00:03
(2/4): apr-util-0.9.4-21. 100% |=========================| 51 kB 00:01
(3/4): httpd-suexec-2.0.5 100% |=========================| 28 kB 00:01
(4/4): apr-0.9.4-24.5.i38 100% |=========================| 88 kB 00:01
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
Installing: apr ######################### [1/4]
Installing: apr-util ######################### [2/4]
Installing: httpd ##################### [3/4]warning: user apache does not exist – using root
Installing: httpd ##################### [3/4]warning: user apache does not exist – using root
Installing: httpd ######################### [3/4]
Installing: httpd-suexec ######################### [4/4]

Installed: httpd.i386 0:2.0.52-22.ent.centos4
Dependency Installed: apr.i386 0:0.9.4-24.5 apr-util.i386 0:0.9.4-21 httpd-suexec.i386 0:2.0.52-22.ent.centos4
Complete!
[root@dione ~]#
Side note

For some reason the apache user wasn’t created so I had to run the following extra bits

[root@dione ~]# useradd -u 48 -g apache -s /sbin/nologin -d /var/www apache

Next we add the following lines to a file specifically for this vhost. We do this by using the common /etc/httpd/conf.d directory:

/etc/httpd/conf.d/mailserver.conf:
ServerName mailserver.seekbrain.com
ProxyPass / http://telesto.seekbrain.com/
ProxyPassReverse / http://telesto.seekbrain.com/

I then restart Apache and enable it at boot time:

[root@dione conf.d]# service httpd restart
Stopping httpd: [FAILED]
Starting httpd: [ OK ]
[root@dione conf.d]# chkconfig –level 345 httpd on

Dynamic DNS Update
Now, we have our virtual host but how on earth are we supposed to know where it is when it’s IP is constantly changing? Introducing ddclient with DynDNS! I’m going to assume you’ve signed up for a DynDNS account and sorted out all the standard “dynamic hostname” setup.

I install ddclient using Dag Wieers RPMs (because it’s easy):

[root@dione ~]# wget http://dag.wieers.com/packages/ddclient/ddclient-3.6.7-1.2.el4.rf.noarch.rpm
–23:06:22– http://dag.wieers.com/packages/ddclient/ddclient-3.6.7-1.2.el4.rf.noarch.rpm
=> `ddclient-3.6.7-1.2.el4.rf.noarch.rpm’
Resolving dag.wieers.com… 217.22.63.77
Connecting to dag.wieers.com|217.22.63.77|:80… connected.
HTTP request sent, awaiting response… 302 Found
Location: http://apt.sw.be/packages/ddclient/ddclient-3.6.7-1.2.el4.rf.noarch.rpm [following]
–23:06:25– http://apt.sw.be/packages/ddclient/ddclient-3.6.7-1.2.el4.rf.noarch.rpm
=> `ddclient-3.6.7-1.2.el4.rf.noarch.rpm’
Resolving apt.sw.be… 193.1.193.67
Connecting to apt.sw.be|193.1.193.67|:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 42,143 (41K) [application/x-redhat-package-manager]

100%[=================================================================================================================>] 42,143 28.58K/s

23:06:27 (28.56 KB/s) – `ddclient-3.6.7-1.2.el4.rf.noarch.rpm’ saved [42143/42143]

[root@dione ~]# rpm -Uvh ddclient-3.6.7-1.2.el4.rf.noarch.rpm
warning: ddclient-3.6.7-1.2.el4.rf.noarch.rpm: V3 DSA signature: NOKEY, key ID 6b8d79e6
Preparing… ########################################### [100%]
1:ddclient ########################################### [100%]
[root@dione ~]#

I then configure it by making a few quick changes to /etc/ddclient/ddclient.conf. I won’t run through these since they’re fairly self explanatory. I then enabled ddclient to start during boot:

[root@dione ddclient]# service ddclient start
Starting ddclient: [ OK ]
[root@dione ddclient]# chkconfig –level 345 ddclient on

Now, for me I added a CNAME from mailserver.seekbrain.com to my DynDNS entry. It means I can remember the .seekbrain.com address easily AND the same name works from both in and outside the network.

Conclusion

Well that about wraps it up for now. In the next part we’ll put the finishing touches on the network by adding some monitoring to the network as a whole. I’ve also got a few extras ideas destined for future HOWTO guides.

Until then, have fun! 🙂