Sabbatical Update II

Month Two

Last month when I posted my Sabbatical Update I talked a bit about my 4 goals and where I was. I thought I’d do the same update, because it’s easy to reuse the post. ๐Ÿ™‚


Last month around this time I had not yet started on the fitness goal, I totally blame both being busy and some profound laziness. But this month I have defeated laziness and settled into a fitness routine. I got a personal trainer with the goal of weight loss and muscle gain. It’s way different than CrossFit or HITT. It’s really focused on lifting heavy and isolating muscles, eating and rest. Yikes, eating. I eat 6 times a day, measured out healthy food and I am still not used to eating so much. Chicken, rice, potatoes, beef, veggies, etc. This is very different than any training I have done in the past, but I have to admit, despite the constant being sore, I really love it.

II. Level Up!

I have put HTB and THM on hold as I concentrate on getting the eJPT certification. It’s slow going, but I am making progress.

III. Leadership Skills

Still working on this through personal development, books and such. Not much to update on here.

IV. Rest

I am resting, but it’s a busy rest. I have taken my kids camping, done some road trips and enjoyed a lot of down time.

Sabbatical Update

Month One

My paid three months off started October 1st. Sadly my plans are not going as well as I had hoped. I have four goals I’d like to accomplish by the end of my Sabbatical in January of 2022. Goals I think are good. Maybe?

  1. Regain my pre-Covid fitness level.
  2. Level up on Python and build proficiency in Cybersecurity by spending several hours a day on HackTheBox, TryHackMe, and BugBounty. Ending in December with a eJPT certification and at least one bug bounty complete. I have wanted to advance in these areas for a long time, but just have not had the time. I enjoy this stuff so much. I am working on my Linux systems 100% of the time again, and I have really missed that.
  3. Improve my leadership skills.
  4. Rest.


It’s been three weeks and my fitness goal has no progress. I am having trouble finding where to land. CrossFit again? HITT? Boxing? Heavy lifting? I just don’t know! I am forcing myself to do something by the end of this week and give whatever it is a few weeks at least, even if I hate it.

Level Up

This is the one area I am really making progress in. In three weeks I have learned so, so much. I am in the top 4% on TryHackMe, and I have almost completed the Pentester track on HackTheBox and the Bug Bounty track on HackTheBox Academy. I am also about 1/2 way through a Python book. So pretty solid here. I am spending about 4-6 hours a day on this goal.

Leadership Skills

This is a difficult one. Not just to accomplish, but to gauge progress on. I started on this about a year ago. I have some hard things that need doing, and it’s very exhausting to be honest. Career coaching and counseling play a big part in figuring this out. My mantra is simple. “I can’t lead others if I can’t lead myself”. So I am working on leading myself right now.


This one, I am pretty much just failing hard at. For good reason though. I am a dad. I am dad to many teens. I spend so, so much time driving kids to school, appointments, and events and such. Like it’s an insane amount of my time that goes to this stuff, not to mention just parenting and trying my best to love these kids and not burn out. The load is heavy, but it’s worth carrying, so I do. There is no sleeping in, there is no getting to bed early. I am still burning the candle at both ends, and it’s thankless work that frankly yields very little rewards in the now. It’s a long game I am playing and I hope that when it’s time for these kids to be adults, that they are good ones. I’ll rest when I am dead, right? Seriously though, I am trying to figure out how to build in rest. I do go for coffee after I drop off kids, and sometimes I go to a park and breath in the fall air, when it’s not filled with smoke and dust … because … Fresno.

I really did need this though. I am so thankful for where I work. A Sabbatical is one of the many, many amazing perks I enjoy working at Automattic (VIP). You might think about joining me, we are hiring.

TIL: Injection

Today I Learned:

I studied for over 10 hours today! I learned quite a bit, as well as a lot of review. One of the most fun things I learned at HackTheBox was this:

Using Burp Suite and the repeater (as one method, you could also use cURL, etc.) you can send the following:


Along with changing the content type to:


to attempt injection. It won’t work on most web servers because of the brackets, but if a REST API is active, it may work, effectively turning the request into JSON:

{ "username" : "admin", "password" : {"$ge":"0"} }

This won’t work every time as it really depends on the code, but it was something very cool to learn.

Today I also learned about Xmind and Obsidian. Check them out, they are pre



