Category Archives: Linux

Regex – Grep reference

 

Regex operator

Meaning

.

Matches any single character.

?

The preceding item is optional and will be matched, at most, once.

*

The preceding item will be matched zero or more times.

+

The preceding item will be matched one or more times.

{N}

The preceding item is matched exactly N times.

{N,}

The preceding item is matched N or more times.

{N,M}

The preceding item is matched at least N times, but not more than M times.

Represents the range if it’s not first or last in a list or the ending point of a range in a list.

^

Matches the empty string at the beginning of a line; also represents the characters not in the range of a list.

$

Matches the empty string at the end of a line.

\b

Matches the empty string at the edge of a word.

\B

Matches the empty string provided it’s not at the edge of a word.

\<

Match the empty string at the beginning of word.

\>

Match the empty string at the end of word.

(a|b)

Match a or b

[abc]

Range (a or b or c)

[^abc]

NOT a or b or c

[a-z]

Any letter (lowercase) from a to z

[A-Z]

Any letter (uppercase) from a to z

[a-zA-Z]

Any letter (upper and lowercase) from a to z

[0-9]

Any digit from 0 to 9

A most exhaustive cheat sheet is available here

Netcat – such a powerful ‘cat’!

I was just looking around info about netcat and telnet, trying to understand a bit more. Well… in few words: no point to install telnet if you have netcat! 🙂 Netcat is perfect for scripting, ’cause it’s non-interactive, UDP/TCP capable, can be a listener as well… very powerful tool. Here some example.

How to check if your httpd is up and running:

~ $ nc -zv localhost 80
Connection to localhost 80 port [tcp/http] succeeded!

…and it closes gracefully 😉

How to check port-range ports:

~ $ nc -zv localhost 20-25
nc: connect to localhost port 20 (tcp) failed: Connection refused
Connection to localhost 21 port [tcp/ftp] succeeded!
Connection to localhost 22 port [tcp/ssh] succeeded!
nc: connect to localhost port 23 (tcp) failed: Connection refused
nc: connect to localhost port 24 (tcp) failed: Connection refused
nc: connect to localhost port 25 (tcp) failed: Connection refused

… or a list of ports:

$ nc -zv localhost 20 22 80 443
nc: connect to localhost port 20 (tcp) failed: Connection refused
Connection to localhost 22 port [tcp/ssh] succeeded!
Connection to localhost 80 port [tcp/http] succeeded!
Connection to localhost 443 port [tcp/https] succeeded!

NOTE: If you want to grep or play with the “output” of the command, you need to use 2>&1
For example:

nc -zv localhost 1-1024 <strong>2>&1</strong> | grep succeeded

How to check the service that’s running on that port:

(From man) Alternatively, it might be useful to know which server software is running, and which versions. This information is often contained within the greeting banners. In order to retrieve these, it is necessary to first make a connection, and then break the connection when the banner has been retrieved. This can be accomplished by specifying a small timeout with the -w flag, or perhaps by issuing a “QUIT” command to the server:

$ echo "QUIT" | nc host.example.com 20-30
SSH-1.99-OpenSSH_3.6.1p2
Protocol mismatch.
220 host.example.com IMS SMTP Receiver Version 0.84 Ready

In some cases, it’s handy to add -q 1 at the end, if nc hangs (I’ve noticed this in some cases) Like this:

$ echo "QUIT" | nc host.example.com 20-30 <strong>-q 1</strong>

Or how to send/receive a file:

On the receiver side:

$ nc -l 1234 > /tmp/file_to_receive

On the sender side:

$ cat file_to_send | nc receiver_ip_or_fqdn 1234

or

$ nc receiver_ip_or_fqdn 1234 < file_to_send

There are plenty of things that you can do. These are just simple examples… enjoy! 🙂

Lighttpd and virtualhosts

Here a quick how to, about how to configure Lighttpd to run with Virtualhosts.
This has been installed and tested on a Raspberry Pi.

apt-get install lighttpd php5 php5-cgi

Enable modules:

lighttpd-enable-mod auth cgi fastcgi fastcgi-php nagios3 simple-vhost ssl status

Content of /etc/lighttpd/lighttpd.conf

