Sunday, May 29, 2011

Captain, I'm giving her all she's got.

I need to use Linux specifically for one program my friend some asshole wrote.  The machine it's on has only 512 MB of RAM and just running the GUI on Ubuntu 10.4 LTS puts it 20%-30% into the swap file.

The quickest and surest way to free up the much needed RAM is to disable the gdm.  You can do this by renaming/breaking the script that init loads at boot time.

$ sudo mv /etc/init/gdm.conf /etc/init/gdm.broke
and reboot.

You may send me a check for the RAM you save.  Contact me for details.

Friday, May 20, 2011

A trail of breadcrumbs.

This is an accounting of 'first steps' when building a virtual server with FreeBSD.  Documentation on these steps will be sparse.

1. Install host system
2. Configure system files

Configure: /etc/rc.conf

hostname="HOSTNAME"

## this section is hardware/system
moused_enable="YES"
sshd_enable="YES"
zfs_enable="YES"

## this section is the aggregated network interfaces
ifconfig_em0="up"
ifconfig_em1="up"
ifconfig_em2="up"
cloned_interfaces="lagg0"
ifconfig_lagg0="laggproto lacp laggport em0 laggport em1 laggport em2"
ipv4_addrs_lagg0="10.0.10.149/24"
defaultrouter="10.0.10.1"

## this section is NFS and file sharing
nfs_client_enable=YES
syslogd_flags="-ss"
rpcbind_enable="YES"
nfs_server_enable="YES"
mountd_flags="-r"

## configure jails here
ezjail_enable="YES"
## first jail IP
ifconfig_lagg0_alias0="inet 10.0.10.148/32"

Configure DNS: /etc/resolv.conf
nameserver 8.8.8.8  ## 8.8.8.8 is google DNS, put yours or something that works here

3. Create ZFS pool and move selected folders from boot drive to ZFS array
# zpool create tank mirror ad8 ad12
# zfs create tank/src
# zfs create tank/obj
# zfs create tank/jails
# zfs create tank/ports
# zfs set mountpoint=/usr/src tank/src
# zfs set mountpoint=/usr/obj tank/obj
# zfs set mountpoint=/usr/jails tank/jails
# zfs set mountpoint=/usr/ports tank/ports

4. download source code and ports tree
# pkg_add -r cvsup-without-gui
# cp /usr/src/share/examples/cvsup/standard-supfile /root
# rehash
# vi /root/standard-supfile
############ change the CHANGETHIS line to something like:
*default host=cvsup3.us.FreeBSD.org

# cvsup /root/standard-supfile
# portsnap fetch extract


6. Make your server do stuff.

Thursday, May 19, 2011

ZFS is the best file system ever.

NOTE: I will be using the term 'RAID' very loosely later in this post.  When I describe later RAID 1 and RAID 10 style arrays I am using these terms to illustrate how ZFS works in a manner most people are familiar with.

ZFS takes everything I used to know about partitions, volumes and disk space and spins it up in a blender.  Unlike the traditional file system where the size of your disk or array must be specified at the beginning, ZFS allows you to simply pick your parity and add devices as your needs for speed or space increase.  ZFS is similar to RAID but has many advantages over traditional RAID.  I'm not going to go into detail as there are many Sun/Oracle Solaris developer articles on the subject.  You can start reading about it here.

Assuming you have FreeBSD installed and two identical disks that have not been partitioned or sliced in any way named ad8 and ad10 we can get our first disk pool going with zpool.  I'm going to call my disk pool tank because most people do.
# zpool create tank mirror ad8 ad10
That created a RAID 1 style vdev, or virtual device mounted at location /tank.  Note there are other types of vdevs; I will not go into detail on them, but other types include raidz, raidz2 and no parity.   We will be able to use the amount of space equal to one of the disks, and we will have excellent read I/O and acceptable write I/O.  We will be able to continue using the pool in the event of one of the disks failing.

To ensure the pool is mounted at boot time, echo this statement to /etc/rc.conf:
# echo 'zfs_enable=YES'>>/etc/rc.conf
We can see the health of the pool by typing:
# zpool status -v
Let's assume now that we have filled the tank up and we need to add more space.  The best way to do this is to purchase two more disks of the same capacity we had on ad8 and ad10, and add them to the the pool as another mirrored vdev.  Assuming these new disks are identified as ad12 and ad14, type:
# zpool add tank mirror ad12 ad14
Now when you do a status -v on your zpool you will see two mirrors listed.

