Github Repos
swift, viper, rxswift

[github repo link]


[github repo link]

[github repo link]

My apps
iOS App Store

Philly Bike Dock


Tuckerton Pool
Unity3D C#

Jack's Gauntlet

Amoratis 7

Mac App Store

Tuckerton Pool
Unity3D C#

Play Store

Jack's Gauntlet

I created the custom Bootstrap WordPress theme this site is using.
Download or fork on GitHub

CHMOD Converter

I made this CHMOD WordPress widget.
Get it at

Kielbasa Geo Support

Right now, Kielbasa Geo is a new app and we are not aware of any issues or problems. If we ever become aware of them, this space is here to include details, tips, and resources for helping Kielbasa Geo Support users to get the most out of their use of Kielbasa Geo Support.

If you would like to ask a question, please contact jack – AT – . As a free app, support cannot be guaranteed for Kielbasa Geo Support, but I will do my best to help with any questions.

Date Posted: July 13, 2024

iOS Bluetooth Curtains

This video shows how I connected a motor to a set of curtains. I controlled it with an Arduino and some relay switches. Then I attached a Bluetooth transceiver and made a Bluetooth powered iOS app to control the curtains wirelessly. Watch.

Technologies used:
– iOS (with SwiftUI)
– Bluetooth
– Arduino

Date Posted: May 11, 2020

I have written a machine learning app

Apple has posted some new machine learning models on its dev site and I have created an app based on these models. The idea of the app is to help somebody to make a list of things by pointing their camera at objects. This could be used by someone taking inventory. In college, I worked at a retail job selling jewelry. At the end of each day, we painstakingly counted all of the diamonds by hand. It would have saved time if we could have walked around and let iOS do the counting for us. This is not a new area. People have been attempting this with various technologies for many years. I think as computers get smarter and Apple provides better API’s, this becomes increasingly viable.

Date Posted: December 25, 2018

My Latest Homebrew Project: KnowItCall

Date Posted: July 20, 2018

Does the world need another pool video game?

I have a made a portfolio of apps that demonstrate my experience with different technologies. In this post, I tell the story of building a billiards game.

Something wonderful happened on Sunday, May 14, 2017. Mother’s Day. A day that will go down in history, at least for me. I visited my parents for Mother’s Day. It had been a few months since I had last visited. I discovered that my father had become an addict. A pool addict. On his iPad.

My dad evangelized me with religious fervor to play the pool app he had discovered. He played that pool app every free moment he could, and he turned me into a convert as well. Dad insisted! Seeing how much my father enjoyed playing pool on his iPad inspired me to build a pool app of my own. I had recently released a spaceship video game, but I was trying to think of something that would be even more accessible to people, something everybody would instantly love. My father enlightened me that a pool game could be exactly what I was looking for.

A quick web search showed me that (more…)

Date Posted: September 18, 2017

The Concept of “Atomic” in Objective-C

We all live in a Swift world now, right? Well, usually. But for many tasks (such as unit testing, frameworks, cryptography, and so on), I still often find myself using Objective-C. I have a feeling that Objective-C is going to be with us for awhile. Some of the least understood concepts in Objective C are the way that elements of data encapsulation (ahem, such as variables) are designated with words such as: atomic, non-atomic, strong, and weak.

Sometimes in life, we just “know” how something works by the very act of using it repeatedly. These terms are like that. But if asked to articulate them, it can be a challenge. I like challenges, so I am going to write a few posts in which I articulate these concepts.

For this post, I will examine what “atomic” means. Here it comes:

Just like a stove having different burners so that multiple things can be cooking at the same time, it’s often helpful to have a computer processor do several things at once. This is known as threading. Every program has a main thread. Now imagine we write a program which downloads an image. If we download the image in the main thread, then everything else in the program will be frozen until the image is finished downloading. However, if we place the action of downloading the image into its own thread, then that can take place while we are using other features of the program.

Now suppose the main thread of our program can get and set a variable with a name for the image. Now imagine there is also a second thread that can set or get the same variable for image name. If we make the variable “atomic” then this will ensure that the entire name is set or retrieved.

This play by play will help to visualize what would happen WITHOUT it being atomic:

THREAD 1[Set variable to bob.jpg]
THREAD 1(Write b)
THREAD 1(Write o)
THREAD 2[Set variable to lucy.png]
THREAD 2(Write l)
THREAD 1(Write b)
THREAD 1(Write .)
THREAD 2(Write u)
THREAD 1(Write j)
THREAD 2(Write c)
THREAD 1(Write p)