server.modules = (
        "mod_access",
        "mod_alias",
        "mod_compress",
        "mod_redirect",
#       "mod_rewrite",
)

server.document-root        = "/var/www"
server.upload-dirs          = ( "/var/cache/lighttpd/uploads" )
server.errorlog             = "/var/log/lighttpd/error.log"
server.pid-file             = "/var/run/lighttpd.pid"
server.username             = "www-data"
server.groupname            = "www-data"
server.port                 = 80


index-file.names            = ( "index.php", "index.html", "index.lighttpd.html" )
url.access-deny             = ( "~", ".inc" )
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

compress.cache-dir          = "/var/cache/lighttpd/compress/"
compress.filetype           = ( "application/javascript", "text/css", "text/html", "text/plain" )

# default listening port for IPv6 falls back to the IPv4 port
include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
include_shell "/usr/share/lighttpd/create-mime.assign.pl"
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"

To easily manage virtual hosts, edit /etc/lighttpd/conf-available/10-simple-vhost.conf

server.modules += ( "mod_simple_vhost" )
simple-vhost.server-root = "/var/www/vhost"
simple-vhost.default-host = "error.default.loc"
simple-vhost.document-root = "/"

This configuration above will allow you to manage your virutalhosts simply storing them in a folder under /var/www/vhost
No extra configuration is needed from the server side.
Simply go into /var/www/vhost and create a folder named as the virtualhost you would like to manage.
In this particular case, please make sure to have a folder called error.default.loc with a page inside which will be displayed in case of ANY error.
For example, if you want to manage mysite.example.com, simply do the following:

cd /var/www/vhost
mkdir mysite.example.com
chown www-data:www-data mysite.example.com

…and put the html/php files inside that new folder! 🙂

To test if our webserver works, you can always use curl command as explained here.

Puppet – Let’s start

Puppet is a quite powerful configuration manager tool which allows you to configure automatically hosts and keep configurations consistence.

I did some tests using 3 VMs:

  • puppetmaster (server)
  • puppetagent01 (client)
  • puppetagent02 (client)

Of course, most of the work is done on puppetmaster server. On the last two machines you will simply see the outcome of the configurations that you’re going do set on puppetmaster.

Important: all the machines have to be able to communicate between each others. Please make sure DNS is working or set local names/IPs in /etc/hosts file, and do some ping tests before proceeding.

Client setup

On each puppetagent machine, just install the package puppet

apt-get install puppet

By default, the client will look for a host called “puppet” on the network.
If your DNS/hosts file doesn’t have this entry, and it can’t be resolved, you can manually set the name of the puppetmaster in /etc/puppet/puppet.conf file, adding this line under [main] section:

server=puppetmaster.yournet.loc

Now, no more configuration is required from the client side. Just edit /etc/default/puppet to start at boot time and start the service.

# Defaults for puppet - sourced by /etc/init.d/puppet

# Start puppet on boot?
START=yes

# Startup options
DAEMON_OPTS=""

 

service puppet start

Starting the service, will make automatically a request to the server to be added under his control.

If you want to do some tests, you can eventually use the following command to run puppet only once. This will also force the polling updates, which by default runs every 30 minutes.

puppet agent --no-daemonize --onetime --verbose

You can repeat all these steps on the second client machine.

Server setup

apt-get install puppetmaster

Check if the service is running, otherwise, start it up.

Sign clients’ certificates on the server side

Puppet uses this client/server certificate sign system to add/remove hosts from being managed by the server.

To see who has requested to be “controlled” use this command:

puppet cert --list

This will show all the hosts waiting to be added under puppetmaster server.

puppet cert --sign

This command will add the host.

Puppetmaster configuration files

The main configuration file is /etc/puppet/manifests/site.pp

Inside manifests folder, I’ve created a subfolder called classes with extra definitions (content of these files is showed later in this post).

/etc/puppet/manifests# tree
.
|___ classes
|   |___ apache.pp
|   |___ mysite.pp
|   |___ ntpd.pp
|   |___ packages.pp
|___ site.pp

/etc/puppet/manifests/site.pp