So wait, that's it?  We just doubled the capacity of /tank?  Yes.  Not only did we double the capacity, but we also doubled the speed.  We effectively converted our "RAID 1" into a "RAID 10".  This will give us excellent read and write I/O, and the ability to continue working if any one disk from any one vdev fails.  If you want it bigger or faster, keep adding vdevs.

We will periodically want to scrub the pool to make sure there aren't any errors.  To do this type:
# zpool scrub tank
This will queue up a disk scrub which we can monitor with the zpool status -v.  You might want to add this to a weekly cron job.  If any errors are discovered, they can be easily cured via the metadata ZFS keeps on the parity disks with the clear switch.
# zpool clear tank
ZFS keeps a lot more metadata than traditional hardware RAID systems, making it much safer for data archiving.  It also allows you to take a snapshot of the data.  This will allow you to retrieve deleted files or rollback to a specific period of time.  Snapshots are stored in the root of the filesystem in a .zfs folder.  For example, /tank/.zfs/snapshot.  To take a snapshot, type:
# zfs snapshot tank@19may2011
Notice there is no leading '/'; you will now have a folder named /tank/.zfs/snapshot/19may2011/ with what looks like everything you had in there before.  In the event that you need to restore something from a snapshot folder, simply cp it to where it was.  For example:
# cp /tank/.zfs/snapshot/19may2011/my_song.mp3 /tank/
Your missing/overwritten file will be restored to the state it was at that snapshot.

Move data up to 6X faster than you used to with LACP 802.3ad.

If you have a Cisco or other programmable switch capable of LACP 802.3ad then you're most of the way to having faster data transfer than you may have thought possible.  The simplicity of this process still throws me for how powerful it is.  LACP is simply bonding two or more network interfaces at the switch and at the computer so that they act as a single virtual network interface.  This increases the speed and availability by two, three, four or up to six times.  It is not recommended to use more than six physical interfaces in one Link Aggregate.

FreeBSD refers to the link aggregate as laggN where N is the ID of the virtual interface.  For example your first lagg would be lagg0 followed by lagg1 and so on.  The server I am working on is a fresh install of FreeBSD 8.2 amd64 with four physical network interfaces em0 em1 em2 and em3.  It is going to be the permanent replacement of a virtual server that currently has three aggregated network interfaces.  I am using a Cisco 3750 in this specific case, but I have used this same process on a variety of other Cisco switches.  We're going to do the switch first, then we'll set up the server.  This example assumes you are using Gigabit ports 0/10 through 0/13.

After you get into enable mode on the switch type:
# config t
(config)# int range gi0/10-13
(config-if-range)# channel-group 1 mode active
(config-if-range)# channel-protocol lacp
(config-if-range)# exit
(config)# exit
Then type show run to make sure your new interfaces have the new channel- switches in them.

interface GigabitEthernet0/10
 description admin
 switchport access vlan 20
 switchport mode access
 channel-protocol lacp
 channel-group 1 mode active
 spanning-tree portfast
The group number is pretty arbitrary; you can make the number whatever you want for documentation.  Just make sure it's not already used somewhere else on that switch.  Sometimes I have issues getting the channel-protocol line to stick when I choose an int range instead of calling the interface separately.  If this happens to you, simply go back into config t and call each interface separately, give it the channel-protocol line and exit back to config t for the next one, like this:
# config t
(config)# int gi0/10
(config-if)#channel-protocol lacp
(config-if)#exit
(config)#int gi0/11
(config-if)#channel-protocol lacp
(config-if)#exit
(config)#int gi0/12
..And so on.

The switch is done.  We're going to add a few lines to our /etc/rc.conf file and that'll do it for the server.  Pull up /etc/rc.conf with an editor and add:
ifconfig_em0="up"
ifconfig_em1="up"
ifconfig_em2="up"
ifconfig_em3="up"
cloned_interfaces="lagg0"
ifconfig_lagg0="laggproto lacp laggport em0 laggport em1 laggport em2 laggport em3"
ipv4_addrs_lagg0="10.0.10.149/24"
defaultrouter="10.0.10.1"
The ifconfig_lagg0="laggproto lacp laggport em0 laggport em1 laggport em2 laggport em3" entry is all one line.

