Steve Jobs Leadership Essay

Eventually I will get to writing something new content here, but for now here is an essay I wrote about former Apple CEO and founder Steve Jobs leadership qualities. NOTE: I wrote this for a class project during in 2011 which was when he was still alive.

Below is the original essay.

Steve Jobs is an extraordinary American CEO and great leader. In this paper, I am going to illustrate six of his most significant leadership qualities. These qualities include his: ability to inspire others, ability to personally connect with customers, strong sense of responsibility, sense of determination, immense creativity, and clear brilliance. The collective result of these qualities is what has led Steve Jobs to be the successful and influential person he is today.

The first quality that Jobs possesses as a leader is his ability to inspire others. He has accomplished many things that have made him an extraordinary leader in his life; many things that people can admire. His life is already filled with many great accomplishments that reflect his leadership qualities. He is CEO of Apple Computers; which he co-founded. He was also the CEO of Pixar. Many people who aspire to work in or design aspects of the world of technology look to him as an inspiration. They see his success as something to strive for.

The second quality that Steve Jobs possesses as a leader is his ability to connect with customers. Throughout the founding phases of both Apple and Pixar, people reported that customers always found Jobs very personable. In fact, they believed in him and his company so much that he has become the 136th richest person in the world! This clearly illustrates his sense of leadership and his ability to connect with customers.

The next quality that Steve Jobs possesses as a leader is his strong sense of responsibility. This quality is apparent when looking at his dedication to the companies that he is involved with. In an article about the 25 most fascinating entrepreneurs the author said that Jobs is different than most other business owners in that he takes personal responsibility for what Apple makes and how the products affect the user. Jobs is involved in the design process from beginning to end and helps to choose each and every aspect of the products that he creates. This really depicts leadership because he is setting an example for the employees he works with and sets a standard for other companies as well.

Another quality that Jobs possesses as an effective leader is his sense of determination. This quality led him to help found Apple computers and pull it through times of despair along with becoming one of the greatest entrepreneurs in our country’s history. It all began with his upbringing. Apple computer’s co-founder was born on February 24, 1955 in San Francisco, California. After he was born he was put up for adoption by his biological parents. He was adopted by Paul and Clara Jobs of Santa Clara California. The Jobs lives in Mountain View California, which is in what is known as the Silicon Valley. Steve worked with electronics with his father in their garage. His father, Paul, show him how to take apart and reconstruct electronics, a hobby which fascinated and inspired young Steve. After this, Steve was determined to find a way to incorporate technology into his daily life.

The fifth quality that contributes to Steve Jobs’ ability as a leader is his immense creativity. In 1974 Jobs became a video game designer with Atari. At the age of 21, in 1976 he founded Apple Computer with his friend Wozniak. They both had to sacrifice things that they valued very much to help fund there new venture. Job’s sold his VW bus and Wozniak sold his scientific calculator. That showed his determination and commitment to pursue his dreams. The events that have followed, especially in regard to apple, show the extent of his creative abilities. In fact Jobs is so creative that simple trips to an apple orchard inspired him to create the multi-billion dollar company. Jobs says that “Creativity is just connecting things.” This statement shows what a great leader he is because his entire company connects people with products that make their lives easier and better.

Finally, Steve Jobs’ clear brilliance is a quality that people see in him as a component of his effective leadership. Jobs did not like formal schooling. During his elementary school years he was quite a troublemaker. His fourth grade teacher had to bribe him to study. Even though he did not think school was that important, he was extremely brilliant. The administrators at Steve’s elementary school wanted to push him up to high school because he tested extremely well, but his parents declined. During high school, Steve Jobs spent a lot of time at Hewitt Packard (HP) where he became friends with Steve Wozniak, a brilliant computer engineer. After graduating from high school, Jobs enrolled at Reed College in Portland, Oregon. Lacking direction, he dropped out after six months. For the next eighteen months, he dropped in on a variety of creative classes. By testing so well that his school administrators offered to push him up to high school, and by surrounding himself with other brilliant people, Steve clearly showed that he was a brilliant man.

Collectively, these are the characteristics that contribute to Jobs’ effectiveness as a leader. His accomplishments have inspired others. He connects with customers. He takes all of the responsibility for the company. He shows determination in everything he does. Jobs is an extremely creative and brilliant person. With these great leadership qualities he has made himself, Apple Computer, and Pixar extremely successful.

Sources: IP Packet Header Drawings

