Page 1 of 3 123 LastLast
Results 1 to 10 of 40

Thread: My Notes for Installing Zimbra 7.1.3 on Ubuntu Server 10.04.3 LTS

Hybrid View

  1. #1
    Join Date
    Sep 2011
    Location
    Texas
    Posts
    150
    Rep Power
    4

    Smile My Notes for Installing Zimbra 7.1.3 on Ubuntu Server 10.04.3 LTS

    EDIT 2012-04-26: I am making a new thread covering this same process but with Ubuntu 10.04.4 LTS and Zimbra 7.2.0 OSE. This thread will remain as it is and I will continue to make updates but only for the 7.20 thread.

    MODERATORS: Please do not delete this thread, it contains info related to this specific version which will not be covered in the new thread.


    Greetings and salutations,

    I hope this thread will be helpful to those who follow in my foot steps as well as getting any advice based on what I've done / documented. I am a documentation freak so this will probably grow into a very LARGE step-by-step process. If useful, it will probably be best to convert to a wiki once completed.

    This is a Work-In-Progress topic so I will be updating this thread frequently as I go through this evaluation process. If my administration decides to go with a different solution, my evaluation (and continued documentation) will stop. But until then, I will continue updating my progress all the way to the last person that is converted and using the system.

    High-level overview

    This thread will cover installation of Ubuntu server inside a virtual machine vSphere 4.1 running on ESXi 4.1 servers. It will also cover the installation and configuration of Zimbra OSE and the Zimbra desktop client. This is a merge of several other guides, comments and my own experience of putting it all together in one place in a format that is easy for me to follow and reproduce the same results (yes, I create documentation that I will have to re-read one day because of my bad memory problems!). Please excuse my ignorance since I am fairly new to Linux and Zimbra.

    Company background and environment

    I am in the process of evaluating different mail options for my company. We are a small shop of about 200 employees and are currently using Microsoft Exchange 2003 on a physical server.

    We are looking to either migrate the 2003 server into a virtual machine for vSphere or acquire the new Exchange 2007 and install into a VM or use an external host such as Google Apps or switch to a different mail system (like Zimbra, Mercury Mail or hMailServer). We are not fully utilizing Exchange features and are mainly using it for email, contacts, calendars and shared calendars (for scheduling meeting rooms). We use Active Directory (Windows 2003 domain) to manage users and distribution lists. The desktops are mainly Windows XP and some newer boxes are coming in with Windows 7. We are using Microsoft Outlook with personal folders since we have mailbox size restrictions of 200 MB per mailbox as well as the web interface for people that constantly move from desk-to-desk. iPhones and iPads are also being used as portable devices.

    The email server will be sitting behind a firewall on our LAN. Here is a graphic representation of the network layout:



    About the IT staff

    We are primarily a Microsoft Windows shop and as such, most of us (3) have Microsoft certifications such as MCSE, MCDBA and MCP. None of us are Unix administrators but we are fairly competent in the use of the system from having to support an AIX server so we are comfortable in the VI editor but know very little in terms of Unix hardware and software administration (just basic user stuff, enough to be dangerous)

    The evaluation and deployment process

    I mentioned some of the aspects of Phase 1 and 2 in the section above. I won't go into detail about them mainly because they are very specific and diverse to each organization (and this topic is primarily about Ubuntu/Zimbra). So this topic is mainly covering Phase 3 and touch on some of the later phases as time allows. If my company goes with Zimbra, expect to see more info regarding the later phases.


    • Phase 1 - Define the needs and goals for the project.
    • Phase 2 - Collect information about various solutions and have a high-level overview of features, advantages and disadvantages.
    • Phase 3 - Setup a hands-on demonstration on how the system will accomplish our goals and work in our environment (or a very good flowchart and screenshot presentation).
    • Phase 4 - Setup a fully-functional system for testing, training and migration.
    • Phase 5 - Create Backup / Restore process and documentation
    • Phase 6 - Install client software on all devices
    • Phase 7 - Create and deploy training materials (videos)
    • Phase 8 - Migrate users to new system and setup email forwarding
    • Phase 9 - Decommission old system


    Tools utilized in this process




    Helpful links

    The list below are sources of information that helped me configure this system as well as some places that might be helpful to me later on as this process continues.


    Assumptions

    This documentation will need to make use of some very-specific information that will most-likely be different for each person / location. And as such, I will note some of these in this section. They will be highlighted in red throughout the document as a reminder that you should plug-in your own value rather than actually using my "place-holder" value.

    Under no circumstance should you use that actual values I list below. They are place-holders for the real thing. This is just a checklist template you need to have answered before you start the install process.

    Wherever you see RED in this document, you need to substitute it for what your company uses. Use the list below as a template you need to have answered before you continue.


    • Ubuntu Server name: mail
    • Internet domain: mydomain.com
    • Server domain alias (Windows): work
    • Server fully-qualified domain: work.mydomain.com
    • Ubuntu Server IP address: 192.168.107.14
    • Ubuntu Server IP subnet mask: 255.255.255.0
    • Ubuntu Server IP gateway: 192.168.107.1
    • Internal DNS Server 1: 192.168.107.23
    • Internal DNS Server 2: 192.168.107.212
    • Internal Active Directory: 192.168.107.212
    • External ISP DNS Server 1: 200.100.10.1
    • External ISP DNS Server 2: 200.100.10.2
    • External IP to Domain: 198.100.100.100
    • Ubuntu Admin ID: administrator
    • Ubuntu Admin Password: myadminpass
    • Ubuntu Root Password: myrootpass
    • Zimbra Admin Password: myzimbrapass


    I also assume the reader knows how to use the VI editor. If not, you will need to beef up your skill set or use a different editor in place of it.
    Last edited by LHammonds; 05-03-2012 at 11:35 PM.
    Type su - zimbra -c "zmcontrol -v" to get your version and copy that into your profile (more info here)

  2. #2
    Join Date
    Sep 2011
    Location
    Texas
    Posts
    150
    Rep Power
    4

    Smile Analysis and Design

    Analysis and Design

    The user base will probably not exceed 300 any time soon based on the company size over the last 75 years.

    A single server design is chosen for this deployement based on the amount of current users (~200)

    The Ubuntu Server Long-Term Support (LTS) is free but we have the option of buy support and that is the main reason this server was selected.

    Zimbra OSE is also free but we have the option of buying support by upgrading to the Network Edition.

    The Ubuntu LTS / Zimbra OSE combination makes for an excellent choice to evaluate the products (without incurring licensing fees) as well as having an upgrade path to obtain support.

    Much of how the system will run is based on how you install / configure Ubuntu before you ever install Zimbra.

    The largest decision over the configuration of Ubuntu seems to be how the hard drive space is sliced up (partitioned). I lot of my time was spent researching and learning the various options when it comes to the design layout of the storage.

    The Zimbra documentation's recommendation for Ubuntu in this area basically says to put everything on one LVM/Volume. I can see how tech support would want to favor a setup like this because it makes it easier to troubleshoot. However, I would rather make use of a design that allows for dynamic growth and fine-tuning if need be. I also do not like being caught offguard with a scenario where space is filled up with immediate option other than deleting files. Longterm life and growth of the system as well as budgeting concerns have to be taken into consideration.

    Based on my observations my first Zimbra install, I decided that a single volume wasn't a good idea, especially having continual-growth of a folder that is on the root volume. I would rather contain the root volume to mainly just static data that won't grow much and push the other folders that are dynamic into their own volumes. I also want to configure it where the file systems are not taking up 100% of the logical volume. This will allow me (through automated scripts) to grow the file system as needed and give me some time to add more drives if necessary or shrink other volumes to get more space.

    Here are my thoughts on how to slice up the space.
    • Boot - This will remain static in size. It is also the only space residing outside the Logical Volume Manager (LVM)
    • Root volume - Operating system and everything else which should remain fairly static. (e.g. file system will take up entire logical volume)
    • Swap volume - This will remain static in size. However, if amount of RAM is adjusted, this should be adjusted as well. (e.g. file system will take up entire logical volume)
    • Opt volume - This Zimbra storage will continue to grow over time.
    • Backup volume - This will contain a local backup of the Opt volume and individually compressed mailbox archives. So space needs to be around double /opt/zimbra.
    • Temp volume - This location will be used to hold data during backups, archives and restores and should be about double the size of opt/zimbra.
    • Offsite Storage - This will be handled elsewhere but will be mounted on this server.


    My estimated mailbox store will be about 65 GB so the initial files space with be 75 GB. This documentation will be based on this amount. Adjust these numbers to fit your scenario as necessary.

    To get a good idea of the hard drive layout and to understand the process better, I had to draw out the design and after many revisions and re-thinking, here is what it ended up looking like:



    This design allows space to be immediately added to the expected-growth volumes (opt, backup, temp). Later on, I will have a script that watches each volume and will automatically allocate additional space as needed and send a notification email stating what has been done and how much space is still free to allocate...maybe even have a countdown of how many more times the script will be able to auto-adjust before additional hard drives need to be added.

    The two extra 100 GB VMDK drives are not actually added during this initial setup but I will document later how to add them for the scenario of needing more space.

    I also have a ToDoList project file I've been using to help me stay on task with this monster so if anyone would like a copy, just ask and I'll post what I have for download. (totally not expecting anyone to see this line in the wall of text...hehehe)

    Virtual Machine Settings

    Virtual Manager: VMware vSphere Client 4.1
    Virtual Host: VMware ESXi Server 4.1


    • Configuration: Custom
    • Name: ZimbraMail
    • Datastore: MainOffice-LUN0
    • Virtual Machine Version: 7
    • Guest Operating System: Linux, Version: Ubuntu Linux (64-bit)
    • Number of virtual processors: 1
    • Memory Size: 2048 MB
    • Number of NICs: 1
    • NIC 1: VM Network
    • Adapter: E1000, Connect at Power On: Checked
    • SCSI controller: LSI Logic Parallel
    • Select a Disk: Create a new virtual disk
    • Create a Disk: 650 GB, No thin provisioning, No cluster features, Store with the virtual machine
    • Advanced Options: Virtual Device Node = SCSI (0:0)
    • Remove Floppy Drive
    • Mount CD/DVD Drive to Ubuntu ISO (ubuntu-10.04.3-server-amd64.iso). Make sure CD/DVD is set to Connect at power on
    • Set boot options to Force BIOS Setup so you can set CDROM to boot before the Hard Disk




    Install PuTTY

    The 1st time I installed Ubuntu and Zimbra, I used the console for everything but it was painfully slow to view man (manual) pages and navigating in VI (text editor). However, I found out that PuTTY is a far better solution for your Ubuntu console because it handles the screen draws much faster and allows for scrolling and copying text.

    Download the portable edition and run the install...except it doesn't really "install" like a normal program, it simply extracts to a specified folder and will run from that folder even if you put it on a USB stick and carry over to a new computer (requires no install to run and thus leaves a very small footprint on your system)


    1. Start PuTTY
    2. Type the following and click the Save button:
      Host Name: mail (or the IP such as 192.168.107.14)
      Port: 22
      Connection type: SSH
      Saved Sessions: zimbra
    3. Now all you have to do is double-click on the zimbra session and it will connect to your server (when online).
    Last edited by LHammonds; 11-04-2011 at 10:42 PM.
    Type su - zimbra -c "zmcontrol -v" to get your version and copy that into your profile (more info here)

  3. #3
    Join Date
    Sep 2011
    Location
    Texas
    Posts
    150
    Rep Power
    4

    Smile Install Ubuntu Server 10.04.3 LTS

    Install Ubuntu Server

    NOTE: During the setup process, we are going to use the root account to make things easier. Later on, it will be best to use the "sudo" command to only temporarily grant root access rather than logging in with root access.


    1. Power on the Virtual Machine (VM)
    2. Press {ENTER} to accept English
    3. Select Install Ubuntu Server {ENTER}
    4. Press {ENTER} to accept English
    5. Press {ENTER} to accept United States
    6. Select No to not detect keyboard layout
    7. Press {ENTER} to accept USA
    8. Press {ENTER} to accept USA
    9. Type mail {ENTER} (this is your hostname)
    10. Press {ENTER} to accept detected time zone (America/Chicago)
    11. Select Manual {ENTER}
    12. Select SCSI3 (0,0,0) (sda) - 697.9 GB VMware Virtual disk {ENTER}
    13. Select Yes to create new empty partition table, {ENTER}
    14. Select pri/log 697.9 GB FREE SPACE {ENTER}
    15. Select Create a new partition {ENTER}
    16. Type 200 MB, {ENTER} (NOTE: This will be the /boot partition)
    17. Select Primary {ENTER}
    18. Select Beginning {ENTER}
    19. Select Use as: Ext4 journaling file system {ENTER}
    20. Select Ext2 file system {ENTER}
    21. Select Mount point: / {ENTER}
    22. Select /boot - static files of the boot loader {ENTER}
    23. Select Bootable flag: off {ENTER} (NOTE: This toggles it on)
    24. Select Done setting up the partition {ENTER}
    25. Select Configure the Logical Volume Manager {ENTER}
    26. Select Yes to write change to disks and configure LVM, {ENTER}
    27. Select Create volume group {ENTER}
    28. Type LVG {ENTER}
    29. Select /dev/sda free #1 (697731MB; FREE SPACE), {SPACEBAR}, {ENTER}
    30. Select Yes to write change to disks and configure LVM, {ENTER}
    31. Select Create logical volume {ENTER}
    32. Select LVG (697726MB) {ENTER}
    33. Type swap {ENTER}
    34. Type 8G {ENTER} (NOTE: This is double the amount of RAM)
    35. Select Create logical volume {ENTER}
    36. Select LVG (689728MB) {ENTER}
    37. Type bak {ENTER}
    38. Type 250G {ENTER}
    39. Select Create logical volume {ENTER}
    40. Select LVG (439730MB) {ENTER}
    41. Type opt {ENTER}
    42. Type 75G {ENTER}
    43. Select Create logical volume {ENTER}
    44. Select LVG (314732MB) {ENTER}
    45. Type temp {ENTER}
    46. Type 250G {ENTER}
    47. Select Create logical volume {ENTER}
    48. Select LVG (64734MB) {ENTER}
    49. Type root {ENTER}
    50. Type 4G {ENTER}
    51. Select Finish {ENTER}
    52. Select #1 8.0 GB directly under LVM VG LVG, LV swap, {ENTER}
    53. Select Use as: do not use {ENTER}
    54. Select swap area {ENTER}
    55. Select Done setting up the partition {ENTER}
    56. Select #1 4.0 GB directly under LVM VG LVG, LV root, {ENTER}
    57. Select Use as: do not use {ENTER}
    58. Select Ext4 journaling file system {ENTER}
    59. Select Mount point: none {ENTER}
    60. Select / - the root file system {ENTER}
    61. Select Done setting up the partition {ENTER}
    62. Select #1 250.0 GB directly under LVM VG LVG, LV bak, {ENTER}
    63. Select Use as: do not use {ENTER}
    64. Select Ext4 journaling file system {ENTER}
    65. Select Mount point: none {ENTER}
    66. Select Enter manually {ENTER}
    67. Type /var/backup {ENTER}
    68. Select Label: none {ENTER}
    69. Type backup {ENTER}
    70. Select Done setting up the partition {ENTER}
    71. Select #1 125.0 GB directly under LVM VG LVG, LV opt, {ENTER}
    72. Select Use as: do not use {ENTER}
    73. Select Ext4 journaling file system {ENTER}
    74. Select Mount point: none {ENTER}
    75. Select /opt - add-on application software packages {ENTER}
    76. Select Label: none {ENTER}
    77. Type zimbra {ENTER}
    78. Select Done setting up the partition {ENTER}
    79. Select #1 250.0 GB directly under LVM VG LVG, LV temp, {ENTER}
    80. Select Use as: do not use {ENTER}
    81. Select Ext4 journaling file system {ENTER}
    82. Select Mount point: none {ENTER}
    83. Select Enter manually {ENTER}
    84. Type /var/temp {ENTER}
    85. Select Label: temp {ENTER}
    86. Type backup {ENTER}
    87. Select Done setting up the partition {ENTER}
    88. Here is what the screen looks like at this point: Partitions
    89. Select Finish partitioning and write changes to disk {ENTER}
    90. Select Yes to write changes to disk, {ENTER}
    91. Type Administrator, {ENTER} for the full name (NOTE: Do not use "zimbra" as a choice here)
    92. Press {ENTER} to accept the default of the lowercase name of administrator
    93. Type myadminpass, {ENTER}, myadminpass, {ENTER}
    94. Select No, {ENTER} to not encrypt your home directory
    95. Press {ENTER} to accept a blank line for the HTTP proxy
    96. Select Install security updates automatically, {ENTER}
    97. Highlight only OpenSSH server and press {SPACEBAR} to enable, {ENTER} to continue. NOTE: This allows us to use PuTTY after installation to connect to the server.
    98. Select Yes, {ENTER} to install GRUB boot loader to the master boot record
    99. Installation Complete - from the VM menu, select VM --> Edit Settings and select CD/DVD Drive 1 and change to "Client Device" which will effectively remove the ISO. Now press {ENTER} to reboot.


    Initial Configurations


    1. At the console login prompt, login with your administrator account (administrator / myadminpass)
    2. At the $ prompt, type sudo passwd root {ENTER}, type your administrator password (myadminpass), it will ask for a new password, type myrootpass and verify. NOTE: This enables the root account.
    3. At the $ prompt, change to the super user root account by typing su {ENTER} and then provide the new root password you just configured.
    4. Type vi /etc/network/interfaces {ENTER} and change the following: (We need to change the network interface card (NIC) from using DHCP to a static IP)

      From:
      Code:
      iface eth0 inet dhcp
      To:
      Code:
      iface eth0 inet static
      address 192.168.107.14
      netmask 255.255.255.0
      gateway 192.168.107.1
      network 192.168.107.0
      broadcast 192.168.107.255
      NOTE #1: You may need to manually remove the DHCP record (lease) associated to this Ubuntu server from your DHCP server so the correct IP can be found by other machines on the network. This can be avoided by temporarily configuring the VM Network Adapter connection to be "Host Only Network" instead of "VM Network" so the server is isolated during setup...at least until you reach the testing of the static IP below.

      NOTE #2: You might also need to manually add a HOST(A) record to your Windows DNS server (for mail.mydomain.com and mail.work.mydomain.com)
    5. Restart the network by typing /etc/init.d/networking restart
    6. Sanity check! Type ifconfig and make sure the settings are correct. Then type ping Google or similar and see if ping works.
    7. Shutdown and power off the server by typing shutdown -P now {ENTER}
    8. At this point forward, you can use PuTTY to access the console rather than the console itself for better performance, ability to scroll, etc.
    9. In VM menu, select VM --> Snapshot --> Take Snapshot. Give it a name like STEP 1 and description of Ubuntu Server 10.04.3 LTS, clean install, Static IP: 192.168.107.14 and click OK


    Software Configurations

    1. Start the Ubuntu server and connect using PuTTY.
    2. At the login prompt, login with your administrator account (administrator / myadminpass) and then type su and the root password (myrootpass)
    3. At the $ prompt, type aptitude -y install vim-nox for use instead of the built-in VI editor. more info
    4. At the $ prompt, type aptitude -y install bind9 to install a local DNS server.
    5. At the $ prompt, type aptitude -y install p7zip-full to install 7-zip archive utility.
    6. Type dpkg-reconfigure dash and answer No
    7. Remove AppArmor to avoid problems by typing the following:
      Code:
      /etc/init.d/apparmor stop
      update-rc.d -f apparmor remove
      aptitude remove apparmor apparmor-utils
    8. Reboot the server by typing reboot


    VMware Tools

    If you are installing under VMware like me, be sure to install the tools to insure maximum performance in a virtual environment.

    1. In the VM toolbar for the VM, click Guest, Install VMware Tools
    2. At the Ubuntu prompt, type the following:
      Code:
      
      mkdir /mnt/cdrom
      mount /dev/cdrom /mnt/cdrom
      ls /mnt/cdrom
      tar zxvf /mnt/cdrom/VMwareTools-x.x.x-xxxx.tar.gz -C /tmp/   (use the correct numbers version discovered from the list command in the prior step)
      cd /tmp/vmware-tools-distrib/
      ./vmware-install.pl -d
      reboot
      


    Configure Ubuntu for File Sharing

    This file sharing section is optional but can be handy if you need to swap files between the Linux server and a Windows machine.

    This documentation will utilize this share for passing pre-configured files (configs, scripts, etc.) to make it faster/easier during installation.

    1. Start the Ubuntu server and connect using PuTTY.
    2. At the login prompt, login with your administrator account (administrator / myadminpass) and then type su and the root password (myrootpass)
    3. Install Samba by typing aptitude -y install samba smbfs (NOTE: To share a folder with Windows, you just need the samba package, to connect to a Windows share, you need both samba and smbfs)
    4. Type the following commands:
      Code:
      cp /etc/samba/smb.conf /etc/samba/smb.conf.bak
      mkdir -p /srv/samba/share
      chown nobody:nogroup /srv/samba/share/
    5. Edit the configuration file by typing vi /etc/samba/smb.conf
    6. Change workgroup = WORKGROUP to workgroup = work (you are using the domain alias)
    7. Change:
      Code:
      #   security = user
      to:
      Code:
         security = user
    8. Add the following section to the end of the file:
      Code:
      [share]
      comment = Ubuntu File Server Share
      path = /srv/samba/share
      browsable = yes
      guest ok = yes
      read only = no
      create mask = 0755
    9. Save and exit the file.
    10. Restart the samba services to utilize the new configuration by typing:
      Code:
      restart smbd
      restart nmbd
    11. You should now be able to click Start --> Run and type \\mail or \\192.168.107.14 {ENTER} and see an explorer window with a Share folder. Drag-n-drop a file into the Share folder. If it worked, it will not display an error message and you should be able to view it from the server by typing ls -l /srv/samba/share/
    12. Shutdown and power off the server by typing shutdown -P now {ENTER}
    13. In VM menu, select VM --> Snapshot --> Take Snapshot. Give it a name like STEP 2 and description of Ubuntu Server 10.04.3 LTS, File share configured, Static IP: 192.168.107.14. The Snapshot Manager should now have a nice hierarchy of snapshots (STEP 1 --> STEP 2 --> You are here)


    Configure Windows Remote Mount Point

    The remote offsite location is a Windows 2008 server that has a vast amount of hard drive space and currently backs up other servers.

    Part of the backup process will be to write files to a mounted folder to a Windows share.

    First, let's document the variables for this solution below and highlight them in red throughout the document for easy identification.

    The values below are merely samples which you need to change in order to match your environment:

    Windows AD Domain Name: work
    Windows Server Name: SRV-Backup
    Windows Server IP: 192.168.107.218
    Windows Share Name: zimbra
    Windows Physical Share Location: D:\Zimbra\
    Windows Share ID: zimbrashare
    Windows Share Password: zimbrapassword

    Create a share on a Windows 2008 server


    1. In Windows Explorer, right-click on the D:\Zimbra folder and select Properties
    2. Click the Sharing tab
    3. Click the Advanced Sharing button
    4. Place a checkmark beside Share this folder
    5. Change the Share name to zimbra
    6. Set the Comment to Zimbra Backup
    7. Click the Permissions button
    8. Select Everyone and click the Remove button
    9. Click the Add button
    10. Type in your zimbra share account: work\zimbrashare and click the Check Names button, click OK
    11. Place a checkmark for Allow Full Control and click OK, click OK, click OK


    Create an NFS mount to the Windows 2008 server

    Connecting to a Windows share requires the samba and smbfs packages to be installed. If you do not have them, type aptitude -y install samba smbfs


    1. At the login prompt, login with your administrator account (administrator / myadminpass) and then type su and the root password (myrootpass)
    2. Type the following commands:
      Code:
      
      mkdir -p /mnt/zmbackup
      touch /etc/cifspw
      chmod 0600 /etc/cifspw
      echo -e "username=work\zimbrashare\npassword=zimbrapassword"
      
    3. Type vi /etc/hosts and add the following line anywhere in the file:
      Code:
      
      192.168.107.218	srv-backup
      
    4. At this point, you might want to type ping srv-backup to make sure you typed the right IP address as well as seeing a good response.
    5. To mount this system for backups, type the following command:
      Code:
      
      mount -t cifs //srv-backup/zimbra /mnt/zmbackup --options nouser,rw,nofail,noatime,noexec,credentials=/etc/cifspw
      
    6. To dismount the windows share, type the following command:
      Code:
      
      umount /mnt/zmbackup
      


    The scripts will call a common mount and unmount function to connect to this share only when needed.

    However, if you would rather have it mounted all the time (even after a reboot), do the following (but remember to not use the mount/umount functions in the scripts later):


    1. Type vi /etc/fstab and add the following line at the bottom of the file:
      Code:
      //srv-backup/zimbra	/mnt/zmbackup	cifs nouser,rw,nofail,noatime,noexec,credentials=/etc/cifspw	0	0
    2. Type mount -a and if it does not spew out any error messages, it will quietly mount the share.
    3. To test it, type cp /etc/hosts /mnt/zmbackup/hosts.txt and look on the Windows server and see if the file shows up. Then type rm /mnt/zmbackup/hosts.txt and verify that the file was deleted on the windows server.
    4. If you need to unmount it, simply type umount /mnt/zmbackup and it will remain unmounted until you reboot. To make it permanent, you need to remove the line you added in the /etc/fstab file.
    Last edited by LHammonds; 01-23-2012 at 04:22 PM.
    Type su - zimbra -c "zmcontrol -v" to get your version and copy that into your profile (more info here)

  4. #4
    Join Date
    Sep 2011
    Location
    Texas
    Posts
    150
    Rep Power
    4

    Smile Configure DNS

    Configure Domain Resolution (DNS)


    1. Connect to the server using PuTTY
    2. At the login prompt, login with your administrator account (administrator / myadminpass) and then type su and the root password (myrootpass)
    3. Sanity check! Make sure BIND is running. Type /etc/init.d/bind9 status
    4. At this point, you can save yourself a lot of typing if you have a copy of the configuration files on your PC and simply copy them to the share. Then you can set the appropriate file permissions and copy them where they need to go. But if not and this is your 1st time installing the server, here are the details for configuring by hand.
    5. Edit the hosts by typing vi /etc/hosts and change the following:

      From:
      Code:
      127.0.0.1	localhost
      127.0.1.1	mail.work.mydomain.com mail
      To:
      Code:
      127.0.0.1	localhost.localdomain localhost
      192.168.107.14	mail.mydomain.com mail
    6. Edit the DNS servers by typing vi /etc/resolv.conf and set it to the following:

      Code:
      nameserver 127.0.0.1
      nameserver 192.168.107.23
      nameserver 192.168.107.212
      nameserver 200.100.10.1
      nameserver 200.100.10.2
      domain mydomain.com
      search mydomain.com
    7. Type the following commands:

      Code:
      mkdir /var/cache/bind/internal
      mkdir /var/cache/bind/external
      touch /var/cache/bind/internal/db.mydomain.com
      touch /var/cache/bind/internal/db.107.168.192.in-addr.arpa
      touch /var/cache/bind/external/db.mydomain.com
      cp /etc/bind/named.conf.options /etc/bind/named.conf.options.bak
      cp /etc/bind/named.conf.local /etc/bind/named.conf.local.bak
      cp /etc/bind/named.conf.default-zones /etc/bind/named.conf.default-zones.bak
    8. Stop the DNS server by typing /etc/init.d/bind9 stop
    9. Edit the DNS options by typing vi /etc/bind/named.conf.options and set the following:
      Code:
      options {
      	directory "/var/cache/bind";
      	query-source address * port 53;
      	forwarders {
      		200.100.10.1; 200.100.10.2;
      	};
      	auth-nxdomain no;	# conform to RFC1035
      	listen-on-v6 { any; };
      };
      NOTE: The IP addresses are public IP addresses of the DNS servers you use in the outside world. The query-source address line is to allow your machine to hit the DNS if oddball DNS ports are blocked. You can leave it commented if you do not need it.
    10. Restart the network by typing /etc/init.d/networking restart
    11. Type the following vi /etc/hostname and add the following text, save and exit:

      Code:
      mail.mydomain.com
    12. To check results, type hostname and then hostname -f which should result with:

      Code:
      mail
      mail.mydomain.com
    13. Edit the local DNS file by typing vi /etc/bind/named.conf.local and set the following:
      Code:
      acl internals {
              127.0.0.0/8;
              192.168.107.0/24;
      };
      
      view "internal" {
              match-clients { internals; };
              recursion yes;
              zone "mydomain.com" {
                      type master;
                      file "/var/cache/bind/internal/db.mydomain.com";
              };
              zone "107.168.192.in-addr.arpa" {
                      type master;
                      file "/var/cache/bind/internal/db.107.168.192.in-addr.arpa";
              };
      };
      
      view "external" {
              match-clients { any; };
              recursion no;
              zone "mydomain.com" {
                      type master;
                      file "/var/cache/bind/external/db.mydomain.com";
              };
      };
    14. Edit the internal reverse zone file by typing vi /var/cache/bind/internal/db.107.168.192.in-addr.arpa and set the following:

      Code:
      $TTL 86400
      @       IN      SOA     mail.mydomain.com.  root.mydomain.com. (
                      201109231448    ; Serial (increment after edit)
                      604800          ; Refresh
                      86400           ; Retry
                      2419200         ; Expire
                      86400)          ; Negative Cache TTL
      	NS	mail.mydomain.com.
      1	PTR	mail.mydomain.com.
    15. Edit the internal zone file by typing vi /var/cache/bind/internal/db.mydomain.com and set the following:

      Code:
      ; mydomain.com
      $TTL    86400
      @       IN      SOA             mail.mydomain.com. root.mydomain.com. (
                                      201109231335    ; Serial (increment after edit)
                                      604800          ; Refresh
                                      86400           ; Retry
                                      2419200         ; Expire
                                      604800)         ; Negative Cache TTL
      ; Define the nameservers and the mail servers
      @       IN      NS              192.168.107.14.
              IN      MX      10      mail.mydomain.com.
              IN      A               192.168.107.14
      mail    IN      A               192.168.107.14
    16. Edit the external zone file by typing vi /var/cache/bind/external/db.mydomain.com and set the following:

      Code:
      ; mydomain.com
      $TTL    86400
      @       IN      SOA             mail.mydomain.com. root.mydomain.com. (
                                      201109231335    ; Serial (increment after edit)
                                      604800          ; Refresh
                                      86400           ; Retry
                                      2419200         ; Expire
                                      604800)         ; Negative Cache TTL
      ; Define the nameservers and the mail servers
      @       IN      NS              198.100.100.100.
              IN      MX      10      mail.mydomain.com.
              IN      A               198.100.100.100
      mail    IN      A               198.100.100.100
    17. Since views were used, they also need to be used in the default zone. Type vi /etc/bind/named.conf.default-zones and set the following:

      Code:
      // prime the server with knowledge of the root servers
      
      acl internals-default {
      	127.0.0.0/8;
      	192.168.107.0/24;
      	192.168.106.0/24;  // Keep adding all your internal subnets here.
      };
      
      view "internal-default" {
              match-clients { internals-default; };
              recursion yes;
      
      	zone "." {
      		type hint;
      		file "/etc/bind/db.root";
      	};
      
      // be authoritative for the localhost forward and reverse zones, and for
      // broadcast zones as per RFC 1912
      
      	zone "localhost" {
      		type master;
      		file "/etc/bind/db.local";
      	};
      
      	zone "127.in-addr.arpa" {
      		type master;
      		file "/etc/bind/db.127";
      	};
      
      	zone "0.in-addr.arpa" {
      		type master;
      		file "/etc/bind/db.0";
      	};
      
      	zone "255.in-addr.arpa" {
      		type master;
      		file "/etc/bind/db.255";
      	};
      };
    18. Ensure the correct ownership and permissions of all config files:
      Code:
      chown root:bind /var/cache/bind/internal/*
      chown root:bind /var/cache/bind/external/*
      chmod 0644 /var/cache/bind/internal/*
      chmod 0644 /var/cache/bind/external/*
    19. Start the DNS server by typing /etc/init.d/bind9 start
    20. That was a lot of typing and room for error so check the log for any errors: vi /var/log/daemon.log
    21. Sanity check! At this point, if you type nslookup mail.mydomain.com, you should see that your internal DNS server (127.0.0.1) returned the result of your internal IP address (192.168.107.14 for your FQDN of mail.mydomain.com)
    22. Sanity check! Type dig mydomain.com mx and make sure you see a status of NOERROR along with an MX record to your FQDN, NS record for your internal IP and an A record your FQDN to your internal IP.
    23. Shutdown and power off the server by typing shutdown -P now {ENTER}
    24. In VM menu, select VM --> Snapshot --> Take Snapshot. Give it a name like STEP 3 and description of Ubuntu Server 10.04.3 LTS, Split-DNS configured, Static IP: 192.168.107.14. Click OK. The Snapshot Manager should now have a nice hierarchy of snapshots (STEP 1 --> STEP 2 --> STEP 3 --> You are here)


    Final Ubuntu Changes
    1. Start the Ubuntu server and connect using PuTTY.
    2. At the login prompt, login with your administrator account (administrator / myadminpass) and then type su and the root password (myrootpass)
    3. Update the package database by typing aptitude update
    4. Install the latest updates by typing aptitude -y safe-upgrade
    5. Shutdown and power off the server by typing shutdown -P now {ENTER}
    6. In VM menu, select VM --> Snapshot --> Take Snapshot. Give it a name like STEP 4 and description of Ubuntu Server 10.04.3 LTS, all patches applied, Static IP: 192.168.107.14. The Snapshot Manager should now have a nice hierarchy of snapshots (STEP 1 --> STEP 2 --> STEP 3 --> STEP 4 --> You are here)
    Last edited by LHammonds; 11-04-2011 at 10:43 AM.
    Type su - zimbra -c "zmcontrol -v" to get your version and copy that into your profile (more info here)

  5. #5
    Join Date
    Sep 2011
    Location
    Texas
    Posts
    150
    Rep Power
    4

    Smile Install and Configure Zimbra and SSL

    Install Zimbra

    NOTE: Install Zimbra by typing "./install.sh" and uninstall by typing "./install.sh -u"

    Prerequisite packages:
    • NPTL
    • sudo-1.7.2p1-1ubuntu5.3
    • libidn11-1.15-2
    • libpcre3-7.8-3build1
    • libgmp3c2-2:4.3.2+dfsg-1ubuntu1
    • libexpat1-2.0.1-7ubuntu1
    • libstdc++6-4.4.3-4ubuntu5
    • libperl5.10-5.10.1-8ubuntu2.1


    Suggested prerequisites:
    • perl-5.10.1
    • sysstat
    • sqlite3


    Install Procedure:
    1. Start the Ubuntu server and connect using PuTTY.
    2. At the login prompt, login with your administrator account (administrator / myadminpass) and then type su and the root password (myrootpass)
    3. Download the Open Source Edition from Open Source Edition Downloads: Enterprise Messaging and Collaboration Software by Zimbra

      Method #1 - Download from your PC

      A. Download the .tgz file and copy it to the Ubuntu share --> \\mail\share or \\192.168.107.14\share
      B. Once copied to the server, access the console and type the following:

      Code:
      mv /srv/samba/share/zcs* /temp
      Method #2 - Download directly from the server

      A. Obtain the download URL from the Zimbra OSE page
      B. Type the following commands on the server console (using the correct URL)

      Code:
      cd /temp
      wget http://files.zimbra.com/downloads/7.1.3_GA/zcs-7.1.3_GA_3346.UBUNTU10_64.20110928134610.tgz
    4. Extract the archive by typing the following commands:

      Code:
      mkdir /var/temp/install
      tar -C /var/temp/install --strip-components=1 -xzf /var/temp/zcs*
    5. Start the installation program by typing the following:

      Code:
      cd /var/temp/install
      ./install.sh
    6. Agree to license agreement? Press y {ENTER}
    7. If you are missing any prerequisites, exit the installation and install them. You can install all at one time by separating each name with a space after apt-get install such as the following:
      Code:
      aptitude -y install sysstat sqlite3
    8. Install zimbra-ldap? Press y {ENTER}
    9. Install zimbra-logger? Press y {ENTER}
    10. Install zimbra-mta? Press y {ENTER}
    11. Install zimbra-snmp? Press y {ENTER}
    12. Install zimbra-store? Press y {ENTER}
    13. Install zimbra-apache? Press y {ENTER}
    14. Install zimbra-spell? Press y {ENTER}
    15. Install zimbra-memcached? Press n {ENTER} (if multi-server, press y instead)
    16. Install zimbra-proxy? Press n {ENTER} (if multi-server, press y instead)
    17. The system will be modified. Continue? Press y {ENTER}
    18. DNS ERROR resolving MX for localhost.localdomain. Change domain name? Press y {ENTER}
    19. Now we put the correct domain name in so type mydomain.com {ENTER}
    20. You are presented a menu for resolving unconfigured options, press 3 {ENTER}
    21. Select Admin password, press 4 {ENTER}. Then type your new password (myzimbrapass) {ENTER}
    22. Press r {ENTER} for previous menu
    23. Press a {ENTER} to apply changes.
    24. Press y {ENTER}, {ENTER} to save configuration (/opt/zimbra/config.9066)
    25. The system will be modified - continue? Press y {ENTER}
    26. Notify Zimbra of your installation? Press n {ENTER} (feel free to answer yes if this is not a test system)
    27. Press {ENTER} to exit setup. NOTE: Log files placed in /opt/zimbra/log
    28. Shutdown and power off the server by typing the following:
      Code:
      /etc/init.d/zimbra stop
      shutdown -P now
    29. In VM menu, select VM --> Snapshot --> Take Snapshot. Give it a name like STEP 5 and description of Ubuntu Server 10.04.3 LTS, Zimbra 7.1.3 OSE installed, Static IP: 192.168.107.14. The Snapshot Manager should now have a nice hierarchy of snapshots (STEP 1 --> STEP 2 --> STEP 3 --> STEP 4 --> STEP 5 --> You are here)


    Admin Console and Initial Test


    1. Start the Ubuntu server.
    2. Access the webmail control panel by opening a web browser and typing this in the address bar: https://192.168.107.14:7071
    3. If your browser barks about an untrusted connection, tell it to continue anyway and add an exception for it so it will not have a problem with it next time.
    4. Login as admin@mydomain.com / myrootpassword
    5. Create a new user account.
    6. When done creating a new user, open a new browser tab and access: http://192.168.107.14/ and login with your new user account. See if you can send an email! If it does not work, well, what can I say...you followed the advice of a Linux newbie.


    Scripted sendmail


    My scripts heavily reply upon the ability to send email notifications and this step (along with installing heirloom-mailx before Zimbra) will enable that ability.
    1. At the login prompt, login with your administrator account (administrator / myadminpass) and then type su and the root password (myrootpass)
    2. To configure the sendmail command to work with Zimbra, type the following:
      Code:
      update-alternatives --install /usr/sbin/sendmail mta-send /opt/zimbra/postfix/sbin/sendmail 25
    3. Test sendmail by typing the following and then check your admin email to see if it is there:
      Code:
      sendmail -t{ENTER}
      to:admin@mydomain.com{ENTER}
      from:webmaster@mydomain.com{ENTER}
      subject: Test from Ubuntu sendmail{ENTER}
      {ENTER}
      Testing 1-2-3{ENTER}
      .{ENTER}


    Zimbra and SSL Encryption

    I do not see a reason not to use SSL, especially if your user accounts and passwords match other systems such as Active Directory. A compromised email password can also compromise your network in that case.

    With that in mind, this is what I have done to make sure it is used at my location.

    If you just installed Zimbra, the installation process created a self-signed certificate.

    Step #1 - Enable SSL as the primary method of logging onto your server:


    1. At the login prompt, login with your administrator account (administrator / myadminpass) and then type su and the root password (myrootpass)
    2. At the server console, type the following to convert webmail to use encrypted https instead of http:
      Code:
      su - zimbra -c "zmtlsctl https"
    3. For additional documentation, here is how you would switch back to non-SSL mode:
      Code:
      su - zimbra -c "zmtlsctl http"
    4. For additional documentation, here is how you could use either SSL or non-SSL mode:
      Code:
      su - zimbra -c "zmtlsctl mixed"
    5. Type reboot to reboot the server for the HTTPS change to take effect.


    Step #2 - Export the certificate for Windows.

    The certificate on the Zimbra server cannot be directly used by Windows and needs to be converted into a format that can be used. Do so using the following commands:
    Code:
    openssl x509 -in /opt/zimbra/ssl/zimbra/ca/ca.pem -out /srv/samba/share/cacert.der -outform DER
    chmod 0644 /srv/samba/share/cacert.der
    Step #3 - Import the certificate on Windows.

    For Windows machines, you might need to install the certificate manually to avoid Internet Explorer, MS Outlook and Google Chrome issues with self-signed certificates.

    Here are two methods for doing so.

    Method A - Domain Group Policy

    If you have a Windows domain, this is a very easy process to get all your machines to automatically accept the self-signed certificate on your Zimbra server.


    1. On the domain controller, open Active Directory Users and Computers
    2. Right-click on your domain and select Properties
    3. Select the Group Policy tab
    4. Select the Default Domain Policy and click the Edit button
    5. Expand Computer Configuration --> Windows Settings --> Security Settings --> Public Key Policies
    6. Right-click on Trusted Root Certification Authorities and click Import
    7. Import Wizard - Click Next
    8. Type the path to the cacert.der from your Zimbra server or click Browse (if you browse, you will need to change the file type to All Files in order to see the certificate file) and then click Next
    9. Select Place all certificates in the following store --> Trusted Root Certification Authorities and click Next, Finish
    10. The import was successful - Click OK
    11. You should now see your mail server domain in the list. Example: mail.mydomain.com
    12. Close Group Policy Object Editor and any other windows you opened

    Any Windows machine on your domain should now be able to open Internet Explorer and visit your SSL-enabled mail server without complaining about the self-signed certificate. Same goes for Outlook, Google Chrome and others. You may need to logout and log back in for the policy to take effect on the PCs.

    Method B - Manually Import the Certificate

    If you are forced to manually touch each PC by hand, here is how you can install the certificate (for Windows XP, Windows Vista or Windows 7)


    1. Close Internet Explorer if it is open.
    2. Click Start --> Run (or type in "Search programs and files" box on Windows 7) and type mmc to load an empty Microsoft Management Console.
    3. If you receive a security warning, click the positive acknowledgement button (actual name varies all over the place).
    4. From the menu, click File, Add / Remove Snap-In
    5. Select Certificates and click the Add button
    6. Select Computer account and click Next
    7. Select Local computer and click Finish, OK
    8. Expand Certificates, Trusted Root Certification Authorities and select the Certificates container
    9. Right-click on the Certificates container, and choose the All Tasks --> Import
    10. Import Wizard - Click Next
    11. Type \\192.168.107.14\share\cacert.der and click Next
    12. Select Place all certificates in the following store --> Trusted Root Certification Authorities and click Next, Finish
    13. The import was successful - Click OK
    14. Look in the list of certificates and you should see your domain such as mail.mydomain.com
    15. Close the console (do not bother saving the MMC when asked)


    Step #4 - Update Your Certificate

    As time goes by, the certificate that was created with your installation will expire (360 days from install) and you will need to generate a new one.


    1. At the login prompt, login with your administrator account (administrator / myadminpass) and then type su and the root password (myrootpass)
    2. Type the commands below to generate a new self-signed certificate:
      Code:
      /opt/zimbra/bin/zmcertmgr createca -new
      /opt/zimbra/bin/zmcertmgr createcrt -new -days 365
      /opt/zimbra/bin/zmcertmgr deploycrt self
      /opt/zimbra/bin/zmcertmgr deployca
    3. Check to see if the certificate was deployed to all services by typing /opt/zimbra/bin/zmcertmgr viewdeployedcrt
    4. Now go back through the above steps to export the new certificate and import into all your PCs


    Reference Article: Zimbra Wiki: Administration Console and CLI Certificate Tools
    Last edited by LHammonds; 11-04-2011 at 10:44 AM.
    Type su - zimbra -c "zmcontrol -v" to get your version and copy that into your profile (more info here)

  6. #6
    Join Date
    Sep 2011
    Location
    Texas
    Posts
    150
    Rep Power
    4

    Smile Scripting

    Scripting


    Much of the solutions beyond this point involve scripts (programming snippets / automated commands).

    In particular, they are Bash Scripts. I chose this due to its popularity and the fact it comes with Ubuntu. I try to make use of what comes with the system without requiring additional software / services unless they really add to the bottom line such as decreasing the time it takes for a process to run or to conserve storage and bandwidth usage.

    When setting up a server and testing things out, there is typically very little concern for procedures / process since much of the activity is exploration and experimentation as well as not having an impact on production. However, once a server goes into production, processes and procedures need to be in place to ensure the availability of the services being provided.

    In regards to these scripts, they will be treated like any other program and will require being tested, documented and go through a promotion process.

    The ideal situation would involve 3 servers (for a single server setup). A test / development server, a quality assurance staging server and the production server itself. If 3 servers cannot be utilized, then it can still work well with 2 servers. Testing scripts / programs / restore on the production server is not advisable and many times impractical...how can you test your restore process / data periodically if you only have a production server?

    The QA Staging server would be as close to production as possible. The server should be setup in such a way that production backups are restored to this server which also tests and validates the backup / restore process as well as maintains a close representation of the production server to mitigate variable risk involved when testing new or modified programs and upgrades.

    The test / development server can serve as the QA server if absolutely necessary.

    The directory structure and how scripts can import other scripts will be configured to facilitate this process.

    Example:

    Directory path for scripts to import common variables, functions and server settings: /var/scripts/common/

    Directory path for production scripts: /var/scripts/prod/

    Directory path for QA staging area scripts: /var/scripts/qa/

    Directory path for test / development scripts: /var/scripts/test/

    With a production and test servers on physically different machines, the "common" scripts folder can be custom-tailored for that environment and allow for minimal changes to a script when running on the test, QA or production server. This is similar to "normalizing" a database. If you have a variable, path or function that is duplicated in multiple scripts, consider pulling it out and placing it in the common folder. If ever you need to change who receives the email reports, you only need to update a single script and all programs will use the new reference from that point on.

    Most of my scripts will import a file called "standard.conf" from the common script folder.

    /var/scripts/common/standard.conf (contents of the file on the production server)
    Code:
    ## Global Variables ##
    TEMPDIR="/var/temp"
    ZIMBRADIR="/opt/zimbra"
    SHAREDIR="/srv/samba/share"
    MYDOMAIN="mydomain.com"
    ADMINEMAIL="admin@${MYDOMAIN}"
    REPORTEMAIL="lhammonds@${MYDOMAIN}"
    BACKUPDIR="/var/backup"
    OFFSITEDIR="/mnt/zmbackup"
    OFFSITETESTFILE="${OFFSITEDIR}/online.txt"
    ARCHIVEMETHOD="tar.7z"    ## Choices are tar.7z or tgz
    HOSTNAME=$(hostname -s)
    SCRIPTNAME=$0
    MAILFILE="${TEMPDIR}/mailfile.$$"
    
    ## Global Functions ##
    
    function f_sendmail()
    {
      ## Purpose: Send email message.
      ## Parameter #1 = Subject
      ## Parameter #2 = Body
      echo "From: ${ADMINEMAIL}" > ${MAILFILE}
      echo "To: ${REPORTEMAIL}" >> ${MAILFILE}
      echo "Subject: ${1}" >> ${MAILFILE}
      echo "" >> ${MAILFILE}
      echo -e ${2} >> ${MAILFILE}
      echo "" >> ${MAILFILE}
      echo -e "\n\nServer: ${HOSTNAME}\nProgram: ${SCRIPTNAME}\nLog: ${LOGFILE}" >> ${MAILFILE}
      ${ZIMBRADIR}/postfix/sbin/sendmail -t < ${MAILFILE}
      rm ${MAILFILE}
    }
    
    function f_mount()
    {
      ## Mount the pre-configured Windows share folder.
      ## NOTE: The Windows share should have a file called "online.txt"
      if [ ! -f ${OFFSITEDIR}/online.txt ]; then
        mount -t cifs //kdc-doubletake/zimbra ${OFFSITEDIR} --options nouser,rw,nofail,noatime,noexec,credentials=/etc/cifspw
      fi
    }
    
    function f_umount()
    {
      ## Dismount the Windows share folder.
      ## NOTE: The unmounted folder should have a file called "offline.txt"
      if [ -f ${OFFSITEDIR}/online.txt ]; then
        umount ${OFFSITEDIR}
      fi
    }

    /var/scripts/common/standard.conf (contents of the file on the test server)
    Code:
    ## Global Variables ##
    TEMPDIR="/tmp"
    ZIMBRADIR="/opt/zimbra800"
    SHAREDIR="/srv/samba/share"
    MYDOMAIN="mytestdomain.com"
    ADMINEMAIL="test1@${MYDOMAIN}"
    REPORTEMAIL="test2@${MYDOMAIN}"
    BACKUPDIR="/tmp"
    OFFSITEDIR="/mnt/fakedir"
    OFFSITETESTFILE="${OFFSITEDIR}/online.txt"
    ARCHIVEMETHOD="tar.7z"    ## Choices are tar.7z or tgz
    HOSTNAME=$(hostname -s)
    SCRIPTNAME=$0
    MAILFILE="${TEMPDIR}/mailfile.$$"
    
    ## Global Functions ##
    
    function f_sendmail()
    {
      ## Purpose: Send email message.
      ## Parameter #1 = Subject
      ## Parameter #2 = Body
      echo "From: ${ADMINEMAIL}" > ${MAILFILE}
      echo "To: ${REPORTEMAIL}" >> ${MAILFILE}
      echo "Subject: ${1}" >> ${MAILFILE}
      echo "" >> ${MAILFILE}
      echo -e ${2} >> ${MAILFILE}
      echo "" >> ${MAILFILE}
      echo -e "\n\nServer: ${HOSTNAME}\nProgram: ${SCRIPTNAME}\nLog: ${LOGFILE}" >> ${MAILFILE}
      ${ZIMBRADIR}/postfix/sbin/sendmail -t < ${MAILFILE}
      rm ${MAILFILE}
    }
    
    function f_mount()
    {
      ## Mount the pre-configured Windows share folder.
      ## NOTE: The Windows share should have a file called "online.txt"
      if [ ! -f ${OFFSITEDIR}/online.txt ]; then
        mount -t cifs //kdc-doubletake/zimbra ${OFFSITEDIR} --options nouser,rw,nofail,noatime,noexec,credentials=/etc/cifspw
      fi
    }
    
    function f_umount()
    {
      ## Dismount the Windows share folder.
      ## NOTE: The unmounted folder should have a file called "offline.txt"
      if [ -f ${OFFSITEDIR}/online.txt ]; then
        umount ${OFFSITEDIR}
      fi
    }
    When receiving email notifications, the server name, script name and path will be included at the bottom of the email every time. It will be readily apparent if the email was generated from the test, qa or production server simply because of the location (even if test, qa and production are all on the same server).

    Here are the scripts to help automate the creation of this structure on the various servers (would run all of them if all are the same box)

    setup-script-prod.sh
    Code:
    #!/bin/bash
    if [ ! -d /var/scripts/prod ]
      mkdir -p /var/scripts/prod
    fi
    if [ ! -d /var/scripts/common ]
      mkdir -p /var/scripts/common
    fi
    chown root:root /var/scripts
    chown root:root /var/scripts/prod
    chown root:root /var/scripts/common
    chmod 0777 /var/scripts
    chmod 0755 /var/scripts/prod
    chmod 0755 /var/scripts/common
    setup-script-qa.sh
    Code:
    #!/bin/bash
    if [ ! -d /var/scripts/qa ]
      mkdir -p /var/scripts/qa
    fi
    if [ ! -d /var/scripts/common ]
      mkdir -p /var/scripts/common
    fi
    chown root:root /var/scripts
    chown root:root /var/scripts/qa
    chown root:root /var/scripts/common
    chmod 0777 /var/scripts
    chmod 0777 /var/scripts/qa
    chmod 0755 /var/scripts/common
    setup-script-test.sh
    Code:
    #!/bin/bash
    if [ ! -d /var/scripts/test ]
      mkdir -p /var/scripts/test
    fi
    if [ ! -d /var/scripts/common ]
      mkdir -p /var/scripts/common
    fi
    chown root:root /var/scripts
    chown root:root /var/scripts/test
    chown root:root /var/scripts/common
    chmod 0777 /var/scripts
    chmod 0777 /var/scripts/test
    chmod 0777 /var/scripts/common
    Last edited by LHammonds; 12-08-2011 at 07:37 AM.
    Type su - zimbra -c "zmcontrol -v" to get your version and copy that into your profile (more info here)

  7. #7
    Join Date
    Sep 2011
    Location
    Texas
    Posts
    150
    Rep Power
    4

    Smile Keep Zimbra in Sync with Active Directory

    Keep Zimbra in Sync with Active Directory

    For my scenario, I want mailboxes created automatically when I create an Active Directory (AD) account. I do not want the mailbox to authenticate against AD though. To accomplish this, two or three scripts will be created and setup to run on a regular basis.

    The 1st script will be run on a Windows server and will create a comma-delimited (CSV) file for all users who belong to a security group called "GRP_ZimbraEmail" which allows me to selectively pick who is allowed to have a mailbox. The script will probably just run once per day (after hours). The CSV file will be placed on Ubuntu's Samba share.

    The 2nd script will be running on Ubuntu and checking for the input file very often (every minute). It will then cycle through all the AD users and see which users do not have a mailbox account and then create the mailbox using the supplied details.

    export_zimbra_ad_users.vbs
    Code:
    Option Explicit
    '****************************************
    '** Name: export_zimbra_ad_users.vbs
    '** Version: 1.1
    '** Date: 2011-10-29
    '** Author: LHammonds
    '** Purpose: Export AD users to a comma-delimited file
    '**          that are authorized to have a Zimbra mailbox.
    '****************************************
    '* Field #1 = LoginID
    '* Field #2 = First Name
    '* Field #3 = Middle Initial
    '* Field #4 = Last Name
    '* Field #5 = Full Name
    '* Field #6 = Title
    '* Field #7 = Description
    '* Field #8 = Comments
    '* Field #9 = Telephone
    '* Field #10 = Home Phone
    '* Field #11 = Mobile Phone
    '* Field #12 = Fax Number
    '* Field #13 = Pager
    '* Field #14 = Company
    '* Field #15 = Office
    '* Field #16 = Street Address
    '* Field #17 = PO Box
    '* Field #18 = City
    '* Field #19 = State
    '* Field #20 = Postal Code
    '* Field #21 = Country
    '* Field #22 = Password Replacement Value
    '* Field #23 = Unused (mainly to avoid the end-of-line character being read into the last value)
    
    '** NOTE: This could use a data cleanup routine that replaces all commas in a  **
    '** variable with something else such as a period instead to avoid CSV issues. **
    
    Const ForAppending = 8
    Const FilePath = "D:\Reports\adlist.csv"
    Const ZimbraSecurityGroup = "GRP_ZimbraEmail"
    Const DefaultPassword = "ChangeThisPassword"
    
    Dim objRootDSE, strDNC, objDomain, objFSO, objFile
    
    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDNC = objRootDSE.Get("DefaultNamingContext")
    Set objDomain = GetObject("LDAP://" & strDNC)
    
    '** Create / Overwrite the export file. **
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.CreateTextFile(FilePath)
    objFile.Close
    Set objFile = Nothing
    
    Call TrollTheFolders(objDomain)
    
    Sub TrollTheFolders(pobjDomain)
      '** Function: Traverse the AD structure to find users wherever they may reside. **
      '**           The trick is that this function is called recursively in order to **
      '**           inspect every sub-folder that may contain user accounts.          **
      Dim lobjFile, lobjFSO, lobjMember, lstrLine, lblnInZimbraGroup
      Dim lstrSamAccountName, lstrFirstName, lstrInitials, lstrLastName
      Dim lstrFullName, lstrTitle, lstrDescription, lstrComment
      Dim lstrTelephoneNumber, lstrHomePhone, lstrMobile, lstrFaxNumber, lstrPager
      Dim lstrCompany, lstrOffice, lstrStreetAddress, lstrPostOfficeBox
      Dim lstrCity, lstrState, lstrPostalCode, lstrCountry, lstrPassword
      Dim lcolGroups, lobjGroup, lstrTemp
    
      For Each lobjMember In pobjDomain
        '** Examine each object but process only "user" objects. **
        If lobjMember.Class = "user" Then
          Set lobjFile = objFSO.OpenTextFile (FilePath, ForAppending, True)
          If Not (isempty(lobjMember.samAccountName)) Then lstrSamAccountName = lobjMember.samAccountName Else lstrSamAccountName = "" End If
          If Not (isempty(lobjMember.GivenName)) Then lstrFirstName = lobjMember.GivenName Else lstrFirstName = "" End If
          If Not (isempty(lobjMember.initials)) Then lstrInitials = lobjMember.initials Else lstrInitials = "" End If
          If Not (isempty(lobjMember.sn)) Then lstrLastname = lobjMember.sn Else lstrLastName = "" End If
          If Not (isempty(lobjMember.CN)) Then lstrFullName = lobjMember.CN Else lstrFullName = "" End If
          If Not (isempty(lobjMember.title)) Then lstrTitle = lobjMember.title Else lstrTitle = "" End If
          If Not (isempty(lobjMember.Description)) Then lstrDescription = lobjMember.Description Else lstrDescription = "" End If
          If Not (isempty(lobjMember.comment)) Then lstrComment = lobjMember.comment Else lstrComment = "" End If
          If Not (isempty(lobjMember.telephoneNumber)) Then lstrTelephoneNumber = lobjMember.telephoneNumber Else lstrTelephoneNumber = "" End If
          If Not (isempty(lobjMember.homePhone)) Then lstrHomePhone = lobjMember.homePhone Else lstrHomePhone = "" End If
          If Not (isempty(lobjMember.mobile)) Then lstrMobile = lobjMember.mobile Else lstrMobile = "" End If
          If Not (isempty(lobjMember.otherFacsimileTelephoneNumber)) Then lstrFaxNumber = lobjMember.otherFacsimileTelephoneNumber Else lstrFaxNumber = "" End If
          If Not (isempty(lobjMember.pager)) Then lstrPager = lobjMember.pager Else lstrPager = "" End If
          If Not (isempty(lobjMember.company)) Then lstrCompany = lobjMember.company Else lstrCompany = "" End If
          If Not (isempty(lobjMember.physicalDeliveryOfficeName)) Then lstrOffice = lobjMember.physicalDeliveryOfficeName Else lstrOffice = "" End If
          If Not (isempty(lobjMember.streetAddress)) Then lstrStreetAddress = lobjMember.streetAddress Else lstrStreetAddress = "" End If
          If Not (isempty(lobjMember.postOfficeBox)) Then lstrPostOfficeBox = lobjMember.postOfficeBox Else lstrPostOfficeBox = "" End If
          If Not (isempty(lobjMember.l)) Then lstrCity = lobjMember.l Else lstrCity = "" End If
          If Not (isempty(lobjMember.st)) Then lstrState = lobjMember.st Else lstrState = "" End If
          If Not (isempty(lobjMember.postalCode)) Then lstrPostalCode = lobjMember.postalCode Else lstrPostalCode = "" End If
          If Not (isempty(lobjMember.countryCode)) Then lstrCountry = lobjMember.countryCode Else lstrCountry = "" End If
          lstrPassword = DefaultPassword
          lblnInZimbraGroup = 0
          For Each lobjGroup in lobjMember.Groups
            '** See if this member belongs to the group that allows Zimbra mailboxes **
            If LCase(lobjGroup.cn) = LCase(ZimbraSecurityGroup) Then
              lblnInZimbraGroup = 1
            End If
          Next
          If lblnInZimbraGroup = 1 Then
            '** Member is associated to the Zimbra Email group and thus allowed to have a Zimbra mailbox. **
            lstrLine = lstrSamAccountName & "," & lstrFirstName & "," & lstrInitials & "," & lstrLastName & "," & lstrFullName & "," &_
                lstrTitle & "," & lstrDescription & "," & lstrComment & "," & lstrTelephoneNumber & "," & lstrHomePhone & "," & lstrMobile & "," &_
                lstrFaxNumber & "," & lstrPager & "," & lstrCompany & "," & lstrOffice & "," & lstrStreetAddress & "," & lstrPostOfficeBox & "," &_
                lstrCity & "," & lstrState & "," & lstrPostalCode & "," & lstrCountry & "," & lstrPassword & ",unused"
            lobjFile.WriteLine(lstrLine)
          End If
          lobjFile.Close
          Set lobjFile = Nothing
        End If
        If lobjMember.Class = "organizationalUnit" or lobjMember.Class = "container" Then
          '** Recurse further down to find the users. **
          TrollTheFolders(lobjMember)
        End If
      Next
    End Sub
    Sample adlist.csv
    Code:
    mmouse,Mickey,,Mouse,Mickey Mouse,,Lab Assistant,,,,,,800-867-5309,,,,,,,,0,ChangeThisPassword,unused
    jdirt,Joe,,Dirt,Joe Dirt,Chief Information Officer,Chief Information Officer,,800-555-5555,,,,,ABC,Information Systems,404 Hollywood Street,,Hollywood,CA,90210,840,ChangeThisPassword,unused
    ddiggler,Dirk,,Diggler,Dirk Diggler,Database Administrator,IS-Database Administrator,,800-555-0404,800-789-1234,888-111-2222,,,,Information Systems,404 Cowboy Country Road,,Hickville,TX,77501,840,ChangeThisPassword,unused
    jdoe,John,,Doe,John Doe,System Analyst,IS-Telco Systems Analyst,,800-999-8888,,,,,,Information Systems,666 Gov Road,,Washington,WA,10110,840,ChangeThisPassword,unused
    import-ad.sh
    Code:
    #!/bin/bash
    #############################################
    ## Name          : import-ad.sh
    ## Version       : 1.2
    ## Date          : 2011-11-02
    ## Author        : LHammonds
    ## Purpose       : Add mailbox accounts for AD users that have none.
    ## Compatibility : Verified on Ubuntu Server 10.04.3 LTS, Zimbra 7.1.2 - 7.1.3 OSE
    ## Requirements  : Zimbra must be online, must be run as root user.
    ## Run Frequency : Run very frequently (every minute)
    ## Exit Codes    :
    ##    0 = Success
    ##    1 = Failure
    ################ CHANGE LOG #################
    ## DATE       WHO WHAT WAS CHANGED
    ## ---------- --- ----------------------------
    ## 2011-10-11 LTH Created script.
    ## 2011-10-29 LTH Better logging, mail support, bug fixes.
    ## 2011-11-02 LTH Moved standard variables/functions to external file.
    #############################################
    
    ## Import standard variables and functions. ##
    source /var/scripts/common/standard.conf
    
    LOGFILE="${TEMPDIR}/import-ad.log"
    MAILFILE="${TEMPDIR}/import-ad-mail.$$"
    ADLISTORG="${SHAREDIR}/adlist.csv"
    ADLISTNEW="${TEMPDIR}/import-ad-adlist.$$"
    ZMUSERS="${TEMPDIR}/import-ad-zmuserlist.$$"
    ZMCMD="${TEMPDIR}/import-ad-zmcmd.$$"
    NEWUSERS=""
    RETURNVALUE=0
    
    ## Temporarily change the default field separator to a comma. #
    OLDIFS="${IFS}"
    IFS=","
    
    ## If the Active Directory user list file is not found, exit the script. #
    if [ ! -f ${ADLISTORG} ]; then
      ## No file to process.  Exit script.
      exit 0
    fi
    echo "`date +%Y-%m-%d_%H:%M:%S` - Active Directory file found! Import process started." >> ${LOGFILE}
    
    ## Create files and set permissions for only the root user. #
    touch ${ZMCMD}
    touch ${ZMUSERS}
    chmod 0600 ${ZMCMD}
    chmod 0600 ${ZMUSERS}
    ## Take ownership and set permissions for only the root user. #
    chown root:root ${ADLISTORG}
    chmod 0400 ${ADLISTORG}
    ## Move the file to a working folder. #
    mv ${ADLISTORG} ${ADLISTNEW}
    ## Create a list of users in Zimbra for the specified domain. #
    ${ZIMBRADIR}/bin/zmprov -l getAllAccounts ${MYDOMAIN} > ${ZMUSERS}
    
    ## Loop through the Active Directory user list. #
    while read -a ADLINE ; do
      ## Slot 0 = UserID
      ## Slot 1 = First Name (GivenName)
      ## Slot 2 = Initials
      ## Slot 3 = Last Name (sn)
      ## Slot 4 = Full Name (CN)
      ## Slot 5 = Title
      ## Slot 6 = Description
      ## Slot 7 = Comment
      ## Slot 8 = Telephone / Work Number
      ## Slot 9 = Home Phone
      ## Slot 10 = Mobile Phone
      ## Slot 11 = Fax Number (facsimileTelephoneNumber)
      ## Slot 12 = Pager
      ## Slot 13 = Company
      ## Slot 14 = Office (physicalDeliveryOfficeName)
      ## Slot 15 = Street Address
      ## Slot 16 = Post Office Box
      ## Slot 17 = City (l)
      ## Slot 18 = State (st)
      ## Slot 19 = Postal Code
      ## Slot 20 = Country Code (co)
      ## Slot 21 = Password
      ## Set the "Found Match" variable to false #
      FOUND=0
      ## Loop through the Zimbra User List. #
      while read -a ZMLINE ; do
        ## Convert Usernames to lower case. #
        ZMUSERID=${ZMLINE[0],,}
        ADUSERID=${ADLINE[0],,}
        ## Add domain address to the end of the AD Username #
        ADUSERID=${ADUSERID}"@"${MYDOMAIN}
        ## Compare the lowercase AD username to the lower case Zimbra username. #
        if [ ${ADUSERID} == ${ZMUSERID} ]; then
          ## Match found. Exit this while loop. #
          FOUND=1
          break
        fi
      done < ${ZMUSERS}
      if [ ${FOUND} -eq 0 ]; then
        ## We have an AD user that does not have a Zimbra mailbox. #
        NEWUSERS="${NEWUSERS}${ADLINE[0]}@${MYDOMAIN}\n"
        echo "`date +%Y-%m-%d_%H:%M:%S` --- Adding new user: ${ADLINE[0]}@${MYDOMAIN}" >> ${LOGFILE}
        echo "createAccount ${ADLINE[0]}@${MYDOMAIN} \"${ADLINE[21]}\" gn \"${ADLINE[1]}\" initials \"${ADLINE[2]}\" sn \"${ADLINE[3]}\" cn \"${ADLINE[4]}\" title \"${ADLINE[5]}\" description \"${ADLINE[6]}\" zimbraNotes \"${ADLINE[7]}\" telephoneNumber \"${ADLINE[8]}\" homePhone \"${ADLINE[9]}\" mobile \"${ADLINE[10]}\" facsimileTelephoneNumber \"${ADLINE[11]}\" pager \"${ADLINE[12]}\" company \"${ADLINE[13]}\" physicalDeliveryOfficeName \"${ADLINE[14]}\" street \"${ADLINE[15]}\" postOfficeBox \"${ADLINE[16]}\" l \"${ADLINE[17]}\" st \"${ADLINE[18]}\" postalCode \"${ADLINE[19]}\" co \"${ADLINE[20]}\"">> ${ZMCMD}
      fi
    done < ${ADLISTNEW}
    
    ## If the Zimbra command file is not empty, we need to process it. #
    if [ -s ${ZMCMD} ]; then
      ${ZIMBRADIR}/bin/zmprov < ${ZMCMD} 1>/dev/null 2>&1
      RETURNVALUE=$?
      if [ ${RETURNVALUE} -ne 0 ]; then
        ## Something went wrong with the mailbox creation.
        ## This error should notify administrators to the problem.
        echo "`date +%Y-%m-%d_%H:%M:%S` --- ERROR: zmprov reported the following error: ${RETURNVALUE}" >> ${LOGFILE}
        echo "`date +%Y-%m-%d_%H:%M:%S` - Import aborted.  EXIT CODE = 1" >> ${LOGFILE}
        f_sendmail "Zimbra Active Directory Import" "ERROR: zmprov reported the following error: ${RETURNVALUE}\n\nRemaining temporary files:\n${ZMUSERS}\n${ZMCMD}\n${ADLISTNEW}\n"
        exit 1
      fi
      ## Send email notification of the new users added to Zimbra. #
      ## NOTE: To be 100% sure about this, we could loop through the users #
      ##       and verify that they now have Zimbra mailboxes. #
      f_sendmail "Zimbra Notification - New Users" "The following users were added to Zimbra:\n\n${NEWUSERS}"
    else
      ## There were no new users to process. #
      echo "`date +%Y-%m-%d_%H:%M:%S` --- No new users to import." >> ${LOGFILE}
    fi
    echo "`date +%Y-%m-%d_%H:%M:%S` - Active Directory import completed." >> ${LOGFILE}
    
    ## Restore the default field separator value. #
    IFS="${OLDIFS}"
    
    ## Remove temporary files. #
    rm ${ZMUSERS}
    rm ${ZMCMD}
    rm ${ADLISTNEW}
    Sample email when new mailboxes are created:
    Code:
    Subject: Zimbra Notification - New Users
    
    The following users were added to Zimbra:
    
    ddiggler@mydomain.com
    jdoe@mydomain.com
    jsmith@mydomain.com
    lhammonds@mydomain.com
    mmouse@mydomain.com
    
    Server: mail
    Program: /var/scripts/prod/import-ad.sh
    Log: /var/temp/import-ad.log
    Here is a sample log file (NOTE: There are no entries if no file is found):
    Code:
    2011-10-29_17:06:49 - Active Directory file found! Import process started.
    2011-10-29_17:06:52 --- Adding new user: ddiggler@mydomain.com
    2011-10-29_17:06:53 --- Adding new user: jdoe@mydomain.com
    2011-10-29_17:06:53 --- Adding new user: jsmith@mydomain.com
    2011-10-29_17:06:53 --- Adding new user: lhammonds@mydomain.com
    2011-10-29_17:06:53 --- Adding new user: mmouse@mydomain.com
    2011-10-29_17:06:56 - Active Directory import completed.
    2011-10-29_17:07:29 - Active Directory file found! Import process started.
    2011-10-29_17:07:32 --- No new users to import.
    2011-10-29_17:07:32 - Active Directory import completed.
    If you keep a database of all your user's IDs and passwords, you could export that information to the Linux box and have it safely tucked away and used in-between the AD Export and AD Import process. It could run through the AD user list and replace the default password with their existing password making it operate seamlessly within the environment.

    If user passwords are unknown, the process would be to let the individual know their mailbox was created with a standard password and that they need to login and change it ASAP.

    Reference Articles:
    Last edited by LHammonds; 12-08-2011 at 07:32 AM.
    Type su - zimbra -c "zmcontrol -v" to get your version and copy that into your profile (more info here)

  8. #8
    Join Date
    Sep 2011
    Location
    Texas
    Posts
    150
    Rep Power
    4

    Default Global Address List for iPhones

    Global Address List for iPhones

    I have a working solution in place for our iPhone users to access the Internal Global Address List (GAL) when they start a new email message and click the "To" button to show a list of all contacts in our company (not just personal contacts).

    Normally, you will only get a list of contacts in your personal folder. I have tried various ways to get this to work such as sharing the _InternalGAL folder but could not get anything to work well. I certainly do not want to give my users the credentials to the galsync account (which is my admin account).

    This method uses a service account (dummy mailbox) to hold a copy of the GAL. Each iPhone user then adds an additional CardDAV account and enters the shared account's details.

    For this example, I created a mailbox called "addresslist@mydomain.com" and then logged into that account and shared the contacts folder as "Public" for anyone to access.

    Next, login to the admin console, expand Configuration --> Domains and click on mydomain.com. Click the Configure GAL button. Set the following and click Next, Finish:

    GAL mode: Internal
    Most results returned by GAL search: 250
    Use GAL Sync account (recommended): Check
    GAL sync account name: admin@mydomain.com (or whatever galsync account you want)
    Datasource name for internal GAL: InternalGAL
    Internal GAL polling interval: 1 days

    Next, force the initial sync by typing the following at the Ubuntu console as the root user:

    Code:
    su - zimbra -c "zmgsautil forceSync -a admin@mydomain.com -n InternalGAL"
    If you login to the web mail client and login with the galsync (admin) account, you should see the "_InternalGAL" folder under the Address Book tab and it should be populated with your internal users.

    Before the account can be backed up with the script below, the services need to be restarted.

    Code:
    /etc/init.d/zimbra stop
    /etc/init.d/zimbra start
    Now setup the script below to run on a regular schedule which will backup the GAL Sync's "_InternalGAL" folder to an archive. It will then extract the archive and change references of "_InternalGAL" to "Contacts" in all files so it can be restored in a folder that the iPhone will recognize. Then it is re-packed into an archive and restored to the "addresslist" account which completely replaces whatever is in the "Contacts" folder with the updated list. As an additional step, it will delete specific addresses which are not desired to show up in the global list.

    Also note that this is not necessary on the Pro Network Edition which has an iPhone sync utility.

    /var/scripts/prod/gal-sync.sh
    Code:
    #!/bin/bash
    #############################################
    ## Name          : sync-gal.sh
    ## Version       : 1.1
    ## Date          : 2011-11-02
    ## Author        : LHammonds
    ## Purpose       : Expose Internal GAL (Global Address List) for use on iPhones
    ## Compatibility : Verified on Ubuntu Server 10.04.3 LTS, Zimbra 7.1.3 OSE
    ## Requirements  : Zimbra must be online, must be run as root user.
    ## Run Frequency : Once per day (after hours preferable but not necessary)
    ## Exit Codes    : (if multiple errors, value is the addition of codes)
    ##    0 = Success
    ##    1 = Security failure
    ##    2 = zmmailbox getRestURL failure
    ##    4 = zmmailbox postRestURL failure
    ##    8 = zmmailbox getAllContacts failure
    ##   16 = tar extraction failure
    ##   32 = tar creation failure
    ################# CHANGE LOG #################
    ## DATE       WHO WHAT WAS CHANGED
    ## ---------- --- ----------------------------
    ## 2011-10-28 LTH Created script.
    ## 2011-10-31 LTH Added check for root ID.
    ## 2011-11-02 LTH Moved standard variables / functions to external file.
    
    ## NOTE: Should add detection of address list account.
    
    ##############################################
    
    ## Import common variables and functions. ##
    source /var/scripts/common/standard.conf
    
    GALSYNCACCT="admin@${MYDOMAIN}"
    PUBLICGALACCT="addresslist@${MYDOMAIN}"
    EXCEPTIONS="addresslist@${MYDOMAIN};admin@${MYDOMAIN};test@${MYDOMAIN};test2@${MYDOMAIN}"
    GALSYNCDIR="${TEMPDIR}/galsync"
    LOGFILE="${TEMPDIR}/gal-sync.log"
    CONTACTFILE="${TEMPDIR}/gal-sync-contact.$$"
    GALARCHIVE1="galsync1.tgz"
    GALARCHIVE2="galsync2.tgz"
    CONTACTNUMDEL=0
    CONTACTNUMALL=0
    RETURNVALUE=0
    ERRORFLAG=0
    
    #######################################
    ##            FUNCTIONS              ##
    #######################################
    
    function f_cleanup()
    {
      ## Purpose: Cleanup files and folders used by the script.
      if [ -d ${GALSYNCDIR} ]; then
        rm -rf ${GALSYNCDIR}
      fi
      if [ -f ${TEMPDIR}/${GALARCHIVE1} ]; then
        rm ${TEMPDIR}/${GALARCHIVE1}
      fi
      if [ -f ${TEMPDIR}/${GALARCHIVE2} ]; then
        rm ${TEMPDIR}/${GALARCHIVE2}
      fi
      if [ -f ${CONTACTFILE} ]; then
        rm ${CONTACTFILE}
      fi
    }
    
    function f_emergencyexit()
    {
      ## Purpose: Exit script as cleanly as possible.
      ## Parameter #1 = Error Code.
      f_cleanup
      f_sendmail "Zimbra iPhone GAL Sync Error" "EXIT CODE = ${1}"
      echo "`date +%Y-%m-%d_%H:%M:%S` - GAL Sync aborted.  EXIT CODE: ${1}" >> ${LOGFILE}
      ## Write script name and error code to the system log.
      logger "${SCRIPTNAME}: ERROR CODE = ${1}"
      exit $1
    }
    
    #######################################
    ##           MAIN PROGRAM            ##
    #######################################
    
    echo "`date +%Y-%m-%d_%H:%M:%S` - GAL Sync started." >> ${LOGFILE}
    
    ## Requirement Check: Script must run as root user.
    if [ "$(id -u)" != "0" ]; then
      ## FATAL ERROR DETECTED: Document problem and terminate script.
      echo "`date +%Y-%m-%d_%H:%M:%S` - GAL Sync aborted.  ERROR: Root user required." >> ${LOGFILE}
      ERRORFLAG=$((${ERRORFLAG} + 1))
      f_emergencyexit ${ERRORFLAG}
    fi
    
    ## Backup the global address listing.
    ${ZIMBRADIR}/bin/zmmailbox -z -m ${GALSYNCACCT} getRestURL "/_InternalGAL?fmt=tgz" > ${TEMPDIR}/${GALARCHIVE1}
    RETURNVALUE=$?
    if [ ${RETURNVALUE} -ne 0 ]; then
      ## FATAL ERROR DETECTED: Document problem and terminate script.
      echo "`date +%Y-%m-%d_%H:%M:%S` --- ERROR: ${ZIMBRADIR}/bin/zmmailbox -z -m ${GALSYNCACCT} getRestURL '/_InternalGAL?fmt=tgz'" >> ${LOGFILE}
      echo "`date +%Y-%m-%d_%H:%M:%S` --- Return Value: ${RETURNVALUE}" >> ${LOGFILE}
      ERRORFLAG=$((${ERRORFLAG} + 2))
      f_emergencyexit ${ERRORFLAG}
    fi
    
    ## Prepare the extraction folder and set appropriate permissions.
    mkdir -p ${GALSYNCDIR}
    chmod 0600 ${GALSYNCDIR}
    ## Extract the archive to modify its contents.
    tar -xf ${TEMPDIR}/${GALARCHIVE1} -C ${GALSYNCDIR} 1>/dev/null 2>&1
    RETURNVALUE=$?
    if [ ${RETURNVALUE} -ne 0 ]; then
      ## FATAL ERROR DETECTED: Document problem and terminate script.
      echo "`date +%Y-%m-%d_%H:%M:%S` --- ERROR: tar -xf ${TEMPDIR}/${GALARCHIVE1} -C ${GALSYNCDIR}" >> ${LOGFILE}
      echo "`date +%Y-%m-%d_%H:%M:%S` --- Return Value: ${RETURNVALUE}" >> ${LOGFILE}
      ERRORFLAG=$((${ERRORFLAG} + 16))
      f_emergencyexit ${ERRORFLAG}
    fi
    
    ## Search and replace all meta data occurances of "_InternalGAL" with "Contacts"
    ## This will allow the contacts to be restored to the "Contacts" folder.
    sed -i 's/_InternalGAL/Contacts/g' ${GALSYNCDIR}/*.meta
    sed -i 's/_InternalGAL/Contacts/g' ${GALSYNCDIR}/_InternalGAL/*.meta
    
    ## Count the number of meta files (contacts) in the GAL folder.
    CONTACTNUMALL=`ls -1 ${GALSYNCDIR}/_InternalGAL/*.meta | wc -l`
    
    ## Create a new archive with the modified data.
    tar -czf ${TEMPDIR}/${GALARCHIVE2} ${GALSYNCDIR} 1>/dev/null 2>&1
    RETURNVALUE=$?
    if [ ${RETURNVALUE} -ne 0 ]; then
      ## FATAL ERROR DETECTED: Document problem and terminate script.
      echo "`date +%Y-%m-%d_%H:%M:%S` --- ERROR: tar -czf ${TEMPDIR}/${GALARCHIVE2} ${GALSYNCDIR}" >> ${LOGFILE}
      echo "`date +%Y-%m-%d_%H:%M:%S` --- Return Value: ${RETURNVALUE}" >> ${LOGFILE}
      ERRORFLAG=$((${ERRORFLAG} + 32))
      f_emergencyexit ${ERRORFLAG}
    fi
    
    ## Replace contacts in the iPhone GAL account.
    ${ZIMBRADIR}/bin/zmmailbox -z -m ${PUBLICGALACCT} postRestURL "//?fmt=tgz&resolve=reset" ${TEMPDIR}/${GALARCHIVE2}
    RETURNVALUE=$?
    if [ ${RETURNVALUE} -ne 0 ]; then
      ## FATAL ERROR DETECTED: Document problem and terminate script.
      echo "`date +%Y-%m-%d_%H:%M:%S` --- ERROR: ${ZIMBRADIR}/bin/zmmailbox -z -m ${PUBLICGALACCT} postRestURL '//?fmt=tgz&resolve=reset'" >> ${LOGFILE}
      echo "`date +%Y-%m-%d_%H:%M:%S` --- Return Value: ${RETURNVALUE}" >> ${LOGFILE}
      ERRORFLAG=$((${ERRORFLAG} + 4))
      f_emergencyexit ${ERRORFLAG}
    fi
    
    ## Export all contacts to a working file to determine which contacts to remove.
    ${ZIMBRADIR}/bin/zmmailbox -z -m ${PUBLICGALACCT} getAllContacts > ${CONTACTFILE}
    RETURNVALUE=$?
    if [ ${RETURNVALUE} -ne 0 ]; then
      ## FATAL ERROR DETECTED: Document problem and terminate script.
      echo "`date +%Y-%m-%d_%H:%M:%S` --- ERROR: ${ZIMBRADIR}/bin/zmmailbox -z -m ${PUBLICGALACCT} getAllContacts" >> ${LOGFILE}
      echo "`date +%Y-%m-%d_%H:%M:%S` --- Return Value: ${RETURNVALUE}" >> ${LOGFILE}
      ERRORFLAG=$((${ERRORFLAG} + 8))
      f_emergencyexit ${ERRORFLAG}
    fi
    
    ## Obtain list of Contact IDs with matching email addresses in the exception list.
    while read LINEID LINEVALUE; do
      if [ "${LINEID}" = "Id:" ]; then
        CURRID=${LINEVALUE}
      fi
      if [ "${LINEID}" = "email:" ]; then
        ## Determine if this is an email address that we are looking for.
        if `echo ${EXCEPTIONS} | grep -q "${LINEVALUE}"`
        then
          ## Found a contact to remove from the address book.
          ## Verify that the contact ID is an integer.
          case ${CURRID} in
          *[!0-9]*)
            echo "`date +%Y-%m-%d_%H:%M:%S` --- WARNING: Invalid integer for contact ID detected: ${CURRID}" >> ${LOGFILE}
            ;;
          *)
            CONTACTNUMDEL=$((${CONTACTNUMDEL} + 1))
            if [ "${CONTACTIDS}" != "" ]; then
              ## This is not the 1st contact added to the list.
              CONTACTIDS="${CONTACTIDS},${CURRID}"
            else
              ## This is the 1st contact added to the list (do not add a comma).
              CONTACTIDS="${CURRID}"
            fi
            ;;
          esac
        fi
      fi
    done < ${CONTACTFILE}
    
    if [ "${CONTACTIDS}" != "" ]; then
      ## Remove any addresses in the address book that match the exceptions.
      ${ZIMBRADIR}/bin/zmmailbox -z -m ${PUBLICGALACCT} deleteContact ${CONTACTIDS}
      RETURNVALUE=$?
      if [ ${RETURNVALUE} -ne 0 ]; then
        ## WARNING DETECTED: Send email notification.
        echo "`date +%Y-%m-%d_%H:%M:%S` --- WARNING: ${ZIMBRADIR}/bin/zmmailbox -z -m ${PUBLICGALACCT} DeleteContact" >> ${LOGFILE}
        echo "`date +%Y-%m-%d_%H:%M:%S` --- Return Value: ${RETURNVALUE}" >> ${LOGFILE}
        f_sendmail "Zimbra iPhone GAL Sync Warning" "WARNING: ${ZIMBRADIR}/bin/zmmailbox -z -m ${PUBLICGALACCT} getAllContacts, RETURN VALUE = ${RETURNVALUE}"
      fi
    fi
    
    echo "`date +%Y-%m-%d_%H:%M:%S` - GAL Sync completed.  Processed = ${CONTACTNUMALL}, removed = ${CONTACTNUMDEL}." >> ${LOGFILE}
    
    ## Perform cleanup routine.
    f_cleanup
    ## Exit with the combined return code value.
    exit ${ERRORFLAG}
    Sample gal-sync.log showing all possible errors and good exits at the end.
    Code:
    2011-10-31_13:40:20 - GAL Sync started.
    2011-10-31_13:40:20 - GAL Sync aborted.  ERROR: Root user required.
    2011-10-31_13:40:20 - GAL Sync aborted.  EXIT CODE: 1
    2011-10-31_13:41:30 - GAL Sync started.
    2011-10-31_13:41:33 --- ERROR: /opt/zimbra/bin/zmmailbox -z -m administrator@mydomain.com getRestURL '/_InternalGAL?fmt=tgz'
    2011-10-31_13:41:33 --- Return Value: 444
    2011-10-31_13:41:33 - GAL Sync aborted.  EXIT CODE: 2
    2011-10-31_13:41:43 - GAL Sync started.
    2011-10-31_13:41:46 --- ERROR: tar -xf /temp/galsync1.tgz -C /temp/galsync
    2011-10-31_13:41:46 --- Return Value: 555
    2011-10-31_13:41:46 - GAL Sync aborted.  EXIT CODE: 16
    2011-10-31_13:41:56 - GAL Sync started.
    2011-10-31_13:41:59 --- ERROR: tar -czf /temp/galsync2.tgz /temp/galsync
    2011-10-31_13:41:59 --- Return Value: 666
    2011-10-31_13:41:59 - GAL Sync aborted.  EXIT CODE: 32
    2011-10-31_13:42:10 - GAL Sync started.
    2011-10-31_13:42:15 --- ERROR: /opt/zimbra/bin/zmmailbox -z -m addresslist@mydomain.com postRestURL '//?fmt=tgz&resolve=reset'
    2011-10-31_13:42:15 --- Return Value: 777
    2011-10-31_13:42:15 - GAL Sync aborted.  EXIT CODE: 4
    2011-10-31_13:42:21 - GAL Sync started.
    2011-10-31_13:42:28 --- ERROR: /opt/zimbra/bin/zmmailbox -z -m addresslist@mydomain.com getAllContacts
    2011-10-31_13:42:28 --- Return Value: 888
    2011-10-31_13:42:28 - GAL Sync aborted.  EXIT CODE: 8
    2011-10-31_13:42:36 - GAL Sync started.
    2011-10-31_13:42:45 --- WARNING: /opt/zimbra/bin/zmmailbox -z -m addresslist@mydomain.com DeleteContact
    2011-10-31_13:42:45 --- Return Value: 999
    2011-10-31_13:42:46 - GAL Sync completed.  Processed = 19, removed = 4.
    2011-10-31_13:42:51 - GAL Sync started.
    2011-10-31_13:43:00 - GAL Sync completed.  Processed = 19, removed = 4.
    2011-10-31_13:47:05 - GAL Sync started.
    2011-10-31_13:47:14 - GAL Sync completed.  Processed = 19, removed = 4.
    Sample error email notification:
    Code:
    Subject: Zimbra iPhone GAL Sync Error
    
    EXIT CODE = 32
    
    Server: mail
    Program: /var/scripts/prod/gal-sync.sh
    Log: /var/temp/gal-sync.log
    Sample warning email notification:
    Code:
    Subject: Zimbra iPhone GAL Sync Warning
    
    WARNING: /opt/zimbra/bin/zmmailbox -z -m addresslist@[COLOR="red"]mydomain.com[/URL] getAllContacts, RETURN VALUE = 999
    
    Server: mail
    Program: /var/scripts/prod/gal-sync.sh
    Log: /var/temp/gal-sync.log
    Sample of /var/log/messages:
    Code:
    Oct 31 13:40:20 mail lhammonds: /var/scripts/prod/gal-sync.sh: ERROR CODE = 1
    Oct 31 13:41:33 mail root: /var/scripts/prod/gal-sync.sh: ERROR CODE = 2
    Oct 31 13:41:46 mail root: /var/scripts/prod/gal-sync.sh: ERROR CODE = 16
    Oct 31 13:41:59 mail root: /var/scripts/prod/gal-sync.sh: ERROR CODE = 32
    Oct 31 13:42:15 mail root: /var/scripts/prod/gal-sync.sh: ERROR CODE = 4
    Oct 31 13:42:28 mail root: /var/scripts/prod/gal-sync.sh: ERROR CODE = 8
    This is how I setup an iPhone

    to access personal emails:


    1. Click the Settings icon
    2. Select Mail, Contacts, Calendars, Add Account..., Other, Add Mail Account
    3. Set the following and click Next:
      Name: John Doe
      Address: JDoe@mydomain.com
      Password: ******
      Description: JDoe @ mydomain
    4. Select IMAP, set the following and click Next, Finish
      Incoming Hostname: mail.mydomain.com
      Incoming User Name: JDoe
      Incoming Password: *****
      Outgoing Hostname: mail.mydomain.com
      Outgoing User Name: JDoe
      Outgoing Password: *****


    to access personal calendars:


    1. Click the Settings icon
    2. Select Mail, Contacts, Calendars, Add Account..., Other, Add CalDAV Account
    3. Set the following and click Next:
      Server: mail.mydomain.com
      User Name: JDoe
      Password: ******
      Description: Personal Calendars @ mydomain


    to access personal contacts:


    1. Click the Settings icon
    2. Select Mail, Contacts, Calendars, Add Account..., Other, Add CardDAV Account
    3. Set the following and click Next:
      Server: mail.mydomain.com
      User Name: JDoe
      Password: ******
      Description: Personal Contacts @ mydomain


    to access the Global Address List:


    1. Click the Settings icon
    2. Select Mail, Contacts, Calendars, Add Account..., Other, Add CardDAV Account
    3. Set the following and click Next:
      Server: mail.mydomain.com
      User Name: addresslist
      Password: ******
      Description: Global Address List @ mydomain


    References: GAL Sync Account (wiki)
    Last edited by LHammonds; 11-10-2011 at 03:58 PM.
    Type su - zimbra -c "zmcontrol -v" to get your version and copy that into your profile (more info here)

  9. #9
    Join Date
    Sep 2011
    Location
    Texas
    Posts
    150
    Rep Power
    4

    Default Zimbra Backup

    Zimbra Backup

    There are various methods of backup that can be utilized but these are the ones I will be exploring:


    1. Backup to local folder using RSync
    2. Backup individual mailboxes
    3. Backup using LVM snapshots


    If I have time, I will also explore the setup of an additional server to serve as a hot-spare so-to-speak. I'd like to see a backup server configured to receive backups from the production server and in the event the production server goes dark, spin up the backup server to be its replacement.

    For the 1st method of using RSync, there is one major catch using RSync alone in that you cannot backup files currently in use. That means you have to shutdown the services in order to get a complete backup. With this in mind, my solution is to utiliize two scripts. The 1st script will backup what it can while the server is "online" and the 2nd script will run during off-hours to shutdown the services (make it offline) and perform a complete backup.

    The online script will be scheduled to run multiple times throughout the day and will not cause any downtime.

    The offline script will be scheduled once per day at a time that will cause the least amount of impact because the server will go offline for about 3 to 5 minutes. It will then compress the backup into a single archive and move it to an offsite server.

    My offsite storage will be on a Windows 2008 server. The 1st thing to do will be the configuration of the Windows server to allow the Ubuntu server to connect and manage files.




    Backup - RSync while online

    /var/scripts/prod/rsync-online.sh
    Code:
    #!/bin/bash
    #############################################
    ## Name          : rsync-online.sh
    ## Version       : 1.1
    ## Date          : 2011-11-04
    ## Author        : LHammonds
    ## Purpose       : Partial backup while Zimbra is online.
    ## Compatibility : Verifed on Ubuntu Server 10.04.3 LTS, Zimbra 7.1.2 - 7.1.3 OSE
    ## Requirements  : Zimbra must be online, must be run as root user.
    ## Run Frequency : Several times throughout the day.
    ## Exit Codes    : (if multiple errors, value is the addition of codes)
    ##    0 = Success
    ##    1 = rsync failure
    ################ CHANGE LOG #################
    ## DATE       WHO WHAT WAS CHANGED
    ## ---------- --- ----------------------------
    ## 2011-10-21 LTH Created script.
    ## 2011-11-04 LTH Moved common variables and functions to external file.
    #############################################
    
    ## Import common variables and functions. ##
    source /var/scripts/common/standard.conf
    
    LOGFILE="${TEMPDIR}/rsync.log"
    TARGET="${BACKUPDIR}/zimbra"
    LOCKFILE="${TEMPDIR}/rsync.lock"
    ERRORFLAG=0
    RETURNVALUE=0
    
    #######################################
    ##            FUNCTIONS              ##
    #######################################
    
    function f_cleanup()
    {
      if [ -f ${LOCKFILE} ];then
        ## Remove lock file so other rsync jobs can run.
        rm ${LOCKFILE} 1>/dev/null 2>&1
      fi
      echo "`date +%Y-%m-%d_%H:%M:%S` - Online RSync backup exit code: ${ERRORFLAG}" >> ${LOGFILE}
    }
    
    #######################################
    ##           MAIN PROGRAM            ##
    #######################################
    if [ -f ${LOCKFILE} ]; then
      ## rsync lock file detected.  Abort script.
      f_sendmail "Online RSync Backup Aborted - Lock File" "This script tried to run but detected the lock file: ${LOCKFILE}\n\nPlease check to make sure the file does not remain when rsync is not actually running."
      exit 1
    else
      echo "`date +%Y-%m-%d_%H:%M:%S` ${SCRIPTNAME}" > ${LOCKFILE}
    fi
    
    echo "`date +%Y-%m-%d_%H:%M:%S` - Online RSync backup mode started." >> ${LOGFILE}
    
    ## Output the current version to a text file which will be included in the backup.
    ## NOTE: You can also view /opt/zimbra/.install_history
    su - zimbra -c "zmcontrol -v > ${ZIMBRADIR}/conf/zimbra_version.txt"
    
    ## rsync will copy what it can to the target location.
    rsync -apogHK --delete --exclude=*.pid ${ZIMBRADIR} ${TARGET} 1>/dev/null 2>&1
    RETURNVALUE=$?
    if [ ${RETURNVALUE} -ne 0 ]; then
      ## ERROR: Send email notification.
      echo "`date +%Y-%m-%d_%H:%M:%S` --- ERROR: Online RSync failed. ${ZIMBRADIR} -> ${TARGET}" >> ${LOGFILE}
      f_sendmail "Online RSync Backup Failure - rsync" "ERROR: Online rsync failed. ${ZIMBRADIR} -> ${TARGET}, RETURN VALUE = ${RETURNVALUE}"
      ERRORFLAG=${ERRORFLAG} + 1
    fi
    ## Document statistics.
    echo "`date +%Y-%m-%d_%H:%M:%S` - Disk usage for both source and target:" >> ${LOGFILE}
    echo "`du -sh ${ZIMBRADIR}`" >> ${LOGFILE}
    echo "`du -sh ${TARGET}`" >> ${LOGFILE}
    echo "`date +%Y-%m-%d_%H:%M:%S` - Online RSync backup mode completed." >> ${LOGFILE}
    
    ## Perform cleanup routine.
    f_cleanup
    ## Exit with the combined return code value.
    exit ${ERRORFLAG}
    Last edited by LHammonds; 11-10-2011 at 03:56 PM.
    Type su - zimbra -c "zmcontrol -v" to get your version and copy that into your profile (more info here)

  10. #10
    Join Date
    Sep 2011
    Location
    Texas
    Posts
    150
    Rep Power
    4

    Default Backup - RSync while offline

    Backup - RSync while offline

    Although this backup takes the services down, the RSync job just prior to taking the services down ensures the vast majority of the data is already backed up. The only thing that has to be done after the services are down is to copy the changes in the last minute and the files that could not be copied while the services were running.

    The actual downtime is typically between 3 to 5 minutes of my server and I doubt it will require longer downtime time even as the data store increases.

    /var/scripts/prod/rsync-offline.sh
    Code:
    #!/bin/bash
    #############################################
    ## Name          : rsync-offline.sh
    ## Version       : 1.4
    ## Date          : 2012-01-09
    ## Author        : LHammonds
    ## Purpose       : Complete backup while Zimbra is offline.
    ## Compatibility : Verified on Ubuntu Server 10.04.3 LTS, Zimbra 7.1.2 - 7.1.3 OSE
    ## Requirements  : p7zip-full (if ARCHIVEMETHOD=tar.7z)
    ## Run Frequency : Once per day after hours.
    ## Exit Codes    : (if multiple errors, value is the addition of codes)
    ##    0 = success
    ##    1 = rsync failure
    ##    2 = archive failure
    ##    4 = archive purge failure
    ##    8 = configuration error
    ##   16 = crontab backup error
    ##   32 = crontab restore warning
    ##   64 = mount warning
    ################ CHANGE LOG #################
    ## DATE       WHO WHAT WAS CHANGED
    ## ---------- --- ----------------------------
    ## 2011-10-21 LTH Created script.
    ## 2011-10-28 LTH Added 7-Zip compression (gunzip optional)
    ## 2011-11-04 LTH Move common variables and funtions to external file.
    ## 2011-11-08 LTH Added zimbra subfolder to remote site for organization.
    ## 2012-01-09 LTH Bugfix for f_PurgeOldestArchive
    #############################################
    
    ## Import common variables and functions. ##
    source /var/scripts/common/standard.conf
    
    LOGFILE="${TEMPDIR}/rsync.log"
    TEMPLOG="${TEMPDIR}/rsync-offline-temp.$$"
    LOCKFILE="${TEMPDIR}/rsync.lock"
    TARGETDIR="${BACKUPDIR}/zimbra"
    OFFSITEBACKDIR="${OFFSITEDIR}/zimbra"
    ARCHIVEFILE="`date +%Y-%m-%d-%H-%M`_zimbra-backup.${ARCHIVEMETHOD}"
    ZMCRONFILE="${TEMPDIR}/zimbra-crontab.$$"
    ERRORFLAG=0
    
    #######################################
    ##            FUNCTIONS              ##
    #######################################
    function f_PurgeOldestArchive()
    {
      ## Purpose: Delete the oldest archive on the remote site.
      ## Return values:
      ##    0 = Success
      ##    1 = Cannot delete file
      ##    9 = Configuration error, path empty
    
      ## Variable Error Check. *
      if [ ${OFFSITEBACKDIR} = "" ]; then
        ## Make darn sure the path is not empty since we do NOT
        ## want to start purging files from a random location.
        echo "`date +%Y-%m-%d_%H:%M:%S` --- Purge error: OFFSITEBACKDIR site variable is empty!" >> ${TEMPLOG}
        return 9
      fi
      ## Get the name of the oldest file.
      OLDESTFILE=`ls -1t ${OFFSITEBACKDIR} | tail -1`
      FILESIZE=`ls -la ${OFFSITEDIR}/${OLDFILE} | awk '{print $5}' | sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'`
      if [ "${OLDESTFILE}" = "" ]; then
        ## Error. Filename variable empty.
        echo "`date +%Y-%m-%d_%H:%M:%S` --- Purge error: OLDESTFILE variable is empty." >> ${TEMPLOG}
        return 9
      else   
        FILESIZE=`ls -lak "${OFFSITEBACKDIR}/${OLDESTFILE}" | awk '{ print $5 }' | sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'`
        echo "`date +%Y-%m-%d_%H:%M:%S` --- Purging old file: ${OFFSITEBACKDIR}/${OLDESTFILE}, Size = ${FILESIZE} kb" >> ${TEMPLOG}
        rm "${OFFSITEBACKDIR}/${OLDESTFILE}"
        if [ -f "${OFFSITEBACKDIR}/${OLDESTFILE}" ]; then
          ## File still exists.  Return error.
          return 1
        else
          return 0
        fi
      fi
    }
    
    function f_cleanup()
    {
      echo "`date +%Y-%m-%d_%H:%M:%S` - Offline RSync backup exit code: ${ERRORFLAG}" >> ${TEMPLOG}
      ## Copy temporary log file into main log file.
      cat ${TEMPLOG} >> ${LOGFILE}
    
      if [ -f ${LOCKFILE} ];then
        ## Remove lock file so other rsync jobs can run.
        rm ${LOCKFILE} 1>/dev/null 2>&1
      fi
      ## Email the log to the administrator.
      EMAILBODY=""
      while read FILELINE; do
        EMAILBODY=${EMAILBODY}${FILELINE}"\n"
      done < ${TEMPLOG}
      f_sendmail "Offline RSync Backup Log" "${EMAILBODY}"
      if [ -f ${TEMPLOG} ]; then
        rm ${TEMPLOG}
      fi
    }
    
    function f_emergencyexit()
    {
      ## Purpose: Exit script as cleanly as possible.
      ## Parameter #1 = Error Code
      f_cleanup
      exit $1
    }
    
    #######################################
    ##           MAIN PROGRAM            ##
    #######################################
    if [ -f ${LOCKFILE} ]; then
      # rsync lock file detected.  Abort script.
      f_sendmail "Offline RSync Backup Aborted - Lock File" "This script tried to run but detected the lock file: ${LOCKFILE}\n\nPlease check to make sure the file does not remain when rsync is not actually running."
      exit 1
    else
      echo "`date +%Y-%m-%d_%H:%M:%S` ${SCRIPTNAME}" > ${LOCKFILE}
    fi
    
    echo "`date +%Y-%m-%d_%H:%M:%S` - Offline RSync backup started." >> ${TEMPLOG}
    
    ## If the 7-Zip archive method is specified, make sure the package is installed.
    if [ "${ARCHIVEMETHOD}" = "tar.7z" ]; then
      if [ ! -f "/usr/bin/7za" ]; then
        ## Required package (7-Zip) not installed.
        echo "`date +%Y-%m-%d_%H:%M:%S` - CRITICAL ERROR: 7-Zip package not installed.  Please install by typing 'aptitude -y install p7zip-full'" >> ${TEMPLOG}
        ERRORFLAG=2
        f_emergencyexit ${ERRORFLAG}
      fi
    fi
    
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Partition status:" >> ${TEMPLOG}
    df -h >> ${TEMPLOG}
    
    ## Output the current version to a text file to be included in the backup.
    ## NOTE: You can also view /opt/zimbra/.install_history
    su - zimbra -c "zmcontrol -v > ${ZIMBRADIR}/conf/zimbra_version.txt"
    
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Begin pre-shutdown rsync command." >> ${TEMPLOG}
    rsync -apogHK --delete --exclude=*.pid ${ZIMBRADIR} ${TARGETDIR} 1>/dev/null 2>&1
    
    ## Backup the zimbra crontab schedule.
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Backup and disable Zimbra crontab schedule." >> ${TEMPLOG}
    crontab -u zimbra -l > ${ZMCRONFILE}
    RETURNVALUE=$?
    if [ ${RETURNVALUE} -ne 0 ]; then
      ## Something went wrong with the backup of the crontab file.
      ## This error will be considered fatal and terminate the script.
      f_sendmail "RSync Offline Backup Error - Crontab" "Could not backup crontab for the zimbra user account.  RETURN VALUE = ${RETURNVALUE}"
      ERRORFLAG=$((${ERRORFLAG} + 16))
      f_emergencyexit ${ERRORFLAG}
    else
      ## Backup successful, now disable the zimbra crontab schedule.
      echo "" > ${TEMPDIR}\emptyfile.$$
      crontab -u zimbra ${TEMPDIR}\emptyfile.$$
      rm ${TEMPDIR}\emptyfile.$$ 1>/dev/null 2>&1
      ## Add a copy of the crontab file to the Zimbra folder to be backed up.
      cp ${ZMCRONFILE} ${ZIMBRADIR} 1>/dev/null 2>&1
    fi
    
    StartTime="$(date +%s)"
    
    ## Stop Zimbra Services.
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Stopping Zimbra services." >> ${TEMPLOG}
    /etc/init.d/zimbra stop 1>/dev/null 2>&1
    
    ## Kill any orphaned Zimbra processes.
    pkill -9 -u zimbra 1>/dev/null 2>&1
    
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Space consumed in ${ZIMBRADIR} = `du -sh ${ZIMBRADIR} | awk '{ print $1 }'`" >> ${TEMPLOG}
    
    ## Now that Zimbra is offline, rsync can quickly copy all remaining files to the backup target.
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Begin post-shutdown rsync command." >> ${TEMPLOG}
    rsync -apogHK --delete --exclude=*.pid ${ZIMBRADIR} ${TARGETDIR} 1>/dev/null 2>&1
    RETURNVALUE=$?
    
    ## Quickly start the Zimbra services.
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Starting Zimbra services." >> ${TEMPLOG}
    /etc/init.d/zimbra start 1>/dev/null 2>&1
    
    if [ ${RETURNVALUE} -ne 0 ]; then
      ## rsync command failed.  Send warning email.
      f_sendmail "RSync Offline Backup Failure - rsync" "rsync failed with return value of ${RETURNVALUE}"
      ERRORFLAG=$((${ERRORFLAG} + 1))
    fi
    
    ## Calculates downtime of Zimbra services.
    FinishTime="$(date +%s)"
    ElapsedTime="$(expr ${FinishTime} - ${StartTime})"
    Hours=$((${ElapsedTime} / 3600))
    ElapsedTime=$((${ElapsedTime} - ${Hours} * 3600))
    Minutes=$((${ElapsedTime} / 60))
    Seconds=$((${ElapsedTime} - ${Minutes} * 60))
    
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Zimbra downtime: ${Hours} hour(s) ${Minutes} minute(s) ${Seconds} second(s)" >> ${TEMPLOG}
    
    ## Restore the zimbra crontab schedule.
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Restore Zimbra crontab schedule." >> ${TEMPLOG}
    crontab -u zimbra ${ZMCRONFILE}
    RETURNVALUE=$?
    if [ ${RETURNVALUE} -ne 0 ]; then
      ## Could not restore the zimbra crontab schedule.
      ## This is considered a non-fatal error and the script will continue.
      f_sendmail "Offline RSync Backup Warning - Crontab" "Could not restore the zimbra crontab schedule using ${ZMCRONFILE}  RETURN VALUE = ${RETURNVALUE}"
      ERRORFLAG=$((${ERRORFLAG} + 32))
    else
      ## Zimbra crontab schedule restored.  Remove temp file.
      rm ${ZMCRONFILE}
    fi
    
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Space consumed in ${TARGETDIR} = `du -sh ${TARGETDIR} | awk '{ print $1 }'`" >> ${TEMPLOG}
    
    ## Show status of Zimbra services.
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Status of Zimbra services:" >> ${TEMPLOG}
    su - zimbra -c "zmcontrol status" >> ${TEMPLOG}
    
    ## Compress the backup into a single file based on archive method specified.
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Compressing archive: ${TEMPDIR}/${ARCHIVEFILE}" >> ${TEMPLOG}
    case "${ARCHIVEMETHOD}" in
    tar.7z)
      tar -cpf - ${TARGETDIR} | 7za a -si -mx=9 -w${TEMPDIR} ${TEMPDIR}/${ARCHIVEFILE} 1>/dev/null 2>&1
      ## Restore using one of the following commands (do not uncomment, only for notation):
      ## 7za x -so -w/tmp ${TEMPDIR}/${ARCHIVEFILE} | tar -C / -xf -
      ## 7za x -so -w/tmp ${TEMPDIR}/${ARCHIVEFILE} | tar -C ${TEMPDIR}/restore --strip-components=1 -xf -
      ;;
    tgz)
      tar -cpzf ${TEMPDIR}/${ARCHIVEFILE} ${TARGETDIR} 1>/dev/null 2>&1
      ## Restore using one of the following commands (do not uncomment, only for notation):
      ## tar -C / -xzf ${TEMPDIR}/${ARCHIVEFILE}
      ## tar -C ${TEMPDIR}/restore --strip-components=1 -xzf ${TEMPDIR}/${ARCHIVEFILE}
      ;;
    *)
      tar -cpzf ${TEMPDIR}/${ARCHIVEFILE} ${TARGETDIR} 1>/dev/null 2>&1
      ;;
    esac
    
    RETURNVALUE=$?
    if [ ${RETURNVALUE} -ne 0 ]; then
      ## tar command failed.  Send warning email.
      f_sendmail "Offline RSync Backup Failure - tar" "tar failed with return value of ${RETURNVALUE}"
      ERRORFLAG=$((${ERRORFLAG} + 2))
    fi
    
    ## Mount the Windows share folder. ##
    f_mount
    sleep 2
    if [ ! -f ${OFFSITETESTFILE} ]; then
      ## Could not find expected file on remote site.  Assuming failed mount.
      ERRORFLAG=$((${ERRORFLAG} + 64))
      f_sendmail "Offline RSync Backup - Win Mount Error" "${HOSTNAME} could not detect ${OFFSITETESTFILE}"
    else
      ## Remote site is available.
      FREESPACE=`df -k ${OFFSITEDIR} | grep ${OFFSITEDIR} | awk '{ print $3 }'`
      BACKUPSIZE=`ls -lak "${TEMPDIR}/${ARCHIVEFILE}" | awk '{ print $5 }'`
    
      ## Make sure space is available on the remote server to copy the file.
      if [ ${FREESPACE} -lt ${BACKUPSIZE} ]; then
        ## Not enough free space available.  Purge existing backups until there is room.
        ENOUGHSPACE=0
        while [ ${ENOUGHSPACE} -eq 0 ]
        do
          f_PurgeOldestArchive
          RETURNVALUE=$?
          case ${RETURNVALUE} in
          1)
            ## Cannot purge archives to free up space.  End program gracefully.
            echo "`date +%Y-%m-%d_%H:%M:%S` - ERROR: Not enough free space on ${OFFSITEDIR} and cannot purge old archives.  Script aborted." >> ${TEMPLOG}
            ## Stop and exit the script with an error code.
            ERRORFLAG=$((${ERRORFLAG} + 4))
            f_emergencyexit ${ERRORFLAG}
            ;;
          9)
            ## Configuration error, end program gracefully.
            echo "`date +%Y-%m-%d_%H:%M:%S` - ERROR: Configuration problem. Script aborted." >> ${TEMPLOG}
            ## Stop and exit the script with an error code.
            ERRORFLAG=$((${ERRORFLAG} + 8))
            f_emergencyexit ${ERRORFLAG}
            ;;
          esac
          FREESPACE=`df -k ${OFFSITEDIR} | grep ${OFFSITEDIR} | awk '{ print $3 }'`
          if [ ${FREESPACE} -gt ${BACKUPSIZE} ]; then
            ## Enough space is now available.
            ENOUGHSPACE=1
          else
            ## Not enough space is available yet.
            ENOUGHSPACE=0
          fi
        done  
      fi
    
      ## Copy the backup to an offsite storage location.
      echo "`date +%Y-%m-%d_%H:%M:%S` --- Copying archive file to offsite location." >> ${TEMPLOG}
      cp ${TEMPDIR}/${ARCHIVEFILE} ${OFFSITEBACKDIR}/${ARCHIVEFILE} 1>/dev/null 2>&1
      if [ ! -f ${OFFSITEBACKDIR}/${ARCHIVEFILE} ]; then
      ## NON-FATAL ERROR: Copy command did not work.  Send email notification.
        echo "`date +%Y-%m-%d_%H:%M:%S` --- WARNING: Remote copy failed. ${OFFSITEBACKDIR}/${ARCHIVEFILE} does not exist!" >> ${TEMPLOG}
        f_sendmail "Offline RSync Backup Failure - Remote Copy" "Remote copy failed. ${OFFSITEBACKDIR}/${ARCHIVEFILE} does not exist\n\nBackup file still remains in this location: ${HOSTNAME}:${TEMPDIR}/${ARCHIVEFILE}"
      else
        ## Remove local copy of the compressed backup file
        rm ${TEMPDIR}/${ARCHIVEFILE}
      fi
    fi
    ## Unmount the Windows shared folder.
    f_umount
    
    ## Calculate total time for backup.
    FinishTime="$(date +%s)"
    ElapsedTime="$(expr ${FinishTime} - ${StartTime})"
    Hours=$((${ElapsedTime} / 3600))
    ElapsedTime=$((${ElapsedTime} - ${Hours} * 3600))
    Minutes=$((${ElapsedTime} / 60))
    Seconds=$((${ElapsedTime} - ${Minutes} * 60))
    
    echo "`date +%Y-%m-%d_%H:%M:%S` --- Total backup time: ${Hours} hour(s) ${Minutes} minute(s) ${Seconds} second(s)" >> ${TEMPLOG}
    echo "`date +%Y-%m-%d_%H:%M:%S` - Offline RSync backup completed." >> ${TEMPLOG}
    
    ## Perform cleanup routine.
    f_cleanup
    ## Exit with the combined return code value.
    exit ${ERRORFLAG}
    Example output in the log file:
    Code:
    2011-10-28_17:43:21 - Offline RSync backup started.
    2011-10-28_17:43:21 --- Partition status:
    Filesystem           1K-blocks      Used Available Use% Mounted on
    /dev/mapper/LVG-root   3842104   1467924   2179008  41% /
    none                   2025164       188   2024976   1% /dev
    none                   2030020         0   2030020   0% /dev/shm
    none                   2030020       296   2029724   1% /var/run
    none                   2030020         0   2030020   0% /var/lock
    none                   2030020         0   2030020   0% /lib/init/rw
    none                   3842104   1467924   2179008  41% /var/lib/ureadahead/debugfs
    /dev/sda1               182331     33053    139550  20% /boot
    /dev/mapper/LVG-bak  240306696   3333320 224766480   2% /var/backup
    /dev/mapper/LVG-opt  120152260   3287176 110761636   3% /opt
    /dev/mapper/LVG-temp 240306696    799184 227300616   1% /var/temp
    2011-10-28_17:43:22 --- Begin pre-shutdown rsync command.
    2011-10-28_17:45:10 --- Backup and disable Zimbra crontab schedule.
    2011-10-28_17:45:10 --- Stopping Zimbra services.
    2011-10-28_17:45:54 --- Space consumed in /opt/zimbra = 3.3G
    2011-10-28_17:45:58 --- Begin post-shutdown rsync command.
    2011-10-28_17:47:05 --- Starting Zimbra services.
    2011-10-28_17:48:32 --- Zimbra downtime: 0 hour(s) 3 minute(s) 22 second(s)
    2011-10-28_17:48:32 --- Restore Zimbra crontab schedule.
    2011-10-28_17:48:33 --- Space consumed in /temp/zimbra = 3.4G
    2011-10-28_17:48:35 --- Status of Zimbra services:
    Host mail.mydomain.com
    	antispam                Running
    	antivirus               Running
    	ldap                    Running
    	logger                  Running
    	mailbox                 Running
    	mta                     Running
    	snmp                    Running
    	spell                   Running
    	stats                   Running
    	zmconfigd               Running
    2011-10-28_17:48:50 --- Compressing archive: /var/temp/2011-10-28_zmbackup.tar.7z
    2011-10-28_18:10:09 --- Copying archive file to offsite location.
    2011-10-28_18:23:38 --- Total backup time: 0 hour(s) 38 minute(s) 28 second(s)
    2011-10-28_18:23:39 - Offline RSync backup completed.
    2011-10-28_18:23:39 - Offline RSync backup exit code: 0

    To test the online script, make sure you are root and type the following commands:
    Code:
    nohup ./rsync-online.sh &
    tail -f /var/temp/rsync-online*.log
    The command above will start the script in the background and will allow it to run even if you log off the system.

    The tail command will display the last 10 lines of the log. The -f option will keep the command active and continuously show the end of the log...thus you can sit there and just watch the entries show up in the log as they are written (works with any log file). Also note that this is the temporary log file which everything is placed until the very end...which is then copied to the main log file shared between both online and offline scripts.

    Press CTRL+C to stop watching the log file.

    Reference: OSE Backup Procedures (multiple)

    NOTE: Synchronize files with rsync
    Last edited by LHammonds; 01-16-2012 at 01:49 PM.
    Type su - zimbra -c "zmcontrol -v" to get your version and copy that into your profile (more info here)

Similar Threads

  1. zmperditionctl start asking for password
    By k7sle in forum Administrators
    Replies: 32
    Last Post: 02-20-2008, 10:13 AM
  2. Replies: 31
    Last Post: 12-15-2007, 08:05 PM
  3. Post instsallation problems
    By Assaf in forum Installation
    Replies: 14
    Last Post: 01-29-2007, 10:38 AM
  4. 3.1 on FC4 problems
    By cohnhead in forum Installation
    Replies: 8
    Last Post: 05-26-2006, 11:16 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •