ATTENTION: CifarelliWiki is not now, nor was it ever, intended to be a public wiki.

New tvpc

From CifarelliWiki
Jump to: navigation, search

The distribution is Archlinux x86_64


Hardware

ASUS E-45M1-M Pro E-450 A50M R (Hudson M1 APU, includes ATI HD 6320 graphics) UEFI MB
2 Seagate ST31000524AS 1T, SATA 6 32M as a Raid 1 array
G.Skill 8GB (2 x 4GB) DDR3 240 pin
300W PS

Disk setup

First, we want to make GPT partitions, so we use gdisk (which is like the old fdisk, but it is GPT compatible). So we make 3 partitions on each disk (sda and sdb):

partition 1: type ef00, 6GB (2048 - 12584959)
partition 2: type 8200, 8GB (12584960 - 29362175)
partition 3: type fd00, 917.5GB (29362176 - 1953525134)

create a VFAT filesystem on the 1st partition:

# mkfs.vfat -F32 /dev/sda1
# mkfs.vfat -F32 /dev/sdb1

(we only need one, but we're building a poor man's mirror for this partition.)

and swap on the 2nd:

# mkswap /dev/sda2
# mkswap /dev/sdb2

and a raid disk out of the 3rd partition:

# mdadm /dev/md0 --create --level=1 --raid-devices=2 /dev/sda3 /dev/sdb3

let it build and the make a volume group on it:

# vgchange -ay
# pvcreate /dev/md0
# vgcreate vg0 /dev/md0
# lvcreate /dev/vg0 -L 20G -n root
# lvcreate /dev/vg0 -L 20G -n var
# lvcreate /dev/vg0 -L 20G -n boot
# lvcreate /dev/vg0 -L 825G -n home
# mkfs -t ext2 /dev/vg0/boot
# mkfs -t ext4 /dev/vg0/root
# mkfs -t ext4 /dev/vg0/var
# mkfs -t ext4 /dev/vg0/home

Mountpoints as follows:

/dev/vg0/root /
/dev/vg0/boot /boot
/dev/sda2     /boot/efi
/dev/sdb2     /boot/efi2
/dev/vg0/var  /var
/dev/vg0/home /home

and follow the Arch install directions [1] or [2]

don't forget to add the mdadm and lvm2 hooks in mkinitcpio in /etc/mkinitcpio.conf

HOOKS="base udev autodetect pata scsi sata mdadm lvm2 filesystems usbinput fsck"

UPDATE: you need the mdadm_udev hook instead of the deprecated mdadm hook as of Feb '13. The hook "block" replaces pata, scsi, sata and keyboard replaces usbinput. Also add the dm_mod module to the MODULES list:

MODULES="dm_mod"
HOOKS="base udev autodetect modconf block mdadm_udev lvm2 filesystems keyboard fsck"

and

# mkinitcpio -p linux


(note that the install cd includes gdisk, but you will need to install it separately after the install.)

UPDATE: I added an opt partition, also of size 20G.

UEFI Setup

This was the thing that took the longest. At this time (Nov 2012) we are making the transition from the old BIOS/MBR motherboards/partitions to the newer UEFI/GPT MB/Partitions.

But, in the end it was mostly just following these instructions [3] using EFISTUB and rEFInd.

But modified to copy kernels to /boot/efi2 as well as /boot/efi

UPDATE: Jan 2014 /dev/sda failed (of course), and when I was replacing it I somehow messed it up (I think by using the -w flag on efibootmgr).

So I switched to gummiboot, using /dev/sdb1 as the efi partition. /dev/sda1 exists, but the boot nvram entry now points to /dev/sdb1 instead.

Couple of things:

- Don't forget that the disks need to be partitioned as GPT disks use gdisk for this. (parted, gparted, gptfdisk, (maybe) fdisk with GPT support are other options, but gdisk works).

- Don't use efibootmgr -w to "write a unique signature" on your new disk. If you get this error, there is probably something else wrong.

- I booted into an arch install for rescue, but for some reason efibootmgr below wouldn't work properly within the chroot. It could be because the arch install in the chroot was newer, and some incompatible shlib may have been picked up. But worse was it caused dump-* files to be created in /sys/firmware/efi/efivars, resulting in "no room on device" or similar error I cant remember now when creating the boot entry in nvram. Needed to not only delete the dump-* files, but also reboot the rescue with kernel parameter efi_no_storage_paranoia to get the boot entry created.

If a disk fails, you need to rebuild the array /dev/md0 and may have to reinstall the bootloader. Well, it seems to me you always have to do something with the bootloader, but damned if I can predict it.

Setup the partitions

Create FAT32 UEFI System Partitions on /dev/sdb1 as above.
Mount the UEFI System Partitions at /boot/efi. [and /dev/sda1 on /boot/efi2 to save the latest kernel in case a disk crashes]
Create /boot/efi/EFI/arch/ directory.
Copy /boot/vmlinuz-linux to /boot/efi/EFI/arch/vmlinuz-arch.efi (and /boot/efi2/EFI/arch/vmlinuz-arch.efi). 
   The .efi file extension is very important as some UEFI firmwares refuse to launch a file without the .efi file extension.
Copy /boot/initramfs-linux.img to /boot/efi/EFI/arch/initramfs-arch.img.
Copy /boot/initramfs-linux-fallback.img to /boot/efi/EFI/arch/initramfs-arch-fallback.img.
   A new feature to be introduced in kernel 3.7 is the ability to store the kernel boot parameters in a file.
   [begin: unnecessary, but no harm.  only needed for refind]
   I did this even though the kernel I'm on is only 3.6.6.
   So, create /boot/efi/EFI/arch/linux.conf with the kernel parameters to be passed to the kernel. 
   This file should consist of only one line and simply contains all the kernel parameters to be used by the EFISTUB loader to the kernel:

   root=PARTUUID=31be0116-401c-4499-96c0-7433afd9a9be ro rootfstype=ext4 add_efi_memmap initrd=\EFI\arch\initramfs-arch.img
   [end: unnecessary]

Kernel copy service

Since the kernel and initramfs will be placed in /boot everytime they're upgraded, we add a copy service to systemd (systemd has the ability to monitor files and execute scripts when they change).

create /etc/systemd/system/efistub_copy.path

[Unit]
Description=Copy EFISTUB Kernel and Initramfs to UEFISYS Partition

[Path]
PathChanged=/boot/initramfs-linux-fallback.img
Unit=efistub_copy.service

[Install]
WantedBy=multi-user.target


and /etc/systemd/system/efistub_copy.service

[Unit]
Description=Copy EFISTUB Kernel and Initramfs to UEFISYS Partition

[Service]
Type=oneshot
ExecStart=/bin/cp -f /boot/vmlinuz-linux /boot/efi/EFI/arch/vmlinuz-arch.efi
ExecStart=/bin/cp -f /boot/initramfs-linux.img /boot/efi/EFI/arch/initramfs-arch.img
ExecStart=/bin/cp -f /boot/initramfs-linux-fallback.img /boot/efi/EFI/arch/initramfs-arch-fallback.img
ExecStart=/bin/cp -f /boot/vmlinuz-linux /boot/efi2/EFI/arch/vmlinuz-arch.efi
ExecStart=/bin/cp -f /boot/initramfs-linux.img /boot/efi2/EFI/arch/initramfs-arch.img
ExecStart=/bin/cp -f /boot/initramfs-linux-fallback.img /boot/efi2/EFI/arch/initramfs-arch-fallback.img

The path service needs to be enabled and started - it's the actual monitor.

# systemctl enable efistub_copy.path
# systemctl start efistub_copy.path

The copy service is static; it will be called by the path service, so it does not need to be enabled/started.

Booting EFISTUB with gummiboot

Install gummiboot and create a boot entry in the nvram:

# pacman -Sy gummiboot
# gummiboot --path=/boot/efi install

to display the efi system's view of gummiboot's install:

# gummiboot --path=/boot/efi

will display:

Boot Loader Binaries:
          ESP: /dev/disk/by-partuuid/bb38ac70-1730-41c1-aad5-355b6288a299
         File: └─/EFI/gummiboot/gummibootx64.efi (gummiboot 31)
         File: └─/EFI/Boot/bootx64.efi (gummiboot 31)

Boot Loader Entries in EFI Variables:
        Title: Linux Boot Manager
           ID: 0x0000
       Status: active, boot-order
    Partition: /dev/disk/by-partuuid/bb38ac70-1730-41c1-aad5-355b6288a299
         File: └─/EFI/gummiboot/gummibootx64.efi

To view the nvram:

# modprobe efivars
# efibootmgr -v

will display:

BootCurrent: 0000
Timeout: 1 seconds
BootOrder: 0000,0005
Boot0000* Linux Boot Manager    HD(1,800,bff800,bb38ac70-1730-41c1-aad5-355b6288a299)File(\EFI\gummiboot\gummibootx64.efi)
Boot0005* Hard Drive    BIOS(2,0,00)SATA: ST31000524AS            .

Note that the uuid in the Linux Boot Manager entry is the partition uuid (the one displayed by partx).

Check the man page on efibootmgr for how to manipulate the nvram boot entries.

Now configure gummiboot:

1. edit /boot/efi/loader/loader.conf

#timeout 3
default arch*

(yes I've commented out the timeout; I'm only using the default entry)

2. edit or create /boot/efi/loader/entries/arch.conf

title Arch Linux
efi /EFI/arch/vmlinuz-arch.efi
options initrd=/EFI/arch/initramfs-arch.img ro root=UUID=31be0116-401c-4499-96c0-7433afd9a9be rootfstype=ext4 add_efi_memmap

Note that the UUID listed in the options is not the partition uuid (the one from partx) but rather the one generated by genfstab. In my case (LVM) that should be obvious, I think.

To display both UUIDs, use blkid:

# blkid
/dev/sdb1: UUID="5885-A37A" TYPE="vfat" PARTUUID="bb38ac70-1730-41c1-aad5-355b6288a299"
/dev/sdb2: UUID="5a47cb61-c9fe-4d9b-a023-51fa2e4d6b8c" TYPE="swap" PARTUUID="42f54815-bf32-4e54-ab37-4c64fdbcf68c"
/dev/sdb3: UUID="7773f1ad-724e-380e-be26-e23d9c3c6710" UUID_SUB="c91517c3-2e3f-5d91-b814-3d08be39d6bf" LABEL="archiso:0" TYPE="linux_raid_member" PARTUUID="1a77ba1f-8088-4626-8897-c6a6425b0424"
/dev/sda1: UUID="B8D7-B197" TYPE="vfat" PARTUUID="a9b4d71e-8b65-4b9a-a721-46222658ab68"
/dev/sda2: UUID="f84116cb-eb0e-4a20-9686-1229a6357bab" TYPE="swap" PARTUUID="086c52c1-8ab4-4414-b36a-1c3b39007cfb"
/dev/sda3: UUID="7773f1ad-724e-380e-be26-e23d9c3c6710" UUID_SUB="1328c0c8-363d-2ee4-9ec4-1627694fcee0" LABEL="archiso:0" TYPE="linux_raid_member" PARTUUID="30f3324e-0543-48fc-aaca-659695413ed1"
/dev/md0: UUID="ZM6x42-fHmt-tDaN-Dfqc-9K5i-4eWh-HL68VU" TYPE="LVM2_member"
/dev/mapper/vg0-root: UUID="31be0116-401c-4499-96c0-7433afd9a9be" TYPE="ext4"
/dev/mapper/vg0-boot: UUID="32b0e434-38c3-4f0b-92b7-fa390953d9ec" TYPE="ext2"
/dev/mapper/vg0-var: UUID="3693fd50-2c30-4e24-9492-c2dde4939c99" TYPE="ext4"
/dev/mapper/vg0-home: UUID="fd2557be-5567-464e-a7fb-dba9b4944318" TYPE="ext4"

Now create a path monitor and install service for gummiboot. This is necessary because gummiboot assumes by default that the EFI partition is mounted at /boot, and we are mounting it at /boot/efi. So when an upgrade occurs, the gummiboot install fails.

/etc/systemd/system/gummiboot_install.path:

[Unit]
Description=Reinstall gummiboot on upgrade to UEFISYS Partition

[Path]
PathChanged=/usr/lib/gummiboot/gummibootx64.efi
Unit=gummiboot_install.service

[Install]
WantedBy=multi-user.target

/etc/systemd/system/gummiboot_install.service:

[Unit]
Description=Install gummiboot bootloader to UEFISYS Partition on upgrade

[Service]
Type=oneshot
ExecStart=/usr/bin/gummiboot --path=/boot/efi install

Enable the path service as before:

# systemctl enable gummiboot_install.path
# systemctl start gummiboot_install.path

Booting EFISTUB with rEFInd

** this section no longer necessary, but of no real harm.  now using gummiboot **

Now setup for booting EFISTUB using rEFInd. This part got a little tricky.

EFI, unlike MBR, allows you to boot directly a number of OSs, so in that respect it is like a bootloader. rEFInd is a boot loader, so it's like you install it as an EFI "loader", and it then allows you to load any number of other kernels. So I guess it's just more mature as an EFI loader at this time than egrub or elilo.

It took a little trial and error, but apparently what it does is scan for all loadable efi images in the efi partition you created before. So (if you allow it), it also adds itself and any other kernels it finds. Following the instructions, I modified the config file (EFI/refind/refind.conf) to explicitly include the kernels, which (I think) added them again. The instructions said to modify this file "accordingly, it is well documented", and it gave examples of adding entries, so really a little more explanation would have been good.

(Note, everything done below is also done with /boot/efi2)

install refind:

# pacman refind-efi
# mkdir /boot/efi/EFI/refind
# cp /usr/lib/refind/refindx64.efi /boot/efi/EFI/refind/refindx64.efi
# cp /usr/lib/refind/config/refind.conf /boot/efi/EFI/refind/refind.conf
# cp -r /usr/share/refind/icons /boot/efi/EFI/refind/icons

now create /boot/EFI/arch/refind_linux.conf

"Boot with defaults" "root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 ro rootfstype=ext4 add_efi_memmap systemd.unit=graphical.target"
"Boot to Terminal"   "root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 ro rootfstype=ext4 add_efi_memmap systemd.unit=multi-user.target"

It seems like refind scans for this file and adds entries for each one, but it doesnt seem to find icons for it, and noe that I have done this I'm not sure I'm really using this file.

Now I edited EFI/refind/refind.conf and made the following changes:

Uncomment/modify:

...
timeout 5
...
icons_dir \EFI\icons
...
dont_scan_dirs EFI/boot,EFI/arch,EFI/refind

(actually, I ended up removing the EFI/boot directory, which was supposed to be some kind of failsafe)

Add these lines at the end:

menuentry "Arch Linux" {
        icon EFI/icons/os_linux.icns
        loader \EFI\arch\vmlinuz-arch.efi
        initrd \EFI\arch\initramfs-arch.img
        options "ro root=UUID=31be0116-401c-4499-96c0-7433afd9a9be rootfstype=ext4 add_efi_memmap initrd=\EFI\arch\initramfs-arch.img"
}

menuentry "Arch Linux Fallback" {
        icon EFI/icons/os_linux.icns
        loader \EFI\arch\vmlinuz-arch.efi
        initrd \EFI\arch\initramfs-arch-fallback.img
        options "ro root=UUID=31be0116-401c-4499-96c0-7433afd9a9be rootfstype=ext4 add_efi_memmap initrd=\EFI\arch\initramfs-arch-fallback.img"
}

Now execute this:

# modprobe efivars
# efibootmgr -c -g -d /dev/sdX -p Y -w -L "rEFInd" -l '\EFI\refind\refindx64.efi'

Truth be told, I did something a bit more roundabout - I think what I've listed here is sufficient. In reality though I executed the efibootmgr line without the 'dont_scan' option in the config file, didnt like how the boot screen looked, and then did it again with the dont scan, which made multiple entries in EFI (I may have done it more than twice), so I deleted as many as I could but it wouldnt remove all of them, so then I added it the way I wanted and set the bootorder to 0001,0000. That resulted in a pretty decent boot screen (although the text annoyingly says "Boot Arch Linux from" and I cant figure out where to set "from").


Also create a service for when refind is updated:

/etc/systemd/system/refind_copy.path:

[Unit]
Description=Copy rEFInd bootloader to UEFISYS Partition

[Path]
PathChanged=/usr/share/refind/refind_x64.efi
Unit=refind_copy.service

[Install]
WantedBy=multi-user.target


/etc/systemd/system/refind_copy.service:

[Unit]
Description=Copy rEFInd bootloader to UEFISYS Partition

[Service]
Type=oneshot
ExecStart=/bin/cp -f /usr/share/refind/refind_x64.efi /boot/efi/EFI/refind/refindx64.efi
ExecStart=/bin/cp -f /usr/share/refind/refind_x64.efi /boot/efi2/EFI/refind/refindx64.efi
** end unnecessary **

Booting with GRUB

After the second Seagate drive failed, I couldn't get gummiboot to work (ARGH!!)

So converted to grub, which now supports UEFI much better.

Install:

# pacman grub dosfstools efibootmgr

Mount in /boot/efi:

# mount /dev/sda1 /boot

Execute grub-install:

# grub-install  --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=grub --recheck --debug

Create the config:

# grub-mkconfig -o /boot/grub/grub.cfg

Reboot and you are back to grub.

UPDATE: After installing a new video card (XFX HD 5450) I had to change the kernel command parameters. Honestly I'm not convinced this was necessary, but as with many things related to graphics, it didn't *seem* to work at first, but works after doing this. The way it works makes me suspicious that this is what fixed it. Anyway, to add to the kernel command line parameters, modify /etc/default/grub:

Change:

GRUB_CMDLINE_LINUX_DEFAULT="quiet"

To:

GRUB_CMDLINE_LINUX_DEFAULT="quiet video=HDMI-A-1:640x480@60 radeon.audio=1"

As an aside, I also had to select the proper device using pavcontrol.

If a disk fails

2 failed disks; 3 different boot methods. Frustrating, but we've learn a few things:

(I have to stop buying Seagate drives. Went to a WD Red for the last update.)

  1. Use smartctl -i /dev/sda to find the serial number, if you have identical disks.
  2. Print this page please before upgrading.
  3. Boot a rescue arch image to partition the disk, if adding the new disk causes UEFI to loose the prior boot disk (which it has 2x now)
  4. To boot from a UEFI shell (v1 or v2):
Shell> fs0:
 fs0:> cd \EFI\ARCH
 fs0:> vmlinuz-arch.efi initrd=/EFI/ARCH/initramfs-arch.img root=UUID=31be0116-401c-4499-96c0-7433afd9a9be rootfstype=ext4 add_efi_memmap

As mentioned before, the UUID is the lv /dev/vg0/root.

Network

eth0: Just plug in the cable. Dhcpcd is already running for all wired interfaces in Arch.

Wireless: Of course, more complicated, but getting better.

I'm using an Intel Centrino Advanced-N 6205 PCIe 1x card. Includes the half height bracket and an external antenna for signal strength. The card was detected without any trouble, the firmware and iwlwifi driver loaded as well.

Need to install iw and wpa_supplicant:

# pacman -Sy iw wpa_supplicant

Setup wpa_supplicant:

# cd /etc/wpa_supplicant
# cp ./wpa_supplicant.conf ./wpa_supplicant.conf.reference
# wpa_passphrase paulc_ap4 '<wireless password>' > ./wpa_supplicant.conf

Edit wpa_supplicant.conf and add lines to make it look like this:

update_config=1
ctrl_interface=/var/run/wpa_supplicant
eapol_version=1
ap_scan=1
fast_reauth=1
network={
        ssid="paulc_ap4"
        proto=WPA RSN
        key_mgmt=WPA-PSK WPA-EAP
        pairwise=CCMP
        group=CCMP
        #psk="<wireless password>" <-- obviously you dont need to keep this
        psk=<psk generated by wpa_passphrase>
}

Honestly I don't know how much of this we need. But it was taken from the wpa_supplicant.conf.reference. Note that RSN means "Robust Security Network" and is synonomous with WPA2.

change permissions to 0640:

# chmod 0640 ./wpa_supplicant.conf

Now create a system service /etc/systemd/system/network-wireless@.service:

[Unit]
Description=Wireless network connectivity (%i)
Wants=network.target
Before=network.target
BindsTo=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device

[Service]
Type=oneshot
RemainAfterExit=yes

ExecStart=/usr/bin/ip link set dev %i up
ExecStart=/usr/bin/wpa_supplicant -B -i %i -c /etc/wpa_supplicant/wpa_supplicant.conf
ExecStart=/usr/bin/dhcpcd %i

ExecStop=/usr/bin/ip link set dev %i down

[Install]
WantedBy=multi-user.target

When you want to use wireless,

# systemctl start network-wireless@wlan0

and to use wireless all the time:

# systemctl enable network-wireless@wlan0

[UPDATE] I decided to go with static IPs, which requires a few different things:

First, you need your own resolv.conf. The only necessary entry is the one for your wireless router, but I added OpenDNS and Google servers for reference. Because dhcpcd for eth0 will still overwrite resolv.conf on boot, name this file resolv.conf.head (it will be added by dhcpcd to resolv.conf, at the head):

nameserver 192.168.4.1
# OpenDNS nameservers
nameserver 208.67.222.222
nameserver 208.67.220.220
# Google nameservers
nameserver 8.8.8.8
nameserver 8.8.4.4

# OpenDNS ipv6 nameservers
nameserver [2620:0:ccc::2]
nameserver [2620:0:ccd::2]                                                                          
# Google ipv6 nameservers
nameserver [2001:4860:4860::8888]
nameserver [2001:4860:4860::8844]

Next, you need a modified /etc/systemd/system/network-wireless@.service:

[Unit]
Description=Wireless network connectivity (%i)
Wants=network.target
Before=network.target
BindsTo=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/etc/conf.d/network@%i

ExecStart=/usr/bin/ip link set dev %i up
ExecStart=/usr/bin/wpa_supplicant -B -i %i -c /etc/wpa_supplicant/wpa_supplicant-%i.conf
#ExecStart=/usr/bin/dhcpcd %i
ExecStart=/usr/bin/ip addr add ${address}/${netmask} broadcast ${broadcast} dev %i
ExecStart=/usr/bin/sh -c 'test -n ${gateway} && /usr/bin/ip route add default via ${gateway}'
ExecStart=/usr/bin/cp /etc/resolv.conf.static /etc/resolv.conf
#  
# Permanent ARP Entries:
# supposed to be the new way, but didn't work for me  
#ExecStart=/usr/bin/ip n add 192.168.4.102 lladdr 6c:88:14:99:18:20 dev %i nud perm  
#ExecStart=/usr/bin/ip n add 192.168.4.105 lladdr 00:13:ef:10:06:be dev %i nud perm  
# beast:
ExecStart=/usr/bin/arp -i %i -s 192.168.4.102 6c:88:14:99:18:20
# raspberrypi:
ExecStart=/usr/bin/arp -i %i -s 192.168.4.105 00:13:ef:10:06:be

ExecStop=/usr/bin/ip addr flush dev %i
ExecStop=/usr/bin/ip link set dev %i down

[Install]
WantedBy=multi-user.target

For a reason I was never able to ascertain, sometimes arp doesn't work properly on a wireless connection. This prevents us from finding those hosts, even though we can reach them from other machines. The problem happens on both windows and linux hosts, so I assume it's the wireless router. So here we add static arp entries.

On Kubuntui and Raspbian, add a script /etc/network/if-up.d/static-arp-entries (make it executable, 755)

#!/bin/sh

# tvpc
arp -i wlan0 -s <ip address> <MAC address>

# raspberrypi
arp -i wlan0 -s <ip address> <MAC address>

On Arch, add to network-wireless@.service as above.

On Windows 8.1 (and probably Windows 7), in Powershell running as Administrator:

netsh interface ipv4 delete neighbors 4 "192.168.4.103"
netsh interface ipv4 add neighbors 4 "192.168.4.103" "aa-bb-cc-dd-ee-ff"

replace the 4 (which is the index of the interface) with the index found when you do an "arp -a". These are permanent (they survive a reboot).

Bonding

UPDATE

I've been experimenting with powerline networking, now that they are approaching gigabit speeds. I have to say I'm pleasantly surprised.

I bought 4 ZyXEL PAL5215 (600Mbps) and have re-configured this server with a bonded interface, primary eth0, backup wlan0.

In the process I cleaned up the networking using netctl, which allows you to setup multiple profiles and switch between them easily.

setup netctl and bonding:

Disable network-wireless@wlan0, dhcpcd@eth0, and disable-eth0.service.

install netctl and ifenslave

# pacman -Sy netctl ifenslave

setup profiles in /etc/netctl

/etc/netctl/failover:

Description="Bonded interface ethernet to wireless failover"
Interface=bond0
Connection=bond
BindsToInterfaces=('eth0' 'wlan0')
IP=dhcp
#IP=static
#Address="10.0.1.103/24"
#Gateway="10.0.1.1"
#DNS=('10.0.1.1' '208.67.222.222' '208.67.220.220' '8.8.8.8' '8.8.4.4' '[2620:0:ccc::2]' '[2620:0:ccd::2]' '[2001:4860:4860::8888]' '[2001:4860:4860::8844]')

/etc/netctl/ethernet-dhcp (not needed, but we started with this):

Description='A basic dhcp ethernet connection'
Interface=eth0
Connection=ethernet
IP=dhcp
DHCPClient=dhcpcd
DHCPReleaseOnStop=no

/etc/netctl/wireless-wpa-config (also not needed...):

Description='A wpa_supplicant configuration file based wireless connection'
Interface=wlan0
Connection=wireless
Security=wpa-config
WPAConfigFile='/etc/wpa_supplicant/wpa_supplicant-wlan0.conf'
IP=dhcp

Create /etc/modules-load.d/bonding.conf to load the bonding module at boot:

bonding

Create /etc/modprobe.d/bonding.conf for the bonding module parameters:

options bonding mode=active-backup miimon=100 primary=eth0 max_bonds=0

activate the 'failover' profile (if switch-to fails try enable):

# netctl switch-to failover

enable wpa_supplicant@wlan0

systemctl enable wpa_supplicant@wlan0

Note that it will look for the file /etc/wpa_supplicant/wpa_supplicant-wlan0.conf (or more generally /etc/wpa_supplicant-interface.conf) to configure the wireless connection. We already created that above - use as is.

NOTE: BE SURE TO CHANGE THE DHCP RESERVATION ON THE AP TO USE THE BONDED ETHERNET MAC (from bond0)

At the time of this writing, there is a problem with the systemd dependencies (what else is new...). Create

# cd /etc/systemd/system
# mkdir wpa_supplicant@wlan0.service.d
# cd wpa_supplicant@wlan0.service.d

Create /etc/systemd/system/wpa_supplicant@wlan0.service.d/customdependency.conf

[Unit]
After=netctl@failover.service

reboot and check:

# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc fq_codel master bond0 state UP mode DEFAULT group default qlen 1000
    link/ether 30:85:a9:3d:c7:5f brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master bond0 state UP mode DORMANT group default qlen 1000
    link/ether 30:85:a9:3d:c7:5f brd ff:ff:ff:ff:ff:ff
4: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 30:85:a9:3d:c7:5f brd ff:ff:ff:ff:ff:ff

and

# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)

Bonding Mode: fault-tolerance (active-backup)
Primary Slave: eth0 (primary_reselect always)
Currently Active Slave: eth0
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0

Slave Interface: eth0
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 1
Permanent HW addr: 30:85:a9:3d:c7:5f
Slave queue ID: 0

Slave Interface: wlan0
MII Status: up
Speed: Unknown
Duplex: Unknown
Link Failure Count: 0
Permanent HW addr: 6c:88:14:97:04:fc
Slave queue ID: 0

and try unplugging the ethernet cable. It will seemlessly failover to wireless - all connections will remain active!

UPDATE: After putting in the netcfg profiles, I could no longer reach the server from the internal network. Not sure of the cause, but it's extremely inconvenient so I went to a straight ethernet config without netcfg (which also didnt switch reliably - insisting on stay with failover after a reboot, despite the switch-to and disable/enables I did). Probably I did something wrong with netctl, but not bothering at this time to figure it out.

So,

 systemctl disable netctl-ifplugd@eth0
 systemctl enable dhcpcd@eth0


Also, remove /usr/lib/dhcpcd/dhcpcd-hooks/35-localroutes or comment out

route del default eth0

When did I put that in? Why didn't I document it in these pages?

X Setup

Install these packages:

xorg-server
xorg-apps
xorg-xinit
xorg-twm
xorg-xclock
xterm

and for this setup, we will use the ati proprietary drivers:

make sure the dkms service is started

# pacman -Sy dkms
# systemctl enable dkms
# systemctl start dkms
# pacman catalyst-dkms catalyst-utils

and config with

# aticonfig --initial

Oddly enough, that was enough to get it working. Since I never installed xf86-video-ati, no need to blacklist radeon.

Test with startx.


UPDATE: the problem with using catalyst is that it doesn't keep up with Arch's aggressive update schedule. So I had to configure the catalyst and xorg113 repositories in /etc/pacman.conf in order to pick up the latest beta release of the driver (that supports the latest 3.8 kernel). I tried the open source driver and I simply cannot get it to work. Uninstall catalyst-dkms and install catalyst, reinstall catalyst-utils.

UPDATE 2: mesa still needs to be installed, otherwise kwin crashes (and you get no window decorations). Also, uninstall catalyst and install catalyst-hook instead, that way the fglrx module will get rebuilt with every kernel upgrade (much like catalyst-dkms).

KDE

Install using kde-meta.

# pacman -Sy kde-meta
# pacman -Sy clementine pavucontrol
# pacman -Sy alsa-tools
# pacman -Sy alsatools
# pacman -Sy alsa-utils
# pacman -Sy net-tools
# pacman -Sy bluedevil
# pacman -Sy flashplayer
# pacman -Sy firefox chromium
# pacman -Sy gstreamer0.10-good-plugins gstreamer0.10-bad-plugins gstreamer0.10-ugly-plugins gstreamer0.10-ffmpeg
# pacman -Sy pulseaudio-alsa
# pacman -Sy gstreamer0.10-pulseaudio
# pacman -Sy pulseaudio paprefs
# pacman -Sy gnome-media
# systemctl enable pulseaudio
# pulseaudio --start
# gconftool-2 -t string --set /system/gstreamer/0.10/default/audiosink pulsesink
# gconftool-2 -t string --set /system/gstreamer/0.10/default/audiosrc pulsesrc
# gconftool-2 -t string --set /system/gstreamer/0.10/default/musicaudiosink pulsesink

At some point I need to figure out why I have to use pavcontrol and/or kde system preferences for every user I create in order for hdmi sound to work (same problem I had with spdif on other systems), but honestly 1 user will be enough for these purposes. It could have something to do with audio group, which I didnt add to the users supplemental groups, but it works now so we'll worry about it later.

Pulseaudio

The holy grail of sound systems. I have trouble though.

What I'm trying to achieve is whole house audio. Everyone says its possible. Every time I think I have it working, the next reboot it stops and I can't get it back.

As I type this, it's working. I'm on beast, streaming to RTP and enabled speakers on tvpc through hdmi. Sound is great. Here are the settings in paprefs:

On beast (or any client ie the one playing music):
   Network Access tab -> check "Make discoverable PulseAudio network sound devices available locally"
   Network Server tab -> nothing checked
   Multicast/RTP tab -> check "Enable Multicast/RTP sender" & "Create separate audio device for Multicast/RTP"
On tvpc (or any "server", ie the one with speakers):
   Network Access tab -> check "Make discoverable PulseAudio network sound devices available locally" & "Make Apple Airplay Devices available locally"
   Network Server tab -> check "Enable network access to local sound devices", "Allow other machines on the LAN to discover local sound devices" and "Don't require authentication"
   Multicast/RTP tab -> check "Enable Multicast/RTP receiver"
   Simultaneous Output tab -> check "Add virtual output..."

On beast, start pavucontrol, and when the stream is playing, select RTP Multicast on the Playback tab. It works (for now).

On tvpc, make sure that the RTP Multicast playback stream selects "...HMDI..." or "Simultaneous Output ...HDMI..."

Bluetooth

# pacman -Sy bluedevil
# systemctl enable bluetooth
# systemctl start bluetooth

UPDATE: bluedevil uses the deprecated bluez4 (bluez version 4.x) - install from the AUR bluedevil-bluez5-git. UPDATE: bluedevil in the main repositories is now 5.x+

Rsync

Install package rsync

Edit /etc/rsyncd.conf, add:

[music]
        path = /home/media/Collection
        comment = Music Collection
        hosts allow = 192.168.4.0/24
        read only = no
        list = yes
        uid = media
        gid = users

start/enable the rsyncd service.

NTP

install ntp, edit /etc/ntp.conf - comment out the servers and replace with

server 0.north-america.pool.ntp.org
server 1.north-america.pool.ntp.org
server 2.north-america.pool.ntp.org
server 3.north-america.pool.ntp.org

ddclient

install ddclient

edit /etc/ddclient/ddclient.conf

##
## EasyDNS (easydns.com)
##
server=members.easydns.com,  \
protocol=easydns,            \
login=paulc,                 \
password=<password>          \
pcifarelli.net

Since it contains a password, set the permissions of this file to 0600 (owner/group can stay as root). and also uncomment

use=web, web=checkip.dyndns.org/, web-skip='IP Address'

and set

daemon=600

and enable the service

also, install dnsutils so you can check with nslookup, and postfix so that you have sendmail

squid

install squid

Squid access from outside the network is strictly controlled.

edit /etc/squid/squid.conf to allow access:

comment out:

#acl localnet src 10.0.0.0/8    # RFC1918 possible internal network
#acl localnet src 172.16.0.0/12 # RFC1918 possible internal network

modify:

acl localnet src 192.168.0.0/16 # RFC1918 possible internal network

to

acl localnet src 192.168.4.0/24 # RFC1918 possible internal network

uncomment:

http_access deny to_localhost


acl localnet src 192.168.4.0/24
acl vacationplace src 13.11.1.21/32
...
http_access allow localnet
http_access allow vacationplace

also change the port for security reasons:

http_port <im-not-telling>

(L)AMP (apache, mysql, php)

Install apache and php (mysql was already installed)

# pacman -S apache php php-apache php-pear

and (perhaps later)

# pear install channel://pear.php.net/Text_Highlighter-0.7.3

apache

Edit /etc/httpd/conf/httpd.conf, change

ServerAdmin paul@cifarelli.net
...
ServerName 192.168.4.103:80

and /etc/httpd/conf/extra/httpd-default.conf

ServerTokens Prod
ServerSignature Off

Create self-signed certificate

# cd /etc/httpd/conf
# openssl genrsa -des3 -out server.key 2048
# openssl req -new -key server.key -out server.csr
# cp server.key server.key.org
# openssl rsa -in server.key.org -out server.key
# openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt

UPDATE: RapidSSL certs are cheap (~$9/yr at this time), so I've upgraded. The process is similar. Generate a certificate signing request using the same private key that you generated above:

# openssl req -new -sha256 -key ./server.key -out cifarelli.net.rapidssl.csr

Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:Bronxville
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Cifarelli.net
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:www.cifarelli.net
Email Address []:paul@cifarelli.net

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Note that if you want to use the cert for all cifarelli.net aliases, make the common name *.cifarelli.net. Otherwise only www.cifarelli.net and cifarelli.net will be valid.

Go to https://www.ssls.com and login. Paste the generated CSR and follow the trail of emails and approvals.

Uncomment in /etc/httpd/conf/httpd.conf

Include conf/extra/httpd-ssl.conf

and change /etc/httpd/conf/extra/httpd-ssl.conf

ServerName cifarelli.net:443
ServerAdmin paul@cifarelli.net

When you get approved for the cert, you will get an email with 2 - your cert and an "intermediate certificate". Save your cert as

/etc/httpd/conf/server-rapidssl.pem

In /etc/httpd/conf/extra/httpd-ssl.conf, point

SSLCertificateFile    "/etc/httpd/conf/server-rapidssl.pem"
SSLCertificateKeyFile "/etc/httpd/conf/server.key"

UPDATE: SSLCertificateChainFile is obsolete as of apache 2.4.8. Instead, append the intermediate certificate to the server-rapidssl.crt file.

Don't forget to set permissions safely:

# chmod 0750 /etc/httpd/conf/
# chmod 0640 /etc/httpd/conf/server.key

If you want to allow a user to create their own website in their user directory, create ~/public_html and make sure their home directory is executable (default perms on home dirs are 0700; they need to be 0701 to serve ~user pages).

php

Edit httpd.conf and add

LoadModule php5_module modules/libphp5.so

and at the end

# PHP
Include conf/extra/php5_module.conf

Uncomment the following line:

MIMEMagicFile conf/magic

Edit conf/extra/php5_module.conf and add index.phtml to the DirectoryIndex directive:

DirectoryIndex index.php index.phtml index.html


Add this line in /etc/httpd/conf/mime.types:

application/x-httpd-php5		php php5

restart httpd

Test PHP: Create the file test.php in your Apache DocumentRoot directory and inside it put:

<?php phpinfo(); ?>

Check http://localhost/test.php

tomcat

install tomcat7 and edit /etc/topcat7/tomcat-users.xml
install maven
install apache-ant
install [AUR] glassfish-web-v4 and change the port in /opt/glassfish4-web/glassfish/domain1/config/domain.xml (optional) - 
   this is used if you want to develop in a non-production mode on the server.  
   I've worked on my laptop with both a glassfish server and a tomcat server and installed the resulting wars on the server.
   Consequently the service is not running on the server, to start it:
      # systemctl start glassfish-web

Tomcat will be running on port 8080. Tomcat webapps are in /usr/share/tomcat7 and logs are in /var/log/tomcat7.

You must configure /etc/tomcat7/tomcat-users.xml

<tomcat-users>
  <role rolename="tomcat"/>
  <role rolename="manager-gui"/>
  <role rolename="manager-script"/>
  <role rolename="manager-jmx"/>
  <role rolename="manager-status"/>
  <role rolename="admin-gui"/>
  <role rolename="admin-script"/>
  <user username="paulc" password="CHANGEME" roles="tomcat,manager-gui,manager-script,manager-jmx,manager-status,admin-gui,admin-script"/>
</tomcat-users>

The username is used to install war files with the manager app and can be anything.

mysql

Start the mysqld daemon and run the setup script:

# mysql_secure_installation

Restart mysqld and enable for bootup.

Enable networking in /etc/mysql/my.cnf:

#skip-networking

Enable autocompletion in my.cnf by changing no-auto-rehash to

auto-rehash

Now go back to /etc/php/php.ini and uncomment:

extension=mysql.so

and restart httpd

Upgrading

NOTE: After upgrading mysql run this:

# mysql_upgrade -p -u root

load the mediawiki database

copy the wikidb database from maximus:

# mysqldump --databases wikidb -u root -p > ./wikidb

load it on tvpc:

# mysql -u root -p < ./wikidb

create the wikiuser:

# grant all on wikidb.* to wikiuser@localhost identified by '<password>';
# flush privileges;

Mediawiki

Install php-gd and uncomment "extension=gd.so" in php.ini, same for php-intl (needs icu, already installed) and php-xcache (here add "extension=xcache.so") and finally install mediawiki, all available from the official repositories.

Create /etc/webapps/mediawiki/httpd-mediawiki.conf from the provided example apache.example.conf in the same directory. Edit it to remove the open_basedir line, which is already in php.ini.

Add the following lines to /etc/httpd/conf/httpd.conf

LoadModule php5_module modules/libphp5.so
Include conf/extra/php5_module.conf
Include /etc/webapps/mediawiki/httpd-mediawiki.conf

Adjust the open_basedir in /etc/php/php.ini to include the webapps directory (allows update.php to be run from the command line):

open_basedir = /srv/http/:/home/:/tmp/:/usr/share/pear/:/usr/share/webapps/

Adjust permissions in /usr/share/webapps/mediawiki/.htaccess, e.g. to

allow from all

Restart httpd

Open the wiki in a browser and do the initial setup to create /usr/share/webapps/mediawiki/LocalSettings.php.

Edit LocalSettings.php to set the $wgLogo = ""; so that there is no logo.

and, because people can't behave themselves, change the permissions so that only I can create users, and only I can edit.

$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['*']['edit'] = false;

and, to make almost all the pages private

$wgGroupPermissions['*']['read'] = false;
$wgWhitelistRead = array( "Main Page", "Server Setup", "New tvpc" );


Finally, enable the syntax highlighting extension (which is distributed with the base package, no additional installation):

wfLoadExtension( 'SyntaxHighlight_GeSHi' );


Don't forget to set the group for LocalSettings.php to http, and set the perms to 0640.

Edit /srv/http/index.html to add a link to mediawiki.

Setup monitoring of the mirror

Edit /etc/mdadm.conf:

MAILADDR paul@cifarelli.net
PROGRAM /usr/local/bin/diskfailmail.pl

and create /usr/local/bin/diskfailmail.pl

 #!/usr/bin/perl
 
 $emailto1 = 'paul.cifarelli@thomsonreuters.com';
 $emailto2 = 'paul.cifarelli@gmail.com';
 $emailto3 = 'paulc2@optonline.net';
 $whoami = 'paul@cifarelli.net';
 $hostn = 'pcifarelli.net (tvpc)';
 
 use Socket;
 use Sys::Syslog;
 
 $event1 = "Event: $ARGV[0], Array: $ARGV[1], Component: $ARGV[2]";
 
 openlog 'diskfailmail', 'pid', 'user';
 
 syslog 'info', "mdadm event $event1";
 
 $email1 = "To: $emailto1
 From: $whoami
 Subject: $hostn mdadm event
 
 $event1
 ";
 $email2 = "To: $emailto2
 From: $whoami
 Subject: $hostn mdadm event
 
 $event1
 ";
 $email3 = "To: $emailto3
 From: $whoami
 Subject: $hostn mdadm event
 
 $event1
 ";
 
 `echo '$email1' |/usr/sbin/sendmail -f $whoami -t`;
 `echo '$email2' |/usr/sbin/sendmail -f $whoami -t`;
 `echo '$email3' |/usr/sbin/sendmail -f $whoami -t`;
 
 closelog;

and chmod its permissions to rwx for root only.

test the email notification:

# mdadm --monitor --test --scan

Then start and enable the mdadm service

apcupsd

Install apcupsd

(Optional) edit /etc/apcupsd/apcupsd.conf

UPSNAME tvpcups