PART II โ€“ Deploying NGINX (And A Service)

In Part I we built the hardware and installed K3s on our Raspberry Pi cluster. Now we are going to deploy some pods and a service.

The first thing we are going to do is deploy 12 NGINX servers across our cluster. We do this with a manifest file that we deploy on the master node.

Manifest: Specification of a Kubernetes API object in JSON or YAML format. A manifest specifies the desired state of an object that Kubernetes will maintain when you apply the manifest. Each configuration file can contain multiple manifests.

K8s Documentation

You can snag the two yaml files that we are going to be using from my GitHub repo here.

Log into the master node and create a file named nginx.yaml file with the following contents.

apiVersion: apps/v1
kind: Deployment
  name: nginx
  namespace: default
  replicas: 12
      app: nginx
        app: nginx
      - name: nginx
        image: nginx:stable
        imagePullPolicy: Always
        - containerPort: 80
        name: web

Some of what we are doing with this manifest file is defining our App nginx, how many replicas we want, 12 as well as the port, 80 and where we want to grab our nginx image from. With this line: image: nginx:stable we are going to go out and download the stable nginx image from You can view this here:

This is a super high level view of what is going on. The K8s documentation is excellent, so if you want to dive deeper, you can.

Now that we have our manifest file ready, we can deploy it!

kubectl apply -f nginx.yaml

deployment.apps/nginx created

That’s it! Now we can view the pods with the following command.

kubectl get pods -o wide
nginx-57d876fbcb-4gxkr   1/1     Running   9          16d   rpi2   <none>           <none>
nginx-57d876fbcb-zcfbw   1/1     Running   9          16d   rpi2   <none>           <none>
nginx-57d876fbcb-c8sth   1/1     Running   9          16d   rpi2   <none>           <none>
nginx-57d876fbcb-482nt   1/1     Running   9          16d   rpi4   <none>           <none>
nginx-57d876fbcb-6s2sv   1/1     Running   10         16d   rpi1   <none>           <none>
nginx-57d876fbcb-qv8bg   1/1     Running   10         16d   rpi1   <none>           <none>
nginx-57d876fbcb-lh6dn   1/1     Running   10         16d   rpi1   <none>           <none>
nginx-57d876fbcb-5tkbj   1/1     Running   9          16d   rpi4   <none>           <none>
nginx-57d876fbcb-vgcdj   1/1     Running   11         16d   rpi5   <none>           <none>
nginx-57d876fbcb-529lw   1/1     Running   11         16d   rpi5   <none>           <none>
nginx-57d876fbcb-v99r6   1/1     Running   11         16d   rpi5   <none>           <none>
nginx-57d876fbcb-v62jk   1/1     Running   9          16d   rpi4   <none>           <none>

Magic. Right? K3s is powerful and super easy to use. Trying to get K8s working on bare metal is a bear of a task, K3s definitely make it easier.

We are not done yet. Now we need to be able to access these notes. Notice above that the IP address are not on our subnet. For example These are cluster IP’s and they are only available within the cluster. So what we need to do is expose our app to the rest of the network. To do that we are going to use a service. I would stop right now and go read this. It will be worth understanding what a service is.

On the master node, create a file named nodeport.yaml with the following contents.

apiVersion: v1
kind: Service
  name: nginx-nodeport
  namespace: default
  type: NodePort
    app: nginx
    - name: web
      port: 8080
      targetPort: 80
      nodePort: 31234

Basically we are going to port forward the external port 321234 to port 80 on our web server. Now let’s deploy!

kubectl apply -f nodeport.yaml

deployment.apps/nginx-nodeport created

To see if it really worked you can run the following command.

kubectl get services
NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          
kubernetes       ClusterIP       <none>        443/TCP          
nginx-nodeport   NodePort   <none>        8080:31234/TCP   

Now for the real test. Visit a node with the 31234 port in a browser. For example: You should see the default nginx page.


When I first ran through the tutorial, so much was just not working. This was due to a few things. First, between the author publishing the tutorial video and my attempt, a major release happened. Lots changed. As well, the manifest files just were not working. Not sure why that is, but they were not. So I scrapped those and built them from scratch using the documentation.

The biggest issue was the nodeport. I could not for the life of me reach the web server on my network. If you run into this as well, hopefully the following will be helpful.