import 'classes/*.pp'
# This add all the custom .pp files into classes folder
class puppettools {
# Creates a file, setting permissions and content
        file { '/usr/local/sbin/puppet_once.sh':
                owner => root, group => root, mode => 755,
                content => "#!/bin/sh\npuppet agent --no-daemonize --onetime --verbose $1\n",
        }
# Install (if not present) some puppet modules required for 'vimconf' class
        exec { "install_puppet_module":
        command => "puppet module install puppetlabs-stdlib",
        path => [ "/bin", "/sbin", "/usr/bin", "/usr/sbin",
              "/usr/local/bin", "/usr/local/sbin" ],
        onlyif  => "test `puppet module list | grep puppetlabs-stdlib | wc -l` -eq 0"
        }
}

class vimconf {
# Modify vimrc conf file, enabling syntax on
        file_line { 'vim_syntax_on':
        path  => '/etc/vim/vimrc',
        match => '^.*syntax on.*$',
        line  => 'syntax on',
        }
}

node  default {
# this will be applied to all nodes without specific node definitions
        include packages
        include vimconf
        include ntp
        include puppettools
}

node  'puppetagent01' inherits default {
# this specific node, gets all the default classes PLUS some extras
        include mysite
}

Here the content of the single files .pp in classes folder:

class apache {
	package { 'apache2-mpm-prefork':
		ensure => installed
	}

	service { 'apache2':
		ensure => running,
		hasstatus => true,
		hasrestart => true,
	}
}

 

class mysite {

	include apache

	file { '/etc/apache2/sites-available/mysite':
		owner => root, group => root, mode => 0644,
		source => "puppet:///files/mysite/mysite_apache.conf",
	}

	file {'/var/www/mysite.localdomain':
		ensure => directory,
	}

	file {'/var/www/mysite.localdomain/index.html':
                owner => root, group => www-data, mode => 0755,
                source => "puppet:///files/mysite/index.html",
	}

	 exec {'/usr/sbin/a2dissite * ; /usr/sbin/a2ensite mysite':
            	onlyif => '/usr/bin/test -e /etc/apache2/sites-available/mysite',
		notify => Service['apache2'],
	}
}

 

class ntp {
		package { ntp: ensure => present }
		file { "/etc/ntp.conf":
			owner	 => root,
			group	 => root,
			mode	=> 444,
			backup => false,
			source	=> "puppet:///files/etc/ntp.conf",
			require => Package["ntp"],
                        notify  => Service["ntp"],
		}
		service { "ntp":
			enable => true ,
			ensure => running,
			subscribe => [Package[ntp], File["/etc/ntp.conf"],],
		}
	}

 

class packages  {
        Package { ensure => "installed" }

        package { "screen": }
        package { "dselect": }
        package { "vim": }
        package { "curl": }
}

 

It’s important to remember to NOT duplicate entries.
For example, in this case, we have a specific file where we have setup ntp service, including the required package. This means that we do NOT have to add this package in the list into packages.pp, otherwise you will get an error and configs won’t get pushed.

As I’m sure you’ve noted, there are references to some “files”.
Yes, we need some extra configuration, to tell puppet to run as file server as well and where files are located.

In our example we are storing our files in here:

mkdir -p /etc/puppet/files

Now we need to add the following in /etc/puppet/fileserver.conf

[files]
  path /etc/puppet/files
allow *

Last bit, is creating the subfolders and place the files required for our configuration:

mkdir -p /etc/puppet/files 
cd /etc/puppet/files 
mkdir mysite mkdir etc

Inside mysite create mysite_apache.conf and index.html files.

Example mysite_apache.conf

<VirtualHost *:80> 
  ServerName mysite.localdomain 
  DocumentRoot /var/www/mysite.localdomain 
</VirtualHost>

For index.html, you can simply have some text, just for testing purposes.

In this example, we have also setup ntp to be installed and to have a custom ntp.conf file pushed.
For this reason, we need to make sure to have this file present into /etc/puppet/files/etc as declared into our .pp file.

After doing all these changes, you should restart your puppetmaster service on the server.

If all went well, you should have the following:

  • puppetagent02 host with screen, dselect, vim (installed and with syntax on), ntp (installed, running with custom ntp.conf file)
  • puppetagent01: with the same as puppetagent02 PLUS apache with a running website

Of course this is just a raw example and you can use template and other super features.
But I think it’s a good start 😉

 

Sources:


https://forge.puppetlabs.com/puppetlabs/stdlib
http://finninday.net/wiki/index.php/Zero_to_puppet_in_one_day
http://www.puppetcookbook.com/
http://foaa.de/old-blog/2010/07/playing-with-puppets-on-debian/trackback/index.html
http://www.harker.com/puppet/BayLISA100715.html
http://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html

Dynamic DNS update script

Below a script that I’ve created to update your Dynamic DNS service.

It has been tested on Raspian (Raspberry Pi), Ubuntu 18.04 and Debian 9.

It works with Internet.bs, No-ip.com and CloudFlare

https://bitbucket.org/thtieig/dynip_update/src/master/

Also, for who as a router running DD-WRT, here a quick article about how to set it up.

Enjoy! 😉

SSL PASSIVE FTP with virtual users on Raspberry Pi

I found this handy plugin to backup my blog: BackWPup
It has also an interesting feature which is the ability to backup remotely, for example on a FTP server.

So… here we go! 🙂

Few notes:

  • This uses vsftpd software
  • It will work ONLY over SSL
  • Due to SSL encryption, the FTP will also work ONLY in PASSIVE mode (ACTIVE mode is disabled)
  • This configuration has been made based of the fact that this raspberry pi is behind a router
  • This will use ONLY virtual users, chroot’ed, to increase the security (vsftpd will use a custom PAM auth file, which won’t lookup in /etc/passwd files – for this reason, any local user attempts to login will fail)
  • Virtual users usernames and credentials will be stored in a file
  • There is a workaround in place to avoid some common issues like “500 OOPS: Vsftpd: Refusing to Run With Writable Root Inside Chroot ()” – FYI, allow_writeable_chroot=yes does NOT work on vsftpd version 2.3.5.

Install required packets:

apt-get install vsftpd apache2-utils libpam-pwdfile

Create SSL certificate:

openssl req -x509 -nodes -days 7300 -newkey rsa:2048 -keyout /etc/ssl/certs/vsftpd.pem -out /etc/ssl/certs/vsftpd.pem
chmod 600 /etc/ssl/certs/vsftpd.pem

Add a local user with limited access (like no console) that vsfpd will use to run virtual users:

useradd --home /home/vsftpd --gid nogroup -m --shell /bin/false vsftpd

Create directory structures for the virtual users:

mkdir -p /space/ftpusers/
chmod a-w /space/ftpusers/
mkdir -p /space/ftpusers/ftp01/rw
chmod a-w /space/ftpusers/ftp01
chown -R vsftpd:nogroup /space/ftpusers/ftp01

Please note that all new virtual users added need its home directory manually created as per above. Also, due to the chroot option and the current limitation on vsftpd, if you want a user to be able to write in its home directory, you need to create an extra folder. Its root home folder has to be -w. This is a workaround that works 🙂

Setup PAM authentication

Create a new file /etc/pam.d/vsftpd.virtual and add the following:

auth required pam_pwdfile.so pwdfile /etc/vsftpd/vsftpd.users
account required pam_permit.so

Now, let’s reorder a bit vsftp files in a directory:

mkdir -p /etc/vsftpd
cd /etc/
mv vsftpd.conf vsftpd
ln -s /etc/vsftpd/vsftpd.conf .

Add new users (password max 8 characters):

htpasswd -c -d -b /etc/vsftpd/vsftpd.users ftp01 ftp01password

Use the flag -c only the first time to create the file. If you re-use it, the file will be overwritten!
Also the -d flag is required because vsftpd is unable to read MD5 hashed password (default if -d is not used). The downside of this is a password limited to 8 characters.
Openssl could be used to produce a MD5 based BSD password with algorithm 1 using # openssl passwd -1 (not tested)

Let’s configure vsftpd

vi /etc/vsftpd.conf

# Main Settings
listen=YES
listen_port=21
connect_from_port_20=NO
ftpd_banner=Welcome to my FTP :-)
use_localtime=YES
force_dot_files=YES

