Problem

RAID-1 (mirroring) is a popular approach to protect the system from
a harddisk failure. It is either done in hardware or software.
The usual hardware solution is to buy a RAID disk controller like
the popular 3ware ATA RAID controllers and then not having to deal
with any software incompatibilities because the system just sees one
large physical disk.

The software solution is less expensive and more flexible, but
usually makes more trouble during booting. Because an important
point in establishing a software RAID-1 for the system disk
partitions is whether one can directly boot from the resulting
mirror setup without ugly BIOS and/or boot loader tricks.
Additionally, IMHO it is also important that in case of a major
problem with the RAID-1 software driver, one is still able to easily
rescue boot from the mirror setup by treating it like a plain disk
setup again.

Possibilities

For software solutions in
FreeBSD 6 one can choose between
the raw ata(4),
the good old ccd(4),
the GEOM gvinum(8)
and the GEOM gmirror(8).
Each one has its pros and cons:

ATA:
Although the ATA driver's RAID functionality is intended
for hardware RAID controllers, it allows for creating an
ATA RAID-1 on disks with any controller. This is the most
raw approach, is suitable for ATA/IDE drives only and has
functional restrictions.

CCD:
This is the good old Concatenated Disk Driver (CCD) which
provides both Concatenation, RAID-0 (Striping) and RAID-1
(Mirroring). It was converted to use GEOM in FreeBSD 5,
but it has less features than GEOM mirror AFAIK.

GEOM Vinum:
This is the GEOM-based re-implementation of the old Vinum, a
logical volume manager inspired by Veritas Volume Manager.
It provides all major RAID levels including RAID-1 and
additionally is a full-scale volume manager.

GEOM Mirror:
This is the GEOM Mirror, a dedicated GEOM class for
establishing a RAID-1. It is a full-featured from-scratch
implementation and IMHO the best RAID-1 for production use.

I currently prefer GEOM mirror for establishing such a RAID-1
solution for the system disk partitions because it both provides the
possibility to directly boot from the mirror without tricks and is a
really clean and modern solution. Additionally, GEOM based solutions
can be stacked in an arbitrary way, i.e., the resulting GEOM mirror
is just another GEOM "provider" on which one can base any other
GEOM "consumers", including GEOM striping (gstripe), GEOM based
disk encryption (gbde) or my most favorite: GEOM labeling (glabel)
of UFS filesystems (see tunefs(8) for "tunefs -L").

Solutions

The FreeBSD 6 geom(4) framework
is an excellent abstraction layer for disk I/O. The GEOM gmirror(8) class is a software
RAID-1 implementation which can be used even for establishing a
mirror for the system disk partitions. GEOM mirror is very flexible
and actually can be established for any GEOM "providers", including
whole disks or just particular slices on a disk. Unfortunately each
approach has again pros and cons and hence should be carefully
understood before using one of them:

GEOM mirror on whole disk:
This is straight-forward and obvious and results in having
the whole disk mirrored, including its MBR. Unfortunately
is works only if the two disks are really equal in size or
at least requires that the mirror is established on the
smaller disk first and that space is lost on the second
disk. Finally, in case of a replacement disk (which usually
is a lot larger because available disks expand and expand in
size without actually getting a lot more expensive), one
completely waste disk space.

GEOM mirror on slices of a disk:
This is a little bit less obvious, but provides a lot more
flexibility and especially allows the usage of disks of
different size plus the possibility to still use (either for
a second mirror or as plain partitions) the unused space on
the disks.

GEOM mirror on partitions of a slice on a disk:
This is even less obvious, but provides the ultimative
flexibility and especially allows the usage of slices of
different size or to mirror just a subset of the partitions.

As the first approach "GEOM mirror on whole disk" is usually not
reasonable in practice (where disks are often just nearly equal in
size), and the third approach "GEOM mirror on partitions of a slice
on a disk" is usually total overkill (both from the requirement,
configuration and understanding point of view), I personally prefer
the second approach "GEOM mirror on slices of a disk" as it provides
good enough flexibility but still easy enough management.

Implementation

The following is a step-by-step command list for remotely converting
a production FreeBSD 6.2-STABLE (i386 or amd64 PC architecture
based) system from a single-disk/single-slice (ad0s1) to a
two-disk/single-slice (ad0s1 & ad1s1) GEOM mirror (gm0) based
setup without the need for console access or Fixit/LiveFS CDROM:

Final notice: In case of a drive failure, after you've replaced the
broken drive with a new one just remember that you have to apply
the second part of the step-by-step list for this drive again.
Especially do not forget to fdisk(8) it again before adding to the
GEOM mirror.