Matt Baxter created very descriptive IP packet header drawings in 2008. Unfortunately, his website, which was where he posted them, has been inaccessible for a long time. I was able to recover these copies of the original PDF files up using the Internet Archive’s Wayback Machine I uploaded the PDF versions of the drawings here in case anyone else is interested in scalable, high quality copies of them.

TCP Packet Header

IPv4 Packet Header

IPv6 Packet Header

UDP Packet Header

ICMP Packet Header

Integration Testing Ansible Playbooks with Travis CI and Docker

The process behind performing integration tests on Ansible playbooks is almost exactly the same as the one used to test individual roles. In fact, this tutorial is based on a modified version of Continuous Testing of Ansible Roles with Docker and Travis CI by Ignacio Sánchez Ginés. This tutorial is a demonstration of how I set up continuous integration testing of the WordPress playbook I wrote to deploy this website.

First of all, you will need to create an Ansible inventory file with localhost as a host in your desired host group. As a group variable, you will need to specify the name of the local user and that the connection is local.
See: Working with Inventory

For example, you should have something like this in your hosts file.


Now that you have a hosts file, you will COPY it into your Dockerfile. You will obviously want to install ansible, sudo, any other dependencies you may need using a RUN command. If you need to install an Ansible Galaxy role, you can do so with a RUN command after Ansible has been installed.
See: Dockerfile reference and Best practices for writing Dockerfiles

Installing Ansible Galaxy Roles:
# Install Dependencies from Ansible Galaxy
RUN ansible-galaxy install geerlingguy.repo-epel
RUN ansible-galaxy install geerlingguy.repo-remi

This is the CentOS 7 Dockerfile I use to CI test my WordPress playbook.

If you wish to use Ubuntu or Fedora, you can find similar systemd and init based images in Ignacio’s GitHub repository.

Now you need to create a .travis.yml configuration file. Below, you can find the one I use to test my WordPress playbook. I run a syntax check before I try running the actual playbook. Also, if your playbook contains secret variables such as passwords or API keys, I recommend encrypting them using Ansible Vault, and keeping them in a directory that is outside of your repository. You can create a “dummy” secrets file for testing purposes.
See: How To Use Vault to Protect Sensitive Ansible Data on Ubuntu 16.04

If you would like to keep your Dockerfiles in a sub directory, you can specify the location using the --file flag, and replace the ., which specifies the directory you are currently in, with the name of the sub directory you want.

For example, if you want to store your Dockerfiles in the ./travis sub directory, you build command would look something like this.
- 'sudo docker build --no-cache --rm --file=travis/Dockerfile.${distribution}-${version} --tag=${distribution}-${version}:ansible travis'

If you have variables you would like to test different values for, you can use sed to change them.
See: Sed – An Introduction and Tutorial by Bruce Barnett

For example:
- '/bin/sed -e "s/resty_install_from_source: true/resty_install_from_source: false/" -i defaults/main.yml'

After you change the variables, you will obviously need to run another series of tests. Below is the CI test configuration I am using for my OpenResty role.

Finally, you will need to enable Travis CI on your repository, which you can reference the Travis CI getting started for instructions.

If you prefer a video tutorial on how to set up Travis CI, here is a decent one.

Regular Expressions and In-Place Slice Manipulation in Go

Regular expressions are very useful for parsing strings. If you need to replace a substring or split up an array, you should consider using regular expressions. I will admit that I am not an expert in regards to using them, however, I will not dismiss their usefulness. You may find the Regex Cheat Sheet very useful.

In Go, the regexp package includes many useful functions that utilize regular expressions.

Here is a simple CLI program that calculates the sum of the integer values in a string. It splits the string into a slice and then sums up all of the integer values in the slice. In this application, the string is split up using the regular expression [^0-9]+. The ^ indicates that that we do not want to match on a character that is an integer within the range of [0-9]. While the + “greedy” quantifier indicates that we want to match when there are one or more characters. In this example, we are simply delimiting the string based on non-digit values such as letters and other special characters.

One important thing to note about func (*Regexp) Split is that it creates an empty element in the slice if it starts splitting the string at the first or last element. In this example, this is handled by catching the error that is thrown when strconv.Atoi(intSlice[i]) fails to convert a string to an integer value at a given index. After an error is thrown, the bad index which is delete in place by taking the valid indexes up to the bad index and then appending the indexes that follow it. This is implemented with intSlice = append(intSlice[:i], intSlice[i:]...). After you remove the element, the length of the slice needs to be decremented.