# FTP Passive settings
pasv_enable=YES
pasv_min_port=1100
pasv_max_port=1150
pasv_addr_resolve=YES
pasv_enable=YES
pasv_addr_resolve=YES
pasv_address=<span style="color: #ff0000;"><EXTERNAL IP or DYN DNS></span>

# Virtual user settings
local_enable=YES
chroot_local_user=YES
secure_chroot_dir=/var/run/vsftpd/empty
virtual_use_local_privs=YES
guest_enable=YES
guest_username=vsftpd
pam_service_name=vsftpd.virtual
user_sub_token=$USER
local_root=/space/ftpusers/$USER
hide_ids=YES

# Anonymous settings
anonymous_enable=NO
anon_upload_enable=NO
no_anon_password=NO
anon_other_write_enable=NO
anon_mkdir_write_enable=NO

# Write permissions
write_enable=YES
local_umask=022
async_abor_enable=YES

# SSL
ssl_enable=YES
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
require_ssl_reuse=NO
ssl_ciphers=HIGH
rsa_cert_file=/etc/ssl/certs/vsftpd.pem

# Logging
xferlog_enable=YES
log_ftp_protocol=NO
syslog_enable=NO
vsftpd_log_file=/var/log/vsftpd.log

Now, on your router, make sure that the module ip_conntrack_ftp is loaded using lsmod command.
This is required for FTP PASSIVE mode to work.
I’ve realised that this can be called also nf_conntrack_ftp.
A good way to check all the alias associated to that netfilter module is using the following command:

# modinfo nf_conntrack_ftp
filename: /lib/modules/3.3.7/kernel/net/netfilter/nf_conntrack_ftp.ko
alias: nfct-helper-ftp
alias: <span style="color: #ff0000;">ip_conntrack_ftp</span>
description: ftp connection tracking helper
author: Rusty Russell <[email protected]>
license: GPL
depends: nf_conntrack
intree: Y
vermagic: 3.3.7 mod_unload MIPS32_R1 32BIT
parm: ports:array of ushort
parm: loose:bool

Also, make sure to setup a port forwarding like as below:

$IPT -t nat -A PREROUTING -p tcp -i $EXTIF -d $EXTIP --dport 21 -j DNAT --to $FTPIP:21 # FTP connection port
$IPT -t nat -A PREROUTING -d $EXTIP -p tcp -m tcp --dport 1100:1150 -j DNAT --to-destination $FTPI # FTP PASS ports
$IPT -A FORWARD -i $EXTIF -d $FTPI -p tcp --dport 21 -j ACCEPT
$IPT -A FORWARD -i $EXTIF -d $FTPI -p tcp --dport 1100:1150 -j ACCEPT

How to build a Debian package from source

There are plenty of articles on the net… but here I’m posting my notes about compiling netatalk.

First of all, you need the minimum packages:

apt-get install build-essential dh-make autotools-dev

I needed this on my Raspberry Pi for this article, and I didn’t want to make dirty the system using the common “make / make install” commands.

This are the simple steps I’ve followed (all as root – even if it’s not the best practise).

mkdir /tmp/netatalk
cd /tmp/netatalk
wget http://downloads.sourceforge.net/project/netatalk/netatalk/3.1.7/netatalk-3.1.7.tar.gz
tar xzvf netatalk-3.1.7.tar.gz
cd netatalk-3.1.7

Make sure the folder has this format: <name_of_the_package>-<version> ALL in lowercase!

dh_make -e [email protected] -f ../netatalk-3.1.7.tar.gz

It will ask for the type of the package. To make things easier, just select single entering s.

Edit the file debian/control adding the missing bits (example below):

Source: netatalk
Section: net
Priority: extra
Maintainer: root <[email protected]>
Build-Depends: debhelper (>= 8.0.0), autotools-dev
Standards-Version: 3.9.3
Homepage: http://netatalk.sourceforge.net/
#Vcs-Git: git://git.debian.org/collab-maint/netatalk.git
#Vcs-Browser: http://git.debian.org/?p=collab-maint/netatalk.git;a=summary

Package: netatalk
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: AppleTalk user binaries
 Open Source AFP fileserver capable of serving many Macintosh clients simultaneously as an AppleShare file server (AFP)

