# Linux

# General

Anything that are related to Linux but does not fit into the category of networking, storage, database or Desktop Environments

# Batch Image Resize

## Keeping Aspect Ratio

```
mogrify -path [Full path to store the resized images] -resize [width]x[height] -quality [quality] -format [format] *.JPG
```

## No Aspect Ratio

```
mogrify -path [Full path to store the resized images] -resize [width]x[height]! -quality [quality] -format [format] *.JPG
```

# Cheking Printer Ink Level

It can be frustrating sometimes that Linux users aren't able to check the ink levels on our printers like Windows users could, but luckily there are packages that will resolve this problem for major printer manufacturers:

1. Install [libieee1284-devel](https://github.com/twaugh/libieee1284 "libieee1284-devel")
2. Install [libinklevel](http://libinklevel.sourceforge.net/ "libinklevel")
3. Install [ink](http://ink.sourceforge.net/ "ink")
4. Use command `ink -p usb` to check

# Convert PNG to ICO using ImageMagick

```
convert logo.png -define icon:auto-resize=64,48,32,16 logo.ico
```

# How to do Mac/iOS Stuff in Linux

### Converting Apple Developer Certificate to .p12 with OpenSSL

1. Convert the developer certificate file you receive from Apple into a PEM certificate file. Run the following command-line statement from the OpenSSL bin directory: `openssl x509 -in developer_identity.cer -inform DER -out developer_identity.pem -outform PEM`
2. If you are using the private key from the keychain on a Mac computer, convert it into a PEM key: `openssl pkcs12 -nocerts -in mykey.p12 -out mykey.pem`
3. You can now generate a valid P12 file, based on the key and the PEM version of the iPhone developer certificate: `openssl pkcs12 -export -inkey mykey.key -in developer_identity.pem -out iphone_dev.p12`

# Sendmail Sample Usage

mail.txt:

```
MIME-Version: 1.0 <br></br>Content-Type: text/html <br></br>From: newsletter@shopbah.com <br></br>Subject: TESTING 123 hehehe <br></br><br></br><html><head><title>TESTING ONLY BAH</title></head> <br></br><body> <br></br><strong>Content line</strong> 1 <br></br><strong>Content line</strong> 2 <br></br><strong>Content line</strong> 3 <br></br></body></html> 
```

\* `sendmail address@example.com < mail.txt`

</body></html>

# Windows - Issues

## IIS Service Unavailable Error

1. Search for "run"
2. In the run dialog, enter "`iisreset`" and press run

# Networking

Linux network troubleshooting and administration

# CentOS 7 - Configuring Cacti

## Install Required Dependencies

```
yum -y install mariadb-server php php-cli php-mysql net-snmp-utils rrdtool php-snmp gcc mariadb-devel net-snmp-devel autoconf automake libtool dos2unix
```

## Enable Required Services for Cacti

```
chkconfig httpd on<br></br>chkconfig mariadb on<br></br>chkconfig crond on
```

## Download and Extract Cacti

cd /var/www/html   
wget http://www.cacti.net/downloads/cacti-0.8.8c.tar.gz   
tar -xzvf cacti-0.8.8c.tar.gz

## Setting Up Cacti for Apache

### Add Cacti User &amp; Enable Cron Jobs

```
adduser cacti<br></br>echo "*/5 * * * * cacti php /var/www/html/cacti/poller.php &>/dev/null" >> /etc/cron.d/cacti
```

### Fix Cacti Directory Permission

```
cd /var/www/html/cacti<br></br>chown -R cacti.apache rra log<br></br>chmod 775 rra log
```

### Set Up Cacti Database

```
mysql -p cacti < /var/www/html/cacti/cacti.sql<br></br>GRANT ALL ON cacti.* TO cactiuser@localhost IDENTIFIED BY 'MyV3ryStr0ngPassword'; <br></br>flush privileges; <br></br>exit<br></br>cd /var/www/html/cacti/include/ <br></br>vi config.php (and change $database_* configuration and $url_path)
```

## Open Firewall Ports to HTTP and HTTPS

```
firewall-cmd --permanent --zone=public --add-service=https <br></br>firewall-cmd --permanent --zone=public --add-service=http <br></br>firewall-cmd --reload
```

Login to cacti using admin:admin and go to “Console -&gt; System Utilities” and click on “Rebuild Poller Cache” after the first login!

# IPTables - Forwarding Between LAN and WLAN 

Add the following to `/etc/udev/rules.d/10-network.rules`, substitute `LAN_MAC_ADDR` and `WLAN_MAC_ADDR` with your Ethernet device and WLAN device MAC addresses for persistent network names:

```
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="LAN_MAC_ADDR", NAME="ether0" <br></br>SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="WLAN_MAC_ADDR", NAME="wifi0" 
```

Add the following to `/etc/sysctl.d/30-ip_forward.conf`:

```
net.ipv4.ip_forward=1<br></br>net.ipv4.conf.default.forwarding=1<br></br>net.ipv4.conf.all.forwarding=1 <br></br>Add the following to /etc/iptables/iptables.rules: <br></br>*nat <br></br>:PREROUTING ACCEPT [783:65928] <br></br>:INPUT ACCEPT [73:9660] <br></br>:OUTPUT ACCEPT [6180:382480] <br></br>:POSTROUTING ACCEPT [18:1260] <br></br>-A POSTROUTING -o wifi0 -j MASQUERADE <br></br>COMMIT<br></br><br></br>*filter <br></br>:INPUT ACCEPT [0:0] <br></br>:FORWARD ACCEPT [0:0] <br></br>:OUTPUT ACCEPT [176:192839] <br></br>-A INPUT -i lo -m comment --comment "Inbound from loopback (lo)" -j ACCEPT <br></br>-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT <br></br>-A INPUT -p icmp -j ACCEPT <br></br>-A INPUT -j NFLOG --nflog-group 1 <br></br>-A INPUT -j REJECT --reject-with icmp-host-prohibited <br></br>-A FORWARD -i wifi0 -j ACCEPT <br></br>-A FORWARD -i wifi0 -o ether0 -m comment --comment "ether0 <\- wifi0" -j ACCEPT <br></br>-A FORWARD -i ether0 -o wifi0 -m comment --comment "wifi0 -> ether0" -j ACCEPT <br></br>-A FORWARD -j REJECT --reject-with icmp-host-prohibited <br></br>COMMIT
```

# Connecting to OpenVPN Using NetworkManager

## Install the required packages

```
sudo apt-get install network-manager network-manager-openvpn network-manager-openvpn-gnome 
```

## Creating individual files from client.ovpn file

*These files must be kept safe and private at all times*

1. Make a directory called openvpn in your home directory
2. Copy the client.ovpn file into dir openvpn
3. Optional: Keep an original copy of the file – call it client.ovpn.orig
4. Next we will create 4 files under the openvpn directory. Open the client.ovpn file in a text editor
5. Create a file called ca.crt – copy the text between and from client.ovpn into this file
6. Create a file called client.crt – copy the text between and from client.ovpn into this file
7. Create a file called client.key – copy the text between and from client.ovpn into this file
8. Create a file called ta.key – copy the text between and from client.ovpn into this file
9. At this point i have a total of 6 files under my openvpn directory

## Modify the client.ovpn file

Just before the ## —–BEGIN RSA SIGNATURE—– line add the below lines and save:

```
ca ca.crt<br></br>cert client.crt<br></br>key client.key<br></br>tls-auth ta.key 
```

## Setting up the Network Manager

1. Click on Ubuntu network icon on the top right
2. Select VPN Connections -&gt; Configure VPN ( the Network Connections window will open )
3. Click on the VPN tab and click Import
4. Select the client.ovpn file we just modified and it should automatically import some things into the next screen
5. Connection Name will be = client – change this to something meaningful ( i set it to companyVPN )
6. Gateway must be imported already
7. Type is : Password with Certificates ( TLS ) – this was also set for me
8. Provide the username and password for VPN
9. User certificate will be client.crt
10. CA certificate will be ca.crt
11. Private Key will be client.key
12. Click on Advanced -&gt; TLS Authentication Tab
13. Key file will be ta.key
14. Key Direction must be set based on the key direction in your client.ovpn file
15. Open the client.ovpn file and search for “key-direction” and note the number after that ( mine is key-direction 1 )
16. Put this number in the Key Direction field in the TLS Authentication Tab
17. Click save on all windows and close all windows.

## Time to test connection

1. Click on network icon on the top right
2. Select VPN Connections and you should see your connection there – click it
3. If successfully connected, you will see a message and then you can verify your IP address with ifconfig
4. There is a Disconnect VPN under VPN Connection for obvious reasons

# OpenVPN - Firewall Configuration

## FirewallD

Use the following commands to open all ports required by OpenVPN:

```
firewall-cmd --list-services<br></br>firewall-cmd --permanent --add-service openvpn<br></br>firewall-cmd --permanent --add-masquerade<br></br>firewall-cmd --query-masquerade<br></br>firewall-cmd --reload
```

## IPTables

My IPTables configuration `/etc/iptables/iptables.rules` for OpenVPN:

```
*filter <br></br>:INPUT ACCEPT [0:0] <br></br>:FORWARD ACCEPT [0:0] <br></br>:OUTPUT ACCEPT [32:2712] <br></br>:LOGGING - [0:0] <br></br>-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT <br></br>-A INPUT -p icmp -m icmp --icmp-type 8 -j REJECT --reject-with icmp-host-prohibited <br></br>-A INPUT -p icmp -m icmp --icmp-type 0 -j REJECT --reject-with icmp-host-prohibited <br></br>-A INPUT -p icmp -j ACCEPT <br></br>-A INPUT -i lo0 -m comment --comment "Allow loopback lo0" -j ACCEPT <br></br>-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT <br></br>-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT <br></br>-A INPUT -p udp -m udp --dport 1194 -j ACCEPT <br></br>-A INPUT -j LOGGING <br></br>-A INPUT -j REJECT --reject-with icmp-host-prohibited <br></br>-A FORWARD -i tun+ -j ACCEPT <br></br>-A FORWARD -j REJECT --reject-with icmp-host-prohibited <br></br>-A LOGGING -j LOG --log-prefix "DROPPED: " \--log-level 7 <br></br>-A LOGGING -j DROP <br></br>COMMIT <br></br># Completed on Mon Jun 30 06:48:44 2014 <br></br># Generated by iptables-save v1.4.7 on Mon Jun 30 06:48:44 2014 <br></br>*nat <br></br>:PREROUTING ACCEPT [0:0] <br></br>:POSTROUTING ACCEPT [2:165] <br></br>:OUTPUT ACCEPT [2:165] <br></br>-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE <br></br>COMMIT 
```

# RHEL VLAN and Bonding Configuration

### Check list:

- Check whether the 8021q module has been loaded.
- lsmod | grep 8021q
- If the 8021q module is not loaded, run the following command to load it: modprobe 8021q

### Configuration

Add the following lines to /etc/modprobe.conf :

```
alias bond0 bonding<br></br><br></br>options bonding max_bonds=1<br></br><br></br>Edit /etc/sysconfig/network-scripts/ifcfg-eth0 it should look something like this:<br></br>DEVICE=eth0<br></br>USERCTL=no<br></br>ONBOOT=yes<br></br>MASTER=bond0<br></br>SLAVE=yes<br></br>BOOTPROTO=none<br></br>HWADDR=<br></br><br></br>Edit /etc/sysconfig/network-scripts/ifcfg-eth1 it should look something like this:<br></br>DEVICE=eth1<br></br>USERCTL=no<br></br>ONBOOT=yes<br></br>MASTER=bond0<br></br>SLAVE=yes<br></br>BOOTPROTO=none<br></br>HWADDR=
```

Now create the Bond0 interface:

NOTE: No IP address will be assigned to the bond0 device.

Create a new file `/etc/sysconfig/network-scripts/ifcfg-bond0` it should look like this:

```
DEVICE=bond0<br></br>BOOTPROTO=none<br></br>ONBOOT=yes<br></br>TYPE=Ethernet<br></br><br></br>BONDING_OPTS="mode=1 miimon=100"
```

NOTE: mode could be different, these are the mode options, but if Blade server is using Virtual Connect user should use mode=1.

mode=0 (balance-rr) Round-robin  
mode=1 (active-backup) Active-backup  
mode=2 (balance-xor) XOR  
mode=3 (broadcast) Broadcast  
mode=4 (802.3ad) IEEE 802.3ad Dynamic link aggregation  
mode=5 (balance-tlb) Adaptive transmit load balancing  
mode=6 (balance-alb) Adaptive load balancing

The first four modes are the most commonly used:

#### VLAN tag setup

This will be a virtual interface with a VLAN tag of 48. User's VLAN set-up is most likely different so just replace 48 with the VLAN tag of user's network. i.e. bond1.50 would be the bonded interface for VLAN 50.

Create a new file `/etc/sysconfig/network-scripts/ifcfg-bond0.48` it should look like this:

```
DEVICE=bond0.48<br></br>ONBOOT=yes<br></br>TYPE=Ethernet<br></br>BOOTPROTO=static<br></br>VLAN=yes<br></br>NETMASK=255.255.255.0<br></br>NETWORK=192.168.48.0<br></br>IPADDR=192.168.48.100
```

Ensure that the default gateway in this configuration is recorded in the /etc/sysconfig/network file otherwise it may not work properly. Once done, it should look something like:

```
NETWORKING=yes<br></br>HOSTNAME=<br></br>GATEWAY=192.168.48.1
```

User has now setup bonding and VLAN tagging. User needs to restart networking to make the changes active.

```
service network restart
```

#### Testing

Verify bonding interface is up and running

```
ifconfig -a
```

Verify configuration (RHEL 5 is using `sysfs` , so check out `/sys/class/net/` )

# Setup SFTP to Public Directory (/var/www)

### Configuring SSH for SFTP

1. `vim /etc/ssh/sshd_config`
2. Comment the following line:
    
    
    1. `<span class="typ">Subsystem</span><span class="pln"> sftp </span><span class="pun">/</span><span class="pln">usr</span><span class="pun">/</span><span class="kwd">local</span><span class="pun">/</span><span class="pln">libexec</span><span class="pun">/</span><span class="pln">sftp</span><span class="pun">-</span><span class="pln">server</span>`
3. Add the following lines:
    
    
    1. `<span class="typ">Subsystem</span><span class="pln"> sftp </span><span class="kwd">internal</span><span class="pun">-</span><span class="pln">sftp</span>`
    2. `<span class="typ">Match</span> <span class="typ">Group</span> <span class="pun"><</span><span class="pln">sftp </span><span class="kwd">group</span><span class="pun">></span>`
    3. `<span class="typ">ChrootDirectory</span> <span class="pun">%</span><span class="pln">h </span>`
    4. `<span class="typ">ForceCommand</span> <span class="kwd">internal</span><span class="pun">-</span><span class="pln">sftp</span>`
    5. `<span class="pln">X11Forwarding </span><span class="kwd">no</span> `
    6. `<span class="typ">AllowTcpForwarding</span> <span class="kwd">no</span>`
4. Save and close
5. Reload ssh `sudo systemctl restart sshd`

### Add SFTP User and Set Permission

1. `sudo groupadd <user> -g <sftp group> -s /bin/false -d /var/www/html`
2. `sudo passwd <user>`
3. `sudo chown root /var/www/html`
4. `sudo chmod 755 /var/www/html`
5. `sudo mkdir /var/www/html/<dir>`
6. `sudo chmod 775 /var/www/html/<dir>`
7. `sudo chown apache:apache /var/www/html/<dir>`
8. `sudo chmod g+s /var/www/html/<dir>`

### Selinux

1. `sudo setsebool -P ssh_chroot_rw_homedirs on`
2. `sudo setsebool -P httpd_unified 1`
3. `sudo setfacl -d -m g:apache:rw /var/www/html/<dir>`

### References

1. [Spiceworks Article](https://community.spiceworks.com/how_to/112551-setup-a-sftp-server-running-on-centos-linux-7)
2. [CentOS Docs](https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s1-acls-setting.html)

# FirewallD - Opening a Port

Use this command to find your active zone(s):

```
firewall-cmd --get-active-zones
```

It will say either public, dmz, or something else. You should only apply to the zones required.

In the case of dmz try:

```
firewall-cmd --zone=dmz --add-port=<port>/tcp --permanent
```

Otherwise, substitute dmz for your zone, for example, if your zone is public:

```
firewall-cmd --zone=public --add-port=<port>/tcp --permanent
```

Then remember to reload the firewall for changes to take effect.

```
firewall-cmd --reload
```

# Using LetsEncrypt for OpenVPN WebSSL

Using letsencrypt for OpenVPN Access Server is nothing more than symlinking the files to letsencrypt keys and certs:

1. `<span class="pln">sudo </span><span class="pun">-</span><span class="pln">s</span>`
2. `<span class="pln">cd </span><span class="pun">/</span><span class="pln">usr</span><span class="pun">/</span><span class="kwd">local</span><span class="pun">/</span><span class="pln">openvpn_as</span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span>`
3. `<span class="pln">mv web</span><span class="pun">-</span><span class="pln">ssl web</span><span class="pun">-</span><span class="pln">ssl</span><span class="pun">.</span><span class="pln">bak</span>`
4. `<span class="pln">mkdir web</span><span class="pun">-</span><span class="pln">ssl</span>`
5. `<span class="pln">ln </span><span class="pun">-</span><span class="pln">s </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">letsencrypt</span><span class="pun">/</span><span class="pln">live</span><span class="pun">/<</span><span class="pln">letsencrypt domain dir</span><span class="pun">></span><span class="str">/privkey.pem web-ssl/</span><span class="pln">server</span><span class="pun">.</span><span class="pln">key</span>`
6. `<span class="pln">ln </span><span class="pun">-</span><span class="pln">s </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">letsencrypt</span><span class="pun">/</span><span class="pln">live</span><span class="pun">/<</span><span class="pln">letsencrypt domain dir</span><span class="pun">></span><span class="str">/cert.pem web-ssl/</span><span class="pln">server</span><span class="pun">.</span><span class="pln">crt</span>`
7. `<span class="pln">ln </span><span class="pun">-</span><span class="pln">s </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">letsencrypt</span><span class="pun">/</span><span class="pln">live</span><span class="pun">/<</span><span class="pln">letsencrypt domain dir</span><span class="pun">></span><span class="str">/fullchain.pem web-ssl/</span><span class="pln">ca</span><span class="pun">.</span><span class="pln">crt</span>`
8. `<span class="pln">systemctl restart openvpnas</span>`

# Monitor Mode on Broadcom-wl Driver

## Enable monitor mode:

```
$ echo 1 > /proc/brcm_monitor0
```

*Enabling monitor mode will create a `prism0` network interface. Wireshark and other network tools can use this new `prism0` interface.*

## To disable monitor mode:

```
$ echo 0 > /proc/brcm_monitor0
```

# SSH Tunneling

`ssh -p <port> <username>@<remote host> -L <local listening port>:<remote's host ip>:<remote's host port> -N`

\*\*Note:\*\*  
Remote's host and port can be any host and port accessible by the remote host, e.g. to access the router web interface on 192.168.1.1 (remote) use &lt;local listening port&gt;:192.168.1.1:80

# Syncing Files with FTP

I came across a problem when doing migration last time, the server grew too big that I cannot just simply compress the files and move it to another server, it was more than 20GB files. So, I came across an FTP client called LFTP that will synchronize files and folders over FTP. The script below is the script I used to sync the files, let's call it sync.sh:

1. ```
    <span class="com">#!/bin/bash<br></br>HOST='<ftp host>'<br></br>USER='<ftp user>'<br></br>PASS='<password>'<br></br>RCD='<remote directory to sync>'<br></br>lftp -e "<br></br>open $HOST<br></br>user $USER $PASS<br></br>mirror --verbose --continue $RCD<br></br>bye<br></br>"</span>
    ```

To sync only certain folders, use the following sciprts:

1. ```
    <span class="com">#!/bin/bash<br></br>HOST='<ftp host>'<br></br>USER='<ftp user>'<br></br>PASS='<password>'<br></br>RCD='<remote directory to sync>'<br></br>lftp -e "<br></br>open $HOST<br></br>user $USER $PASS<br></br>mirror --verbose --continue --exclude '.*' --exclude '.*/' --include '<folder1>' --include '<folder2>' $RCD<br></br>bye<br></br>"</span>
    ```

To have sync overnight even when logged out, use the command `nohup bash sync.sh > sync.log`.

# ArchLinux - Setting Up Fortinet SSL VPN

1. Install ppp, openfortivpn and networkmanager's fortinet plugin package: `sudo pacman -Syu ppp openfortivpn networkmanager-fortisslvpn`
2. Get certificate digest by running: `sudo openfortivpn <IP Address>:<Port> --username=<username>`
3. Enable kernel module: `modprobe ppp_generic`
4. Reconnect with openfortivpn: `sudo openfortivpn <IP Address>:<Port> --username=<username> --trusted-cert <certificate digest>`
5. Now you can connect to the VPN by creating a new Fortinet SSLVPN (fortisslvpn) connection:
	- Enter the `Gateway` in the format `<IP Address>:<Port>`
	- Your username and password
	- Finally click "Advanced" and enter the certificate digest into `Trusted certificate` field

### References
- [ArchLinux PPP](https://wiki.archlinux.org/index.php/Ppp)
- [Openfortivpn](https://github.com/adrienverge/openfortivpn)

# Desktop Environments

Everthing to do about Desktop Environments, including LXDE, XFCE, KDE and Gnome

# Getting Cursor Pointer Theme for LXDE

1. Installing the package `xcursor-themes`
2. Then go to `Preferences` > `Customize Look and Feel`
3. Select your cursor pointer theme under `Mouse Cursor` tab

# LXDE Volume Keybinding

Add the following lines to `~/.config/openbox/lxde-rc.xml`:

```
<keybind key="XF86AudioMute"> 
  <action name="Execute"> 
    <command>amixer sset Master toggle</command> 
  </action> 
</keybind> 
<keybind key="XF86AudioRaiseVolume"> 
  <action name="Execute"> 
    <command>amixer sset Master 5%+</command> 
  </action> 
</keybind> 
<keybind key="XF86AudioLowerVolume"> 
  <action name="Execute"> 
    <command>amixer sset Master 5%-</command> 
  </action>
</keybind>
```
  
Issue command => `openbox --restart`

# LXDE Blueproximity Settings

**Locking Command**: `xscreensaver-command -activate`  
**Unlock Command**: `pkill xscreensaver`  
**Proximity Command**: `xscreensaver-command -time || daemonize /usr/bin/xscreensaver -no-splash`  
**Daemonize Utility**: To stop blueproximity from hanging when using the proximity command, it requires the daemonize command (http://software.clapper.org/daemonize/). Using "xscreensaver -no-splash &" or "xscreensaver -no-splash" will cause blueproximity to hang.

# Auto Suspend USB

**There are 2 settings that needs to changed:**  
1. Add `usbcore.autosuspend=0 usbcore.autosuspend_delay_ms=-1` to `/boot/grub/grub.cfg` kernel param
2. Disable monitor power manager control in `xfce4-power-manager` settings
3. Install `acpid`
4. Add the following udev rules to `/etc/udev/rules.d/99-usb-autosuspend.rules`:
```
ACTION=="add", SUBSYSTEM=="usb", TEST=="power/control",
ATTR{power/control}="on"
ACTION=="add", SUBSYSTEM=="usb", TEST=="power/autosuspend",
ATTR{power/autosuspend}="0"
ACTION=="add", SUBSYSTEM=="usb", TEST=="power/autosuspend_delay_ms",
ATTR{power/autosuspend_delay_ms}="-1"
```

# LXDE Visual Artifacts when Switching from Desktops with Chrome

LXDE Visual Artifacts when Switching Desktops. Install a [composite manager](http://en.wikipedia.org/wiki/Compositing_window_manager) will remove the artifacts, below is a list of composite managers:

- [xcompmgr](http://www.freedesktop.org/wiki/Software/xapps) - a minimal alternative to Compiz
- [Compton](https://github.com/chjj/compton) - A bug-fixed fork of dcompmgr, which is a fork of xcompmgr
- [Cairo Compmgr (Cairo Composite Manager)](http://cairo-compmgr.tuxfamily.org/) - a compositing add-on for existing window managers. It uses [Cairo](http://en.wikipedia.org/wiki/Cairo_(graphics)), a vector graphics library also used in [GTK+](http://en.wikipedia.org/wiki/GTK%2B).
- [Unagi Compositing Manager](http://unagi.mini-dweeb.org/) - a compositing manager which can be used along with an existing window manager. It uses the XCB library.
I used Compton for my composite manager:

Install `compton` package
Add `@compton -b` to the end of `/etc/xdg/lxsession/LXDE/autostart`

**References:**
1. https://wiki.archlinux.org/index.php/Compton

# Scripts

Contains all the script I used for my administration

# Script - Backup Script for Home Directories and MySQL Databases

```
#!/bin/sh

# Home directory to backup must be absolute path, with trailing slash 
home_dir='/home/' 
# Target backup directory, must be absolute path, with trailing slash 
backup_dir='/backups/'

# Database user 
db_user='root' 
# Database Password 
db_pwd=''

cd "$home_dir" 
# Get list of users based on home dir 
users=`find . -maxdepth 1 -type d \( -iname "*" ! -iname "backups" ! -iname "lost+found" \) -exec echo {} \; | sed "s#./##" | grep -v '^/home$'`
for user in $users; do 
    # Skip if user string is empty 
    if [ $user == "" -o $user == ".." -o $user == "." ]; then 
        continue 
    fi 
    # Archive all files in directory 
    archive="$backup_dir`date +%Y%m%d`.$user.tar.gz" 
    tar czf "$archive" "$user" 
done

# Database backup script 
if [ ! -z "$db_pwd" ]; then 
    databases=`mysql -u$db_user -p$db_pwd -e "SHOW DATABASES;" | tr -d "| " | grep -v Database` 
else
    databases=`mysql -u$db_user -e "SHOW DATABASES;" | tr -d "| " | grep -v Database` 
fi 
cd $backup_dir 
for db in $databases; do 
    if [[ "$db" != "information_schema" ]] && [[ "$db" != "performance_schema" ]] && [[ "$db" != "mysql" ]] && [[ "$db" != _* ]] ; then 
        sql="`date +%Y%m%d`.$db.sql" 
        echo "Dumping database: $db" 
        if [ -z "$db_pwd" ]; then 
            mysqldump -u$db_user $db > $sql 
        else 
            mysqldump -u$db_user -p$db_pwd $db > $sql 
        fi 
        tar -czf "`date +%Y%m%d`.$db.sql.tar.gz" $sql 
        rm $sql 
    fi 
done 
```

**NOTE**: Add this to `cronjob` to delete backups older than 90 days: `find . -type d -mtime +90 -exec rm {}\;`

# Script - MySQL Dump Databases Separated by DB Name

```
#!/bin/bash

DUMP_EXEC="mysqldump" #path to mysqldump
MYSQL_EXEC="mysql" #path to mysql

MYSQL_USER="root" #db user
MYSQL_PASSWORD="" #db password

databases="$MYSQL_EXEC -u$MYSQL_USER"
if [ "$MYSQL_PASSWORD" ]; then
    databases="$databases -p$MYSQL_PASSWORD"
fi

eval "$databases -e 'show databases'" | while read dbname
do
    if [ "$dbname" ]; then
        echo "Dumping database: $dbname"
        dumpScript="$DUMP_EXEC --max_allowed_packet=1G -u$MYSQL_USER"
        if [ "$MYSQL_PASSWORD" ]; then
            dumpScript="$dumpScript -p$MYSQL_PASSWORD"
        fi
        eval "$dumpScript --complete-insert '$dbname' > '$dbname.sql'"
    fi
done
```

# Script - Move Infected Emails to Quarantine and Notify Users

The following script will do the following:  
1. Parse email headers from ClamScan Results
2. Move infected email to `$QUARANTINE` folder
3. Construct email messages
4. Email the users who has any infected emails in their mailbox

```
#!/bin/bash

ADMIN="admin@domain.com" # Admin email
QUARANTINE="/quarantine/directory/" # Quarantine folder with trailing slash
HEADER="The emails listed has been moved to quarantine and will be deleted after 30 days. If you have any concerns, please contact the server administrator" 
FOOTER="This is an automated email through ClamScan results, please find the script details at 'https://wiki.twcloud.tech/books/linux/page/script---move-infected-emails-to-quarantine-and-notify-users'"

# Getting email information
[ -z "$1" ] && echo "File parameter missing" && exit 1
[ ! -f "$1" ] && echo "File not found / not a regular file" && exit 1
declare -A emails
while read i; do
	file=`echo "$i" | sed -e 's/\:\ .*FOUND//'`
	if [ ! -f "$file" ]; then
		continue
	fi
	infection=`echo "$i" | sed -n 's/\:\ .*FOUND//'`
	to=`cat "$file" | grep -m 1 "^Envelope-to\:\s\+" | sed 's/Envelope-to\:\ //' | grep -EiEio '\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b'`
	# Try find To: header if Envelope-to: not found
	[[ -z "$to" ]] && to=`cat "$file" | grep -m 1 "^To\:\s\+" | sed 's/To\:\ //' | grep -EiEio '\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b'`
	from=`cat "$file" | grep -m 1 "^From\:\s\+" | sed 's/From\:\ //'`
	d=`cat "$file" | grep -m 1 "^Delivery-date\:\s\+" | sed 's/Delivery-date\:\ //'`
	subject=`cat "$file" | grep -m 1 "^Subject\:\s\+" | sed 's/Subject\:\ //'`

	# Send empty "$to" to admin
	[[ -z "$to" ]] && to="$ADMIN"

	# Construct email message
	[[ -z "${emails[$to]}" ]] && emails[$to]="$HEADER"
	emails[$to]="${emails[$to]}\n\nFrom: $from\nDate: $d\nSubject: $subject"

	# Move emails to quarantine
	mv "$file" "$QUARANTINE"
done < "$1"

# Notify email users that the emails are sent to quarantine
for k in "${!emails[@]}"; do
	echo -e "${emails[$k]}\n----------\n$FOOTER" | mail -s "Infected emails quarantined" -c "$ADMIN" $k
done
```

# Delete Old Emails and Notify User

```
ADMIN="admin@domain.com" # Admin email
DOMAIN="domain.com" # Domain name
HEADER="The emails listed has been moved to trash, and will be deleted on the 31st December every year" 
FOOTER="This is an automated email generated through a script, please find the script details at 'https://wiki.twcloud.tech/books/linux/page/delete-old-emails-and-notify-user'"
REMOVE_FILE_AGE=60 # File age to remove in days
USER="user" # Username used to login to the hosting account
TRASH_FOLDER="/home/$USER/trashed_emails/" # Trash folder with trailing slash

# Getting email information
[ -z "$1" ] && echo "Email user parameter missing" && exit 1
[ ! -d "/home/$USER/mail/$DOMAIN/$1/cur" ] && echo "Email not found" && exit 1
# Declarations
declare -A emails

for file in $(find "/home/$USER/mail/$DOMAIN/$1/cur" -type f -mtime +${REMOVE_FILE_AGE} -print); do
    if [ ! -f "$file" ]; then
        continue
    fi
    to="$1@$DOMAIN"
    from=`cat "$file" | grep -m 1 "^From\:\s\+" | sed 's/From\:\ //'`
    d=`cat "$file" | grep -m 1 "^Delivery-date\:\s\+" | sed 's/Delivery-date\:\ //'`
    subject=`cat "$file" | grep -m 1 "^Subject\:\s\+" | sed 's/Subject\:\ //'`

    # Send empty "$to" to admin
    [[ -z "$to" ]] && to="$ADMIN"

    # Construct email message
    [[ -z "${emails[$to]}" ]] && emails[$to]="$HEADER"
    emails[$to]="${emails[$to]}\n\nFrom: $from\nDate: $d\nSubject: $subject"

    # Move emails to trash
    mv "$file" "$TRASH_FOLDER"
done

# Notify email users that the emails are sent to trash
for k in "${!emails[@]}"; do
    echo -e "${emails[$k]}\n----------\n$FOOTER" | mail -s "Inbox Cleared" -c "$ADMIN" $k
done
```

# Server Software

Server software configuration and installation procedures such as Apache, and Postfix

# Apache Option FollowSymLinks not allowed here Error

Apache htaccess `Option FollowSymLinks not allowed here` error:  
```
find /home -name ".htaccess" -type f -exec sed -i '/FollowSymLinks/SymLinksIfOwnerMatch/g' {} ";"
```

# Migrating Self-Signed SSL Certificate to LetsEncrypt Certificate

### Download Let's Encrypt Client

1. `<span class="pln">sudo </span><span class="pun">-</span><span class="pln">s</span>`
2. `<span class="pln">git clone https</span><span class="pun">:</span><span class="com">//github.com/letsencrypt/letsencrypt /opt/letsencrypt</span>`

### Update Apache Configuration

Let's Encrypt does not detect multiple virtual host in a single file, so if you have multiple virtual hosts in a single file, you need to separate it and update the configuration for SSL only. Then redirect all plain-text traffic to SSL using a single virtual host.

Create a new virtual host in `/etc/httpd/conf.d/redirect_ssl.conf` to redirect plain-text traffic to SSL, replace all `<domain>`to your TLD, such as `example.com`:

1. `<span class="tag"><VirtualHost</span><span class="pln"> *:80</span><span class="tag">></span>`
2. `<span class="pln"> ServerName </span><span class="tag"><domain></span>`
3. `<span class="pln"> ServerAlias *.</span><span class="tag"><domain></span>`
4. `<span class="pln"> RewriteEngine on</span>`
5. `<span class="pln"> RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R=301,L]</span>`
6. `<span class="tag"></VirtualHost></span>`

### Setup SSL Certificates

1. `<span class="pln">cd </span><span class="pun">/</span><span class="pln">opt</span><span class="pun">/</span><span class="pln">letsencrypt</span>`
2. `<span class="pun">./</span><span class="pln">letsencrypt</span><span class="pun">-</span><span class="kwd">auto</span> <span class="pun">--</span><span class="pln">apache </span><span class="pun">-</span><span class="pln">d </span><span class="str"><domain></span> <span class="pun">-</span><span class="pln">d www</span><span class="pun">.<</span><span class="pln">domain</span><span class="pun">></span> <span class="pun">-</span><span class="pln">d </span><span class="str"><subdomain></span><span class="pun">.<</span><span class="pln">domain</span><span class="pun">></span>`

Replacing `<domain>` with your domain, subsequent subdomains can be specified with `-d` option.

### Restart Apache and Test

1. `<span class="pln">systemctl restart httpd</span>`

### (Optional) Renewing SSL Certificates

Let's Encrypt issue **90 days** validity certificates, but you can however, renew it earlier in case errors occurred.

To renew the certificates, simply use the following command:

1. `<span class="str">/opt/</span><span class="pln">letsencrypt</span><span class="pun">/</span><span class="pln">letsencrypt</span><span class="pun">-</span><span class="kwd">auto</span><span class="pln"> renew</span>`

If you have just created a new certificate, Let's Encrypt will never issue you a new one, it will only issue a new certificate for your domains if the validity period is **less than 30 days**, so, you can create a cronjob to try and renew the certificate every day, week or month, in case anything goes wrong with your certificate.

To setup cronjob to automatically renew certificate, enter command `crontab -e` to create a new cronjob and add the following line:

1. `<span class="lit">0</span> <span class="lit">3</span> <span class="pun">*</span> <span class="pun">*</span> <span class="lit">1</span> <span class="pun">/</span><span class="pln">opt</span><span class="pun">/</span><span class="pln">letsencrypt</span><span class="pun">/</span><span class="pln">letsencrypt</span><span class="pun">-</span><span class="kwd">auto</span><span class="pln"> renew </span><span class="pun">>></span> <span class="str">/var/</span><span class="pln">log</span><span class="pun">/</span><span class="pln">le</span><span class="pun">-</span><span class="pln">renew</span><span class="pun">.</span><span class="pln">log</span>`

The cronjob above will run on **every monday** at **3 A.M.**, it will append any output from `/opt/letsencrypt/letsencrypt-auto`to `/var/log/le-renew.log`. Please refer to the reference for more info on Linux cronjobs.

### References

1. [Digital Ocean Article](https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-centos-7)
2. [Let's Encrypt Article](https://letsencrypt.org/getting-started/)
3. [Cronjob Format](http://www.nncron.ru/help/EN/working/cron-format.htm)

# LAMP Stack Upgrade Issues

### "Table Doesn't Exists" After MySQL/MariaDB Upgrade

Paste MySQL data directory to upgraded data directory, containing `ibdata1`, `ib_logfile0` and `ib_logfile1`, in `lampp`, it's `/opt/lampp/var/mysql`:

1. `<span class="pln">sudo cp </span><span class="pun">/</span><span class="pln">opt</span><span class="pun">/</span><span class="pln">lampp_backup</span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">mysql </span><span class="pun">/</span><span class="pln">opt</span><span class="pun">/</span><span class="pln">lampp</span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">mysql</span>`
2. `<span class="pln">sudo chown </span><span class="pun">-</span><span class="pln">R mysql</span><span class="pun">:</span><span class="pln">mysql </span><span class="pun">/</span><span class="pln">opt</span><span class="pun">/</span><span class="pln">lampp</span><span class="pun">/</span><span class="pln">mysql</span>`

# Standard Installation Procedures for LAMP Stack on CentOS 7

### 1. System Upgrade

1. `<span class="pln">yum </span><span class="pun">-</span><span class="pln">y update</span>`

### 2. Install Required Software

1. `<span class="pln">yum </span><span class="pun">-</span><span class="pln">y install git policycoreutils</span><span class="pun">-</span><span class="pln">python httpd mariadb mariadb</span><span class="pun">-</span><span class="pln">server php</span><span class="pun">-</span><span class="pln">mysql php</span><span class="pun">-</span><span class="pln">gd php</span><span class="pun">-</span><span class="pln">ldap php</span><span class="pun">-</span><span class="pln">odbc php</span><span class="pun">-</span><span class="pln">pear php</span><span class="pun">-</span><span class="pln">xml php</span><span class="pun">-</span><span class="pln">xmlrpc php</span><span class="pun">-</span><span class="pln">mbstring php</span><span class="pun">-</span><span class="pln">snmp php</span><span class="pun">-</span><span class="pln">soap curl curl</span><span class="pun">-</span><span class="pln">devel</span>`

### 3. Setup MySQL Server

1. `<span class="pln">mysql_secure_installation</span>`

4\. Start and Enable All Services

1. `<span class="pln">systemctl enable httpd</span>`
2. `<span class="pln">systemctl enable mariadb</span>`
3. `<span class="pln">systemctl start httpd</span>`
4. `<span class="pln">systemctl start mariadb</span>`

### 5. Open Firewall Ports

1. `<span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">permanent </span><span class="pun">--</span><span class="pln">zone</span><span class="pun">=</span><span class="kwd">public</span> <span class="pun">--</span><span class="pln">add</span><span class="pun">-</span><span class="pln">service</span><span class="pun">=</span><span class="pln">http</span>`
2. `<span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">permanent </span><span class="pun">--</span><span class="pln">zone</span><span class="pun">=</span><span class="kwd">public</span> <span class="pun">--</span><span class="pln">add</span><span class="pun">-</span><span class="pln">service</span><span class="pun">=</span><span class="pln">https</span>`
3. `<span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">permanent </span><span class="pun">--</span><span class="pln">zone</span><span class="pun">=</span><span class="kwd">public</span> <span class="pun">--</span><span class="pln">add</span><span class="pun">-</span><span class="pln">port</span><span class="pun">=<</span><span class="pln">ssh_port</span><span class="pun">>/</span><span class="pln">tcp</span>`
4. `<span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">reload</span>`

### 6. Change SSH Port

1. `<span class="pln">vim </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">ssh</span><span class="pun">/</span><span class="pln">sshd_config </span><span class="com">#and append 'Port <ssh_port>'</span>`
2. `<span class="pln">semanage port </span><span class="pun">-</span><span class="pln">a </span><span class="pun">-</span><span class="pln">t </span><span class="typ">ssh_port_t</span> <span class="pun">-</span><span class="pln">p tcp </span><span class="str"><ssh_port></span>`
3. `<span class="pln">systemctl restart sshd</span>`

### 7. Enable Shutdown Button

Edit `/etc/systemd/logind.conf` and uncomment the following 2 lines:

1. `<span class="typ">PowerKeyIgnoreInhibited</span><span class="pun">=</span><span class="kwd">no</span>`
2. `<span class="typ">HandlePowerKey</span><span class="pun">=</span><span class="pln">poweroff</span>`

### 8. Reboot System

1. `<span class="pln">reboot</span>`

## (HP MicroServer Only)

Edit `/etc/default/grub` and append `clocksource=hpet nolapic` to the end of `GRUB_CMDLINE_LINUX` variable.

# Slow Loading on Ownloud 8

Change `/var/www/html/owncloud/config/config.php` database host to `127.0.0.1` instead of `localhost`

# Postfix and Dovecot Configuration

<h3 id="bkmrk-installation">Installation</h3>
<ol class="linenums" id="bkmrk-hostnamectl-set-host">
<li class="L0"><code><span class="pln">hostnamectl </span><span class="kwd">set</span><span class="pun">-</span><span class="pln">hostname mail</span><span class="pun">.&lt;</span><span class="pln">domain</span><span class="pun">&gt;.&lt;</span><span class="pln">tld</span><span class="pun">&gt;</span></code></li>
<li class="L1"><code><span class="pln">yum </span><span class="pun">-</span><span class="pln">y install postfix dovecot</span></code></li>
</ol>
<h3 id="bkmrk-postfix-configuratio">Postfix Configuration</h3>
<ol id="bkmrk-append-the-following">
<li>
<p>Append the following to <code>/etc/postfix/main.cf</code>:</p>
<ol class="linenums">
<li class="L0"><code><span class="pln">myhostname </span><span class="pun">=</span><span class="pln"> mail</span><span class="pun">.&lt;</span><span class="pln">domain</span><span class="pun">&gt;.&lt;</span><span class="pln">tld</span><span class="pun">&gt;</span></code></li>
<li class="L1"><code><span class="pln">mydomain </span><span class="pun">=</span> <span class="str">&lt;domain&gt;</span><span class="pun">.&lt;</span><span class="pln">tld</span><span class="pun">&gt;</span></code></li>
<li class="L2"><code><span class="pln">myorigin </span><span class="pun">=</span><span class="pln"> $mydomain</span></code></li>
<li class="L3"><code><span class="pln">home_mailbox </span><span class="pun">=</span><span class="pln"> mail</span><span class="pun">/</span></code></li>
<li class="L4"><code><span class="pln">mynetworks </span><span class="pun">=</span> <span class="lit">127.0</span><span class="pun">.</span><span class="lit">0.0</span><span class="pun">/</span><span class="lit">8</span> <span class="pun">&lt;</span><span class="pln">domain IP</span><span class="pun">&gt;</span></code></li>
<li class="L5"><code><span class="pln">inet_interfaces </span><span class="pun">=</span><span class="pln"> all</span></code></li>
<li class="L6"><code><span class="pln">mydestination </span><span class="pun">=</span><span class="pln"> $myhostname</span><span class="pun">,</span><span class="pln"> localhost</span><span class="pun">.</span><span class="pln">$mydomain</span><span class="pun">,</span><span class="pln"> localhost</span><span class="pun">,</span><span class="pln"> $mydomain</span></code></li>
<li class="L7"><code><span class="pln">smtpd_sasl_type </span><span class="pun">=</span><span class="pln"> dovecot</span></code></li>
<li class="L8"><code><span class="pln">smtpd_sasl_path </span><span class="pun">=</span> <span class="kwd">private</span><span class="pun">/</span><span class="pln">auth</span></code></li>
<li class="L9"><code><span class="pln">smtpd_sasl_local_domain </span><span class="pun">=</span></code></li>
<li class="L0"><code><span class="pln">smtpd_sasl_security_options </span><span class="pun">=</span><span class="pln"> noanonymous</span></code></li>
<li class="L1"><code><span class="pln">broken_sasl_auth_clients </span><span class="pun">=</span><span class="pln"> yes</span></code></li>
<li class="L2"><code><span class="pln">smtpd_sasl_auth_enable </span><span class="pun">=</span><span class="pln"> yes</span></code></li>
<li class="L3"><code><span class="pln">smtpd_recipient_restrictions </span><span class="pun">=</span><span class="pln"> permit_sasl_authenticated</span><span class="pun">,</span><span class="pln">permit_mynetworks</span><span class="pun">,</span><span class="pln">reject_unauth_destination</span></code></li>
<li class="L4"><code><span class="pln">smtp_tls_security_level </span><span class="pun">=</span><span class="pln"> may</span></code></li>
<li class="L5"><code><span class="pln">smtpd_tls_security_level </span><span class="pun">=</span><span class="pln"> may</span></code></li>
<li class="L6"><code><span class="pln">smtp_tls_note_starttls_offer </span><span class="pun">=</span><span class="pln"> yes</span></code></li>
<li class="L7"><code><span class="pln">smtpd_tls_loglevel </span><span class="pun">=</span> <span class="lit">1</span></code></li>
<li class="L8"><code><span class="pln">smtpd_tls_key_file </span><span class="pun">=</span> <span class="str">/etc/</span><span class="pln">letsencrypt</span><span class="pun">/</span><span class="pln">live</span><span class="pun">/&lt;</span><span class="pln">domain</span><span class="pun">&gt;.&lt;</span><span class="pln">tld</span><span class="pun">&gt;/</span><span class="pln">privkey</span><span class="pun">.</span><span class="pln">pem</span></code></li>
<li class="L9"><code><span class="pln">smtpd_tls_cert_file </span><span class="pun">=</span> <span class="str">/etc/</span><span class="pln">letsencrypt</span><span class="pun">/</span><span class="pln">live</span><span class="pun">/&lt;</span><span class="pln">domain</span><span class="pun">&gt;.&lt;</span><span class="pln">tld</span><span class="pun">&gt;/</span><span class="pln">fullchain</span><span class="pun">.</span><span class="pln">pem</span></code></li>
<li class="L0"><code><span class="pln">smtpd_tls_received_header </span><span class="pun">=</span><span class="pln"> yes</span></code></li>
<li class="L1"><code><span class="pln">smtpd_tls_session_cache_timeout </span><span class="pun">=</span> <span class="lit">3600s</span></code></li>
<li class="L2"><code><span class="pln">smtpd_use_tls</span><span class="pun">=</span><span class="pln">yes</span></code></li>
<li class="L3"><code><span class="pln">tls_random_source </span><span class="pun">=</span><span class="pln"> dev</span><span class="pun">:</span><span class="str">/dev/</span><span class="pln">urandom</span></code></li>
<li class="L4"><code><span class="pln">virtual_alias_domains </span><span class="pun">=</span> <span class="str">&lt;domain&gt;</span><span class="pun">.&lt;</span><span class="pln">tld</span><span class="pun">&gt;</span></code></li>
<li class="L5"><code><span class="pln">virtual_alias_maps </span><span class="pun">=</span><span class="pln"> hash</span><span class="pun">:</span><span class="str">/etc/</span><span class="pln">postfix</span><span class="pun">/</span><span class="kwd">virtual</span></code></li>
</ol>
</li>
<li>
<p>Find and uncomment the following lines in <code>/etc/postfix/main.cf</code>:</p>
<ol class="linenums">
<li class="L0"><code><span class="com">#inet_interfaces = localhost</span></code></li>
<li class="L1"><code><span class="com">#mydestination = $myhostname, localhost.$mydomain, localhost</span></code></li>
</ol>
</li>
<li>
<p>Append the following lines to <code>/etc/postfix/master.cf</code>:</p>
<ol class="linenums">
<li class="L0"><code><span class="pln">submission inet n </span><span class="pun">-</span><span class="pln"> n </span><span class="pun">-</span> <span class="pun">-</span><span class="pln"> smtpd</span></code></li>
<li class="L1"><code> <span class="pun">-</span><span class="pln">o syslog_name</span><span class="pun">=</span><span class="pln">postfix</span><span class="pun">/</span><span class="pln">submission</span></code></li>
<li class="L2"><code> <span class="pun">-</span><span class="pln">o smtpd_sasl_auth_enable</span><span class="pun">=</span><span class="pln">yes</span></code></li>
<li class="L3"><code> <span class="pun">-</span><span class="pln">o smtpd_recipient_restrictions</span><span class="pun">=</span><span class="pln">permit_sasl_authenticated</span><span class="pun">,</span><span class="pln">reject_unauth_destination</span></code></li>
<li class="L4"><code> <span class="pun">-</span><span class="pln">o milter_macro_daemon_name</span><span class="pun">=</span><span class="pln">ORIGINATING</span></code></li>
<li class="L5"><code><span class="pln">smtps inet n </span><span class="pun">-</span><span class="pln"> n </span><span class="pun">-</span> <span class="pun">-</span><span class="pln"> smtpd</span></code></li>
<li class="L6"><code> <span class="pun">-</span><span class="pln">o syslog_name</span><span class="pun">=</span><span class="pln">postfix</span><span class="pun">/</span><span class="pln">smtps</span></code></li>
<li class="L7"><code> <span class="pun">-</span><span class="pln">o smtpd_sasl_auth_enable</span><span class="pun">=</span><span class="pln">yes</span></code></li>
<li class="L8"><code> <span class="pun">-</span><span class="pln">o smtpd_recipient_restrictions</span><span class="pun">=</span><span class="pln">permit_sasl_authenticated</span><span class="pun">,</span><span class="pln">reject_unauth_destination</span></code></li>
<li class="L9"><code> <span class="pun">-</span><span class="pln">o milter_macro_daemon_name</span><span class="pun">=</span><span class="pln">ORIGINATING</span></code></li>
</ol>
</li>
<li>
<p>Make sure that the following is present in <code>/etc/postfix/main.cf</code>:</p>
<ol class="linenums">
<li class="L0"><code><span class="pln">alias_maps </span><span class="pun">=</span><span class="pln"> hash</span><span class="pun">:</span><span class="str">/etc/</span><span class="pln">aliases</span></code></li>
</ol>
</li>
<li>
<p>Edit and add the desired email address to <code>/etc/postfix/virtual</code> such as the following:</p>
<ol class="linenums">
<li class="L0"><code><span class="pln">info@</span><span class="str">&lt;domain&gt;</span><span class="pun">.&lt;</span><span class="pln">tld</span><span class="pun">&gt;</span><span class="pln"> admin</span></code></li>
<li class="L1"><code><span class="pln">webmaster@</span><span class="str">&lt;domain&gt;</span><span class="pun">.&lt;</span><span class="pln">tld</span><span class="pun">&gt;</span><span class="pln"> admin</span></code></li>
</ol>
</li>
<li>
<p>Create a map database: <code>postmap /etc/postfix/virtual</code></p>
</li>
</ol>
<h3 id="bkmrk-dovecot-configuratio">Dovecot Configuration</h3>
<ol id="bkmrk-find-and-modify-the-">
<li>
<p>Find and modify the following lines in <code>/etc/dovecot/conf.d/10-master.conf</code>:</p>
<ol class="linenums">
<li class="L0"><code><span class="com"># Postfix smtp-auth</span></code></li>
<li class="L1"><code><span class="pln">unix_listener </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">spool</span><span class="pun">/</span><span class="pln">postfix</span><span class="pun">/</span><span class="kwd">private</span><span class="pun">/</span><span class="pln">auth </span><span class="pun">{</span></code></li>
<li class="L2"><code><span class="pln"> mode </span><span class="pun">=</span> <span class="lit">0660</span></code></li>
<li class="L3"><code><span class="pln"> user </span><span class="pun">=</span><span class="pln"> postfix</span></code></li>
<li class="L4"><code> <span class="kwd">group</span> <span class="pun">=</span><span class="pln"> postfix</span></code></li>
<li class="L5"><code><span class="pun">}</span></code></li>
</ol>
</li>
<li>
<p>Find and modify the following lines in <code>/etc/dovecot/conf.d/10-auth.conf</code>:</p>
<ol class="linenums">
<li class="L0"><code><span class="pln">auth_mechanisms </span><span class="pun">=</span><span class="pln"> plain login</span></code></li>
</ol>
</li>
<li>
<p>Find and modify the following lines in <code>/etc/dovecot/conf.d/10-mail.conf</code>:</p>
<ol class="linenums">
<li class="L0"><code><span class="pln">mail_location </span><span class="pun">=</span><span class="pln"> maildir</span><span class="pun">:~/</span><span class="pln">mail</span></code></li>
</ol>
</li>
<li>
<p>Find and modify the following lines in <code>/etc/dovecot/conf.d/20-pop3.conf</code>:</p>
<ol class="linenums">
<li class="L0"><code><span class="pln">pop3_uidl_format </span><span class="pun">=</span> <span class="pun">%</span><span class="lit">08Xu</span><span class="pun">%</span><span class="lit">08Xv</span></code></li>
</ol>
</li>
<li>
<p>Find and modify the following lines in <code>/etc/dovecot/conf.d/10-ssl.conf</code>:</p>
<ol class="linenums">
<li class="L0"><code><span class="pln">ssl_cert </span><span class="pun">=</span> <span class="pun">&lt;</span><span class="str">/etc/</span><span class="pln">letsencrypt</span><span class="pun">/</span><span class="pln">live</span><span class="pun">/&lt;</span><span class="pln">domain</span><span class="pun">&gt;.&lt;</span><span class="pln">tld</span><span class="pun">&gt;/</span><span class="pln">fullchain</span><span class="pun">.</span><span class="pln">pem</span></code></li>
<li class="L1"><code><span class="pln">ssl_key </span><span class="pun">=</span> <span class="pun">&lt;</span><span class="str">/etc/</span><span class="pln">letsencrypt</span><span class="pun">/</span><span class="pln">live</span><span class="pun">/&lt;</span><span class="pln">domain</span><span class="pun">&gt;.&lt;</span><span class="pln">tld</span><span class="pun">&gt;/</span><span class="pln">privkey</span><span class="pun">.</span><span class="pln">pem</span></code></li>
</ol>
</li>
</ol>
<h3 id="bkmrk-restart-and-enable-s">Restart and Enable Services</h3>
<ol class="linenums" id="bkmrk-systemctl-restart-po">
<li class="L0"><code><span class="pln">systemctl restart postfix</span></code></li>
<li class="L1"><code><span class="pln">systemctl enable postfix</span></code></li>
<li class="L2"><code><span class="pln">systemctl restart dovecot</span></code></li>
<li class="L3"><code><span class="pln">systemctl enable dovecot</span></code></li>
</ol>
<h3 id="bkmrk-open-firewall-ports">Open Firewall Ports</h3>
<ol class="linenums" id="bkmrk-firewall-cmd---perma">
<li class="L0"><code><span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">permanent </span><span class="pun">--</span><span class="pln">add</span><span class="pun">-</span><span class="pln">service</span><span class="pun">=</span><span class="pln">smtp</span></code></li>
<li class="L1"><code><span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">permanent </span><span class="pun">--</span><span class="pln">add</span><span class="pun">-</span><span class="pln">port</span><span class="pun">=</span><span class="lit">587</span><span class="pun">/</span><span class="pln">tcp</span></code></li>
<li class="L2"><code><span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">permanent </span><span class="pun">--</span><span class="pln">add</span><span class="pun">-</span><span class="pln">port</span><span class="pun">=</span><span class="lit">465</span><span class="pun">/</span><span class="pln">tcp</span></code></li>
<li class="L3"><code><span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">permanent </span><span class="pun">--</span><span class="pln">add</span><span class="pun">-</span><span class="pln">port</span><span class="pun">=</span><span class="lit">110</span><span class="pun">/</span><span class="pln">tcp</span></code></li>
<li class="L4"><code><span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">permanent </span><span class="pun">--</span><span class="pln">add</span><span class="pun">-</span><span class="pln">service</span><span class="pun">=</span><span class="pln">pop3s</span></code></li>
<li class="L5"><code><span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">permanent </span><span class="pun">--</span><span class="pln">add</span><span class="pun">-</span><span class="pln">port</span><span class="pun">=</span><span class="lit">143</span><span class="pun">/</span><span class="pln">tcp</span></code></li>
<li class="L6"><code><span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">permanent </span><span class="pun">--</span><span class="pln">add</span><span class="pun">-</span><span class="pln">service</span><span class="pun">=</span><span class="pln">imaps</span></code></li>
<li class="L7"><code><span class="pln">firewall</span><span class="pun">-</span><span class="pln">cmd </span><span class="pun">--</span><span class="pln">reload</span></code></li>
</ol>
<h3 id="bkmrk-configure-dns">Configure DNS</h3>
<ol id="bkmrk-add-an-a-record-for-">
<li>
<p>Add an <code>A</code> record for the mail server:</p>
<ol class="linenums">
<li class="L0"><code><span class="pln">name </span><span class="pun">=</span><span class="pln"> mail</span><span class="pun">.&lt;</span><span class="pln">domain</span><span class="pun">&gt;.&lt;</span><span class="pln">tld</span><span class="pun">&gt;</span><span class="str">`</span></code></li>
<li class="L1"><code><span class="str">IP = &lt;mail server IP&gt;</span></code></li>
</ol>
</li>
<li>
<p>Add an <code>MX</code> record:</p>
<ol class="linenums">
<li class="L0"><code><span class="typ">Hostname</span> <span class="pun">=</span><span class="pln"> mail</span><span class="pun">.&lt;</span><span class="pln">domain</span><span class="pun">&gt;.&lt;</span><span class="pln">tld</span><span class="pun">&gt;</span></code></li>
<li class="L1"><code><span class="typ">Priority</span> <span class="pun">=</span> <span class="lit">5</span></code></li>
</ol>
</li>
<li>
<p>Add the following <code>TXT</code> records:</p>
<ol class="linenums">
<li class="L0"><code><span class="typ">Name</span> <span class="pun">=</span> <span class="pun">@</span></code></li>
<li class="L1"><code><span class="typ">Text</span> <span class="pun">=</span> <span class="str">"v=spf1 ip4:&lt;domain IP&gt; ~all"</span></code></li>
<li class="L2"><code></code></li>
<li class="L3"><code><span class="typ">Name</span> <span class="pun">=</span><span class="pln"> _dmarc</span><span class="pun">.&lt;</span><span class="pln">domain</span><span class="pun">&gt;.&lt;</span><span class="pln">tld</span><span class="pun">&gt;</span></code></li>
<li class="L4"><code><span class="typ">Text</span> <span class="pun">=</span><span class="pln"> v</span><span class="pun">=</span><span class="pln">DMARC1</span><span class="pun">;</span><span class="pln"> p</span><span class="pun">=</span><span class="pln">none</span></code></li>
</ol>
</li>
<li>
<p>Add <code>PTR</code> record for <code>&lt;domain&gt;.&lt;tld&gt;</code></p>
</li>
<li>
<p>Finally, test your email at <code>https://www.mail-tester.com/</code></p>
</li>
</ol>
<h3 id="bkmrk-notes-on-using-let%27s">Notes on Using Let's Encrypt for SSL</h3>
<p id="bkmrk-make-sure-that-encry"><em>Make sure that <code>Encryption</code> is set to <code>STARTTLS</code> when configuring mail clients</em></p>
<h3 id="bkmrk-references">References</h3>
<ol id="bkmrk-krizna-article-ubunt">
<li><a href="http://www.krizna.com/centos/setup-mail-server-centos-7/">Krizna Article</a></li>
<li><a href="https://help.ubuntu.com/community/PostfixBasicSetupHowto#Local_Alias_database">Ubuntu Postfix Alias Configuration</a></li>
</ol>

# Install RethinkDB on CentOS 7

## Installing RethinkDB

```
sudo wget http://download.rethinkdb.com/centos/7/`uname -m`/rethinkdb.repo -O /etc/yum.repos.d/rethinkdb.repo
sudo yum install rethinkdb
```

## Create Service File
Create the service file, `/usr/lib/systemd/system/rethinkdb@.service` with the following content:
```
[Unit]
Description=RethinkDB database server for instance '%i'

[Service]
User=rethinkdb
Group=rethinkdb
ExecStart=/usr/bin/rethinkdb serve --config-file /etc/rethinkdb/instances.d/%i.conf
KillMode=process
PrivateTmp=true

[Install]
WantedBy=multi-user.target
```
Make sure that it has a permission of `644`: `chmod 644 /usr/lib/systemd/system/rethinkdb@.service`

## Creating a Rethink DB Instance
1. Create the RethinkDB data directory: `rethinkdb create -d /path/to/your/rethinkdb/directory`
2. Set the ownership to RethinkDB user: `sudo chown -R rethinkdb.rethinkdb /path/to/your/rethinkdb/directory`
3. Copy RethinkDB sample config file: `sudo cp /etc/rethinkdb/default.conf.sample /etc/rethinkdb/instances.d/instance1.conf`
4. Edit `/etc/rethinkdb/instances.d/instance1.conf`, the line with `directory=` must be changed to point to your Rethink DB data directory.

## Start RethinkDB Instance
<name_instance> in this case would be `instance1`:
```
sudo systemctl enable rethinkdb@<name_instance>
sudo systemctl start rethinkdb@<name_instance>
```

## References
[RethinkDB Startup Doc](https://rethinkdb.com/docs/start-on-startup/)

# Turtl API Server and Client Installation CentOS 7

## Turtl API
### Clone and Configure Turtl API
1. Create a user for turtl API: `sudo useradd turtl`
2. Switch user to `turtl`: `sudo su turtl`
3. Change directory to `turtl`'s home: `cd ~`
1. Install [Clozure CL](https://wiki.twcloud.tech/books/linux/page/installing-clozure-cl-and-quicklisp-on-centos-7)
2. Install [RethinkDB](https://wiki.twcloud.tech/books/linux/page/install-rethinkdb-on-centos-7) and create an instance for Turtl API
3. Install `libuv`: `sudo yum install libuv`
4. Clone Turtl repo: `git clone https://github.com/turtl/api.git`
5. Copy Turtl API config: `cp config/config.default.lisp config/lisp`
6. Edit and configure `config/config.lisp`, make sure to update the following parameters:
  ```
(defvar *local-upload* "<local upload directory>"
(defvar *local-upload-url* "<upload url>"
  ```

### Setup Up Service
Create a service file at `/usr/lib/systemd/system/turtl.service` with the following entry:

```
[Unit]
Description=Turtl API Server

[Service]
User=turtl
Group=turtl
ExecStart=/usr/local/bin/ccl64 --load /home/turtl/api/start.lisp
KillMode=process

[Install]
WantedBy=multi-user.target
```

Start and enable the service:

```
sudo systemctl start turtl
sudo systemctl enable turtl
```

### (OPTIONAL) Configure Reverse Proxy in Apache
Create `httpd` virtual host configuration `/etc/httpd/conf.d/turtl.conf` with the following content, make sure to change `<turtl domain>` to your own domain name:

```
<VirtualHost *:80>
    #Server name configuration
    ServerName <turtl domain>
    ServerAdmin webmaster@<turtl domain>

    #Proxy configuration
    ProxyPreserveHost on
    ProxyRequests off
    ProxyPass / https://wiki.twcloud.tech:8181/
    ProxyPassReverse / https://wiki.twcloud.tech:8181/

    #Logging configuration
    ErrorLog /var/log/httpd/turtl.err
    LogLevel warn
</VirtualHost>
```

### (OPTIONAL) Restrict User Registration
Add the following lines in your Turtl API Virtual Hosts configuration:

```
    #Restrict Registration
    <LocationMatch  "^/users[/]?$">
        AuthType Basic
        AuthName "Restricted"
        AuthUserFile /home/turtl/.htpasswd
        Require valid-user 
    </LocationMatch>
```

Then generate a `.htpasswd` password file in `/home/turtl`: `sudo htpasswd -c /etc/apache2/.htpasswd <whatever username>`. Make sure that it's in the right permission and owner: `chmod 640 /home/turtl/.htpasswd && chown turtl:apache /home/turtl/.htpasswd`

## Installing JS Client
1. Clone `turtl/js` repo to webserver webroot: `sudo mkdir /var/www/turtl && cd /var/www/turtl && sudo git clone https://github.com/turtl/js.git .`
2. Install NodeJS dependencies: `npm install`
3. Copy default config: `cp config/config.js.default config.js`
4. Edit `config/config.js`
5. Update owner and group: `chown -R apache:apache .`
6. Generate assets: `make`

# Software Development

All about software development tricks on Linux

# Creating War File in Linux

1. CD to war directory in the project folder
2. Execute `jar -cvf .war *`

# Standard Procedures for CakePHP Application Deployment

<h3 id="bkmrk-1.-clone-source-file">1. Clone Source File</h3>
<ol class="linenums" id="bkmrk-git-clone-%3Cgit-url%3E">
<li class="L0"><code><span class="pln">git clone </span><span class="pun">&lt;</span><span class="pln">git url</span><span class="pun">&gt;</span></code></li>
</ol>
<h3 id="bkmrk-2.-setup-database">2. Setup Database</h3>
<ol class="linenums" id="bkmrk-mysql--uroot--p-crea">
<li class="L0"><code><span class="pln">mysql </span><span class="pun">-</span><span class="pln">uroot </span><span class="pun">-</span><span class="pln">p</span></code></li>
<li class="L1"><code><span class="pln">create database </span><span class="pun">&lt;</span><span class="pln">database name</span><span class="pun">&gt;;</span></code></li>
<li class="L2"><code><span class="pln">grant all on </span><span class="pun">&lt;</span><span class="pln">database name</span><span class="pun">&gt;.*</span><span class="pln"> to </span><span class="str">'&lt;id&gt;'</span><span class="pun">.</span><span class="str">'localhost'</span><span class="pln"> identified </span><span class="kwd">by</span> <span class="str">'&lt;password&gt;'</span><span class="pun">;</span></code></li>
<li class="L3"><code><span class="pln">cd </span><span class="pun">&lt;</span><span class="pln">path</span><span class="pun">/</span><span class="pln">to</span><span class="pun">/</span><span class="pln">cakephp</span><span class="pun">&gt;/</span><span class="pln">app</span></code></li>
<li class="L4"><code><span class="typ">Console</span><span class="pun">/</span><span class="pln">cake schema create</span></code></li>
<li class="L5"><code><span class="typ">Console</span><span class="pun">/</span><span class="pln">cake schema update </span><span class="pun">-</span><span class="pln">s </span><span class="pun">&lt;</span><span class="pln">update number found </span><span class="kwd">in</span><span class="pln"> app</span><span class="pun">/</span><span class="typ">Config</span><span class="pun">/</span><span class="typ">Schema</span><span class="pun">/&gt;</span></code></li>
</ol>
<h3 id="bkmrk-3.-setup-php">3. Setup PHP</h3>
<p id="bkmrk-edit-%2Fetc%2Fphp.ini-an">Edit <code>/etc/php.ini</code> and add the following line:</p>
<ol class="linenums" id="bkmrk-date.timezone-%3D-%22asi">
<li class="L0"><code><span class="pln">date</span><span class="pun">.</span><span class="pln">timezone </span><span class="pun">=</span> <span class="str">"Asia/Kuala_Lumpur"</span></code></li>
</ol>
<h3 id="bkmrk-4.-allow-write-acces">4. Allow Write Access to tmp</h3>
<ol class="linenums" id="bkmrk-chmod--r-777-app%2Ftmp">
<li class="L0"><code><span class="pln">chmod </span><span class="pun">-</span><span class="pln">R </span><span class="lit">777</span><span class="pln"> app</span><span class="pun">/</span><span class="pln">tmp</span><span class="pun">/</span></code></li>
</ol>
<h3 id="bkmrk-5.-setup-apache">5. Setup Apache</h3>
<p id="bkmrk-edit-%2Fetc%2Fhttpd%2Fconf">Edit <code>/etc/httpd/conf/conf.d</code> and change <code>AllowOverride None</code> to <code>AllowOverride All</code> in <code>&lt;Directory "/var/www/html"&gt;</code> tag. Then, restart httpd:</p>
<ol class="linenums" id="bkmrk-sudo-systemctl-resta">
<li class="L0"><code><span class="pln">sudo systemctl restart httpd</span></code></li>
</ol>
<h3 id="bkmrk-%28optional%29-selinux">(OPTIONAL) SELinux</h3>
<ol class="linenums" id="bkmrk-sudo-setsebool--p-al">
<li class="L0"><code><span class="pln">sudo setsebool </span><span class="pun">-</span><span class="pln">P allow_httpd_anon_write on</span></code></li>
<li class="L1"><code><span class="pln">sudo setsebool </span><span class="pun">-</span><span class="pln">P allow_httpd_sys_script_anon_write on</span></code></li>
<li class="L2"><code><span class="pln">sudo setsebool </span><span class="pun">-</span><span class="pln">P httpd_unified </span><span class="lit">0</span></code></li>
<li class="L3"><code><span class="pln">sudo chcon </span><span class="pun">-</span><span class="pln">R </span><span class="pun">-</span><span class="pln">t </span><span class="typ">httpd_sys_rw_content_t</span> <span class="str">&lt;path_to_cakephp_app&gt;</span><span class="pun">/</span><span class="pln">app</span><span class="pun">/</span><span class="pln">tmp</span><span class="pun">/</span></code></li>
</ol>

# Installing Clozure CL and QuickLisp on CentOS 7

## Download Clozure CL
Open up terminal and enter the command: `svn co http://svn.clozure.com/publicsvn/openmcl/release/1.11/linuxx86/ccl` Where `linuxx86` is one of:
- `darwinx86`
- `linuxx86`
- `freebsdx86`
- `solarisx86`
- `windows`
- `linuxarm`

## Download and Install QuickLisp
1. Download QuickLisp from [https://beta.quicklisp.org/quicklisp.lisp](https://beta.quicklisp.org/quicklisp.lisp)
2. Enter the command: `./ccl/lx86cl64 --load /path/to/quicklisp.lisp`
3. In the CCL prompt enter: `(quicklisp-quickstart:install)(ql:add-to-init-file)`

## Creating Scripts to Run CCL
1. Edit `./ccl/scripts/ccl` and `./ccl/scripts/ccl64` to change `CCL_DEFAULT_DIRECTORY=/usr/local/src/ccl` line to `CCL_DEFAULT_DIRECTORY=~/ccl`
2. Copy the scripts to `/usr/local/bin` directory: `sudo cp ./ccl/scripts/ccl* /usr/local/bin/`

## References
- [Linux Format Article](http://www.pressreader.com/australia/linux-format/20160804/281599534867185)
- [Clozure CL Official Download Page](http://ccl.clozure.com/download.html)

# Sound

Linux sound problems, configuration and installation

# No Sound over Wine

Install `lib32-alsa-plugins lib32-libpulse lib32-openal`

# E: [pulseaudio] module.c: Failed to load module "module-equalizer-sink" (argument: ""): initialization failed.

## Symtoms

Starting pulseaudio will forever `Establishing connection`,
`pulseaudio -v` will reveal the following errors:

```
W: [pulseaudio] module-equalizer-sink.c: module-equalizer-sink is currently unsupported, and can sometimes cause PulseAudio crashes, increased latency or audible artifacts.
W: [pulseaudio] module-equalizer-sink.c: If you're facing audio problems, try unloading this module as a potential workaround.
E: [pulseaudio] module-equalizer-sink.c: Master sink not found
E: [pulseaudio] module.c: Failed to load module "module-equalizer-sink" (argument: ""): initialization failed.
E: [pulseaudio] main.c: Module load failed.
E: [pulseaudio] main.c: Failed to initialize daemon.
I: [pulseaudio] main.c: Daemon terminated.
```

## Solution
**Start pulseaudio using Desktop Manager's autostart script, the following instruction is for LXDE:**

1. Create a desktop file on `~/.config/autostart/pulseaudio-equalizer.desktop`
2. Add the following lines:

```
[Desktop Entry]
Type=Application
Exec=bash -c 'pactl load-module module-equalizer-sink; pactl load-module module-dbus-protocol;'
```

## References
- [PulseAudio Wiki](https://wiki.archlinux.org/index.php/PulseAudio)
- [Archwiki's PulseAudio Troubleshooting](https://wiki.archlinux.org/index.php/PulseAudio/Troubleshooting)

# Storage

Storage administration and tricks, including LVM, SCSi etc.

# LVM Extending from New Physical Volume

<h3 id="bkmrk-create-new-physical-">Create new physical volume from new partition</h3>
<ol id="bkmrk-use-fdisk-utility-to">
<li>Use <code>fdisk</code> utility to create new partition</li>
<li><code>pvcreate /dev/&lt;new partition&gt;</code></li>
<li><code>pvs</code></li>
</ol>
<h3 id="bkmrk-adding-physical-volu">Adding physical volume to volume group</h3>
<ol class="linenums" id="bkmrk-vgextend-%3Cvolume-gro">
<li class="L0"><code><span class="pln">vgextend </span><span class="pun">&lt;</span><span class="pln">volume </span><span class="kwd">group</span><span class="pun">&gt;</span> <span class="str">/dev/</span><span class="pun">&lt;</span><span class="kwd">new</span><span class="pln"> partition</span><span class="pun">&gt;</span></code></li>
</ol>
<h3 id="bkmrk-extending-logical-vo">Extending logical volume</h3>
<ol class="linenums" id="bkmrk-lvextend--l%2B%3Csize%3E%3Cg">
<li class="L0"><code><span class="pln">lvextend </span><span class="pun">-</span><span class="pln">L</span><span class="pun">+&lt;</span><span class="pln">size</span><span class="pun">&gt;&lt;</span><span class="pln">G </span><span class="kwd">or</span><span class="pln"> M</span><span class="pun">&gt;</span> <span class="str">/dev/</span><span class="pun">&lt;</span><span class="pln">volume </span><span class="kwd">group</span><span class="pun">&gt;/&lt;</span><span class="pln">lv name</span><span class="pun">&gt;</span></code></li>
<li class="L1"><code><span class="com">#For XFS:</span></code></li>
<li class="L2"><code><span class="pln">xfs_grow </span><span class="pun">/&lt;</span><span class="pln">mount_point</span><span class="pun">&gt;</span></code></li>
<li class="L3"><code><span class="com">#For EXT4:</span></code></li>
<li class="L4"><code><span class="pln">resize2fs </span><span class="pun">/&lt;</span><span class="pln">mount</span><span class="pun">&gt;/&lt;</span><span class="pln">point</span><span class="pun">&gt;</span></code></li>
</ol>

# System

Linux system tools, administration and tips

# ArchLinux Upgrade Issues

## Error: key "ABCDE1282828181" could not be looked up remotely

Upgrade archlinux-keyring: `pacman -S archlinux-keyring`

## Unable to get past login window after upgrading

This is caused by Nvidia driver being upgraded

nvidia-dkms: `pacman -S nvidia-libgl`

## Failed to start load kernel modules after upgrade:

Possible causes:

- `broadcom-wl` module
- Solved by re-"makepkg" `broadcom-wl` from **AUR**
- Find error message in `systemctl status systemd-modules-load.service`

# CentOS Installation Issues

## HP Microserver Gen 7

### Kernel Panic on Boot (Both Live USB and New Installation)

Add the following lines to the kernel boot parameters: `<span class="pln">nolapic clocksource</span><span class="pun">=</span><span class="pln">hpet</span>`

## <span class="pln">Blank Screen on Startup</span>

Append `nomodeset` to [kernel param](https://wiki.archlinux.org/index.php/kernel_parameters#GRUB "kernel param")

# Changing Default S2RAM to USWSUSP Suspend Module

If you have any issues to suspend your laptop e.g. `suspend` command doesn't work on your laptop, try changing the default sleep module to `uswsusp`:

1. Edit `/etc/pm/config.d/module` and add the following line: `SLEEP_MODULE=uswsusp`
2. Edit `/etc/pm/config.d/defaults` and add the following line: `S2RAM_OPTS="-f"`
3. Reboot and try to let her sleep.

### References

- [OpenSuse Documentation on Suspending](http://en.opensuse.org/SDB:Suspend_to_RAM)
- [AskUbuntu Thread](http://askubuntu.com/questions/54591/use-s2ram-when-closing-lid-with-kde)

# Fixing Incorrect Lid State by Hacking DSDT

When I install a Linux distro to my VAIO notebook, I found that there is an annoying bug with the lid switch. It does not get updated whenever I suspend on lid close, it means `cat /proc/acpi/button/lid/LID/state` will output `state: close`. When I close the lid again, it won't suspend, instead, it will change the state to open. So in order for it to suspend again on lid close after the first suspend, I have to close it, reopen the lid and close it again.

I have tried installing Linux Mint, Fedora, Fuduntu and Xubuntu, but it is not fixed in any of the distros. So, I don't think it is distro problems. While researching this issues (which I spent two full days), I found that Linux got an amazing feature that enable users to dynamically loading DSDT at boot time, there is no need to update the BIOS. So here's the instuctions:

1. Install `iasl` using `yum`, `apt-get` or whatever package management you are using.

2. Extract DSDT:
  ```
  $ sudo cat/sys/firmware/acpi/tables/DSDT > dsdt.aml
  ```

3. Disassemble `dsdt.aml` using the following command, this should create a new file `dsdt.dsl`:
  ```
  $ iasl -d dsdt.aml
  ```

4. Compile it using:
  ```
  $ iasl -tc dsdt.dsl
  ```

5. Fix any compiler errors, warnings and remarks. On my machine, the output is:
  ```
  dsdt.dsl  1352:                         And (CTRL, 0x1E)
  Warning  1106 -                                 ^ Result is not used, operator has no effect

  dsdt.dsl  1584:                     0x00000000,         // Length
  Error    4122 -                              ^ Invalid combination of Length and Min/Max fixed flags

  dsdt.dsl  2443:                                 Name (_T_0, 0x00)
  Remark   5111 -            Use of compiler reserved name ^  (_T_0)

  dsdt.dsl  2521:                                 Name (_T_0, 0x00)
  Remark   5111 -            Use of compiler reserved name ^  (_T_0)

  ```
  a. The first one is on line 1352 can be fixed simply by changing `And (CTRL, 0x1E)` to `And (CTRL, 0x1E, CTRL)`.  
  b. The second one is on line 1584, the length should be `Range Maximum` - `Range Minimum` + 1, on my machine, so fire up a hex calculator and start subtracting. On my machine, it's `0xE0000000` (`0xDFFFFFFF` - `0x00000000` + `0x00000001`).  
  c. The third and fourth line is on line 2443 and 2521, because it uses a reserved name, simply replacing all instances of `_T_0` to `T_0` will stop the complaints. In vim, it is as simple as issuing `:%s/_T_0/T_0/g` in command mode.

6. Once everything is fixed (no errors, warning or remarks), add the following line to `_WAK` method, simply search for `_WAK` in `dsdt.dsl`:
  ```
  If (LNotEqual (0x00, LIDS))
  {
  Store (0x00, LIDS)
  Notify (\_SB.LID, 0x80)
  }
  ```
  **NOTE 1:** You might need to change `\_SB.LID` to match your path to `LID` method or on some machine `LID0`. Method name is preceded by an `_` (underscore), so you can search for `_LID` in `dsdt.dsl`. After you found it, you have to determine the scope, scroll up until you found `Scope` keyword that your `LID` or `LID0` method belongs to, inside the bracket is the scope name. It may be in more than one scope, so, it might be `\_PCI0.SB.LID`. If you specify an incorrect path to `LID` method, you will receive the following error:
```
dsdt.dsl 300: Notify (LID, 0x80)
Error 4068 - ^ Object is not accessible from this scope (LID_)
```
  **NOTE 2:** What this function does is just to update the lid state once it is resumed from sleep. According to the ACPICA documentation, `_WAK` method is called by `AcpiLeaveSleepState()` function of ACPI. If the lid is open, the `LIDS` variable is `0x00`, or `0x01` otherwise. So these few lines translate to "if lid state is not open (closed), change lid state to open and call `LID`method".
7. Compile it using `iasl -tc dsdt.dsl`.
8. If no errors, warnings or remarks, add the following lines to `/etc/grub.d/01_acpi`:
  ```
  # Uncomment to load custom ACPI table
  GRUB_CUSTOM_ACPI="/boot/dsdt.aml"

  # DON'T MODIFY ANYTHING BELOW THIS LINE!

  prefix=/usr
  exec_prefix=${prefix}
  libdir=${exec_prefix}/lib

  . /usr/share/grub/grub-mkconfig_lib
  #. ${libdir}/grub/grub-mkconfig_lib

  # Load custom ACPI table
  if [ x${GRUB_CUSTOM_ACPI} != x ] && [ -f ${GRUB_CUSTOM_ACPI} ] \
      && is_path_readable_by_grub ${GRUB_CUSTOM_ACPI}; then
      echo "Found custom ACPI table: ${GRUB_CUSTOM_ACPI}" >&2
      prepare_grub_to_access_device `${grub_probe} --target=device 
  ${GRUB_CUSTOM_ACPI}` | sed -e "s/^/  /"
      cat << EOF
  acpi (\$root)`make_system_path_relative_to_its_root 
  ${GRUB_CUSTOM_ACPI}`
  EOF
  fi
  ```

9. Add executable bit to it:
  ```
  $ sudo chmod +x /etc/grub.d/01_acpi
  ```

10. Copy the new `dsdt.aml` to `/boot`:
  ```
  $ sudo cp dsdt.aml /boot
  ```

11. Regenerate `grub.cfg`:
  ```
  $ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
  ```
12. Reboot

### References 
- [Archwiki on DSDT](https://wiki.archlinux.org/index.php/DSDT)
- [Redhat's Bug Report](https://bugzilla.redhat.com/show_bug.cgi?id=676031)
- [Ubuntu's Bug Report 1](https://bugs.launchpad.net/ubuntu/+source/linux/+bug/34389)
- [Ubuntu's Bug Report 2](https://bugs.launchpad.net/ubuntu/+source/linux/+bug/44825)
- [Somebody's blog on fixing DSDT errors, remarks and warnings](http://sadevil.org/blog/2012/01/01/fixing-the-acpi-dsdt-of-an-acer-ferrari-one-200/)
- [ACPICA Documentation](https://www.acpica.org/documentation)

# JournalD Administration

## Optimizing JournalD Disk Space Usage

Edit `/etc/systemd/journald.conf` and change the following line:

```
SystemMaxUse=200M 
```

To check disk space used by journald: `journalctl --disk-usage`

# Linux on Macbook Administration

## Blessing the Linux Kernel

1. [Boot into Mac Recovery](https://support.apple.com/en-us/HT201314 "Boot into Mac Recovery")
2. Start terminal and enter:
3. ```
    bless --folder /Volumes/ARCH_EFI/EFI/arch/grub/ --file /Volumes/ARCH_EFI/EFI/arch/grub/grubx64.efi
    ```

## Changing Apple keyboards (Macbook or USB) fnmode in Linux

### Changing it temporarily, as root:

```
echo 2 > /sys/module/hid_apple/parameters/fnmode 
```

### Changing it Permanently:

Edit `/etc/modprobe.d/hid_apple.conf` and add the following line:

```
options hid_apple fnmode=2 
```

# SELinux - Services Blocked by SELinux

## SELinux Blocked Apache Access to Files

```
setsebool -P httpd_unified 1<br></br>sudo /sbin/restorecon -R /var/www/html
```

## VSFTPD OOPS Error

Issue the following command: `setsebool -P ftp_home_dir 1`

## SSH bind port error permission denied

Issue the following command: `semanage port –a –t ssh_port_t –p tcp 1234`

## Permission denied HTTP Error 403

Issue the following command: `chcon -R --reference=/var/www /path/to/webroot`

## SELinux Denied HTTPD Access to MYSQLD on 127.0.0.1

1. `grep mysqld /var/log/audit/audit.log | audit2allow -M mysqld`
2. `semodule -i mysqld.pp`

## SELinux Denied FTP Access to SMB Share

1. Try to login with [ncftp](http://www.ncftp.com/ "ncftp") first and you will see the error "`OOPS: cannot change directory: /path/to/samba_share`"
2. Execute command: `su -c "grep ftpd_t /var/log/audit/audit.log | allow2audit -M ftpd_smb && semodule -i ftpd_smb"`
3. Try to login again with [ncftp](http://www.ncftp.com/ "ncftp") and ls command will return empty list a although it isn't
4. Execute command: `su -c "grep ftpd_t /var/log/audit/audit.log | allow2audit -M ftpd_smb && semodule -i ftpd_smb"`
5. Execute command =&gt; `sudo setsebool -P allow_ftpd_full_access on`
6. Execute command =&gt; `sudo setsebool -P ftp_home_dir on`

## Owncloud Custom Data Directory Denied

Assume owncloud data directory: `/var/data`

```
Install policycoreutils-python<br></br>/etc/init.d/restorecond start<br></br>chkconfig restorecond on<br></br>semanage fcontext -a -t httpd_sys_content_t '/var/data(/.*)?' <br></br>restorecon -Rv /var/data
```

# Standard CentOS Workstation Setup

### Install GUI (MATE Desktop)

1. `<span class="pln">sudo yum install epel</span><span class="pun">-</span><span class="pln">release</span>`
2. `<span class="pln">sudo yum groupinstall </span><span class="str">'X Window System'</span>`
3. `<span class="pln">sudo yum groupinstall </span><span class="str">'MATE Desktop'</span>`
4. `<span class="pln">sudo systemctl isolate graphical</span><span class="pun">.</span><span class="pln">target</span>`
5. `<span class="pln">sudo systemctl </span><span class="kwd">set</span><span class="pun">-</span><span class="kwd">default</span><span class="pln"> graphical</span><span class="pun">.</span><span class="pln">target</span>`

### Install Printer

1. `<span class="pln">sudo yum install cups</span>`
2. `<span class="pln">sudo yum groupinstall </span><span class="str">"Development Tools"</span>`
3. `<span class="pln">sudo systemctl enable cups</span>`
4. `<span class="pln">sudo systemctl start cups</span>`
5. `<span class="pln">sudo yum install foomatic</span>`

Install drivers for the printer available at [Open Printing](http://www.openprinting.org/printers)

### Optional - GUI WiFi Support

1. `<span class="pln">sudo yum install </span><span class="typ">NetworkManager</span><span class="pun">-</span><span class="pln">wifi</span>`

# Ansible

Contains everything on Ansible IT automation tool, playbooks and tricks

# Preparing Windows Host for Ansible

Ansible is an IT automation tool that greatly reduce IT operation overheads, and it is compatible with Windows machine through [Windows Remote Management](https://docs.microsoft.com/en-us/windows/desktop/winrm/portal). However there are some preparations in order to use Ansible with Windows Host. The steps are as foll

# Playbook - Clearing Users' Data Files in a Group of Windows Machines

The playbook below will remove all users' data in a computer that belongs in an inventory group. Below is a list of steps that this playbook will do:

1. Disable and remove the target user
2. Reboot to remove any file locks from the logged in user
3. Remove any files in the user's directory, skipping symbolic links
4. Re-create a public user with the same username and empty password that cannot be changed
5. Enable auto login for the user so that new machine will be configured for auto login as well
6. Reboot computer to enable the configuration

The playbook is as follows, please change the variables encapsulated in `< >` with the desired values:

```
---
- hosts: <inventory group / host>
  tasks:
  - name: remove user account
    win_user:
      name: <username>
      account_disabled: yes
      state: absent
  - name: reboot
    win_reboot:
      msg: "Scheduled reset started, windows will reboot in 90 seconds"
      pre_boot_delay: 90
  - name: remove any files in the folder tree
    ignore_errors: yes
    win_shell: |
      $Path = "C:\Users\<username>"
      Remove-Item "$Path" -Force -Recurse -ErrorAction SilentlyContinue
      if (Test-Path "$Path" -ErrorAction SilentlyContinue)
      {
          $folders = Get-ChildItem -Path $Path -Directory -Force -ErrorAction SilentlyContinue
          ForEach ($folder in $folders)
          {
              Remove-Tree $folder.FullName -Force -ErrorAction SilentlyContinue
          }

          $files = Get-ChildItem -Path $Path -File -Force
          ForEach ($file in $files)
          {
              Remove-Item $file.FullName -Force -ErrorAction SilentlyContinue
          }

          if (Test-Path "$Path" -ErrorAction SilentlyContinue)
          {
              Remove-Item $Path -Force -ErrorAction SilentlyContinue
          }
      }
  - name: re-add user account
    win_user:
      name: <username>
      state: present
      groups: Users
      user_cannot_change_password: yes
      password_expired: no
      password_never_expire: yes
  - name: enable auto logon
    win_shell: |
      Set-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name 'AutoAdminLogon' -Value '1'
      Set-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name 'DefaultUsername' -Value '<default username>'
      Set-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name 'DefaultPassword' -Value ''
  - name: reboot to apply new settings
    win_reboot:
      msg: "Scheduled reset completed, windows will reboot in 5 seconds"
      pre_boot_delay: 5
```

References:
- https://luke.geek.nz/win/using-powershell-setup-automatic-logon-windows-servers/
- https://stackoverflow.com/a/31450526
- https://docs.ansible.com/ansible/2.5/modules/list_of_windows_modules.html

# Playbook - Update Windows Machine (Windows Update Disabled)

This playbook will:

1. Modify windows update service to manual in case the machine is set to disabled
2. Start the windows update service
3. Download and install the updates, reboot if required

The playbook is as follows, please change the encapsulated `< >` values to the desired values:

```
---
- hosts: <inventory group / hosts>
  tasks:
  - name: change windows update service to manual
    win_shell: Set-Service wuauserv -StartupType Manual
  - name: start windows update service
    win_shell: Start-Service wuauserv
  - name: download and install updates
    win_updates:
      reboot: yes
```

# Playbook - Initiate Clamscan on Machines with ClamWin Installed

This playbook will initiate a full scan on all computers using `Clamscan` that is installed through `ClamWin`:

```
---
- hosts: <inventory group / hosts>
  tasks:
  - name: full computer scan
    win_command: '"C:\Program Files (x86)\ClamWin\bin\clamscan.exe" -rv --move=C:\ProgramData\.clamwin\quarantine\ --database=C:\ProgramData\.clamwin\db\ --log=C:\ProgramData\.clamwin\log\ClamScanLog.txt --enable-stats C:\'
```

# Playbook - Disable Windows Updates

This playbook will download [disable_windows_update.ps1](https://wiki.twcloud.tech/books/windows/page/scripts---disable-windows-updates) from a server, reachable by all clients and execute the script to disable windows updates on a group of windows machines. Though it is written to specifically disable windows update, it can be modified to execute other scripts as well. The playbook configuration file is ass follows, replace enclosed `< >` tags with the desired values:

```
---
- hosts: <inventory group / hosts>
  tasks:
  - name: download script to disable windows update
    win_get_url:
      url: http://<url>/disable_windows_update.ps1
      dest: C:\
  - name: execute disable windows update script
    win_shell: C:\disable_windows_update.ps1
  - name: remove script
    win_file:
      path: C:\disable_windows_update.ps1
      state: absent
```