SEE: SliceTricks

go run .\stringSum.go st1ngW1thIn7s


Golang String Sum Windows
Golang String Sum Windows

Traversing Directories Recursively and Sorting Objects by Attribute Value in Go

Lets say you would like to sort all the files in a directory, as well as its sub directories by an attribute like file size.


First, you need to recursively traverse or walk the specified directory, which is easy in Golang with the filepath.Walk() function from the path/filepath package. In order to use filepath.Walk() you need a walkfunc or walk function, which can be nested in your walk function as demonstrated in the sample program below. The walkfunc will allow you to handle errors that occur when you approach directory files or files you do not have permission to access.

Recommended tutorial: Flavio Copes – LIST THE FILES IN A FOLDER WITH GO

As you walk the directories, you will need to get the size of each file, which can be achieved using the stat() system call on Linux. In Golang, you can the os.Stat() function to get an object of type FileInfo which contains an a Size() attribute, which is what we want. As you get the file size for each file in the directory, you will need to store the relative file path and the size in bytes of each file as an object in a slice of type file objects.

Once have the file names and sizes of all of the files, you will then need to sort the files by the size attribute, either from largest to smallest or from smallest to largest, which can easily be done using sort.Slice() from the sort package. If you want sort the files from smallest to largest, you would want to use a less / < function like: sort.Slice(files, func(i, j int) bool { return files[i].size < files[j].size }). However, if you wish to sort from largest to smallest, you would use a greater / > function instead, which would look like this: sort.Slice(files, func(i, j int) bool { return files[i].size > files[j].size }). Finally, you can just simply print the desired number of files from the sorted slice.

I would say that it is important to know that in many Linux filesystems such as EXT3 and EXT4, filenames are stored in a directory table that lists files as name (key), inode (value) pairs. You can find the names of all of the files from the directory table and if you refer to a file’s inode, you can get its file size in bytes.

The relationship between the directory entry, an inode, and blocks of an allocated file
The relationship between the directory entry, an inode, and blocks of an allocated file

Here is a command line utility that takes in a directory as a string, a number of files as an int, and an order to sort them as a string. It then lists the largest or smallest files in the directory ordered by size.

Recommended tutorial: Rapid7 – Building a Simple CLI Tool with Golang

Note that since slices are references to arrays, you do not have to pass them as pointers. You can see this demonstrated with the call to sortFiles(*sortPtr, files) on line 125 as nothing is returned from it.
See: The Minimum You Need To Know About Arrays and Slices in Golang

Feed in the directory using --dir, the file count using --cnt, and the sort order which is either largest or smallest --sort

go run .\largestFiles.go --dir . --cnt 10 --sort smallest

Golang Sorted Files Windows
Golang Sorted Files Windows

On a side note, Golang’s stat() function works quite well on Windows systems, which do not have a native stat() system call.



Installing Infinoted on Debian and Ubuntu

Note: This is an old post from 2016, that was recovered from the database of my old website.

Overview: Gobby is a cross-platform collaborative text editor that enables Google Docs style editing. Unlike Etherpad, Gobby is more focused toward editing code with its support for syntax highlighting as demonstrated below.

Gobby Syntax Highlighting
Gobby Syntax Highlighting

I have used this program for multiple group projects and everyone found it very beneficial as it allowed us all to work on the same file(s) at once even when we were not in the same room. The built-in chat box enabled us to easily communicate while we worked on the project remotely. As an added bonus, the server used by Gobby, Infinoted, can be used with other text editors such as gedit. Hosting the server does not require a very powerful machine as a simple Raspberry PI 2 will suffice. You can download the Gobby client from the project’s website.


Note: items marked in red indicate they may vary based on how you decide to install this service. Whenever you want to install something on a Debain based Linux distribution, you want to, first of all, make sure your package manager, apt, it up to date. To do so, run the following command. sudo apt-get update After you update your package manager, it is always a good idea to make sure all your packages are up to date. sudo apt-get upgrade Now it is safe to install Infinoted using the package manager. sudo apt-get install infinoted Once you have finished installing Infinoted using the package manager, you need to configure it. For security reasons, it is recommended to run a service with a specific user and group. You can choose any username and / or group you want, but it is recommended to chose something that will be easy to recognize for example gobby or infinoted. The following instructions use gobby for both the user and the group. The following command will create a new system user and group named gobby with no login access and home directory:

/home/services/gobby sudo adduser --system --gecos "Infinoted Service" --disabled-password --group --home /home/services/gobby gobby

If you prefer, you could use /var/lib/gobby as the home directory. You should now set the directory permissions for the gobby home directory. You should recursively set the home directory and all other following directories to 770. Setting the permission level to 770 allows only the owner and those in the group to read, write and execute files.

sudo chmod -R 770 /home/services/gobby

The following command should be optional but is very useful if encounter ownership problems in the gobby home directory. It recursively sets both the directory owner and group to gobby. Both the directory owner and group should have been set when you created the gobby user.

sudo chown -R gobby:gobby /home/services/gobby

Now you need to add the users you wish to be easily able to access the files edited on the server to the gobby group. To do so, use the following command as a template by replacing “username” with the desired username without quotes.

sudo adduser "username" gobby

Next, you need to add the keys, data and export directories under the gobby home directory. If you set the directory permissions correctly you should not have to use sudo to create these directories.

mkdir /home/services/gobby/keys

mkdir /home/services/gobby/data

mkdir /home/services/gobby/export

Now it is time to create the Infinoted configuration file, infinoted.conf, in which you specify your desired settings. First, create the file using touch.

sudo touch /etc/xdg/infinoted.conf

Note: the configuration must be located in either /etc/xdg/ or $HOME/.config/ as infinoted looks for the configuration file in the following order.

  1. /etc/xdg/infinoted.conf
  2. $HOME/.config/infinoted.conf

You can use Nano, or your favorite Linux text editor to edit infinoted.conf. sudo nano /etc/xdg/infinoted.conf You should add the following to the file.

Note: you should set your own password, so don’t just blindly copy this.


After you save the configuration file, you should set its permissions. This step should be optional, but it is recommended if you encounter permission errors. sudo chown gobby:gobby /etc/xdg/infinoted.conf sudo chmod 550 /etc/xdg/infinoted.conf Now you can generate the certificate and key files and test Infinoted. infinoted --create-certificate --create-key If everything worked correctly, you should see this:

Infinoted Generate Cert and Key
Infinoted Generate Cert and Key


Once you see the output above, close Infinoted with crtl-c. To run Infinoted on startup, need to create a systemd startup script. Note: this only applies if you are running Debian version 8 or Ubuntu version 15.04 or later. If you are using an earlier version, you will have to improvise with Upstart or init (obsolete). Create a file called /etc/systemd/system/infinoted.service which should contain the following:
Description=Infinoted Daemon
UMask=007 ExecStart=/usr/bin/infinoted &
Restart=on-failure # Configures the time to wait before service is stopped forcefully.

Now start the service using systemctl start infinoted and to verify the service is running, use systemctl status infinoted. If Infinoted is running correctly you should see this:

Systemd Infinoted Running
Systemd Infinoted Running


Finally, enable Infinoted to startup on boot. systemctl enable infinoted

References: Gobby project website

Redis Caching WordPresss on CentOS 7

Caching WordPress with Nginx and Redis is quite simple if you are using Ubuntu, as you can just follow this tutorial, but what if you want to use CentOS, or even better, want to automate the setup using Ansible?

First of all, you will need to install the EPEL and REMI repositories and of course, Redis.

You will need to have the following Nginx modules installed. srcache-nginx-module, HttpRedisModule, redis2-nginx-module, set-misc-nginx-module Fortunately, there is a third party Nginx distribution called OpenResty that comes with all of the required modules. You can either build it from source or install it from their repository. Even better, you can install it using Ansible.

If you wish to install it from source using Ansible, here are the tasks.

The template used for generating the build script.

Or if you wish to use a pre-built binary from a repository, you can use these tasks.

Now, of course, you will need to configure OpenResty and Systemd, so here are example configuration files that you can modify to your liking.

Systemd service file

Here is a link to the nginx.conf I use for this website.

Note: If you wish to use a vhost, you can modify this and use it as a sitename.conf
Here is a link to the default.conf am using for this website. Yes, CloudFlare accepts self-signed connections from servers. I know it is not a pretty solution, but Let’s Encrypt does not work behind reverse proxy servers or in firewalled local development environments.

Now, you will have to install the php71-php-pecl-redis package and configure the connection to the Redis server so it can cache PHP sessions.
As a reference, here are the tasks I use to install and configure PHP for this website.

Now, if everything works, you will be able to ssh into the server and run redis-cli and then monitor and see this whenever a page is requested.

redis-cli monitor output
redis-cli monitor output

Using Golang to Generate Custom Cover Letters