I was getting a connection refused. I have been in IT long enough to know that message means I am actively being denied. It’s not a 404 or a random config error. Something is blocking me. See below.

$ curl
curl: (7) Failed to connect to port 31234: Connection refused

So I took a peak at the firewall, and the last line explained it.

Chain KUBE-SERVICES (2 references)
target     prot opt source               destination
REJECT     tcp  --  anywhere           /* default/nginx-nodeport:web has no endpoints */ tcp dpt:http reject-with icmp-port-unreachable

What! Why! I read through the docs and the life saving articles over at stack overflow and pieced together that when K8s is misconfigured, it adds that line to the firewall. It’s protection. So it was a misconfiguration after all. Where?

Something was up with the naming of the port. Calling it web was failing. I saw this in the error log. So I swapped “web” with the actual port, 80 and that did the trick.

One of the cool commands I used to track this down was describe.

kubectl describe svc nginx-nodeport
Name:                     nginx-nodeport
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
Port:                     web  80/TCP
TargetPort:               web/TCP
NodePort:                 web  31234/TCP
Endpoints:                <none>
Session Affinity:         None
External Traffic Policy:  Cluster

I asked for 12 replicas, so I should see 12 endpoints. But there were none listed. Hmmmmm. Turns out, you create a nodeport with no endpoints, because you are me and you are new to K3s, that the firewall is going to be modified. After my fix, the same command shows me my 12 endpoints. Endpoints:,, + 9

kubectl describe svc nginx-nodeport
Name:                     nginx-nodeport
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
Port:                     web  8080/TCP
TargetPort:               80/TCP
NodePort:                 web  31234/TCP
Endpoints:      ,, + 9 more...
Session Affinity:         None
External Traffic Policy:  Cluster

And now I can reach the page from my network.

<!DOCTYPE html>
<title>Welcome to nginx!</title>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href=""></a>.<br/>
Commercial support is available at
<a href=""></a>.</p>

<p><em>Thank you for using nginx.</em></p>

Raspberry Pi Cluster running K3s – Part I

Let’s build a cluster and run Kubernetes!

Part I – Building The Cluster & Installing Kubernetes

I was doing some cybersecurity research on YouTube one day when I came across a somewhat related video where a guy built an 8 node Raspberry Pi cluster and got it to run Kubernetes, or K8s as it’s widely know. Well actually this is running K3s, which is basically K8s.

I was hooked and decided to give it a try. So I purchased everything I needed to run 8 Raspberry Pi 4 8GB nodes in a cluster. It was a lot of fun to do, and by fun I mean I ran into so many roadblocks and challenges. In fact, I am still stuck at one spot, waiting on Rancher or someone in the Rancher community to lend me a hand. Their install script to install the Rancher GUI, it’s not working.

I decided to document what I did because the video leaves out quite a bit. Some of the config files just don’t work, and I am not able to locate any of the documentation the author of the video, Chuck, mentions several times in the video. Rather I got to know the Rancher docs very well. Which is a good thing. I reached out to Chuck about the documentation, but he has not responded. I imagine my email is just one of many, many emails that he may eventually get to.

I’ll start with what I purchased and where. Then I’ll go into the setup and provide some working yaml files. My hope is that you will be able to follow this guide step by step and in the end have a Raspberry Pi cluster running Kubernetes. How cool is that? On bare metal. And you don’t need 8, that’s super overkill, in fact you can technically do this with just one node, but two makes more sense. A single node can act as both the master and a worker node.

Grocery List

This is list of suggestions for what to get. You will need at a minimum, a Raspberry Pi, power and networking. This is what I purchased to get things going for an 8 node cluster.

Getting Started

The first thing we will need to do is get our first node online. These steps will apply for each node you have in your cluster. We are going to install Raspberry Pi OS Lite which you will download when imaging the memory card. To do this you will use the Raspberry Pi Imager.

Ready for some steps? Here we go.

  1. Take a memory card and put that into the provided adapter and mount that on your computer.
  2. Use the imager to install the OS, it will be in the Operating System menu under Raspberry Pi OS Other.
  3. Unmount the memory card and insert it into the Raspberry Pi. Power the RPI on and let it boot up. This is headless, so you will need to let it go for about 60 seconds. Once it’s booted it will create a directory of files. We are going to edit some of those.
  4. Power off the RPI and remove the card. Mount that card on your computer once again and navigate to mount and the files. On a Mac that’s going to be /Volumes/boot/.
  5. Edit config.txt and at the bottom of the file add arm_64bit=1.
  6. Edit cmdline.txt and add cgroup_memory=1 cgroup_enable=memory ip= The values that will change from node to node is the IP and the hostname. So in this example, would change on the next node and rpimaster would change as that’s the hostname.
  7. Lastly, you need to create an empty file named ssh. On a Mac that’s as simple as touch ssh.
  8. That’s it. Now you can unmount the card, put it back in the RPI and power it on. After a few minutes you should be able ssh to the node.ssh pi@ The password will be raspberry. Wohoo! You are now sitting on your RPI. Repeat this step for as many times as you have nodes.

Installing K3s

  1. This next step needs to be run on each node, this will give us the correct iptables rules for K3s. First run sudo iptables -F bin/iptables-legacy then sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy and lastly run sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
  2. Now it’s time to install K3s. On the master node, run this command. curl -sfL | K3S_KUBECONFIG_MODE="644" sh -s - and sit back and watch it go.

Now you can run a simple command to see if it worked.