… and so on. We end up with bolb.ujcpgy.png (which is some mix of “bob.jpg” and “lucy.jpg” because each thread was adding to the variable at the same time.) However, if we used “atomic” then there would be none of this intermixing. We could be assured the variable was either bob.jpg or lucy.png.

Thread 2’s request is forced to wait until “bob.jpg” is complete, and then it changes the value to “lucy.png” without interruption.

My source? The mother ship: “This means that the synthesized accessors ensure that a value is always fully retrieved by the getter method or fully set via the setter method, even if the accessors are called simultaneously from different threads.”

I have dealt with a somewhat similar issue in Unity3D while writing text one character at a time to the screen for a “typewriter effect.” In that case, a single label was being written to from a method that was called by a.) a timer and b.) a frame refresh. This doubling up resulted in repeating and mixed characters. For example, “the end” came out as “ttthheeee ennnnd.” For me, as I articulate the concept of “atomic” values, that Unity3D typewriter effect, served as a sort of slow motion dramatization of how setting data to a single resource (the label) from two callers can result in intermixed data over time. Atomic solves that issue for encapsulated data in Objective-C.

Date Posted: September 22, 2016

Aim High By Aiming Smart With MVP on iOS


“You have a gift for MVP” they tell me. Maybe so, but I don’t see it like that. What I see is that I have a concern to get things out the door. I have a big picture in my mind. I don’t picture zig zags. While I do leave room for surprises and discovery, I picture a long straight path, with an occasional curve possible if something is encountered that justifies adjustment.

I do the same thing with my apps. I have a full time job, I go to the gym, and occasionally I even sleep. So my personal app development happens in my free time slots such as on weekends, or on nights where I’m not feeling tired so I sit and program with a cup of coffee.

In that spirit, I usually put out an MVP, and then iterate with additional features as time allows. For example, the first version of my Objective-C iOS app Rhythasym had a very elemental interface that wasn’t very pretty, but it was highly functional (before.) A few months later, I made a version 2.0 of Rhythasym which was more slick (after.)

The first version of my Swift iOS app, Philly Bike Dock, contained a plain text list of bike docks in the Philadelphia area (before.) The new 2.0 version features informative new pie charts and fonts that help the user to prioritize information (after.)

In addition to the revamped interface, I added a few onboarding screens to the newest version of Philly Bike Dock and fixed a bug related to reloading information. Lastly, I added the ability for people outside of center city Philadelphia to simulate their location as though they were at Philadelphia’s City Hall. This would help them to see how the app works even if they were not around bike docks. This is helpful for tourists planning a trip to Philly.

Next time around, I will add crash monitoring and analytics. It is valuable and easy to add these things, but, for me, they ranked below basic functionality. I am also tinkering with some server side features which I will operate from my AWS Linux NodeJS server. My server will keep tabs on the status of the bike docks. Let’s picture the scenario of someone wanting a bike, but there are none available at their closest bike dock. Through Philly Bike Dock, they can have my server “watch” the station for them, and when a bike becomes available, my server will use a Parse backend to issue a notification.

I would have run the project aground if I tried to do all this out of the gate. Instead, I released an MVP app with some basic functionality, and I knew that later on I would keep adding more and more.

I first learned about MVP in one of my favorite books, Rules for Revolutionaries, by Guy Kawasaki. It contains a lot of proverbs for product development. My favorite one is “don’t worry, be crappy.” Crap is not meant to be our life’s goal, but sometimes to get a product out the door, we need to simply kick it out the door and iterate later. A nicer way of saying “don’t worry, be crappy” is to say “perfect is the enemy of begun.” It is only crap in the relative sense. It is crap compared to what you know it will someday be. But we would never turn out something we thought was legitimately subpar.

Just think of all the versions of operating systems which have been released. The job of building these things is never, ever done. If programmers had waited to build the “perfect” operating system before releasing it, we still wouldn’t have the first version because the programmers could actually work forever and always have one more thing they could improve.

So what we do instead is to pick a core set of functionality and get it out the door. Sound easy? It never is. Even getting that little set of functionality launched is inevitably filled with travails. If you ship an MVP, you will thank goodness you had the discipline to keep it limited in scope. You will have set the terms of victory by shrinking your challenge down to size, and then conquering that little challenge!