everything else was already setup by default for a usb style ups (the vast majority of ups's these days).

Start and enable the service. Check the status:

# apcaccess status

Should look something like this:

APC      : 001,034,0864
DATE     : 2012-12-01 12:26:43 -0500
HOSTNAME : tvpc
VERSION  : 3.14.10 (13 September 2011) unknown
UPSNAME  : tvpcups
CABLE    : USB Cable
DRIVER   : USB UPS Driver
UPSMODE  : Stand Alone
STARTTIME: 2012-12-01 12:24:40 -0500
MODEL    : Back-UPS ES 550G
STATUS   : ONLINE
LINEV    : 123.0 Volts
LOADPCT  :   1.0 Percent Load Capacity
BCHARGE  : 100.0 Percent
TIMELEFT : 355.8 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME  : 0 Seconds
SENSE    : Medium
LOTRANS  : 092.0 Volts
HITRANS  : 139.0 Volts
ALARMDEL : 30 seconds
BATTV    : 13.6 Volts
LASTXFER : No transfers since turnon
NUMXFERS : 0
TONBATT  : 0 seconds
CUMONBATT: 0 seconds
XOFFBATT : N/A
STATFLAG : 0x07000008 Status Flag
SERIALNO : 4B1241P34296
BATTDATE : 2012-10-12
NOMINV   : 120 Volts
NOMBATTV :  12.0 Volts
FIRMWARE : 843.K4 .D USB FW:K4
END APC  : 2012-12-01 12:27:31 -0500


Mail

To add a new mailbox:

  1. Navigate to http://pcifarelli.net:8846/postfixAdmin and login (the admin account is paul@cifarelli.net)
  2. if the domain doesn't exist, add it
  3. add the mailbox in the domain
  4. if procmail filtering is desired, add the account to /etc/postfix/transport (spam will automatically be moved to a folder "Junk" if the client creates one)
  5. Edit /etc/fetchmailrc to include the new mailbox


To setup a Thunderbird client:

Use mail.pcifarelli.net as an IMAP server, Port: 993, Protocol: SSL, Authentication: Normal Password
Use mail.pcifarelli.net as the outgoing smtp server, Port: 587, Protocol: STARTTLS, Authentication: Normal Password.
Username is your full email address, e.g. paul@cifarelli.net

To change your password, logon to webmail (webmail.cifarelli.net or webmail.pcifarelli.net) and change it there.

The rest of this section tells how it was setup.

Postfix

(note that you already installed postfix here New tvpc#ddclient)

Edit /etc/postfix/main.cf

myhostname = mail.cifarelli.net
mydomain = cifarelli.net
myorigin = $mydomain
...
mydestination = localhost
...
mynetworks_style = subnet
...
relayhost = [mail.optonline.net]
...
home_mailbox = Maildir/


The more proper method for smtp is to use a port that simply enforces TLS without any wrapping. The system service for this is "submission" which is standard and uses port 587. Port 465 is for smtps, which is considered legacy, however, my work does something to prevent 587 from working, so we also enable smtps.

For smtps, you need to add these back into /etc/services:

smtps       465/tcp
smtps       465/udp

Uncomment these in /etc/postfix/master.cf:

smtp     inet  n       -       n       -       -       smtpd
submission     inet  n       -       n       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,permit_mynetworks,check_relay_domains,reject
  -o syslog_name=postfix/submission
smtps     inet  n       -       n       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject

Because our ISP blocks outgoing and incoming port 25, we cannot be a true mail exchanger. Instead we need to use a relay host. This is configured in main.cf:

relayhost = [mailout.easydns.com]:submission
smtp_sasl_auth_enable = yes
smtp_tls_security_level = encrypt
smtp_sasl_tls_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd

and then we need to create the hash /etc/postfix/sasl_passwd and run postmap on it:

[mailout.easydns.com]:submission        cifarelli.net:<thisisthepasswordforcifarelli.net>

save that and:

# chmod 0400 /etc/postfix/sasl_passwd
# postmap /etc/postfix/sasl_passwd


Also append to /etc/postfix/main.cf:

relay_domains = *
virtual_alias_maps = proxy:mysql:/etc/postfix/virtual_alias_maps.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/virtual_domains_maps.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/virtual_mailbox_maps.cf
virtual_mailbox_base = /home/vmail
#virtual_mailbox_limit = 512000000 for my purposes, quotas are just a pain
virtual_mailbox_limit = 0
virtual_minimum_uid = 5000
virtual_transport = virtual
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps
transport_maps = hash:/etc/postfix/transport

smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = /var/run/dovecot/auth-client
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_sasl_security_options = noanonymous
smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/ssl/private/server.crt
smtpd_tls_key_file = /etc/ssl/private/server.key
smtpd_sasl_local_domain = $mydomain
broken_sasl_auth_clients = yes
smtpd_tls_loglevel = 1

UPDATE: use the rapidssl cert from apache:

smtpd_tls_cert_file = /etc/http/conf/server-rapidssl.pem
smtpd_tls_key_file = /etc/http/conf/server.key
# again, for me, quotas are just a pain
message_size_limit = 0

Edit /etc/postfix/virtual_alias_maps.cf as new and add:

user = postfix_user
password = <passwd>
hosts = localhost
dbname = postfix_db
query = SELECT goto FROM alias WHERE address='%s' AND active = true

Edit /etc/postfix/virtual_domains_maps.cf as new and add:

user = postfix_user
password = <passwd>
hosts = localhost
dbname = postfix_db
query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = false AND active = true

Edit /etc/postfix/virtual_mailbox_limits.cf as new and add:

user = postfix_user
password = <passwd>
hosts = localhost
dbname = postfix_db
query = SELECT quota FROM mailbox WHERE username='%s'

Edit /etc/postfix/virtual_mailbox_maps.cf as new and add:

user = postfix_user
password = <passwd>
hosts = localhost
dbname = postfix_db
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = true

Also, these files need to be protected because they have passwords in them (so not everyone should be allowed to even read them. They must however, be owned by root (postfix requirement, although only seems to result in a warning). So change group ownership to "postfix" and set the permissions to 0640:

# cd /etc/postfix
# chgrp postfix virtual_*
# chmod 0640 virtual_*


Run postmap on transport to generate its db:

postmap /etc/postfix/transport

We still need the SSL cert and private key:

cd /etc/ssl/certs
openssl req -new -x509 -newkey rsa:1024 -days 365 -keyout server.key -out server.crt
openssl rsa -in server.key -out server.key
chown nobody:nobody server.key server.crt
chmod 400 server.key
chmod 444 server.crt
mv server.key /etc/ssl/private/
mv server.crt /etc/ssl/private/


Enable and start the postfix daemon

postfixadmin

Install postfixadmin

Change dir to /etc/webapps/postfixadmin, create httpd-postfixadmin.conf from the apache.conf example provided in that directory.

Edit /etc/httpd/conf/httpd.conf and add

Include /etc/webapps/postfixadmin/httpd-postfixadmin.conf

Edit /etc/webapps/postfixAdmin/config.in.php

$CONF['configured'] = true;
// correspond to dovecot maildir path /home/vmail/%d/%u 
$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'YES';

$CONF['database_type'] = 'mysql';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfix_user';
$CONF['database_password'] = '**changeme**';
$CONF['database_name'] = 'postfix_db';

$CONF['encrypt'] = 'dovecot:SHA512-CRYPT';
$CONF['password_validation'] = array(
#    '/regular expression/' => '$PALANG key (optional: + parameter)',
    '/.{8}/'                => 'password_too_short 8',      # minimum length 8 characters
    '/([a-zA-Z].*){3}/'     => 'password_no_characters 3',  # must contain at least 3 characters
    '/([0-9].*){1}/'        => 'password_no_digits 1',      # must contain at least 1 digits
);

Replace **changeme** with the real password.

Navigate to http://pcifarelli.net/postfixAdmin/setup.php and follow the instructions.

We want to secure this directory with an admin password:

# mkdir /usr/share/webapps/secure
# htpasswd -c /usr/share/webapps/secure/.htpasswd paulc
New password:
Re-type new password:
# chown http.http /usr/share/webapps/secure/.htpasswd
# chmod 0640 /usr/share/webapps/secure/.htpasswd

paulc is the admin account in this example.

Edit /usr/share/webapps/postfixadmin/.htaccess and put these contents:

AuthType Basic
AuthName "Restricted Access"
AuthUserFile /usr/share/webapps/secure/.htpasswd
Require user paulc

dovecot

install dovecot

For security reasons, a new user should be created to store the mails:

groupadd -g 5000 vmail
useradd -u 5000 -g vmail -s /sbin/nologin -d /home/vmail -m vmail

A gid and uid of 5000 is used in both cases so that we do not run into conflicts with regular users. All your mail will then be stored in /home/vmail.

You will need to create an empty database and corresponding user. We will be using PostfixAdmin's tables to fill the database later on. In this article, postfix_user will have read/write access to postfix_db using hunter2 for a password. You are expected to create your database and user yourself as shown in the following code. Make sure to assign proper permissions.

# mysql -u root -p

password:
CREATE SCHEMA `postfix_db` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
CREATE USER 'postfix_user'@'localhost' IDENTIFIED BY 'hunter2';
GRANT ALL ON `postfix_db`.* TO `postfix_user`@`localhost`;


cp /etc/dovecot/dovecot.conf.sample /etc/dovecot/dovecot.conf

In /etc/dovecot/dovecot.conf uncomment/edit:

protocols = imap pop3

Create /etc/dovecot/conf.d/10-mysql-vmail.conf:

auth_mechanisms = plain login
passdb {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf
}
userdb sql {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf
}

service auth {
    unix_listener auth-client {
        group = postfix
        mode = 0660
        user = postfix
    }
    user = root
}

mail_home = /home/vmail/%d/%u
mail_location = maildir:~

ssl_cert = </etc/httpd/conf/server-rapidssl.crt
ssl_key = </etc/httpd/conf/server.key


Create /etc/dovecot/dovecot-sql.conf with these contents:

driver = mysql
connect = host=localhost dbname=postfix_db user=postfix_user password=hunter2
# The new name for MD5 is MD5-CRYPT so you might need to change this depending on version
default_pass_scheme = SHA512-CRYPT
# Get the mailbox
user_query = SELECT '/home/vmail/%d/%u' as home, 'maildir:/home/vmail/%d/%u' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=',  quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'
# Get the password
password_query = SELECT username as user, password, '/home/vmail/%d/%u' as userdb_home, 'maildir:/home/vmail/%d/%u' as userdb_mail, 5000 as  userdb_uid, 5000 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
# If using client certificates for authentication, comment the above and uncomment the following
#password_query = SELECT null AS password, ‘%u’ AS user

public mailboxes:

To setup public mailboxes, you need to have namespaces. One private namespace must be configured at least. Create /etc/dovecot/conf.d/20-public-mailboxes.conf:

namespace {
        type = private
        separator = /
        prefix =
        #location defaults to mail_location
        inbox = yes
}

namespace {
        type = public
        separator = /
        prefix = My Company/
        location = maildir:/home/vmail/public
        subscriptions = no
}

Now create /home/vmail/public, giving ownership to vmail:vmail. Under this directory is where you put your public mailboxes. For example, to create a public mailbox notices, you would create /home/vmail/public/.notices/ -> under here would be cur, tmp, new.

The user subscribes to My Company -> notices


Start and enable dovecot

fetchmail

Install fetchmail

Optional: install tk to use fetchmailconf (tk can be useful elsewhere)

However, I configured manually.

create /etc/fetchmailrc

# This file must be chmod 0600, owner fetchmail 
# Daemon configuration
set daemon        300           # Pool every 5 minutes
set syslog                      # log through syslog facility
set postmaster  paulc
set bouncemail

##########################################################################
# Hosts to poll
##########################################################################

# Defaults ===============================================================
# Set antispam to -1, since it is far safer to use that together with
# no bouncemail
defaults:
timeout 300
antispam -1
batchlimit 100

poll mail-hub.optonline.net protocol POP3 user "paulctst1" there with password "<password>" is "paulctst1@optonline.net" here options fetchall

and as it says in the comment,

# chown fetchmail /etc/fetchmailrc
# chmod 0600 /etc/fetchmail

Start and enable the fetchmail service.

procmail

NOTE: procmail and spamassassin are not required for a working virtual mail setup, so the next 2 sections show how to modify the setup to add these features.

Only paulc (my mail) requires server-side filtering (because no one I would host mail for would know what that is), but who knows, maybe someday others will want it.

Add procmail as a valid transport in /etc/postfix/master.cf

procmail unix - n n - - pipe flags=RO user=vmail argv=/usr/bin/procmail -t -m USER=${user} NEXTHOP=${nexthop} EXTENSION=${extension} /etc/postfix/procmailrc.common

Create the script /etc/postfix/procmail.common:

MAILDIR="$HOME/$NEXTHOP/$USER@$NEXTHOP"
DEFAULT="$MAILDIR/"
#VERBOSE=ON
#each user will set his own log file
#LOGFILE="/home/vmail/proclog-$USER-$NEXTHOP"
NL="
"
WS="    "

# All marked spam is forwarded to the spam account
#:0:
#* ^X-Spam-Status:.*Yes
#!spam@cifarelli.net

# Put marked spam in users 'Junk' folder
:0:
* ^X-Spam-Status:.*Yes
.Junk/
 
SWITCHRC="$HOME/$NEXTHOP/$USER@$NEXTHOP/.procmailrc"


make this file owned by root:vmail, and set the permissions to 0770 (or 0550 or 0750).

Edit /etc/postfix/transport and add

paulctst1@optonline.net procmail

And run

# postmap /etc/postfix/transport


Create the procmail switch file as /home/vmail/optonline.net/paulctst1@optonline.net/.procmailrc

When moving to a folder in a rule, make sure to include the '.' and end with the '/':

:0:
* ^(Subject).*Test
.test/

is a rule that will move all mail with a subject ending in "Test" into a subfolder "test".

Spamassassin

Install spamassassin

edit /etc/mail/spamassassin/local.cf:

rewrite_header Subject [SPAM]

and add whitelist_from directives at the end of the file (as from maximus), e.g.:

whitelist_from  *@amazon.com

Create Spamassassin user/group and folder.

groupadd -g 5001 spamd
useradd -u 5001 -g spamd -s /sbin/nologin -d /var/lib/spamassassin -m spamd
chown spamd:spamd /var/lib/spamassassin

update the patterns:

# /usr/bin/vendor_perl/sa-update

Change /etc/conf.d/spamd to:

SAHOME="/var/lib/spamassassin/"
SPAMD_OPTS="--max-children 25 --username spamd --helper-home-dir -D -x --virtual-config-dir=${SAHOME} -s ${SAHOME}spamd.log --pidfile /var/run/spamd.pid"

Modify /etc/postfix/master.cf to pass all mail through spamassasin:

smtp      inet  n       -       n       -       -       smtpd -o content_filter=spamassassin
spamassassin    unix    -       n       n       -       -       pipe user=spamd argv=/usr/bin/vendor_perl/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}

(add the part in italics)

Enable and start the spamassassin service. (and restart the postfix service)

Add the script /etc/cron.daily/update-spamfilters:

 #!/usr/bin/perl
 
 $emailto1 = 'paul.cifarelli@thomsonreuters.com';
 $emailto2 = 'paul.cifarelli@gmail.com';
 $emailto3 = 'paulc2@optonline.net';
 $whoami = 'paul@cifarelli.net';
 $hostn = 'pcifarelli.net (tvpc)';
 
 use Socket;
 use Sys::Syslog;
 
 openlog 'spamfilterupdate', 'pid', 'user';
 
 $date = `date`;
 chomp $date;
 syslog 'info', "spamfilter update for $date";
 $version = `/usr/bin/vendor_perl/sa-update -V`;
 @v = split / /, $version;
 $version = $v[2];
 chomp $version;
 
 $email1 = "To: $emailto3
 From: $whoami
 Subject: $hostn spamfilters update
 
 An error occurred for $date. You are still running version $version.
 ";
 
 $ret = `/usr/bin/vendor_perl/sa-update`;
 if ($ret == 0) {
    syslog 'info', "A spamfilter update was available for $date, and was downloaded and installed successfully. You are now running $version.\n";
 }
 elsif ($ret == 1) {
    syslog 'info', "No spamfilter update was available for $date. You are still running $version.\n";
 }
 else {
    syslog 'info', "An error occurred downloading spamfilters for $date. You are still running $version.\n";
    `echo '$email1' |/usr/sbin/sendmail -f $whoami -t`;
 }
 
 closelog;

Set the permissions to 0744. If you haven't yet, make sure the cronie service is enabled and started. (NOTE that cronie run-parts ignores scripts with '.'s in them by default, so don't add a '.pl' extension.)

RoundCube Webmail

Install roundcubemail, libmcrypt, php-mcrypt, php-imap

cd /etc/webapps/roundcubemail and copy the example apache.conf to httpd-roundcubemail.conf

Edit /etc/webapps/roundcubemail/.htaccess and change the first line to

allow from all

Edit /etc/httpd/conf/httpd.conf and add at the end

Include /etc/webapps/roundcubemail/httpd-roundcubemail.conf

change to /usr/share/webapps/roundcubemail and rename the xintstallerx directory, and change the perms

# cd /usr/share/webapps/roundcubemail
# mv xinstallerx installer
# chmod 0755 installer

create the roundcubemail database and roundcube user

# mysql -u root -p
mysql> create database roundcubemail;
mysql> grant all on roundcubemail.* to roundcube@localhost identified by '<password>';
mysql> flush privileges;

Initialize the database

# mysql -u roundcube -p < SQL/mysql.initial.sql

Navigate over to http://pcifarelli.net:8846/roundcubemail/installer/

  1. set the date.timezone = America/New_York in php.ini
  2. enable extensions iconv.so, exif.so, openssl.so, and mcrypt.so in php.ini
  3. restart httpd
  4. chown http.http /usr/share/webapps/roundcube/temp/
  5. save main.inc.php and db.inc.php in /etc/webapps/roundcubemail/config
  6. set the permissions to 0640 and the group to http for main.inc.php and db.inc.php (again, they contain passwords)

After completing the installation and the final tests please remove the whole installer folder from the document root of the webserver or make sure that enable_installer option in config/main.inc.php is disabled.


Enable the 'password', 'emoticons', and 'help' plugins: Edit /usr/share/webapps/roundcubemail/config/main.inc.php

// List of active plugins (in plugins/ directory)
$config['plugins'] = array('password', 'emoticons', 'help');

goto /usr/share/webapps/roundcubemail/plugins/password and copy config.inc.php.dist to config.inc.php. Edit that file and change:

$config['password_db_dsn'] = 'mysql://postfix_user:<password>@localhost/postfix_db';

where <password> is replaced with the postfix_user password (do not include anglebrackets).

also

$config['password_algorithm'] = 'dovecot';
$config['password_dovecotpw'] = "/usr/bin/doveadm pw";
$config['password_dovecotpw_method'] = "SHA512-CRYPT";

$config['password_query'] = 'UPDATE mailbox SET password=%P WHERE username=%u LIMIT 1';

(the %P tells the password plugin to encrypt the password with CRYPT_MD5 which is the same as md5crypt which is not a simple MD5 digest).

once again we have a password stored in this file, so make sure to set the group to http and perms to (something like) 0640.

# chgrp http config.inc.php
# chmod 0640 config.inc.php

goto /usr/share/webapps/roundcubemail/plugins/help and copy config.inc.php.dist to config.inc.php. Edit that file and change:

$rcmail_config['help_source'] = 'http://trac.roundcube.net/wiki';

Migration from "maximus"

This will be the general procedure:

  1. create the account on tvpc
  2. comment out the entry in fetchmailrc on maximus
  3. convert the mbox format to maildir format (as root):
# cd /home/Mail/paulc2
# mb2md-3.20.pl -s /var/spool/mail/paulc2 -d /home/Mail/paulc2/.maildir/   # convert /var/spool/mail/paulc2
# mb2md-3.20.pl -R -s /home/Mail/paulc2/mail/ -d /home/Mail/paulc2/.maildir/   # convert the folders
# chown -R paulc2.paulc2 .maildir/
  1. gzip up (the .maildir directory)-> move to tvpc
  2. unzip on tvpc into /home/vmail/cifarelli.net/paul@cifarelli.net
  3. move and convert the .procmailrc from maximus:/home/Mail/paulc2 to tvpc:/home/vmail/cifarelli.net/paul@cifarelli.net/.procmailrc
  4. verify imap access to <account> on tvpc
  5. copy login credentials to tvpc fetchmailrc
  6. restart fetchmail on tvpc

Lirc (iMon RM100, a.k.a Antec Veris Multi-Station Basic IR Receiver)

First of all, the remote that comes with this thing is crap, and ultimately we want to use the Harmony remote anyway, so configure that one. It will tell you to set it up as an MCE remote. Good luck doing that because devinput just pretty much does what it wants. Loading the rc_imon_mce module without the rc_imon_pad module just hangs the computer. You can load it in addition though.

After much trial and error, I've configured the lirc to just use the kernel modules that are standard in the kernel. This means setting it up as a devinput device.

I installed lirc and lirc-utils, although after reading through more of the documentation I think only lirc-utils are necessary.

First, the kernel pretty much correctly identifies the iMon and loads the correct modules. Trying to load anything else brought me nothing but heartache, including no change, no response, and in one case crashing the machine. So the next step was to configure Lirc to use the imon device created by the kernel:

Identify the usb device (we only have 1 device, but just for completeness):

# lsusb
...
Bus 009 Device 002: ID 15c2:0043 SoundGraph Inc.

Note the 15c2:0043. Now look for the usb device file:

# ls -al /dev/input/by-id/
total 0
drwxr-xr-x 2 root root 100 Feb 23 14:52 .
drwxr-xr-x 4 root root 360 Feb 24 22:13 ..
lrwxrwxrwx 1 root root   9 Feb 23 09:21 usb-15c2_0043-event-if00 -> ../event4
lrwxrwxrwx 1 root root   9 Feb 23 09:21 usb-15c2_0043-event-mouse -> ../event3
lrwxrwxrwx 1 root root   9 Feb 23 09:21 usb-15c2_0043-mouse -> ../mouse0

usb-15c2_0043-event-if00 is what we are looking for - the target of the link can and will change from boot to boot. I tried the online instructions for the mouse device, but there was no measurable effect that I could see.

Edit /etc/conf.d/lirc.conf

#
# Parameters for lirc daemon
#

LIRC_DEVICE="/dev/input/by-id/usb-15c2_0043-event-if00"
LIRC_DRIVER="devinput"
LIRC_EXTRAOPTS=""
LIRC_CONFIGFILE="/etc/lirc/lircd.conf"

As of Feb 24, 2013 there is a bug in the unit file for lirc, so you have to edit it to use these parameters.

# cd /etc/systemd/system/multi-user.target.wants/
# vi lirc.service

[Service] section should look something like this:

[Service]
EnvironmentFile=/etc/conf.d/lircd.conf
ExecStartPre=/usr/bin/ln -sf /run/lirc/lircd /dev/lircd
ExecStart=/usr/sbin/lircd --pidfile=/run/lirc/lircd.pid  --device=${LIRC_DEVICE} --driver=${LIRC_DRIVER}
Type=forking
PIDFile=/run/lirc/lircd.pid

Don't forget to reload the daemon:

# systemctl --system daemon-reload

Now we need to add the lircd.conf file in /etc/lirc

# wget http://lirc.git.sourceforge.net/git/gitweb.cgi?p=lirc/lirc;a=blob_plain;f=remotes/devinput/lircd.conf.devinput;hb=HEAD
# cp lircd.conf.devinput lircd.conf

Now we need to edit this file for our purposes. Comment out:

##          KEY_KP0                  0x0052
##          KEY_KP1                  0x004F
##          KEY_KP2                  0x0050
##          KEY_KP3                  0x0051
##          KEY_KP4                  0x004B
##          KEY_KP5                  0x004C
##          KEY_KP6                  0x004D
##          KEY_KP7                  0x0047
##          KEY_KP8                  0x0048
##          KEY_KP9                  0x0049

and add:

##          KEY_NUMERIC_0            0x0200
##          KEY_NUMERIC_1            0x0201
##          KEY_NUMERIC_2            0x0202
##          KEY_NUMERIC_3            0x0203
##          KEY_NUMERIC_4            0x0204
##          KEY_NUMERIC_5            0x0205
##          KEY_NUMERIC_6            0x0206
##          KEY_NUMERIC_7            0x0207
##          KEY_NUMERIC_8            0x0208
##          KEY_NUMERIC_9            0x0209
          KEY_KP0            0x0200
          KEY_KP1            0x0201
          KEY_KP2            0x0202
          KEY_KP3            0x0203
          KEY_KP4            0x0204
          KEY_KP5            0x0205
          KEY_KP6            0x0206
          KEY_KP7            0x0207
          KEY_KP8            0x0208
          KEY_KP9            0x0209

The "KEY_NUMERIC_" ones are there for completeness - by default those are what are returned. In the next step however they are not useful.

Save the file.

At this point I tried to create /etc/lirc/lircrc and/or /home/media/.lircrc and they had no effect. I could get irexec to work on the command line, but I then resorted to configuring keys in the KDE Input Devices gui of System Settings.

1. Add qdbus commands for clementine to play, pause, stop, next, prev.
2. Add keyboard commands equating Kp0 to a keyboard 0, Kp1 to 1, Kp2 to 2, ... etc

Don't forget to start the lircd daemon and enable the service for reboot:

# systemctl start lirc
# systemcrl enable lirc.service

Printing

This only loosely belongs here (I do want to print from the server) but I keep forgetting the details so it's best to put them somewhere.

I have an old linksys psu4 printserver connected to an old HP LaserJet 1200 - both extremely adequate for the job. As time goes by they get less easy to support because I guess the computing world is passing them by, but they are simple and all I need, so I don't really want to replace them.

The printserver is configured with a static IP (the only one on my network?) - 192.168.4.9 - and the most reliable way to configure it is as an ipp or http printer. The devices would be:

http://192.168.4.9/printers/P1

or

ipp://192.168.4.9/ipp/P1

For all versions of Windows up to Windows 8, the LaserJet 1200 driver is available.

For Windows 8, LaserJet 1200 is not supported by default. You have 2 options. Go to the as-always-obtuse HP website and after obtaining your PhD in unhelpful you can download the HP Universal PCL6 driver, which probably wouldn't work anyway since I'm pretty sure the 1200 is a PCL5 device - install it and follow the instructions, which will leave you with an unzipped directory and the new driver but will ultimately walk you through adding the printer in the same way that failed and caused you to seek out the printer driver from their website in the first place. Or (after more spelunking through their website) you might stumble across this tidbit - add the printer as you were doing before but when you get to the part where you can't find the printer, click the "Windows Update" button. Your computer will probably appear to hang, but just before you give up and decide to hold down the power button, it will awaken and a whole bunch of old printers will be available for use, including the HP 1200 (and the Photosmart 7760 and a bunch of others).

For Linux it's always available and given that they still support LaserJets from the 1980s I don't see it going away anytime soon.

For the Mac, presently the LaserJet 1200 is still supported as of Lion, but as Apple is trying their best to be as evil as Microsoft, it's only a matter of time before it disappears. I suspect that following the instructions for the HP Photosmart 7760 on Mac OSX will give you the 1200 as well (feel free to follow the instructions as described above at the HP website, which will in all likelihood result in similar fruitless results).


NFS

Install package nfs-utils

create /etc/exports

/home/media/Collection  192.168.4.102(rw,sync,no_subtree_check,no_root_squash,anonuid=1001,anongid=100,insecure)

NOTE that "insecure" is necessary for the avahi service definition - without it you must specify an avahi port below 1024.

start and enable nfs-server

if you add or change shares, reload with

# exportfs -rav

Start & enable rpcbind and nfs-server

Samba

Install package samba

Copy /etc/samba/smb.conf.default /etc/samba/smb.conf

Change the following:

Under the section "[global]"

workgroup = WORKGROUP
server string = PCifarelli Samba Server
hosts allow = 192.168.4. 127.
load printers = yes
passdb backend = tdbsam
interfaces = 192.168.4.0/24
domain master = yes
preferred master = yes
wins support = yes
wins proxy = yes

...

under the section "[printers]"

browseable = yes
guest ok = yes

uncomment the section "[tmp]"

Add the section:

[Music]
   path = /home/media/Collection
   public = yes
   only guest = yes
   writable = yes
   printable = no

Enable and start the services:

systemctl enable smbd
systemctl enable nmbd
systemctl start smbd
systemctl start nmbd

add user:

(Note: this adds a user if the user has a normal unix/linux account)

pdbedit -a -u paulc
pdbedit -a -u media

Avahi (Zeroconf)

By this point avahi is installed. Also install nss-mdns and append mdns4_minimal to the hosts line in /etc/nsswitch.conf.

Add the nfs share for the music collection - /etc/avahi/services/nfs_MusicCollection.service

 <?xml version="1.0" standalone='no'?>
 <!DOCTYPE service-group SYSTEM "avahi-service.dtd">
 <service-group>
   <name replace-wildcards="yes">NFS Music Share on %h</name>
   <service>
     <type>_nfs._tcp</type>
     <port>2049</port>
     <txt-record>path=/home/media/Collection</txt-record>
   </service>
 </service-group>

and the printer - /etc/avahi/services/hp1200.service

 <?xml version="1.0" standalone='no'?>
 <!DOCTYPE service-group SYSTEM "avahi-service.dtd">
 <service-group>
   <name>hp1200</name>
   <service>
     <type>_ipp._tcp</type>
     <subtype>_universal._sub._ipp._tcp</subtype>
     <port>631</port>
     <txt-record>txtver=1</txt-record>
     <txt-record>qtotal=1</txt-record>
     <txt-record>rp=printers/hp1200</txt-record>
     <txt-record>ty=hp1200</txt-record>
     <txt-record>adminurl=http://198.168.4.103:631/printers/hp1200</txt-record>
     <txt-record>note=HP Laserjet 1200</txt-record>
     <txt-record>priority=0</txt-record>
     <txt-record>product=virtual Printer</txt-record>
     <txt-record>printer-state=3</txt-record>
     <txt-record>printer-type=0x801046</txt-record>
     <txt-record>Transparent=T</txt-record>
     <txt-record>Binary=T</txt-record>
     <txt-record>Fax=F</txt-record>
     <txt-record>Color=T</txt-record>
     <txt-record>Duplex=T</txt-record>
     <txt-record>Staple=F</txt-record>
     <txt-record>Copies=T</txt-record>
     <txt-record>Collate=F</txt-record>
     <txt-record>Punch=F</txt-record>
     <txt-record>Bind=F</txt-record>
     <txt-record>Sort=F</txt-record>
     <txt-record>Scan=F</txt-record>
     <txt-record>pdl=application/octet-stream,application/pdf,application/postscript,image/jpeg,image/png,image/urf</txt-record>
     <txt-record>URF=W8,SRGB24,CP1,RS600</txt-record>
   </service>
 </service-group>

and the Samba Shares -

/etc/avahi/services/smb.service

 <?xml version="1.0" standalone='no'?>
 <!DOCTYPE service-group SYSTEM "avahi-service.dtd">
 <service-group>
    <name replace-wildcards="yes">Samba Shares on %h</name>
    <service>
        <type>_smb._tcp</type>
        <port>139</port>
    </service>
 </service-group>

and /etc/avahi/services/smb_for_lion.service

 <?xml version="1.0" standalone='no'?>
 <!DOCTYPE service-group SYSTEM "avahi-service.dtd">
 <service-group>
    <name replace-wildcards="yes">Samba Shares (for Lion) on %h</name>
    <service>
        <type>_smb._tcp</type>
        <port>445</port>
    </service>
 </service-group>

For convenience, add the status hosts to /etc/avahi/hosts

192.168.4.1 router.local
192.168.4.102 beast.local
192.168.4.103 tvpc.local
192.168.4.104 paulcomp.local


enable and start avahi-daemon.

Firewall (iptables script)

I had hopes that I wouldn't need a firewall, except for the one in my router, but it turns out there are people trying to hack my server even though it's only marginally public, so I at least need a basic way of blocking malicious IPs.

The script's simple but a bit long, listed below. You also need a systemd service file:

/etc/systemd/system/firewall.service:

[Unit]
Description=the firewall
After=network.target

[Service]
Type=oneshot
KillMode=none
RemainAfterExit=yes
ExecStart=-/root/firewall.pl start
ExecStop=-/root/firewall.pl stop
ExecReload=-/root/firewall.pl reload

[Install]
WantedBy=multi-user.target


Don't forget to reload and enable,start the service:

# systemctl --system daemon-reload
# systemctl enable firewall
# systemctl start firewall

Move this script? Here's the script (/root/firewall.pl):

 #!/usr/bin/perl
 #
 # firewall.pl - IPTables Firewall script
 #
 # Author: Paul Cifarelli, originally adopted from Oskar Andreasson <blueflux at koffein dot net>
 # (c) of BoingWorld.com, use at your own risk, do whatever you please with
 # it as long as you don't distribute it without due credits to
 # BoingWorld.com
 #
 
 # add some ports to open here:
 @tcp_ports_to_open = (
 );
 
 # block some assholes here:
 @assholes_to_block = (
 qw/
 /
 );
 use Cwd 'abs_path';
 $this_script = abs_path($0);
 
 use Sys::Syslog;
 openlog 'firewall.pl', 'pid', 'user';
 
 $str = "firewall script: " . "ARGVc=" . $#ARGV;
 for ($i=0; $i<=$#ARGV; $i++)
 {
    $str .= " ARGV" . "$i" . "=" . $ARGV[$i];
 }
 syslog 'info', $str;
 
 #
 # your LAN's IP range and localhost IP. /24 means to only use the first 24
 # bits of the 32 bit IP adress. the same as netmask 255.255.255.0
 #
 $LAN_IP_RANGE="192.168.4.0/24";
 $LAN_IP="192.168.4.103/32";
 $LAN_BCAST_ADRESS="192.168.4.255/32";
 $LOCALHOST_IP="127.0.0.1/32";
 $LAN_IFACE="eth0";
 $IPTABLES="/sbin/iptables";
 
 if ($#ARGV >= 0 && ($ARGV[0] eq "-r" or $ARGV[0] eq "--reload" or $ARGV[0] eq "reload" or $ARGV[0] eq "restart"))
 {
    `$this_script stop`;
    `$this_script start`;
    exit;
 }
 
 if ($#ARGV >= 0 && ($ARGV[0] eq "-x" or $ARGV[0] eq "--clear" or $ARGV[0] eq "clear" or $ARGV[0] eq "stop"))
 {
    `$IPTABLES -F`;
    `$IPTABLES -t nat -F PREROUTING`;
    `$IPTABLES -t nat -F POSTROUTING`;
    `$IPTABLES -t nat -F OUTPUT`;
    `$IPTABLES -X check_asshole`;
    `$IPTABLES -X assholes`;
    `$IPTABLES -X welcome`;
    `$IPTABLES -X check_syn`;
    `$IPTABLES -X udpincoming_packets`;
    `$IPTABLES -X tcp_packets`;
    `$IPTABLES -X icmp_packets`;
    `$IPTABLES -P INPUT ACCEPT`;
    `$IPTABLES -P OUTPUT ACCEPT`;
    `$IPTABLES -P FORWARD ACCEPT`;
    exit;
 }
 
 if ($#ARGV >= 0 && ($ARGV[0] ne "enable" and $ARGV[0] ne "start" and $ARGV[0]) )
 {
    print "Usage:\nfirewall [-x|--clear|clear]\n   -x|--clear|clear\tclear rules\n\n";
    exit;
 }
 
 #########
 # Load all required IPTables modules
 #
 # Adds some iptables targets like LOG, REJECT and MASQUARADE.
 #
 `/sbin/modprobe ipt_LOG`;
 `/sbin/modprobe ipt_REJECT`;
 `/sbin/modprobe ipt_MASQUERADE`;
 `/sbin/modprobe ipt_REDIRECT`;
 #
 # Support for owner matching
 #
 `/sbin/modprobe ipt_owner`;
 #
 # multiport
 #
 `/sbin/modprobe ipt_multiport`;
 #
 # Support for connection tracking of FTP and IRC.
 #
 `/sbin/modprobe ip_conntrack_ftp`;
 `/sbin/modprobe ip_nat_ftp`;
 `/sbin/modprobe ip_conntrack_irc`;
 
 
 #CRITICAL:  Enable IP forwarding since it is disabled by default.
 #
 `echo "1" > /proc/sys/net/ipv4/ip_forward`;
 
 
 # Dynamic IP users:
 #
 #   If you get your IP address dynamically from SLIP, PPP, or DHCP, enable this
 #       option.  This enables dynamic-ip address hacking in IP MASQ, making the connection
 #       with Diald and similar programs much easier.
 #
 `echo "1" > /proc/sys/net/ipv4/ip_dynaddr`;
 
 #
 # set default policies for the INPUT, FORWARD and OUTPUT chains
 #
 
 `$IPTABLES -P INPUT DROP`;
 `$IPTABLES -P OUTPUT DROP`;
 `$IPTABLES -P FORWARD DROP`;
 
 #
 # Create separate chains for ICMP, TCP and UDP to traverse
 #
 
 `$IPTABLES -N icmp_packets`;
 `$IPTABLES -N tcp_packets`;
 `$IPTABLES -N udpincoming_packets`;
 
 #
 # ICMP rules
 #
 
 `$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 0 -j ACCEPT`;
 `$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 3 -j ACCEPT`;
 `$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 5 -j ACCEPT`;
 `$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT`;
 
 #
 # TCP rules
 #
 #
 # the allowed chain for TCP connections
 #
 # The "welcome" chain is a final check for non-syn TCP packets.
 # We allow all packets that are part of an established connection or related to a connection
 # the rest we drop
 `$IPTABLES -N welcome`;
 `$IPTABLES -A welcome -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT`;
 `$IPTABLES -A welcome -m limit --limit 3/minute --limit-burst 3 -j LOG --log-prefix "IPT packet died on welcome: "`;
 `$IPTABLES -A welcome -p TCP -j DROP`;
 
 `$IPTABLES -N check_asshole`;
 `$IPTABLES -N assholes`;
 
 # The "check_syn" chain is where we test for acceptable incoming connection requsts
 `$IPTABLES -N check_syn`;
 
 while ($port = pop @tcp_ports_to_open)
 {
    `$IPTABLES -A check_syn -p TCP -s 0/0 --dport $port -j check_asshole`;
 }
 
 #
 # need this to make ftp work - accept all syns received for a "related" port
 # conntrack_ftp intercepts the ftp PORT command and adds the port to the connection track list so that the outbound
 # (passive) and inbound (active) data connection can be made
 `$IPTABLES -A check_syn -p TCP -m state --state RELATED -j check_asshole`;
 #
 `$IPTABLES -A check_syn -m limit --limit 3/minute --limit-burst 3 -j LOG --log-prefix "IPT check_syn packet died: "`;
 `$IPTABLES -A check_syn -p TCP -s 0/0 -j DROP`;
 
 # dont let these morons in ever: (last updated 7/3/2013)
 while ($ass = pop @assholes_to_block)
 {
   `$IPTABLES -A check_asshole -p TCP -s $ass/32 -j assholes`;
 }
 #
 `$IPTABLES -A check_asshole -p TCP -j ACCEPT`; # not an asshole
 
 # the "assholes" chain is where we put those who are banned
 `$IPTABLES -A assholes -m limit --limit 3/minute --limit-burst 3 -j LOG --log-prefix "asshole denied: "`;
 `$IPTABLES -A assholes -p TCP -s 0/0 -j DROP`;
 
 #here we route the packets to the appropriate TCP chains:
 `$IPTABLES -A tcp_packets -p TCP -s 0/0 --syn -j check_syn`;
 `$IPTABLES -A tcp_packets -p TCP -s 0/0 -j welcome`;
 
 #
 # UDP ports
 #
 # accept all UDP
 `$IPTABLES -A udpincoming_packets -p UDP -j ACCEPT`;
 #
 # INPUT chain
 #
 # establish the basic INPUT chain and filter the packets onto the correct
 # chains.
 #
 
 # route the packets to the appropriate chains
 `$IPTABLES -A INPUT -p ICMP -i $LAN_IFACE -j icmp_packets`;
 `$IPTABLES -A INPUT -p TCP -i $LAN_IFACE -j tcp_packets`;
 `$IPTABLES -A INPUT -p UDP -i $LAN_IFACE -j udpincoming_packets`;
 `$IPTABLES -A INPUT -p IGMP -i $LAN_IFACE -j ACCEPT`;
 
 #Allow all packets coming from the lan iterface and destined for our broadcast address or lan address.
 #also allow anything destined for the localhost ip
 `$IPTABLES -A INPUT -p ALL -i $LAN_IFACE -d $LAN_BCAST_ADRESS -j ACCEPT`;
 `$IPTABLES -A INPUT -p ALL -d $LOCALHOST_IP -j ACCEPT`;
 `$IPTABLES -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG --log-prefix "IPT INPUT packet died: "`;
 
 #
 # OUTPUT chain
 #
 # establish the basic OUTPUT chain and filter them onto the correct chain
 #
 # allow everything that comes from localhost, any of our lan addresses
 `$IPTABLES -A OUTPUT -p ALL -s $LOCALHOST_IP -j ACCEPT`;
 `$IPTABLES -A OUTPUT -p ALL -s $LAN_IP -d $LOCALHOST_IP -j ACCEPT`;
 `$IPTABLES -A OUTPUT -p ALL -o $LAN_IFACE -j ACCEPT`;
 #
 `$IPTABLES -A OUTPUT -m limit --limit 3/minute --limit-burst 3 -j LOG --log-prefix "IPT OUTPUT packet died: "`;
 
 closelog;

Dropbox

mkdir ~paulc/builds/dropbox

download dropbox.tar.gz from the AUR into dropbox

untar

makepkg -s

su and install the pkg file

# pacman -U <packagefile>

next do dropbox-kde-systray-icons with same procedure next do dropbox-cli, same procedure

become root, run the daemon (yes, the daemon, not the cli) at the command line:

dropboxd

you'll get a message saying the computer is not linked to any account, with a url to visit. Cut and paste that url into a browser and type in your password; the daemon will then report that you are successfully linked.

The Dropbox is located at /root/Dropbox (since you are running as root)

Create /etc/systemd/system/dropbox.service:

[Unit]
Description=Dropbox (cloud service)
After=network.target

[Service]
Type=oneshot
KillMode=none
RemainAfterExit=yes
ExecStart=-/usr/bin/dropbox start
ExecStop=-/usr/bin/dropbox stop
ExecReload=-/usr/bin/dropbox stop;/usr/bin/dropbox start

[Install]
WantedBy=multi-user.target

reload systemd:

# systemctl daemon-reload

enable dropbox:

# systemctl start dropbox
# systemctl enable dropbox

MPD

Install mpd.

As user "media", create /home/media/.config/mpd/mpd.conf:

pid_file "~/.config/mpd/mpd.pid"
db_file "/home/media/mpd/mpd.db"
state_file "/home/media/mpd/mpdstate"
log_file "/home/media/mpd/mpd.log"
playlist_directory "/home/media/Playlists"
music_directory "/home/media/Collection"
sticker_file "/home/media/sticker.sql"
audio_output {
        type            "pulse"
        name            "pulse audio"
}

Also as user "media", create /home/media/mpd

Create an X autostart file (put it in .config/autostart/mpd.desktop):

[Desktop Entry]
Encoding=UTF-8
Type=Application
Name=Music Player Daemon
Comment=Server for playing audio files
Exec=mpd
StartupNotify=false
Terminal=false
Hidden=false
X-GNOME-Autostart-enabled=false

pacmd load-module module-combine sink_name=rtp.hdmi.combined slaves="rtp,alsa_output.pci-0000_00_01.1.hdmi-stereo"
pacmd set-default-sink rtp.hdmi.combined

Shairport

Build from the AUR, install.

Create an X autostart file (put it in .config/autostart/mpd.desktop):

[Desktop Entry]
Encoding=UTF-8
Type=Application
Name=Shairport (Airport) Player Daemon
Comment=Server for playing audio files
Exec=/usr/bin/shairport -a basement
StartupNotify=false
Terminal=false
Hidden=false
X-GNOME-Autostart-enabled=false

NIS

# pacman -Sy ypbind-mt yp-tools ypserv

Move the entry for tvpc to be the first entry in /etc/hosts (even before localhost)

# /etc/hosts: static lookup table for host names
#

#<ip-address>   <hostname.domain.org>   <hostname>
10.0.1.103      cifarelli-nis tvpc
127.0.0.1       localhost.localdomain   localhost
::1             localhost.localdomain   localhost

10.0.1.1        router
10.0.1.102      beast

add the domain into /etc/nisdomainname

# NIS domain to be set by domainname.service
#
NISDOMAINNAME="cifarelli-nis"

set the domainname on the command line

# domainname cifarelli-nis

edit /etc/ypserv.conf, add

10.0.1. :       cifarelli-nis   :       *       : none

edit /var/yp/Makefile (not sure about the publickeys, but make failed without something and that seemed innocuous.

# Should we merge the passwd file with the shadow file ?
# MERGE_PASSWD=true|false
MERGE_PASSWD=false

# Should we merge the group file with the gshadow file ?
# MERGE_GROUP=true|false
MERGE_GROUP=false

...

ALIASES     = /etc/postfix/aliases

...

PUBLICKEYS  = /etc/ssh/ssh_host_key.pub

...

then

# cd /var/yp/
# make

(ignore the errors since we havent started the servers yet)


Now, I think this step should be unnecessary, but it helped me find mistakes, and there is no harm:

# /usr/lib/yp/ypinit -m

add raspberrypi to the list of servers when you come to it.

Edit /var/yp/securenets. Comment out

# 0.0.0.0          0.0.0.0

add

255.255.255.0           10.0.1.0

now edit /etc/yp.conf and add:

domain cifarelli-nis server cifarelli-nis

test with:

# yptest

Ignore the yp_match error - it just means the 'nobody' user is not being served by NIS.

Now start ypbind and ypserv (in that order) For reasons I have yet to figure out, the default timing with rpcbind, nfs-server, ypbind, ypserv in systemd causes nfs and ypbind to fail. So I cheated for now and setup an rc.local.start and rc.local.stop with these scripts:

/etc/systemd/system/rc-local.service:

[Unit]
Description=replicate old rc.local behavior
Wants=network.target
After=network.target

[Service]
Type=idle
RemainAfterExit=yes

ExecStart=/etc/rc.local.start
#
ExecStop=/etc/rc.local.stop

[Install]
WantedBy=multi-user.target

Then enable rc-local.service

and add these 2 scripts: /etc/rc.local.start:

#!/bin/bash
systemctl start ypbind
systemctl start ypserv

and /etc/rc.local.stop:

#!/bin/bash
systemctl stop ypserv
systemctl stop ypbind

and make rc.local.start and rc.local.stop executable.

Setup the clients

Log onto the raspberrypi, as root.

# apt-get install nis

when prompted, answer cifarelli-nis for the nis domain

add to the end of /etc/passwd:

+::::::

add to the end of /etc/group:

+:::

add to the end of /etc/shadow:

+::::::::

enable rpcbind and nis:

# update-rc.d rpcbind enable
# update-rc.d nis enable

Edit /etc/ypserv.securenets. Comment out

# 0.0.0.0          0.0.0.0

add

255.255.255.0           10.0.1.0

edit /etc/default/nis. change

NISSERVER=slave
...
NISMASTER=nis-server

run

# /usr/lib/yp/ypinit -s nis-master

start rpcbind and nis:

# /etc/init.d/rpcbind start
# /etc/init.d/nis start

ownCloud

OwnCloud is like running your own Dropbox. The setup is relatively easy.

Install owncloud as normal from the official repositories.

copy the example config file:

# cd /etc/webapps/owncloud
# cp apache.example.conf httpd-owncloud.conf

edit /etc/httpd/conf to include /etc/webapps/owncloud/httpd-owncloud.conf:

# OwnCloud
Include /etc/webapps/owncloud/httpd-owncloud.conf

make sure these required extensions are uncommented in /etc/php/php.ini:

gd.so
iconv.so
xmlrpc.so
zip.so

These should already be installed; install if not: php-intl, php-mcrypt

and uncomment the following extensions if not already:

bz2.so
curl.so
intl.so
mcrypt.so
openssl.so

If not installed, install exiv2 and enable exif.so.

If not installed, install php-xcache and enable it in either php.ini or /etc/php/conf.d/xcache.ini. (mine was already installed and enabled in php.ini, commented out in xcache.ini, but other parameters were set in xcache.ini).

I use mysql of course, so these were already enabled:

pdo_mysql.o
mysql.o

Note that of this writing mysqli.o was not supported by owncloud; fortunately mysql.o was already the one in use on my server.

Create

/home/media/owncloud 
/home/media/owncloud/data
/home/media/owncloud/apps
/home/media/owncloud/config

and set the ownership for all to http:http. Add the media account to the http group, and add the http account to the media group. This will be where data is kept.

Copy the .htaccess files:

# cp /usr/share/webapps/owncloud/.htaccess /home/media/owncloud
# cp /usr/share/webapps/owncloud/data/.htaccess /home/media/owncloud/data


Set permissions with this script:

#!/bin/bash
ocpath='/home/media/owncloud'
htuser='http'

find ${ocpath}/ -type f -print0 | xargs -0 chmod 0640
find ${ocpath}/ -type d -print0 | xargs -0 chmod 0750

chown -R root:${htuser} ${ocpath}/
chown -R ${htuser}:${htuser} ${ocpath}/apps/
chown -R ${htuser}:${htuser} ${ocpath}/config/
chown -R ${htuser}:${htuser} ${ocpath}/data/

chown root:${htuser} ${ocpath}/.htaccess
chown root:${htuser} ${ocpath}/data/.htaccess

chmod 0644 ${ocpath}/.htaccess
chmod 0644 ${ocpath}/data/.htaccess

Restart apache. Then navigate to https://www.cifarelli.net/owncloud/ This is in a 'first run' mode. Set the data directory to /home/media/owncloud/data and create an admin account. Login and create your users.

Setting up clients

Desktops

Windows

Download the desktop app from https://owncloud.org/. Nothing to it; point it to the server at https://cifarelli.net/owncloud/.

Lightning is the Calendar app for Thunderbird. Install it from Tools -> Addons -> Get AddOns -> Lightning.

Enable multi-calendar support. Go to Tools -> Options -> Advanced -> General (tab) -> Config Editor. Find calendar.network.multirealm. Double click until it shows true. Then 'x-out' as they say. Now go to File -> New -> Calendar. Select 'On the network'. Select 'CalDAV' and enter http://www.cifarelli.net/owncloud/remote.php/caldav/calendars/USER/personal as the location.

OS X

Download the app from https://owncloud.org/, and point it to your server.

iCal is the OS X Calendar App. To configure it for owncloud's calendar functions,

  1. In iCal open Settings, click on Account
  2. Press the + Button
  3. As Accounttype choose CalDAV
  4. Enter Username and Password
  5. As Server address enter only cifarelli.net/owncloud/remote.php/caldav/principals/USER
  6. Click on Create.

Mobile

Android

First, download the $0.99 app from Google Play. Enter user name, password, and cifarelli.net/owncloud as the server. You might want to enable Instant Upload.

Next, download the CalDAV-Sync app from Google Play - this one costs a couple of dollars. Add Account, then enter user name, password, and

cifarelli.net/owncloud/remote.php/caldav/calendars/USER/personal

as the location.

Next download the CardDAV-Sync app from Google Play. Add account, then enter user name, password, and

cifarelli.net/owncloud/remote.php/carddav/

as the server. I couldn't get autoconfigure to do anything. Furthermore, it wouldnt sync from phone to server, so I had to manually upload my contacts. Do this by going to the Contacts App -> Import/export. Export the file, copy it to owncloud, then go to the owncloud website (yours, cifarelli.net), and import the vcf file. When you want to create a new contact, you'll be given a choice of accounts, select the CardDAV account and it will sync to all your devices.

Finally, you can download the Tasks app (Marten Gajda). There's nothing really to configure - it requires CalDAV - Sync and apparently uses settings from there.

iOS
  1. Go to Settings, tap on Mail, Contacts, Calendars
  2. Tap on Add Account, others
  3. At Calendars Tap on CalDAV Account
  4. Enter Server cifarelli.net/owncloud/remote.php/caldav/principals/USER
  5. Enter Username and Password
  6. tap on next, done

VNC

First, install tigervnc. This includes the x0vncserver which will serve the main display :0. This can be started from systemd:

/etc/systemd/system/x0vncserver.service

[Unit]
Description=Remote desktop service (VNC)
After=syslog.target network.target

[Service]
Type=forking
User=media
ExecStart=/usr/bin/sh -c '/usr/bin/x0vncserver -display :0 -rfbport 5900 -passwordfile /home/media/.vnc/passwd &'

[Install]
WantedBy=multi-user.target

Next setup vncserver. Since we autologin, we start vncserver in the .xinitrc in that account. Just before starting the window manager, start vncserver in the background:

 #!/bin/bash
 ...
 vncserver &
 exec startkde

Make sure there are passwords set so that not anyone on the network can grab a running session:

# vncpasswd -f .vnc/passwd

Now setup the window manager for vnc. The big ones don't seem to like running very well, so I use icewm, which almost seems to have been designed just for vncserver. Edit .vnc/xstartup

 #!/bin/sh
 
 unset SESSION_MANAGER
 unset DBUS_SESSION_BUS_ADDRESS
 [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
 xsetroot -solid black
 vncconfig -iconic &
 icewm-session &

Finally, setup icewm. As a minimum, add konsole to .icewm/menu:

prog xterm xterm xterm
prog konsole konsole konsole
...

Xrdp

Install (AUR) xrdp.

Edit /etc/xrdp/xrdp.ini, comment out "autorun". Make sure username and password is set to 'ask' for any entries you want to use, especially sesman-any.

...
username=ask
password=ask
...
# systemctl start xrdp
# systemctl start xrdp-sesman

Edit /etc/xrdb/startwm.sh

after the locale call, add

 if [ -r ~/.vnc/xstartup ]; then
    . ~/.vnc/xstartup
    exit 0
 fi

In the accounts that will use it, set up the ~/.vnc and ~/.icewm as in VNC above.

Use Remote Desktop from Windows or rdesktop from linux to connect and create a new session. Select 'sesman-any' initially (or anytime). Most of the time you have to log in twice - the first almost always fails but the second almost always works.

minidlna

install minidlna

sysctl fs.inotify.max_user_watches=200000

create /etc/sysctl.d/90-inotify.conf:

fs.inotify.max_user_watches = 200000

Edit /usr/lib/systemd/system/minidlna.service:

...
ProtectHome=read-only
...

change the minidlna group to users (is this necessary?):

usermod -g users minidlna

Ok, so something changed and now I can't get this setup to work. So I had to build my own minidlna from the git repository.

Remove the official version:

# pacman -R minidlna

Clone the git repository:

# cd develop/repositories
# git clone https://git.code.sf.net/p/minidlna/git minidlna-git
# cd minidlna-git

In minidlna.c, line 607, comment out this:

 if (!path || access(path, F_OK) != 0)
 {
    DPRINTF(E_ERROR, L_GENERAL, "Media directory \"%s\" not accessible [%s]\n",
       ary_options[i].value, strerror(errno));
    break;
 }

Now build:

# ./autogen.sh
# ./configure
# make clean; make
# sudo make install

Create the systemd startup file /usr/lib/systemd/system/minidlna.service:

[Unit]
Description=minidlna server
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/sbin//minidlnad -f /etc/minidlna.conf

[Install]
WantedBy=multi-user.target

Create the config file /etc/minidlna.conf"

# port for HTTP (descriptions, SOAP, media transfer) traffic
port=8200

# network interfaces to serve, comma delimited
#network_interface=eth0

# specify the user account name or uid to run as
user=media

# set this to the directory you want scanned.
# * if you want multiple directories, you can have multiple media_dir= lines
# * if you want to restrict a media_dir to specific content types, you
#   can prepend the types, followed by a comma, to the directory:
#   + "A" for audio  (eg. media_dir=A,/home/jmaggard/Music)
#   + "V" for video  (eg. media_dir=V,/home/jmaggard/Videos)
#   + "P" for images (eg. media_dir=P,/home/jmaggard/Pictures)
#   + "PV" for pictures and video (eg. media_dir=PV,/home/jmaggard/digital_camera)
#media_dir=/opt
media_dir=AV,/home/media/Collection
media_dir=PV,/home/media/Pictures
media_dir=A,/home/media/Playlists

# set this to merge all media_dir base contents into the root container
# note: the default is no
#merge_media_dirs=no

# set this if you want to customize the name that shows up on your clients
#friendly_name=My DLNA Server
friendly_name=Cifarelli DLNA Server

# set this if you would like to specify the directory where you want MiniDLNA to store its database and album art cache
#db_dir=/var/cache/minidlna

# set this if you would like to specify the directory where you want MiniDLNA to store its log file
#log_dir=/var/log

# set this to change the verbosity of the information that is logged
# each section can use a different level: off, fatal, error, warn, info, or debug
#log_level=general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn

# this should be a list of file names to check for when searching for album art
# note: names should be delimited with a forward slash ("/")
album_art_names=Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg

# set this to no to disable inotify monitoring to automatically discover new files
# note: the default is yes
inotify=yes

# set this to yes to enable support for streaming .jpg and .mp3 files to a TiVo supporting HMO
enable_tivo=no

# set this to beacon to use legacy broadcast discovery method
# defauts to bonjour if avahi is available
tivo_discovery=bonjour

# set this to strictly adhere to DLNA standards.
# * This will allow server-side downscaling of very large JPEG images,
#   which may hurt JPEG serving performance on (at least) Sony DLNA products.
strict_dlna=no

# default presentation url is http address on port 80
#presentation_url=http://www.mylan/index.php
presentation_url=http://10.0.1.103:8200/index.php

# notify interval in seconds. default is 895 seconds.
notify_interval=900

# serial and model number the daemon will report to clients
# in its XML description
serial=12345678
model_number=1

# specify the path to the MiniSSDPd socket
#minissdpdsocket=/var/run/minissdpd.sock

# use different container as root of the tree
# possible values:
#   + "." - use standard container (this is the default)
#   + "B" - "Browse Directory"
#   + "M" - "Music"
#   + "V" - "Video"
#   + "P" - "Pictures"
#   + Or, you can specify the ObjectID of your desired root container (eg. 1$F for Music/Playlists)
# if you specify "B" and client device is audio-only then "Music/Folders" will be used as root
#root_container=.

# always force SortCriteria to this value, regardless of the SortCriteria passed by the client
#force_sort_criteria=+upnp:class,+upnp:originalTrackNumber,+dc:title

# maximum number of simultaneous connections
# note: many clients open several simultaneous connections while streaming
#max_connections=50

# set this to yes to allow symlinks that point outside user-defined media_dirs.
#wide_links=no


Start and enable:

# systemctl start minidlna
# systemctl enable minidlna

Bubble UPnP

install bubbleupnp

systemctl start bubbleupnp

go to http://tvpc:58050 to complete configuration

OpenLDAP

follow the instructions on the ArchWiki

install certbot to get a Let's Encrypt cert create the cert

need to set the cert ownership to ldap:ldap

additionally, need acls for the archive and live dirs:

# setfacl -m "u:ldap:rx" /etc/letsencrypt/live
# setfacl -m "u:ldap:rx" /etc/letsencrypt/archive
# setfacl -R -m "u:ldap:rx" /etc/letsencrypt/live/pcifarelli.net
# setfacl -R -m "u:ldap:rx" /etc/letsencrypt/archive/pcifarelli.net

You need to download the postfix-book.schema, which is reproduced here:

# $Id$
#
# State of Mind
# Private Enterprise Number: 29426
#
# OID prefix: 1.3.6.1.4.1.29426
#
# Attributes: 1.3.6.1.4.1.29426.1.10.x
#

attributetype ( 1.3.6.1.4.1.29426.1.10.1 NAME 'mailHomeDirectory'
	DESC 'The absolute path to the mail user home directory'
       EQUALITY caseExactIA5Match
       SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )

attributetype ( 1.3.6.1.4.1.29426.1.10.2 NAME 'mailAlias'
       DESC 'RFC822 Mailbox - mail alias'
       EQUALITY caseIgnoreIA5Match
       SUBSTR caseIgnoreIA5SubstringsMatch
       SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )

attributetype ( 1.3.6.1.4.1.29426.1.10.3 NAME 'mailUidNumber'
       DESC 'UID required to access the mailbox'
       EQUALITY integerMatch
       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )

attributetype ( 1.3.6.1.4.1.29426.1.10.4 NAME 'mailGidNumber'
       DESC 'GID required to access the mailbox'
       EQUALITY integerMatch
       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )

attributetype ( 1.3.6.1.4.1.29426.1.10.5 NAME 'mailEnabled'
	DESC 'TRUE to enable, FALSE to disable account'
       EQUALITY booleanMatch
       SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )

attributetype ( 1.3.6.1.4.1.29426.1.10.6 NAME 'mailGroupMember'
	DESC 'Name of a mail distribution list'
       EQUALITY caseExactIA5Match
       SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.29426.1.10.7 NAME 'mailQuota'
	DESC 'Mail quota limit in kilobytes'
       EQUALITY caseExactIA5Match
       SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.29426.1.10.8 NAME 'mailStorageDirectory'
	DESC 'The absolute path to the mail users mailbox'
       EQUALITY caseExactIA5Match
       SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )

attributetype: ( 1.3.6.1.4.1.29426.1.10.9 NAME ( 'mailSieveRuleSource' )
	DESC 'Sun ONE Messaging Server defined attribute'
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26  X-ORIGIN 'Sun ONE Messaging Server' )

attributetype ( 1.3.6.1.4.1.29426.1.10.10 NAME 'mailForwardingAddress'
        DESC 'Address(es) to forward all incoming messages to.'
        EQUALITY caseIgnoreIA5Match
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{320} )

#
# Objects: 1.3.6.1.4.1.29426.1.2.2.x
#

objectclass ( 1.3.6.1.4.1.29426.1.2.2.1 NAME 'PostfixBookMailAccount'
       SUP top AUXILIARY
	DESC 'Mail account used in Postfix Book'
	MUST ( mail )
       MAY ( mailHomeDirectory $ mailAlias $ mailGroupMember
		$ mailUidNumber $ mailGidNumber $ mailEnabled
		$ mailQuota $mailStorageDirectory $mailSieveRuleSource ) )

objectclass ( 1.3.6.1.4.1.29426.1.2.2.2 NAME 'PostfixBookMailForward'
       SUP top AUXILIARY
	DESC 'Mail forward used in Postfix Book'
	MUST ( mail $ mailAlias )
	MAY ( mailForwardingAddress ))

To add it, you have to fix the permission of the root (admin) cn:

So, edit the file /etc/ldap/slapd.d/cn=config/olcDatabase\=\{0\}config.ldif, find the line:

olcRootDN: cn=root

and change to:

olcRootDN: cn=root,cn=config

Then copy the password added for the rootDN in slapd.conf as

olcRootPW: {SSHA}...