Then, add debian/rules adding this line, to pass custom configure parameters:

override_dh_auto_configure:
	dh_auto_configure -- --with-init-style=debian-sysv --with-zeroconf

The <TAB> is what you have to press to indent the code. Without that TAB, the file won’t work properly. Before dh_auto_configure there is a TAB 🙂
MAKE SURE that the syntax gets highlighted like this:

debian_rules

I’ve read that it should be good to run dpkg-depcheck -d ./configure before the next step.
Honestly, I didn’t do that because it requires an extra package called devscripts that installs loads of dependencies, which I didn’t want to add on my Raspberry pi.
In a different situation, I would probably have done that.

Then run:

dpkg-buildpackage -us -uc

…and wait.

If you get something like this…

dpkg-deb: building package `netatalk' in `../netatalk_3.1.7-1_armhf.deb'.
dpkg-genchanges >../netatalk_3.1.7-1_armhf.changes
dpkg-genchanges: including full source code in upload
dpkg-source --after-build netatalk-3.1.7
dpkg-buildpackage: full upload (original source is included)

…you’ve been lucky! And you can cd .. and you should have your package .deb created and ready to be installed with a simple dpkg -i .deb

Good luck! 🙂

NOTE: I’ve noticed that the compile might fail due to ‘acl‘ package missing. I’m not a master in compiling, so what I’ve done is the following

apt-get install acl

Than I’ve modified include/atalk/acl.h start at line 63, adding #define O_IGNORE 0 to make it look like following:

#define O_NETATALK_ACL 0
#define O_IGNORE 0
#define chmod_acl chmod

This trick was from here
Than, you need to commit the change with the following command: dpkg-source --commit and save adding a little description like “patch to compile with no ACLs” or something like that.
This made me possible to finish the building of the package and have the deb.

 


 

UPDATE: Debian jessy systemd

# Packages to install

apt-get install build-essential libevent-dev libssl-dev libgcrypt11-dev libkrb5-dev libpam0g-dev libwrap0-dev libdb-dev libtdb-dev libmysqlclient-dev avahi-daemon libavahi-client-dev libacl1-dev libldap2-dev libcrack2-dev systemtap-sdt-dev libdbus-1-dev libdbus-glib-1-dev libglib2.0-dev tracker libtracker-sparql-1.0-dev libtracker-miner-1.0-dev autotools-dev debhelper 

# How to edit debian/rules

override_dh_auto_configure:
	dh_auto_configure -- --with-init-style=debian-systemd  --without-libevent --without-tdb --with-cracklib --enable-krbV-uam --with-pam-confdir=/etc/pam.d --with-dbus-sysconf-dir=/etc/dbus-1/system.d --with-tracker-pkgconfig-version=1.0

And here the already compiled file netatalk_3.1.8

ESXi host on D945GCLF2 Intel Atom mainboard, with NFS storage attached running on RAID1

I’ve used this procedure to create a ESXi host on D945GCLF2 Intel Atom mainboard, with RAID1 storage built in, attached to itself 😉

On that, I have at the moment 3 VMs running (minimal Debian with NFS, FreePBX machine, Debian server with a little LAMP server, SAMBA and web based torrent client)…and more resources available.

How? 🙂

“Simply”, I needed:

HARDWARE

  • D945GCLF2 Intel Atom mainboard
  • 2GB or RAM DDR2 (667 or 533) in a single module
  • IDEtoSD adapter
  • 4GB SD card
  • 2 SATA Hard Drives – same capacity (I’ve used 2×2.5″ 160GB – It’s all installed in a little case)
  • spare SATA CD-ROM and a empty CD-ROM to burn the ESXi ISO (I had issues using a USB stick and utilities like unetbootin or similar… so I ended up with the old fashion but working systems)

SOFTWARE

  • ESXi 4.1 ISO – I couldn’t find a way to patch most recent ISOs. Patch is required to add support for the integrated NIC. Also 4.1 has all the required functions for this project.
  • Here the drivers and script to patch the ISO.
  • Debian net-install iso for the NFS vm.
  • vSphere client installed on your machine, to be able to connect to the host and copy the Debian ISO and manage the HOST.