Visit my website at

Evolution Image credit:
Piotr Siedlecki

Download my apps on the iOS app store!

Date Posted: January 15, 2016

Unity C#: You Can LERP if You Want To

Imagine that you want to move an elevator platform from X1,Y1 to X2,Y2 on the screen in 1 second.

You might reason:

30 fps (frames per second)

1.0 seconds / 30 frames = .033 seconds per frame

100% of movement = 100% of 1 second

There is a 1:1 correlation.


.033 of movement = .033 of 1 second

Result: The box moves .033 of the distance between the cubes each frame. Cumulatively, all those .033 incremental moves will add up to 100% of the distance between X1, Y1 and X2,Y2.

This is a fine approach for something like a video where you can be sure that the frames will be played on time, every time. But for a live phone app where everything is being rendered and moving on the fly, the frame rate can change. If the iPhone has another app running a background task or if your app is doing a lot of things, then the frame rate could drop far below 30 fps. You might be okay with “approximately” two seconds for the square to move, but what if we change devices all together? A different model or generation of iPhone might only run 20 fps.

Because of these things, it is often best not to associate rate of movement with frame rate.

We need to associate the change in movement with the change in time. So when each new frame is shown, we need the delta of the time since the last frame was shown. The delta is the change in time from one frame to the next. We can use this time delta to set a pace for the linear interpolation of an object.

Linear Interpolation

(The following example assumes two ‘place marker’ gameobjects are already placed into the scene along with the platform to be moved. It is also envisioned that all of these are associated with the GameObject variables here in this sample script.)

using UnityEngine;
using System.Collections;