Writing a cover letter for every application is quite cumbersome. So why not automate the process? That is why I wrote a simple Go application to help with the process. The logic is quite simple as all you have to do is fill out a templated Latex .tex file and then compile it. If you want to go even further, the process for generating a custom cover Email is almost the same. Instead of using a templated out .tex file, you just use a templated out .html file.

For this tutorial, I recommend using the popular Moderncv Classic LaTex template. If you wish to use this LateX template for your resume as well, I recommend moving the cover letter and CV / resume sections in main.tex to seperate files. To do so, you can use the \include LateX command. StackExchange: When should I use \input vs. \include?

Here is an example of a templated out cover letter .tex file

First, you take in the arguments, that are dependent on the position, as command line flags. Read this tutorial on building a simple CLI tool.

Using the provided arguments, you can generate default statements.

You might also want to get the current date. Read Date and time formatting in Go.

The user specified and generated values are then passed into a map which is used to fill in the templated out .tex file.

You then read the templated out text file and when a key attribute in the map is found in the templated out file, you replace it with it’s corresponding value attribute.

Now you want to save the string to a new .tex file.

If you wish to just send a cover Email, you do not have to write to a new file as the string can serve as the body of the Email. As already stated, you should use a templated .html file to generate cover Emails.

Now to build the .pdf file, you will have to call an external command to run pdflatex. Read this tutorial on running shelled out commands in Golang.

If you are an over achiever and would like to be able to automatically send generated cover Emails, the gomail library makes this easy. Read the gomail README.

If you would like to keep track of where you sent your applications out, you can simply write to a log file. I recommend writing to a CSV based log file as they import easily into Microsoft Excel and LibreOffice Calc.

You can also pass an “application” object by reference instead of passing variables by value.

You can find my full implementation with sample template files in this git repository.

Brute Force Login Attacks

This simple site as well as others like it, attract more attacks than actual visitors. Just last night this site had a very friendly visitor from the Ukraine that tried to brute force the login page to the admin dashboard. See update: What surprised me was the fact that CloudFlare did not detect this attach even though the security settings for the login page were set to high. As a result, I have enabled rate limiting and configured Google based two-factor authentication for the login page. In addition to the attack on the login page, I also noticed a handful of attacks, that were also from Ukraine, targeting various WordPress plugins.

SSH brute force attacks are also a common occurrence as you can see from this log file. What is interesting is the fact that the attacks often come from two or more hosts from different countries at the same time, often times from residential Internet connections.


I received an Email from CloudFlare informing me that rate limiting through CloudFlare needs to be configured for specific pages. Hey, somebody actually visited my site!

Taking Care of Fellow Team Members

Throughout my educational career, I have gone above and beyond to provide my team members with the best resources I could acquire. I have done so to make group projects quite enjoyable.

One thing  I provided to multiple groups I have worked with was a Gobby / Infinoted server to enable Google Docs like pair programming.  At first I hosted the server on an old desktop machine I had laying around, then I started hosting it on Digital Ocean, followed by AWS for a brief period of time. Everyone who used the Gobby client and server  really liked it. If you would like to set up an Infinoted server, you can now use Docker to get on up and running in just a few minutes.

I also set up git repositories for version control which made collaboration even easier. In order to get my team members familiar with git, I recommended they use GitHub’s easy to use GitHub Desktop client. One reference I recommended was this simple to follow guide which covers the basics of git.

Now unfortunately, not everyone has the best, or even adequate resources to complete a task. There was one group member I had for advanced databases who was still running Windows Vista in the Fall of 2016. With Vista’s end of support date being in the following spring, most developers had already abandoned support for the aged operating system and as a result, my partner was not able to run many modern applications like Visio or Office. In order to help him, I first had him use TeamViewer to remotely access my laptop while we worked on documents together. After that I had him try to download Windows 7 from MSDNAA / DreamSpark / Microsoft Imagine, but low and behold, the client you had to use to download Windows 7 from  Microsoft Imagine would not run on Vista. In order to work around that, I downloaded Windows 7 on my machine and then uploaded the ISO file to a shared SkyDrive / OneDrive folder.

Considering the fact that the computer he was working on was from 2006, I asked him if he had a spare machine he could use in case his PC failed. Unfortunately he did not, so I had him take an old desktop that I had available home. Now ironically, his old PC ended up failing a few days later. I spend quite a bit of time helping my partner with technical problems, however since I was able to understand the situation he was in, I did my best to help him and did not complain to the professor teaching the class.