Procedure

  1. Patch the ISO and burn it on your blank CD.
  2. Connect the IDEtoSD card to the single IDE channel, with the SD. This will be our “main IDE hard drive”.
  3. Make sure to have enabled Hyper Threading Technology in the BIOS.
  4. Connect (temporary) the SATA CD-ROM to one of the two SATA channels, with the ESXi CD in, and complete the installation on the “4GB IDE hard drive” present on the system.
  5. Turn off the host, remove the SATA CD-ROM and connect the two hard drives to the SATA connectors.
  6. Boot up, and create a local datastore with the remaining space of the SD (if this hasn’t been created already automatically) and call it “SD_local“. Here we will store our NFS machine which will provide NFS storage to the host.
  7. Create the RDM devices for our minimal Debian NFS machine follow the below instructions (ensure to make a minimal/basic installation, plus ssh, initramfs-tools, mdadm, nfs-kernel-server, nfs-common, portmap. No graphic interface, no extra packages!).
  8. Create the Debian NFS vm, share the storage using NFS, attach it to the host, and you are ready to go! 😉 The host will be ready to have VMs up and running, with their virtual hard drives stored on a redundant storage.

The scope of this is to allow the Debian NFS VM, which will be stored on the local storage called “SD_local“, to directly access the physical SATA hard drives, create a software RAID1 with them, and using NFS protocol, share the space to the ESXi host and use it to store VMs/ISOs etc.

Of course, this Debian NFS VM, and in particular the SD card, are the single point of failure of this project. But theoretically, a dd of the SD once all is configured can be a good “backup” in case of problems (and a spare 4GB SD home as well 🙂 )

ESXi – How to create a Physical RDM and attach it to a VM

1. Determine the VML ID for the SATA disks

# ls /dev/disks/ -l
-rw------- 1 root root 4041211904 May 19 20:18 t10.ATA_____Memory_Card_Adapter_______________________________________0_
-rw------- 1 root root 939524096 May 19 20:18 t10.ATA_____Memory_Card_Adapter_______________________________________0_:1
-rw------- 1 root root 3097493504 May 19 20:18 t10.ATA_____Memory_Card_Adapter_______________________________________0_:2
-rw------- 1 root root 4177920 May 19 20:18 t10.ATA_____Memory_Card_Adapter_______________________________________0_:4
-rw------- 1 root root 262127616 May 19 20:18 t10.ATA_____Memory_Card_Adapter_______________________________________0_:5
-rw------- 1 root root 262127616 May 19 20:18 t10.ATA_____Memory_Card_Adapter_______________________________________0_:6
-rw------- 1 root root 115326976 May 19 20:18 t10.ATA_____Memory_Card_Adapter_______________________________________0_:7
-rw------- 1 root root 299876352 May 19 20:18 t10.ATA_____Memory_Card_Adapter_______________________________________0_:8
-rw------- 1 root root 160041885696 May 19 20:18 t10.ATA_____ST9160821AS_____________________________5MA57R13____________
-rw------- 1 root root 160041885696 May 19 20:18 t10.ATA_____ST9160821AS_________________________________________5MA8PT4Q
lrwxrwxrwx 1 root root 72 May 19 20:18 vml.010000000020202020202020202020202020202020202030204d656d6f7279 -> t10.ATA_____Memory_Card_Adapter_______________________________________0_
lrwxrwxrwx 1 root root 74 May 19 20:18 vml.010000000020202020202020202020202020202020202030204d656d6f7279:1 -> t10.ATA_____Memory_Card_Adapter_______________________________________0_:1
lrwxrwxrwx 1 root root 74 May 19 20:18 vml.010000000020202020202020202020202020202020202030204d656d6f7279:2 -> t10.ATA_____Memory_Card_Adapter_______________________________________0_:2
lrwxrwxrwx 1 root root 74 May 19 20:18 vml.010000000020202020202020202020202020202020202030204d656d6f7279:4 -> t10.ATA_____Memory_Card_Adapter_______________________________________0_:4
lrwxrwxrwx 1 root root 74 May 19 20:18 vml.010000000020202020202020202020202020202020202030204d656d6f7279:5 -> t10.ATA_____Memory_Card_Adapter_______________________________________0_:5
lrwxrwxrwx 1 root root 74 May 19 20:18 vml.010000000020202020202020202020202020202020202030204d656d6f7279:6 -> t10.ATA_____Memory_Card_Adapter_______________________________________0_:6
lrwxrwxrwx 1 root root 74 May 19 20:18 vml.010000000020202020202020202020202020202020202030204d656d6f7279:7 -> t10.ATA_____Memory_Card_Adapter_______________________________________0_:7
lrwxrwxrwx 1 root root 74 May 19 20:18 vml.010000000020202020202020202020202020202020202030204d656d6f7279:8 -> t10.ATA_____Memory_Card_Adapter_______________________________________0_:8
lrwxrwxrwx 1 root root 72 May 19 20:18 <span style="color: #ff0000;">vml.0100000000202020202020202020202020354d413850543451535439313630</span> -> t10.<span style="color: #0000ff;">ATA_____ST9160821AS</span>_________________________________________5MA5SS2A
lrwxrwxrwx 1 root root 72 May 19 20:18 <span style="color: #ff9900;">vml.0100000000354d413537523133202020202020202020202020535439313630</span> -> t10.<span style="color: #0000ff;">ATA_____ST9160821AS</span>_____________________________5MA43W02____________

2. Find the two hard drives

Highlighted in red and orange (in blue I’ve highlighted the serial number which helps to identify them as well).

3. Check the volumes available

# ls -l /vmfs/volumes drwxr-xr-x 1 root root 8 Jan 1 1970 ed0aa47f-f157c36d-0295-b6663f811221 drwxr-xr-x 1 root root 8 Jan 1 1970 e2f7c177-db75edcf-defa-90346375bdf2 drwxr-xr-x 1 root root 8 Jan 1 1970 2da668ef-40e5d96b-90bf-855ddb9c5547 drwxr-xr-t 1 root root 1.4k May 19 21:29 4fb7f163-a1959434-4766-001cc07e74e5 lrwxr-xr-x 1 root root 35 May 19 23:16 SD_local -> 4fb7f163-a1959434-4766-001cc07e74e5 lrwxr-xr-x 1 root root 35 May 19 23:16 Hypervisor3 -> 2da668ef-40e5d96b-90bf-855ddb9c5547 lrwxr-xr-x 1 root root 35 May 19 23:16 Hypervisor2 -> ed0aa47f-f157c36d-0295-b6663f811221 lrwxr-xr-x 1 root root 35 May 19 23:16 Hypervisor1 -> e2f7c177-db75edcf-defa-90346375bdf2

4. Use one of the available to create a subfolder that will contain the VMDK information for the RDM disks (using SD_local)

# cd /vmfs/volumes/SD_local/
/vmfs/volumes/4fb7f163-a1959434-4766-001cc07e74e5 # mkdir RDMs
/vmfs/volumes/4fb7f163-a1959434-4766-001cc07e74e5 # cd RDMs/

5. Create the devices

vmkfstools -z /vmfs/devices/disks/vml.0100000000202020202020202020202020354d413850543451535439313630 rmd_sata1.vmdk -a lsilogic
vmkfstools -z /vmfs/devices/disks/vml.0100000000354d413537523133202020202020202020202020535439313630 rmd_sata2.vmdk -a lsilogic

6. New RDM devices created and ready to be added to the VM

  • Edit the properties of an existing VM and click Add
  • Select Use an existing virtual disk and click Next >
  • Click Browse. You now need to navigate your local datastore ([SD_local]/RMSs) and select the VMDK’s that we created
  • Select Permanent / Persistent > Next..
  • You should now see your new Hard Disk’s in your VM and vSphere will correctly identify them as Mapped Raw LUN.

7. Run your linux VM and create Linux Raid auto (FD type)

8. Create the mdX device

# mdadm --create /dev/md0 --chunk=4 --level=0 --raid-devices=2 /dev/sda1 /dev/sdb1

9. Create the filesystem and add it to /etc/fstab

 

Sources
http://www.vm-help.com/esx40i/SATA_RDMs.php
http://blog.davidwarburton.net/2010/10/25/rdm-mapping-of-local-sata-storage-for-esxi/