`root@rpimaster:/home/pi# kubectl get nodesNAME        
STATUS  ROLES                  AGE  VERSION
rpimaster  Ready    control-plane,master  21s  v1.21.4+k3s1

Looking good. This master node is the control-plane,master.

Now it’s time to register the rest of the nodes. To do this we are going to tell each node about the master node using a token.

root@rpimaster:/home/pi# cat /var/lib/rancher/k3s/server/node-tokenK10f07158496cafcbd96f225afb04c391d385d967d8009a954dc334afa0aebffaa5::server:332bebecd5a2ba35f9914e75a05bf14f

Now on each node (you will ssh in to each one) run this command.

curl -sfL | K3S_TOKEN="K10f07158496cafcbd96f225afb04c391d385d967d8009a954dc334afa0aebffaa5::server:332bebecd5a2ba35f9914e75a05bf14f" K3S_URL="" K3S_NODE_NAME="rpi1" sh -

The only value you will change from node to node is the K3S_NODE_NAME="rpi1" value.

And that’s it! To see our nodes, run kubectl get nodes. You should see the following output.

pi@rpimaster:~ $ kubectl get nodes
rpimaster Ready control-plane,master 12d v1.21.4+k3s1
rpi7 Ready 11d v1.21.4+k3s1
rpi2 Ready 11d v1.21.4+k3s1
rpi6 Ready 11d v1.21.4+k3s1
rpi5 Ready 11d v1.21.4+k3s1
rpi1 Ready 11d v1.21.4+k3s1
rpi4 Ready 11d v1.21.4+k3s1
rpi3 Ready 11d v1.21.4+k3s1

We are running Kubernetes on bare metal. ๐Ÿ™‚

Next up, we will be deploying NGINX across our nodes. Continue on to Part II!

Some Automattic Perks

Four perks I love at Automattic

Today as I was watching one of my favorite Twitch streams I had a deep sense of thankfulness for all the perks that my company offers. A guest speaker was talking about Toastmasters, and that made me suddenly remember that I want to join my local chapter, but also that I was first introduced to that concept when I was preparing to present at a WordCamp.

Here is a list of some of the things I am taking advantage of at Automattic. I am hoping these entice you to apply. You can see even more benefits of working at Automattic here.

  1. Coaching. I have had a career/life coach for the past year and that has been huge in my growth. I have really grown in my position and pretty soon here will take a logic and big next step. A huge part of my success has been my professional coach. Automattic contracts with some of the best coaches out there and I am very thankful.
  2. Reboot Leadership training. This was an intensive course that taught me a lot about leadership. I don’t think I ever would have taken this on my own. My team lead suggested this training and I am so glad I went through it.
  3. Hardware refreshes. Every 18 months I get a new computer. Sometimes it’s a Macbook, other times it’s a iMac. Just depends. My last update was my anniversary laptop. My Home office is pretty amazing.
  4. Never stop learning. All books and courses and software that I use to learn and grow and carry out my day to day tasks are totally covered by Automattic.

Interested? Apply!

Update WordPress Via WP-CLI

Updating WordPress via the CLI is pretty easy.

First make sure you have wp-cli installed. I’ll use my Linode as an example.

# wget
--2021-08-02 03:09:12--
Resolving (,,, ...
Connecting to (||:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 6094557 (5.8M) [application/octet-stream]
Saving to: โ€˜wp-cli.pharโ€™

wp-cli.phar    100%[===========>]   5.81M  --.-KB/s    in 0.04s

2021-08-02 03:09:12 (140 MB/s) - โ€˜wp-cli.pharโ€™ saved [6094557/6094557]

# chmod +x wp-cli.phar

# sudo mv wp-cli.phar /usr/local/bin/wp

Then it’s as simple as this:

# /usr/local/bin/wp core update

Updating to version 5.8 (en_US)...
Downloading update from
Unpacking the update...
Cleaning up files...
File removed: wp-includes/css/dist/editor/editor-styles-rtl.css
File removed: wp-includes/css/dist/editor/editor-styles-rtl.min.css
File removed: wp-includes/css/dist/editor/editor-styles.css
File removed: wp-includes/css/dist/editor/editor-styles.min.css
4 files cleaned up.
Success: WordPress updated successfully.

Adafruit Clue Projects

One of my team mates at work started a project group for within my team to experiment with a Clue. This thing is so cool! The idea is to try project together as a group. So far there are 5 of us and I imagine it will grow even larger as word spreads.

My Clue arrived today, along with a Wio Terminal which I plan to try several projects with as well. I’ll post updates as they come, including the projects we tackle. Stay Tuned!

Wio Terminal Network Analyzer

What better way to get acquainted with the Wio Terminal than a project! I saw the Dual Band WiFi Analyzer with Wio Terminal example and decided to follow it. It was a pretty smooth and fun process.

You start by setting up the Wio Terminal software, then you update the Wireless Core RTL8720 firmware and install all related libraries.

python3 erase

python3 flash

Then you install the Arduino_GFX Library. But that’s not as easy as the tutorial says. I kept getting a failure and missing files messages. I figured it was just some missing libraries, it’s like trying to install RPMs 10 years ago and solving dependencies. ๐Ÿ™‚ This was a life saver. All the libraries you need to make it work. Make sure you Arduino IDE "Sketch" Menu -> "Include Library" -> "Add.ZIP Library" -> select downloaded ZIP file for each library.

For reference that’s these repos:

Seeed_Arduino_rpcWiFi 26 – master branch
Seeed_Arduino_rpcUnified 16 – master branch
Seeed_Arduino_mbedtls 31 – dev branch
Seeed_Arduino_FS 14 – master branch
Seeed_Arduino_SFUD 12 – master branch

After those are installed, upload and it’s done!

Updates to the home office – Work with me!

I work for a great company. One of the many perks that I and my co-workers enjoy is a regular hardware refresh. That along with a paid three-month sabbatical encouraged every five years, home office, career coaching, time off (open vacation policy) and more! I am sharing so you come and work with me!

So it was time for a hardware refresh this month, and it was also time to pick out my four-year anniversary laptop. Though it’s been well over 5 years, I decided to go for it.

I took this opportunity to overhaul everything! Every 5 years we also get a new monitor, and I was more than happy to get a new one. I am ditching my two monitor setup for a single monitor that’s ultra-wide. Since I am no longer using an iMac I needed to find a webcam, and I have wanted to upgrade from the Yeti microphone to something a little better, since I also do some home recording.

I am very happy with the results. I’ll list the upgrades I chose below and after a few months I think I might review them. Photos of the office are coming soon!

I am thankful for where I work and very blessed to have such a great working environment at home. You might consider applying at Automattic, we are hiring!

Here is the updated office!

  1. Macbook Pro (M1) “W” laptop as a gift after 5 years at Automattic
  2. SAMSUNG G9 monitor. Sent the G9 back. Way too many issues. In it’s place is the Dell Ultrasharp 43 4K USB-C Monitor โ€“ U4320Q. It’s huge!
  3. OWC 14-Port Thunderbolt 3 Dock 
  4. Razer Kiyo Pro Webcam
  5. MOTU M2 2×2 USB-C Audio Interface
  6. Shure MV7 Podcast Microphone with boom
  7. beyerdynamic DT 770 Pro headphones
  8. BENQ Computer Monitor Light ScreenBar
  9. A Few Sound Control Lights

I kept my uplift standing desk, keyboard and mouse, as well as the Polk Audio speakers, subwoofer and Denon receiver that I really, really love.