public class moveSphere : MonoBehaviour {

public GameObject startPlaceholderObject;
public GameObject stopPlaceholderObject;
private float startTime;

// Use this for initialization
void Start () {
startTime = Time.time;
gameObject.transform.position = startPlaceholderObject.transform.position;

// Update is called once per frame
void Update () {
float timeDiff = (Time.time - startTime);
timeDiff = timeDiff / 10.0f;
gameObject.transform.position = Vector3.Lerp(startPlaceholderObject.transform.position,stopPlaceholderObject.transform.position,timeDiff);

That’s it!  The Update() method runs every time a frame is shown. So each time a frame is shown, your program determines how long it has been since the last frame was shown. A calculation is made to determine how much of the final time that increment equals. Then it moves your object along the Vector3 path by that percentage.

Delta, Delta, give me the news!  I got a bad case of loving you.

Change of any changeable quantity, in mathematics and the sciences (more specifically, the difference operator[citation needed]); for example, in:
{y_2-y_1\over x_2-x_1} = {\Delta y \over \Delta x} ,
the average change of y per unit x (i.e. the change of y over the change of x). Delta is the initial letter of the Greek word διαφορά diaphorá, “difference”. (The small Latin letter d is used in much the same way for the notation of derivatives and differentials, which also describe change.)




Date Posted: December 12, 2015

What I Did to Update the Interface for Rhythasym 2.0

In the evenings, I enjoy relaxing by watching a movie, and if I’m still not sleepy I head out onto the porch with my laptop, light a bug candle, and tinker with some open source code. Over the past few months I ended up transforming the Rhythasym UI to a completely new version. Rhythasym is the iPhone app I made with Brian Sleeper, my friend who is a music teacher. To use it, you just move a slider to choose how fast all of the beats play.  By tapping note icons you choose how long each individual beat lasts.

The 1.0 version of Rhythasym was released as a minimum viable product. Here are some improvements for version 2:

  • Switched from using UITableView to UICollectionView to hold the notes. This was conducive to placing the notes horizontally instead of vertically. This was suggested by Brian and several others.
  • With the switch to UICollectionView I wanted to be able to drag and drop the notes to reorder them. I wasn’t very happy with the solutions I found in use already, so I wrote custom code to handle all of the drag reordering.
  • I gave the interface a custom designed feel. The 1.0 interface actually looks like a standard table view and standard, squared buttons. That is not always a bad thing. In some apps, it can be quite helpful because it gives the user cues for knowing how to use the elements based on their prior experience. But I decided that those native elements are most suited for listing text information, not music notes. So I switched Rhythasym to a stylized UICollectionView.
  • I was also able to eliminate ‘edit’ and ‘delete’ buttons by making a drag and drop interface for the notes.

Rhythasym 2.0 is better than 1.0, but it’s not done yet. Software is never done, and never perfect. I’m already out on the porch tinkering with a few refinements for the next version. 😉

Date Posted: May 31, 2015

Cocoa Pods Quick Overview

I know a few people who are taking their first steps into iOS development. Some have heard about Cocoapods but they don’t know how to use them. A quick overview of implementation is as follows:

Start by a full backup of your project files. Then you have nothing to worry about as you try something new because you always have a “way back.”

First we install Cocoa pods from the gem. On Mac OS X Yosemite:

sudo gem install cocoapods

Then we navigate into our project directory:

gem install pods

path to project
pod ‘name of pod’

Once we do this, we use XCode Workspaces instead of projects.

Sometimes things don’t work out so well when trying something new, so it’s always good to leave a trail that leads back to where you began so you can start over if you need to. Using version control is a great idea. Another possibility is to make a backup copy before you make any significant changes. Yet another possibility is to completely remove Cocoapods from your project.

This can be done by installing cocoapods-deintegrate:


gem install cocoapods-deintegrate

This is especially helpful if you are receiving errors such as:
Pods/Target Support Files/Pods/ No such file or directory

Date Posted: April 19, 2015

Amazon AWS IAM S3 – “access policy language”

I maintain my personal website,, on an AWS EC2 instance. A standard security measure is to transfer copies of server logs off of the server itself so that they could be studied later if the server were ever compromised. Being on AWS, I have set up an automated system that copies my logs into an S3 bucket. This involved establishing an S3 bucket and then composing a security access policy. I didn’t want to allow anyone in the world to upload content to my bucket. Also, in the event of an attack on my server, I wouldn’t want the attackers to be able to delete the logs. So I needed a one way solution that gives my server the power to upload logs, but not to delete them.

My main resource was Amazon’s guide to the syntax of writing access policies:

Grammar of the IAM Policy Language

A pre-requisite is that you have already set up a bucket and allowed “All authorized users” to access it.

Here is what I did:
1. Go to AWS management console
2. Select “Identity & Access Management
Access Control and Key Management”
3. Click on user -> Create new user
4. Enter username and click create
5. Download the credentials. It would be easy to overlook this step if you have not done this before. But it’s important because it’s the only time you will get your Secret Access Key (a long string of characters.) We’ll use these credentials later.
6. Select Policies from the menu on the left.
7. Up top, click Create Policy
8. Copy an AWS managed Policy
9. In the ‘Search Policies’ box, type in S3. You will see two results (at least at the time of this writing): AmazonS3FullAccess and AmazonS3ReadOnlyAccess
10. Select the first one (AmazonS3FullAccess)
11. Provide a new policy name (such as “AmazonS3PutOnlyAccess”)
12. Provide a description (such as “Policy for log uploads only.”)
13. In the “Policy Document” section, we see some JSON. This is where we need to do the customization that actually gives us an “upload only” policy. We see some JSON in the text box:
“Version”: “2012-10-17”,
“Statement”: [
“Effect”: “Allow”,
“Action”: “s3:*”,
“Resource”: “*”

Right now, Action contains s3:*. We could have many different kinds of actions, including some that deal with EC2 instances, others that deal with glacier storage, and so on. In this case, we’re addressing what actions can be done with S3. Right now there is an asterisk (*). We simply need to change that from “s3:*” to “s3:Put”

Taking a step back, we see that different possible s3 actions include: list, get, put, etc. An asterisk means that any of these are valid. But we are free to define one or more subsets (separated by commas if more than one.) In our case, we want to allow a single possible action, namely, to Put.

Now that we’ve created our policy…
– we need to go back to Users
– Select the user
– Scroll down to “Attach Policy”
– Use the searchbox to find our newly created policy
– Select the policy and attach it

Now we need an upload script. I modeled my own on this script. You will see at the top where you can include s3key and s3secret.

You can then place this script into one of your cron folders in /etc such as /etc/cron.weekly to have it regularly upload your logs. I actually have my script set to upload a tar copy of all my logs and then clear them off local.

Date Posted: February 25, 2015

Date Posted: December 24, 2014

I made an open source Objective-C app for iOS

Open source and free as in beer:

How it Came to Be

It is keenly important for native app coding ninjas to continuously hone their skills. This ninja hones his skills best by working on some kind of actual project, instead of just doing tutorials and examples. I decided to make an iOS metronome because it would reinforce my skills with views, playing audio, timed events, and math. A music teacher friend mentioned that some metronomes are variable. There is nothing new about this concept of a variable metronome, but not many apps do it so it would be a good challenge. My friend explained some music theory about metronomes, and I set about building the variable metronome app.

Making this app involved…

  • Delegates
  • Properties and methods
  • NSString, int, NSDouble, other data types
  • Timers
  • UITableView and other UI elements such as UIButton, UITextLabel
  • Data sources
  • UI triggering events, UI receiving output
  • Views

I also conducted a few early experiments with some other elements which I decided to leave out of the final program:

  • Sprites
  • SQLite DB
  • NSUserDefinedPrefs

Check out the source code for yourself. Do something cool with it!


This is a great follow up to tweet from last March:

Date Posted: December 21, 2014

Mesh Network Project Update

My buddy Patrick and I met this week at Philadelphia’s Innovation labs as part of the Code for Philly series. We added a pressure sensitive potentiometer to the project as a form of UI. A small step – which is fine because really this is a small project which will be done in about a month, even though we only devote a few hours per week to it. The beauty of this project is simply in the idea of executing on the idea to create an off the shelf resource for teachers who would like to teach their students about electronics.

More info at:

Date Posted: December 6, 2014

Mesh Networking Project

I’m working on a great mesh networking project with Patrick Woodburn. The details are here:

Date Posted: November 22, 2014

Writing A Simple WordPress Unit Test

When we unit test WordPress, the best approach is to use WP_UnitTestCase. This class extends the PHPUnit_Framework_TestCase with functions and properties which are specific to WordPress. The factory object demonstrates this. It handles many functions for you with a minimal amount of coding on your part. For example, if you desired to use factory to create a user, you would simply include the following line in your test:

$user_id = $this->factory->user->create();

So, when you need a user, a post, or some other “testable” thing upon which to work your testing ways, you can get it done quickly. This frees us to focus on writing tests rather than constructing methods to create scenarios.

Set Up

— Install WordPress onto your server

— Install my open source theme which you can get here

— Install my Amoratis CHMOD WordPress plugin which you can get here.

Now that you have WordPress with my theme and my plugin we are ready to begin. Once we launch our tests, we will – in the tests – configure a temporary WordPress install to use this theme and plugin.


Date Posted: September 27, 2014

How to Unit Test A WordPress Plugin

Two popular unit testing tools for WordPress are:

1.) The official WordPress unit test repository



For this article, I will be focusing on option 1, the official he official WordPress unit test repository that is provided by WordPress.

1: Get PHPUnit installed

2: Obtain the unit test repository

svn co wordpress-develop

Note: Yes, at this time WordPress at this time still makes heavy use of SVN.

Using SVN, you can place this repo anywhere on your server. Placing it in your home directory is fine. It does not have to be located in your WordPress website’s folder.

You can put the unit tests anywhere on your machine, and simply configure the tests with the path to your WordPress site.

The main components are:

a PHPUnit Installed globally
b WordPress test repo ~/
c Your WordPress site located anywhere


Let’s look more closely at b “WordPress test repo.” The following table shows what we find. The bold items are the ones we need to focus on for now.




A more detailed look at each item

The configuration file for your test. Remember, even though we are doing WordPress unit tests, these are PHPUnit tests.

This folder actually contains an entire WordPress installation.

The tests themselves. These tests cover every WordPress function under the sun (and possibly under the moon as well.) There are over 1,000 tests in here which can test an entire WordPress installation. But the goal of this tutorial is to test a WordPress plugin. We will not need most of these tests in order to accomplish that. So eventually, we will be coming up with a second test folder, just for that purpose. The tests in our second folder will be exclusively concentrated on the functions of our plugin rather than testing all of WordPress.

This is related to the included copy of WordPress.

This is an important file to us.


1. Create MySQL database and user

2. Copy wp-tests-config-sample.php to wp-tests-config.php

3. Editwp-tests-config.php to include your database username and password

4. Then run phpunit.

This is all it takes to run unit test. To run all tests, we enter:


You should hopefully see many dots forming, perhaps with a few S’s and E’s. Each dot represents a test. A flag of S or E indicates an issue which needs to be addressed.

Simply entering phpunit runs all of the tests. But to run a specific test, we enter:

phpunit /tests/nameOfSpecificTest.php
Date Posted: September 26, 2014

I am Grunt!

Grunt logo

Grunt Logo

It takes a combination of factors to keep things lean and mean so that our websites can load as fast as possible. There are many things we can do to help page performance including, but not limited to:

  • Using a Content Delivery Network (CDN)
  • Optimizing our images to the smallest possible file size
  • Loading JavaScripts at the end, just inside of the closing body tag
  • Combining multiple JavaScript and CSS files down into fewer files where possible
  • Shortening the text and removing extraneous linefeeds in our JavaScript files

Cumulatively, these can shave a few seconds off the page load time of large pages, and even smaller pages can become a bit snappier. Let’s examine that last item in the list which concerns optimizing our JavaScript files.

We can run our files through an optimizer that shrinks them down for us – but this is a time consuming process if we need to do it manually every time we make an adjustment. And then what? They are all shrunk down, and not very “human readable.” So we need to maintain an uncompressed copy somewhere, and then maybe work on that when we need to make changes – and then compress that original version down each time.

Computers have the power to automate the mundane, and to create processes that are streamlined for us. Grunt helps us to automate common tasks which we encounter during our JavaScript development.

I’ve just mentioned shrinking down the files into a more efficient form, but Grunt also handles automated testing, linting, and more. Grunt has a huge (and growing) collection of plugins which extend its power to ever more uses.

How to install Grunt?

1. Install npm (Node Package Manager)
2. Use npm to install Grunt

echo "testing 1 2 3";

//comments are here

$e = "that";


I’m happy to work on almost any Linux, on any server, hosted anywhere, but this page has a recurring theme of AWS Linux on an Amazon Linux AMI. In light of that I will make a special note that as of this writing, the default package manager for CentOS/RHEL (yum) does not contain a package for node. So we can use the instructions on this page to install Node, which Grunt requires:

First, we need EPEL:
EPEL 6: yum install \

EPEL 7: yum install \

Then install the nodejs and npm packages:

$ sudo yum install nodejs npm --enablerepo=epel

Need Some Global Installs
npm install -g grunt-init


And then there is project scaffolding…

Date Posted: September 1, 2014

Jenka Jenka Jenkins!

Let’s kick things off with this video…

Great video – but not much in there regarding PHP. That video is all about working with compiled projects. The focus of this post is using Jenkins for PHP projects.  ___ is another project which was Jenkins-ish… and it is cool, but if we’re going to take precious moments of life to learn something, it might as well be industry standard.

So let’s focus on Jenkins with PHP. Here’s a good primer:


Date Posted: August 24, 2014

GitHub Webhook Gotchas in AWS Linux

I often find myself mentoring people who are just getting involved with technology. Although I solve these kinds of issues in a few minutes these days, I still have empathy for novices who are struggling through these issues for the first time. In that spirit this post addresses a common issue: establishing a webhook which is triggered when code is pushed to a GitHub repo. My hope is that it will help someone encountering these issues for the firs time to solve their problem faster and hopefully to learn something in the process.

The issue described in this post will apply to various Linux distributions, although for me it occurred on an EC2 AWS Linux instance. I had created a repo on GitHub and then established a webhook. Therefore when I pushed code to one of my repos, GitHub would send an HTTP POST to my webhook’s URL. My webhook was a php file which triggered executed a shell command to do a git pull.

That’s it. Interestingly, I could run my webhook successfully from the terminal when I ssh’d into the server:

$ php -f webhook.php

It worked from the command line, but did not work from the web browser. One reason is that when I ran the file using PHP CLI, it was running under the permissions of my own account, but when I visited the script in my web browser it would be running by using the permissions of the apache user or group.

When I logged in via ssh, I worked under my own username. Let’s say it was jack The apache web server performs its actions as the apache user.

My file webhook.php was owned by jack and not apache. The permissions were set in a way that did not allow apache to run it. I changed the owner of the file to apache:apache and set the permissions to 755.

This was part of the solution, but more still had to be done. With a little bit of research I determined that the problem was most likely that the environmental PATH for the apache user probably did not include the path to the git bin.

I checked my own environmental path variable:

env | grep PATH


To get a glimpse of what was taking place, I changed the code to

echo shell_exec(“/usr/bin/git pull”);

In order to get some more information about what was happening, I enabled errors to be output to the web browser. I added some code to my webhook:

echo shell_exec(“/usr/bin/git pull 2>&1”);
fwrite(STDOUT, ‘foo’)

Now I received this error message output in my web browser:

Could not create directory ‘/var/www/.ssh’. Host key verification failed. fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.

The resolution: I simply needed to look in /var/www for .ssh folder in this case instead of ~/.ssh  The key is required in that location for the apache user to complete the pull.


This article was helpful Git Pull from a PHP Script Not So Simple

Date Posted: August 23, 2014

Which Linux Groups Does Your User belong to?

Sometimes you are in a directory which is owned by another user, and yet you would like permission to write files without using sudo. A good example would be when you want to run git to clone or update a repo. We should not be using sudo with git.

So here’s what we do. First, let’s find out which groups our user belongs to. If our username was ec2-hero, we would enter:

$ groups ec2-hero

Next we can do a little $ ls -lah magic in the terminal to see what groups our folder in question belongs to. Check it out:

Terminal listing of directories within wp-content directory

There is a user – but no group!

See that?  We should be seeing something like apache:apache for user and group… but all we see is apache. That is because when I was setting up this installation of apache, I installed WordPress and received a few errors when trying to fix the upload directory. So I changed the owner of the upload directory to apache so that the webserver could write to it.  I didn’t bother to add a group though!

Now here’s the interesting part. By rights the group should also be apache so that other services related to the web server in that group can run as well. So boom, I sprinkled in a little chmod and all was solved:

$ sudo chmod -R apache:apache wordpress

Done, right? WRONG!  Because now, here I was trying to run a git clone into my theme folder. Well, let’s think about this. The folder’s owner/group is apache:apache yet I was not logged in with the apache username and my current username was not in the apache group.

The answer? First, I had to join the apache group. This page contained some awesome info.

$ sudo usermod -a -G apache ec2-hero

(Where ec2-hero was my currently logged in user, and apache is the group I wanted to join. It is important to use the usermod command because both the user and group already existed. At first I tried using useradd [thinking that since I wanted to ‘add’ a user to a group, this would be helpful] but useradd is for creating a new user and it produces an error if you try to use it on a user that already exists.)

This brought me a step closer to success. And yet! I still could not pull a git into that directory. This is because the directory permissions were 755, which is what WP recommends for folders. In certain cases where files need to be written, they recommend more, such as the uploads folder. The case of the themes folder had to at least be elevated for the times when I wanted to do automated gitpulls during development. And so I changed the permissions of the directory to 775 instead. Voila! Everything worked great! I was (finally) able to complete my git clone.


How to fix this add a group!

$ chown

Date Posted:

Unable to Create Directory wp-content/uploads

Unable to create directory

Unable to create directory in WordPress

Having problems with WordPress upload directory. Wanted to just go in there and mkdir, change to 777 – but that’s not really solving the problem. Also not very secure.

I had installed WordPress on AWS Amazon Linux. I checked and found out what the directory and file permissions should be (source).

They state folders should be 755 and files should be 664 at most (666 maybe if using the WP editor, but then they should be changed back to 664.)

So I ran the following commands:

sudo find /path/to/my/files/wordpress -type d -exec chmod 755 {} +

sudo find /path/to/my/files/wordpress -type f -exec chmod 664 {} +

(With thanks to source)

I went back into WordPress and tried to upload the file again. But nope. Not working yet. I checked out the server and I saw that no uploads directory yet existed in wp-content.  I was going to make that directory, but then I decided against it. I would rather that WP be able to make the directory itself if it needed it.  So since the permissions were correct, I decided to run

ls -lah

to see the user of the files. Sure enough, all the files were created by nobody.  I decided that the problem must be that these files were not owned by the web server. Therefore, the solution was to change the ownership of all the files to the web server.

The first step was to find out what the username of my web server was. So I ran this command:

cat /etc/passwd

(Which I found here)

I saw many users including apache, mysql, mail, ftp, nobody and more. Clearly apache was my guy. So I went and recursively chowned the ownership of my wordpress directory to apache.

I used the info on this page (which is basically just a Linux manual page for chown) to accomplish this. I came up with:

sudo chown -R apache /path/to/my/files/wordpress

The result? SUCCESS!  I was immediately able to start uploading files.

Blue checkbox, successful picture upload

Blue checkbox, successfully uploaded picture


Date Posted: