4 way NORAID mirror using ZFS

So I thought about a cool way to backup my files without using anything too fancy and I started to think about ZFS. Don’t know why I didn’t before because it’s ultra ultra resilient. Cheers Oracle. This is in Debian 7 Wheezy.

Step 1 Install zfs

# apt-get install lsb-release
# wget http://archive.zfsonlinux.org/debian/pool/main/z/zfsonlinux/zfsonlinux_6_all.deb
# dpkg -i zfsonlinux_6_all.deb

# apt-get update
# apt-get install debian-zfs

Step 2 Create Mirrored Disk Config with Zpool.
Here i’m using 4 x 75GB SATA Cloud Block Storage Devices to have 4 copies of the same data with ZFS great error checking abilities

zpool create -f noraidpool mirror xvdb xvdd xvde xvdf

Step 3. Write a little disk write utility

#!/bin/bash


while :
do

        echo "Testing." $x >> file.txt
        sleep 0.02
  x=$(( $x + 1 ))
done

Step 4 (Optional). Start killing the Disks with fire, kill iscsi connection etc, and see if file.txt is still tailing.

./write.sh & ; tail -f /noraidpool/file.txt

Step 5. Observe that as long as one of the 4 disks has it’s virtual block device connection your data is staying up. So it will be OK even if there is 3 or less I/O errors simultaneously. Not baaaad.


root@zfs-noraid-testing:/noraidpool# /sbin/modprobe zfs
root@zfs-noraid-testing:/noraidpool# lsmod | grep zfs
zfs                  2375910  1
zunicode              324424  1 zfs
zavl                   13071  1 zfs
zcommon                35908  1 zfs
znvpair                46464  2 zcommon,zfs
spl                    62153  3 znvpair,zcommon,zfs
root@zfs-noraid-testing:/noraidpool# zpool status
  pool: noraidpool
 state: ONLINE
  scan: none requested
config:

        NAME        STATE     READ WRITE CKSUM
        noraidpool  ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            xvdb    ONLINE       0     0     0
            xvdd    ONLINE       0     0     0
            xvde    ONLINE       0     0     0
            xvdf    ONLINE       0     0     0

errors: No known data errors

Step 6. Some more benchmark tests

time sh -c "dd if=/dev/zero of=ddfile bs=8k count=250000 && sync"

Step 7. Some concurrent fork tests

#!/bin/bash

while :
do

time sh -c "dd if=/dev/zero of=ddfile bs=8k count=250000 && sync" &
        echo "Testing." $x >> file.txt
        sleep 2
  x=$(( $x + 1 ))
 zpool iostat
clear
done

or better

#!/bin/bash

time sh -c "dd if=/dev/zero of=ddfile bs=128k count=250000 && sync" &
time sh -c "dd if=/dev/zero of=ddfile bs=24k count=250000 && sync" &
time sh -c "dd if=/dev/zero of=ddfile bs=16k count=250000 && sync" &
while :
do

        echo "Testing." $x >> file.txt
        sleep 2
  x=$(( $x + 1 ))
 zpool iostat
clear
done

bwm-ng ‘elegant’ style output of disk I/O using zpool status


#!/bin/bash

time sh -c "dd if=/dev/zero of=ddfile bs=8k count=250000 && sync" &
while :
do
clear
 zpool iostat
sleep 2
clear
done

To test the resiliency of ZFS I removed 3 of the disks, completely unlatching them


        NAME                      STATE     READ WRITE CKSUM
        noraidpool                DEGRADED     0     0     0
          mirror-0                DEGRADED     0     0     0
            1329894881439961679   UNAVAIL      0     0     0  was /dev/xvdb1
            12684627022060038255  UNAVAIL      0     0     0  was /dev/xvdd1
            4058956205729958166   UNAVAIL      0     0     0  was /dev/xvde1
            xvdf                  ONLINE       0     0     0

And noticed with just one remaining Cloud block storage device I was still able to access the data on the disk as well as create data:

cat file.txt  | tail
Testing. 135953
Testing. 135954
Testing. 135955
Testing. 135956
Testing. 135957
Testing. 135958
Testing. 135959
Testing. 135960
Testing. 135961
Testing. 135962

# mkdir test
root@zfs-noraid-testing:/noraidpool# ls -a
.  ..  ddfile  file.txt  forktest.sh  stat.sh  test  writetest.sh


That’s pretty flexible.

Deploying Devstack successfully in CentOS 7

So, do you want to setup your own openstack infrastructure? With Cinder, Nova, nova API, keystone and the such? That’s easy enough. Here is how to do it.

Step 1. Deploy CentOS7, any basic install should be fine. I deployed using the Rackspace cloud server 8Gigs standard instance type. (standard install should be fine!)

Step 2. Add stack user

adduser stack

Step 3. Add stack to sudoers wheel group, ensuring sudo is there

yum install -y sudo
echo "stack ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers

Step 4. Modify /etc/passwd so that the home directory for stack is /opt/stack . It needs this. And chown

vi /etc/passwd
# make sure home directory for stack is /opt/stack (thats all!)
mkdir /opt/stack
chown -R stack:stack /opt/stack

Step 5. Clone Devstack from git

sudo yum install -y git
su stack
git clone https://git.openstack.org/openstack-dev/devstack
cd devstack

Step 6. Cp base config sample file

cp samples/local.conf .

Step 7. Deploy stack

./stack.sh

Configuring a Console Prompt for BASH Linux

In BASH it’s pretty simple to customize the console prompt. There are a few good reasons for doing this, for instance if you are pulling out data from the commandline or running automation tasks and want to know when each section was executed. Here is how I did it:

Edit .bash_profile

cd
vi .bash_profile

Insert this line into .bash_profile

PS1='bash-\v \d \t \H \w\$ '

source it

$source .bash_profile
bash-4.9 Tue Nov 24 11:32:09 pirax-test ~#

Nice.

Retrieving Xenstore Networking settings from within a Rackspace Server

When a customer of ours is having issues with their networking, such as the configured gateway or netmask, we are able to provide a oneliner that allows them to run on the VM guest a command which takes the information directly from xenstore, (xe-linux-distribution). Find the command below.

xenstore-read vm-data/networking/$(xenstore-ls vm-data/networking | awk '/private/{print$1}')
{"label": "private", "broadcast": "10.255.255.255", "ips": [{"ip": "10.177.194.237", "netmask": "255.255.255.0", "enabled": "1", "gateway": null}], "mac": "BC:76:4E:11:11:11", "dns": ["83.138.151.81", "83.138.151.80"], "routes": [{"route": "10.208.0.0", "netmask": "255.255.0.0", "gateway": "10.166.255.1"}, {"route": "10.116.0.0", "netmask": "255.240.0.0", "gateway": "10.1.1.1"}], "gateway": null}

Please note that the information was modified for privacy. This is just grabbing servicenet. To gather all the vm-data use

xenstore-ls vm-data

Altogether now:

Step 1. Retrieve all vm-data


$ xenstore-ls vm-data
 user-metadata = ""
 rax_service_level_automation = ""Complete""
 build_config = """"
networking = ""
 BC764E182CB = "{"label": "private", "broadcast": "10.177.1.1", "ips": [{"ip": "10.177.1.1", "netmask": "255.255.255.0", "enabled": "1", "gateway": null}], "mac": "BC:76\..."
 BC764E0192DB = "{"ip6s": [{"ip": "2a00:1a48:7803:107:be76:4eff::", "netmask": 64, "enabled": "1", "gateway": "fg80::def"}], "label": "public", "broadcast": "37.188.117.2\..."
meta = "{"rxtx_cap": 80.0}"
auto-disk-config = "False"

Step 2. Retrieve data for Network MACID

xenstore-read vm-data/networking/BC764E182CB
"label": "private", "broadcast": "10.177.255.255", "ips": [{"ip": "10.177.1.1", "netmask": "255.255.255.0", "enabled": "1", "gateway": null}], "mac": "", "dns": ["83.138.151.81", "83.138.151.80"], "routes": [{"route": "10.1.0.0", "netmask": "255.255.255.0", "gateway": "10.177.1.1"}, {"route": "10.1.1.0", "netmask": "255.255.0.0", "gateway": "10.101.1.1"}], "gateway": null}

xenstore-read vm-data/networking/BC764E0192DB
{"ip6s": [{"ip": "2a00:1a48:7803:107:be76:4eff:fe08:9cc3", "netmask": 64, "enabled": "1", "gateway": "fe80::def"}], "label": "public", "broadcast": "37.1.117.255", "ips": [{"ip": "37.188.117.48", "netmask": "255.255.255.0", "enabled": "1", "gateway": "37.1.117.1"}], "mac": "", "gateway_v6": "ge77::def", "dns": ["83.138.151.81", "83.138.151.80"], "gateway": "37.1.117.1"}

Please note I sanitised the MACID and IP address information, altering it not to show my real ips and subnets, it is just to give you an idea of the two virtual intefaces, publicnet & servicenet.

Booting an Image in specific cell/region

This particular oneliner uses NOVA API to boot an image with the id=9876fa2-99df-4be3-989f-eec1e8c08afd and the flavor=general purpose 4GB RAM and the hint ensures that the server reaches the correct cell and hypervisor host.

supernova customer boot --image 9876fa2-99df-4be3-989f-eec1e8c08afd --flavor general1-4 --hint target_cell='lon!z0001' --hint 0z0ne_target_host=c-10-0-12-119 myservername

Checking Size of Database within MySQL

We had an issue where the rackspace intelligence monitor was giving a different value to the control panel instance of a dbaas. So I came up with a way of testing MySQL for the database size. There is nothing more reliable than running the query like this, I think.

SELECT table_schema AS "Database", 
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS "Size (MB)" 
FROM information_schema.TABLES 
GROUP BY table_schema;

Using SNI with Rackspace Cloud Load Balancer and adding upto 20 SSL Certificates on single LB

This is going to be a short and dirty documentation on how to add multiple SSL certificates to a Rackspace Load Balancer.

1. Authorise with rackspace auth api (Get a token with user and api key credentials)
x-auth-key is apikey and x-auth-user is the mycloud username

curl -D - -H "x-auth-user: myusername" -H "x-auth-key: 1c989d8f89dfd87f3df3dff3d6f7fgf" https://auth.api.rackspacecloud.com/v1.0


HTTP/1.1 204 No Content
Server: nginx
Date: Thu, 19 Nov 2015 15:41:38 GMT
Connection: keep-alive
X-Storage-Token: AAA98345kdfg893DFGDF43iudng39dfgjkdfgDFI$JUIDFJGDFJGDFGDJJHDFGJHIfdg34dfgkdfjgiodfgiodfDFGDdg323
X-Storage-Url: https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_1001001
X-NewRelic-App-Data: PxQGUF9aDwETVlhSBQUP
X-CDN-Management-Url: https://cdn3.clouddrive.com/v1/MossoCloudFS_1001001
X-Auth-Token: AAA98345kdfg893DFGDF43iudng39dfgjkdfgDFI$JUIDFJGDFJGDFGDJJHDFGJHIfdg34dfgkdfjgiodfgiodfDFGDdg323
vary: Accept, Accept-Encoding, X-Auth-Token, X-Auth-Key, X-Storage-User, X-Storage-Pass, X-Auth-User
Cache-Control: s-maxage=86319
Front-End-Https: on

Now you can copy and paste the X-Auth-Token. It is needed for the next step

2. Configure the JSON file to upload an additional certificate and private key via API for a domain hostname. Here I am configuring domain.com

file: lb.json

{
  "certificateMapping": {
     "hostName": "domain.com",
     "certificate": "-----BEGIN CERTIFICATE-----\nMIIC/TCCAeWgAwIBAgIJAOjRMYJKDeryMA0GCSqGSIb3DQEBBQUAMBUxEzARBgNV\nBAMMCmRvbWFpbi5jb20wHhcNMTUxMTE5MTQzMjE3WhcNMjUxMTE2MTQzMjE3WjAV\nMRMwEQYDVQQDDApkb21haW4uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEAvHTjzWQchX+Gyl/No+ABR9R+F65rJmEPBEutjgWUynOir7ZYu5vmFol8\nhF054W5Xv3Ii4oYJjDJingOqQUBBxJD4jXx8H79y04JGXl8BBrG7azbRbowc4HoP\nRUiVTNaCPgYAGTreiRXmYKb/beotlGDvl0HQQLeDh4iq1X1E8R/lkFRHVAu0rEgC\nIeuJZ2L3Qu06A5yTCwdTJnZmviLmuDQtkfLDqTA8N67U8zjBgKGsj9t7GDSQ7zGp\n6JbTSJXqsXvd7XMLm2Ns2UelVUToxBTwgOIBn0XzZLCIOIlbIn0LHBk8oYEA4JDF\n1mXeqdsFOCtYvFcQBoUihiDjwDdTNQIDAQABo1AwTjAdBgNVHQ4EFgQU1wBZxNte\n9Q//UOl7ZMUvtsXghPEwHwYDVR0jBBgwFoAU1wBZxNte9Q//UOl7ZMUvtsXghPEw\nDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAUNM56u/cc56ESZY4gubX\nh0UQ8TjVbV2G4EkbBkNnm7RgNK48lFIxc55tshawhdN01JH5ZIgB1RvO1/lqouVs\nJrXwnPULBb4M5FcrjjBVu3bIvOjAUVDogOm7pKP/hJALM9CWMuZcXr5C+sYFczaB\nA7uDuMuQoTZBIGF1NyzfO7vmHT5QbEA/1ZYISWrVFNt8g2oxJY+jdgKacxVujWIs\nFpuiCCdvFVI05wCjj3C8BIN/EAcRIqe5gwr5oI+AtwK7fjK5K47/sREMI+W6Bj1w\nZEDz92S+dNtoSPJTBWiIQFLslTPiaDAu1EjJO1+YRXG7LANdxpQrogvDG1l9VpDW\nRg==\n-----END CERTIFICATE-----",
  "privateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAvHTjzWQchX+Gyl/No+ABR9R+F65rJmEPBEutjgWUynOir7ZY\nu5vmFol8hF054W5Xv3Ii4oYJjDJingOqQUBBxJD4jXx8H79y04JGXl8BBrG7azbR\nbowc4HoPRUiVTNaCPgYAGTreiRXmYKb/beotlGDvl0HQQLeDh4iq1X1E8R/lkFRH\nVAu0rEgCIeuJZ2L3Qu06A5yTCwdTJnZmviLmuDQtkfLDqTA8N67U8zjBgKGsj9t7\nGDSQ7zGp6JbTSJXqsXvd7XMLm2Ns2UelVUToxBTwgOIBn0XzZLCIOIlbIn0LHBk8\noYEA4JDF1mXeqdsFOCtYvFcQBoUihiDjwDdTNQIDAQABAoIBAQCSEJr7d0tv4P6s\n3gI5sIXtkXHFkwczcOi9sJYszICdRXDjdZZimpuD/j3HLaaN5gMWvDTzk2XVBrxO\nspKEDnSrEJ3Es6ZUyQMLkh5OSJ43/QtBNvSuFOTQy2oIjhBBxMSfo/DxnSIb6CBt\n6yFwpJ99MICioHzznAjSxId7/qKvq294emBGwpyP6JbCEtrM6rsnBO4J/uHUDLRj\nlU0zLFwFHNQnhnfIuxOoUZthyCSzZgUquC7C52qIPTZxqCydSi045pDoymn6pT43\n5YdafzWarmEqBGcyqDOyjOz01IEicrmFW7e2+DICIOTOvTSeFQtHbO4Rn2VE2V+x\nGNJY3DoFAoGBAORqB6gFlLUKBXdmP1VcEifjwcVtBaY9QwehbH8En6O0N1t5bKFx\nTBaShm2El+7UCeeSz9hx3vmV/4gn9amJnu6stOEUfjbfxe6mw8OtR13g5iSAI9TQ\nXesf1HoCrUsljzAPvBAKxWSQl9e6fYBxmB1IvFvd4n9uvoNWr/lOfbe3AoGBANM3\neddZYHBB0PhgiJ9aq7QkgqUSdv5JlBdtGdPDr3cpIx9QmXMtf+wc8vZ6CSvC3EIn\npADRt3QAIzxQLpXb3ADjBCwwsFCu27IXlVkvxD+yvqaLbAjB/LgbKqt5wR6YAarj\nDQzNzxhGvrCS+CvYSKospY6UK5+V0nuhuPVcuJRzAoGAAPHLTE+RmNoMwbyjgGfc\nD1wqvfVAc7qHH230c+YB/vxMyk0LPPOp++HpOmS0+CDaVaHOyDdYU7HiF58KrgPK\nq3P9X3zlNLbiK6V248VAqUu3x+jbvRKLgOBl0YdXThs+p1U5Utuoi0zpw9Oal0Bg\n/6YAWWTmfd5oXUSrf51qeasCgYEAgMahBZgbgTXPh6+rfKTWbQWZlbU1UYJgxQui\npIb5cwhkvpHwjNWf2cAorffnoYOzsK3kgw9Z72KqGPq1/G5Iq0293Idu6DJEBkf0\nqaTC3SdIr9fvbUOApmsBz/xyrwl0ctDtwvG0IxP27UceAfVjEEYaRly2YB0DcJdA\nYnA+pVsCgYEAoHfkw/ZPmB7r8LesF0+N93AErJ/IiPoCBFNKijVDplzLQbMeWyxL\njcnFdq8vQT0Os4qzRNCR5QbMcprJIh4LC96OIlGWz5NhKCWbGsKxA8N7YoWGYy9Z\nmRkVP6peBU2cGdXRWjCrxkKR+uJM9BCG0Ix3BOPy29nWaCEl+5wjBEc=\n-----END RSA PRIVATE KEY-----"
  }

3. Call API to add certificatemapping json lb hostname configuration file. This just allows example.com to have SSL on the Load Balancer.
(you can add up to 20 Domains). It’s lots cheaper and not as hard as I might have initially thought!!

curl -v -H "X-Auth-Token: $TOKEN" -d @lb.json -X POST -H "content-type: application/json"  https://lon.loadbalancers.api.rackspacecloud.com/v1.0/1001001/loadbalancers/157089/ssltermination/certificatemappings

It’s also possible to update the Load Balancer Certificates via the API, please see https://developer.rackspace.com/docs/cloud-load-balancers/v1/developer-guide/#update-certificate-mapping for more information

4. Confirm the certificate mappings are added (please note 1001011 is the customer DDI and 157090 is the Load Balancer ID).

curl -v -H "X-Auth-Token: $TOKEN" -X GET https://lon.loadbalancers.api.rackspacecloud.com/v1.0/1001011/loadbalancers/157090/ssltermination/certificatemappings


< HTTP/1.1 200 OK
< Content-Type: application/json
< Via: 1.1 Rackspace Cloud Load Balancer API v1.25.11 (Repose/2.11.0)
< Content-Length: 83
< Date: Thu, 19 Nov 2015 15:49:24 GMT
* Server Jetty(8.0.y.z-SNAPSHOT) is not blacklisted
< Server: Jetty(8.0.y.z-SNAPSHOT)
<
* Connection #0 to host lon.loadbalancers.api.rackspacecloud.com left intact
{"certificateMappings":[{"certificateMapping":{"id":999,"hostName":"domain.com"}}]}

You may note that the lb.json file has the certificate all on one line! how to do this? It's not that hard. Here is how I did it:

cat domain.com.cert | sed ':a;N;$!ba;s/\n/\\n/g'
cat domain.com.key  | sed ':a;N;$!ba;s/\n/\\n/g'
-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAvHTjzWQchX+Gyl/No+ABR9R+F65rJmEPBEutjgWUynOir7ZY\nu5vmFol8hF054W5Xv3Ii4oYJjDJingOqQUBBxJD4jXx8H79y04JGXl8BBrG7azbR\nbowc4HoPRUiVTNaCPgYAGTreiRXmYKb/beotlGDvl0HQQLeDh4iq1X1E8R/lkFRH\nVAu0rEgCIeuJZ2L3Qu06A5yTCwdTJnZmviLmuDQtkfLDqTA8N67U8zjBgKGsj9t7\nGDSQ7zGp6JbTSJXqsXvd7XMLm2Ns2UelVUToxBTwgOIBn0XzZLCIOIlbIn0LHBk8\noYEA4JDF1mXeqdsFOCtYvFcQBoUihiDjwDdTNQIDAQABAoIBAQCSEJr7d0tv4P6s\n3gI5sIXtkXHFkwczcOi9sJYszICdRXDjdZZimpuD/j3HLaaN5gMWvDTzk2XVBrxO\nspKEDnSrEJ3Es6ZUyQMLkh5OSJ43/QtBNvSuFOTQy2oIjhBBxMSfo/DxnSIb6CBt\n6yFwpJ99MICioHzznAjSxId7/qKvq294emBGwpyP6JbCEtrM6rsnBO4J/uHUDLRj\nlU0zLFwFHNQnhnfIuxOoUZthyCSzZgUquC7C52qIPTZxqCydSi045pDoymn6pT43\n5YdafzWarmEqBGcyqDOyjOz01IEicrmFW7e2+DICIOTOvTSeFQtHbO4Rn2VE2V+x\nGNJY3DoFAoGBAORqB6gFlLUKBXdmP1VcEifjwcVtBaY9QwehbH8En6O0N1t5bKFx\nTBaShm2El+7UCeeSz9hx3vmV/4gn9amJnu6stOEUfjbfxe6mw8OtR13g5iSAI9TQ\nXesf1HoCrUsljzAPvBAKxWSQl9e6fYBxmB1IvFvd4n9uvoNWr/lOfbe3AoGBANM3\neddZYHBB0PhgiJ9aq7QkgqUSdv5JlBdtGdPDr3cpIx9QmXMtf+wc8vZ6CSvC3EIn\npADRt3QAIzxQLpXb3ADjBCwwsFCu27IXlVkvxD+yvqaLbAjB/LgbKqt5wR6YAarj\nDQzNzxhGvrCS+CvYSKospY6UK5+V0nuhuPVcuJRzAoGAAPHLTE+RmNoMwbyjgGfc\nD1wqvfVAc7qHH230c+YB/vxMyk0LPPOp++HpOmS0+CDaVaHOyDdYU7HiF58KrgPK\nq3P9X3zlNLbiK6V248VAqUu3x+jbvRKLgOBl0YdXThs+p1U5Utuoi0zpw9Oal0Bg\n/6YAWWTmfd5oXUSrf51qeasCgYEAgMahBZgbgTXPh6+rfKTWbQWZlbU1UYJgxQui\npIb5cwhkvpHwjNWf2cAorffnoYOzsK3kgw9Z72KqGPq1/G5Iq0293Idu6DJEBkf0\nqaTC3SdIr9fvbUOApmsBz/xyrwl0ctDtwvG0IxP27UceAfVjEEYaRly2YB0DcJdA\nYnA+pVsCgYEAoHfkw/ZPmB7r8LesF0+N93AErJ/IiPoCBFNKijVDplzLQbMeWyxL\njcnFdq8vQT0Os4qzRNCR5QbMcprJIh4LC96OIlGWz5NhKCWbGsKxA8N7YoWGYy9Z\nmRkVP6peBU2cGdXRWjCrxkKR+uJM9BCG0Ix3BOPy29nWaCEl+5wjBEc=\n-----END RSA PRIVATE KEY-----

Notice the extra \n's after the processing.

Don't be intimidated by the sed line, it just replaces the \n newline with the character \n instead, so the json file is easier to lay out the cert as a 'string'.

Important notes on SNI:

We know we can add certificate mappings on the Load Balancer.
the Load Balancer has been configured for Allowing secure and insecure traffic, Port 443. SSL is terminated at the load balancer. This is what is known as OFFLOADING, it just means the SSL encryption is seen at the load balancer. Behind the load balancer, there is no encryption between it and the server. This allows the SNI hostname to be forwarded to the server, without it being in an encrypted form within the TCP packet.

5. Now lets install apache2 and configure some virtualhosts, at the most basic level. This is for an example and not a perfect setup

apt-get update
apt-get install httpd
vi /etc/apache2/httpd.conf



ServerName example.com
Documentroot /var/www/example.com/html




ServerName domain.com
Documentroot /var/www/domain.com/html


mkdir -p /var/www/domain.com/html
mkdir -p /var/www/example.com/html
echo 'example.com page body testing' > /var/www/example.com/html/index.html
echo 'domain.com page body testing' > /var/www/domain.com/html/index.html
vi /etc/apache2/apache2.conf

add one line in the file like:

Include /etc/apache2/httpd.conf

I just like to configure apache2 this way.

/etc/init.d/apache2 restart

6. Confirm both websites are working thru LB with SNI

# Curl domain
$ curl domain.com
domain.com page body testing

# curl domain 2
$ curl example.com
example.com page body testing

# curl IP address
curl https://194.213.79.117
someotherdefaultpage

# what happened when curling the IP address? Well..There was no TCP servername/hostname forwarded in the header for SNI support to detect the domain x-forwarded-for

# Lets provide the header
curl https://194.213.79.117 -H "host: example.com"

Testing SSL on the hostnames

openssl s_client -connect domain.com:443
openssl s_client -connect domain.com:443 -host domain.com
openssl s_client -connect domain.com:443 -servername domain.com

List all Cloud Server Details thru the API

Well, this one is a bit cheeky because I borrowed it from a colleague of mine David Coon. Thanks David, I appreciate your assistance!

#!/bin/bash


auth() {
    read -p "What is your Account Number: " ddi
    read -p "Whats your username:" username    
    read -p "Whats your APIkey:" APIkey
    read -p "Which Datacenter are your servers in? " dc
}

token() {
    
    token=`curl -s https://identity.api.rackspacecloud.com/v2.0/tokens -X POST \
    -d '{"auth":{"RAX-KSKEY:apiKeyCredentials":{"username":"'$username'", "apiKey":"'$APIkey'"}}}' \
    -H "Content-Type: application/json" | python -m json.tool  | sed -n '/expires/{n;p;}' |sed -e 's/^.*"id": "\(.*\)",/\1/'`
    echo "Your API Token is ---->  $token"
}

listservers() {
    curl -s -H "X-Auth-Token: $token" "https://$dc.servers.api.rackspacecloud.com/v2/$ddi/servers" | python -m json.tool
}

getservers() {
    read -p "What is the server id?" id
    curl -s -H "X-Auth-Token: $token" "https://$dc.servers.api.rackspacecloud.com/v2/$ddi/servers/$id" | python -m json.tool
}

auth
token
listservers
getservers