When you reboot or activate your new network stack your server will now listen on all four network interfaces making your data transfers four times faster than they used to be.  When you're satisfied that everything is good, go back to your Cisco and copy run start in enable mode to ensure you keep your link aggregation after a switch reboot.


Make sure your disk I/O is fast enough to handle the new speeds by enabling ZFS on your server.  This example makes the network so fast that there is no way you could possibly feed information to it from disk fast enough to use it without some major arrays.  

Sunday, May 15, 2011

Using FreeBSD ports effectively.

When I first started with FreeBSD I wasted a lot of time.  I knew where I wanted to go, but not exactly how I wanted to get there.  One thing I did know was using the FreeBSD Ports Collection was definitely the way to go to install most software as it handled dependencies and lots of other issues automatically.

Occasionally, I would find myself installing programs with a huge list of dependencies; if any of these programs required configuration, the whole process would stop and ask you to configure it.  If you have a long list of dependencies, it might not be viable to sit and watch the console during the compilation of all of the ports as this could take hours depending on how much software is to be installed.  A switch for 'make' takes this problem into consideration and pre-configures nearly all dependencies before starting anything.

For example, if you were to install the 'www/apache22' web server and wanted to increase the possibility of an automated install, use the 'config-recursive' switch, like this:
# whereis apache22
apache22: /usr/ports/www/apache22
# cd /usr/ports/www/apache22
# make config-recursive install clean
This will go through the list of dependencies and bring up the 'make config' page for any that require tuning.  This can save a lot of time.

After you install anything via ports, run 'rehash' to make FreeBSD re-read the the files in the path so it knows that your new program is available.

A similar switch for the 'portupgrade' command is '-c'.  If you're updating the whole system and you want to pre-configure the updates try this:
# portupgrade -c -a
If you find that you no longer need a program installed and you want to ensure that no extraneous ports are left over in the system, remove it with 'pkg_deinstall' using the '-R' switch, like this:
# pkg_deinstall -R audio/amarok
It will uninstall 'amarok' and every dependent port for it that is not being used by another port.  If another program requires the same dependency 'pkg_deinstall' will not remove that dependency.

If you have a port that is affected by a security problem but you absolutely must install the port anyway, you can force it with the 'DISABLE_VULNERABILITIES=true' switch, like this:
# make DISABLE_VULNERABILITIES=true config-recursive install clean
Now the port affected by the security problem will not be blocked from install.

The Playstation Network is (back) online.

I rented TRON for the PS3 last night because Final Fantasy XIII was checked out.  I played the single-player campaign mode last night and didn't get out of Chapter 1 even with my saved progress from the last time I rented it.  This morning I fired it up to get some Light Cycle action in the scene after the ZUSE scene when I noticed the system update from this morning.

I updated the PS3 software with the 3.61 which went pretty quickly; I had to change my PSN password- good thinking Sony, and I logged on to a Quick Match.

I was on the Blue Team and Orange had already gotten the tank.  I captured the tank flag from the Orange Team and sat down for some serious damage.  The arena is a Light Cycle track with 5 'flags' to capture.  The team that holds more flags for the longest wins.  Flag #3 is right in the center of the map.  I shambled my way to Flag #3 as my tank piloting skills apparently aren't that great.  I did manage to blast a few Orange fellows off their Light Cycles and drive over a few pedestrian-based Orange Team.

I spent the next 8 consecutive minutes at Flag #3 which after I captured it was blue for the remainder of the game.  I had good Line of Sight on most of the map so I was able to keep the orbiting enemies at bay with suppressive fire.  I got some trophies and top score first match back for the PSN!

Yay.

Viva la PlaystationNetwork.

Saturday, May 14, 2011

A daemon for your every command: cron

Cron is an excellent way to do regular tasks.  It uses 'vi' as its editor, and the only real requirement is that you use full path names like:
/usr/sbin/portsnap
Instead of:
portsnap
From the root user type:
# crontab -e
This will bring up the schedule to be edited.  The schedule follows the columns of minutes, hours, days, months and day of the week and is very customizable.  FreeBSD allows the switches '@daily', '@weekly', etc, not all systems will allow those.  All of the following examples are single lines.

For example, to schedule the download and update of the new ports tree on a FreeBSD system at 4:41am every day, add:
41 4 * * * /usr/sbin/portsnap -I cron &&/usr/sbin/portsnap update
If you wanted to update the ports you set up with ezjail at 5:05am, add:
5 5 * * * /usr/local/bin/ezjail-admin update -P
To zip and archive your system config files at midnight add this on a single line:

@daily /usr/bin/tar zcvf /tank/backup/etc.tar.gz /etc&&/usr/bin/tar zcvf /tank/backup/usrlocaletc.tar.gz /usr/local/etc
Back up your mysql database every night at 3:00am, add:
0 3 * * * /usr/local/bin/mysqldump -hlocalhost -uintranetguy -pd0ntTe3ll intranet > /var/sqlbackup/intranet.sql
And don't forget your weekly scrub for your ZFS array:
@weekly /sbin/zpool scrub tank
Just like 'vi' you can Esc to command mode and exit with a ':' followed by 'wq' and Enter.

Wednesday, May 11, 2011

ezjail is easy, so virtualize.

FreeBSD is an efficient operating system.  It offers great scalability as well in the form of virtual environments referred to as jails.  Jails offer protected areas for services to run that would not normally be able to exist on the same machine.  They offer separate virtual machines, however they do not need to start their own kernel, they simply run processes off the host system's kernel making each virtual machine little more overhead than the services you're starting inside them.

Installing from ports:
# whereis ezjail
ezjail: /usr/ports/sysutils/ezjail
# cd /usr/ports/sysutils/ezjail
# make install clean
This is a fast process.  ezjail is very light. You can rehash when you're done so you can run it immediately.  The following commands will create and modify the config files under /usr/local/etc/ezjail.

If this is a fresh install and you've not done a buildworld yet, you can install jail binaries.  If you have your /usr/src straightened out all up to date with patches and everything use the second method.
Fresh install method 1:
# ezjail-admin install
If you're all set on the /usr/src and you've done makeworld already method 2:
# ezjail-admin update -p -i
The '-p' will give your jails ports and the '-i' skips the build/make for the world.

There are a few details we need to establish before we make the first jail.  You will need a separate IP address for each jail you create.  We're going to assume you know how to identify your network interface; contact me if you need to know how to do this as it would make an excellent post.  We will need to alias the new IP to the network interface.  To make it stick on reboot, we add the alias line to /etc/rc.conf.  The overall process of making a jail is quite easy.  Simply modify a few files and start creating jails.  First turn syslog and sshd to listen only on the host system's IP address.

Assuming you have an IP of 192.168.1.50 on the host system network interface em0 and the IP block of 192.168.1.51-55 is free (at least 51 for this example).

Echo the following statement to /etc/rc.conf for syslog.
# echo 'syslogd_flags="-ss"'>>/etc/rc.conf
Edit /etc/ssh/sshd_config and add the following line near the top:
ListenAddress 192.168.1.50
If you have other services running on the host system, then you'll have to do something similar to their files.

We're going to commit the IP address to the interface now so we can create the jail, then fix it to boot with it in after that.  Like this:
# ifconfig em0 192.168.1.51/32 alias
Note the subnet is CIDR /32 or 255.255.255.255 as opposed to 255.255.255.0 as you would expect with a vanilla class C network.  The subnet on the jails must be different than that of the host system.

We need the IPs established and for the jails to start at boot.  Edit the file /etc/rc.conf and add:
ezjail_enable=YES
ifconfig_em0_alias0="inet 192.168.1.51/32"

Now our jails will start, and our first jail IP address is specified.  This jail is going to be an FTP server called dudesftp and will live under /usr/jails/dudesftp.
# ezjail-admin create dudesftp 192.168.1.51
A bunch of files will go by starting with /usr/jails.  The jail is now created.  Console in and start setting up your new virtual server.  You will want to set up files like /etc/hosts, /etc/resolv.conf and /etc/rc.conf.  You might also want to turn on sshd and create users for inside the new jail.
# ezjail-admin console dudesftp
That will log you on as root after starting the jail for the first time.  Other useful ezjail-admin commands:

ezjail-admin stop JAILNAME      ## stops the jail JAILNAME
ezjail-admin delete (-w) JAILNAME  ## deletes the jail JAILNAME -w deletes the files that make up the jail as well
ezjail-admin reboot JAILNAME  ## reboots the jail JAILNAME