Refining the design process

assorted-color abstract painting

What got me here won’t get me there

Since I was able to get my Substack post out on time yesterday, my focus has turned to my client’s WordPress project. I almost used the word “consulting” for a moment, but I am way too much involved in the design of the site to call it consulting at this point. And I’m having a hard time. Cause despite my familiarity with the tech stack involved in web hosting and CMS systems, my design skills really haven’t moved past the early days of the web.

Just look at this blog, for example, it’s focused on content, I’m still using a basic WordPress theme, and it’s got no color whatsoever. Part of that was intentional, so that I could focus on content generation and not get hung up on design presentation, but it’s hamstrung me. Part of my spiel whenever I talk to people about these project is about the separation of content and presentation. I tend to focus on content, structuring data, changing it. Design is not really my strong suit. It’s much more of a creative art that I’ve struggled with.

When I was in my twenties, I used to love to play around with Photoshop, making designs with filters and creating awesome images. I’m pretty good with typography as well. When it comes time to laying out text and images, and putting together a color scheme on a web page though, I just don’t know where to start. And therein lies my current problem.

The client came to me with a website that had been fully designed and rolled out between 2016 and 2018. It didn’t look like it was up to the design standards, even of that era. I can’t even put my finger on why I know that, but it just does. The site was broken. The first thing I saw when logging into the admin console was that it had a huge mess of plugins, and I couldn’t make heads or tails of it. I needed to figure out what was essential and what we could get rid of. And there were over twenty five hundred registered accounts in the system. Most of them looked like spam. Sigh.

I never ever ever make changes to a client site without testing it in a staging site, so that was the first order of business. I use Infinite WordPress to manage my sites, so the first thing I did was installed that plugin to connect it to my management console, then I started a backup. After we had that under control I cloned the existing site to staging and got to work. It was a mess. There was a lot of content on the site, over two hundred pages and posts, but the site used custom posts types and fields, and had some sort of content controls that were supposed to paywall the content and was just broken. I spent what must have been a week just trying to inventory the plugins to figure out which ones we could disable to speed things up.

The only other production change that I allowed myself was for analytics. I checked the console a couple of days later and found that the site was getting tons of hits. Apparently the blog content had been indexed by Google, and a lot of people were getting referred to it. Converting those hits into leads was now the priority. The site was still broken though. The navigation didn’t work, so most visitors were falling off. Furthermore, while checking the contact forms to see what emails were being used, I discovered that email for the domain wasn’t working. At all.

I was able to get the email up and running, but it took days to figure out where the problem was and to move the DNS records over to my reseller account. Delving into the theme itself, it appeared that the designer had just cloned the WordPress TwentySixteen theme and started editing it directly. I’m not sure if WordPress had child themes back then, but they had just dumped a bunch of custom PHP functions right after the existing ones, and the template codes were full of SQL queries into the custom fields, which didn’t jive with what the plugin documentation called for. I really didn’t want to spend however much time combing through this code to refactor it. So I recommended to the client that we start from scratch.

I’ve got an Envato account that I subscribe to, my process just involves finding a good theme that fits the tone of what I’m going for, throwing it up on the site, and swapping the boilerplate content with custom copy. And I don’t like writing copy for clients. Or, I should say I’ve avoided doing that in the past. It starts coming close to marketing, which I’ve had an aversion to. I’m working on overcoming that aversion, at least for myself and my projects, but doing that level of work for clients requires a level of intimacy with the project/product that I haven’t had the time for. I’d rather outsource it, and that’s just what I did with the last project that I was involved with.

I’m not going to take that route this time, we’re going to plow through this and get it done, come hell or high water.

One of the problems that I’ve found working through this project is that I tend to try and shape my content to fit the boilerplate in the themes I use. It isn’t working. My client gave me a document with the content that they wanted on the page, and my brain seized up looking at it, trying to figure out where to match it to fit. It’s not going to work. I’m going to spend some more time today going over it again to see if I can provide some structure to it, then I’ve got a work session with the client tomorrow to really try and break it down. I don’t think that we’re going to be able to do this part in WordPress directly. I may need some mind mapping tools or something else to make it work.

Pressing up against the limits of my abilities is going to take some work. We’ve got to bootstrap this site into production to get things moving. Maybe then we can engage a professional to help tune things.

For now, that’s me, designer, developer, editor, admin. While I have some downtime today, I’m going to do some research and see if I can find any other resources to help refine the process.

Not so lazy Sunday

No rest for the wicked.

So yesterday’s party was a hit, and we’ve been pretty productive for what should have been a lazy Sunday. Yesterday, I roasted a seven pound pork butt and made carnitas out of it, and also wound up making the birthday cake and frosting from scratch. Just call me “Daddy Crocker”. This morning everyone but the birthday girl slept in, and I’m writing this in the middle of the afternoon. I spent most of the day cleaning up the mess from yesterday, and making some changes to this website.

We’ve been getting lots of Google referral traffic for two posts, one for a WordPress hack, and another for an obscure Windows server error message that I wrote about. I’m getting enough of them that I figure I might test whether there’s any opportunity for clients, so I put a Boxzilla popup on the two pages containing a contact form. That was easy enough, but I ran into problems with my WordPress SMTP capabilities that required troubleshooting. I wound up switching to the Post SMTP plugin, since it’s free. So, any hits on the form should send me a notification SMS via my cell provider’s text message gateway.

Now, I wait.

I’ve got a lot to do today, so I’m going to wrap this up and continue working on my Substack, which I’m hoping to get out tomorrow. I’m also overdue on my WordPress project for my client, so hopefully I can manage to get both of those done before the day is over.

Private, internal blog for the family

girl wearing grey long-sleeved shirt using MacBook Pro on brown wooden table

Maintaining privacy for your kids by running a private WordPress instance in your home network

Well, I may have finally lost my mind. I quit Facebook over a year ago, but one of the things that I do miss is the throwback posts that they pop up on your feed with pictures and posts from one or five years ago. It’s great for those “oh look how little Elder is in that picture!” kinds of moments. I don’t feel comfortable sharing pictures of my kids on my normie feed anymore, but I still want to do more than just have a folder sitting on my computer somewhere that gets looked at once in a blue moon. Plus, Elder is getting more involved with using the computer, and I wanted to give her a chance to express her creativity without the risk of letting her have a YouTube account. So I did the only thing any sensible tech dad would do. I set up an internal WordPress site for the family to use.

Setting up internal domain

I’m pretty proficient with Windows domain controllers, and manage a lot of contoso.local domains that aren’t externally routable. I decided that I wanted to do this, so that the site could be accessed only from our local network. That way we could easily access it from any of our personal devices, and can potentially allow friends and family to look at it when they visit and join our network.

Bind is the go-to DNS server for Ubuntu, so I started by installing and configuring it. However I quickly got lost in a maze of .conf files and StackExchange posts trying to get it to work, so I dumped it and installed dnsmasq instead. Dnsmasq relies on simple host files instead of the more complicated zone files that bind uses, which is more than enough for what I need at the house.

I setup my /etc/dnsmasq.conf file as follows using this guide:

# Don't forward plain names or non-routed addresses
domain-needed
bogus-priv

# Use OpenDNS, not ISP's DNS router
server=208.67.222.222
server=208.67.220.220

# Replace second IP with your local interface
listen-address=127.0.0.1,192.168.1.123

expand-hosts
domain=dahifi.internal

Then I setup my /etc/hosts file with the records I need, pointing to the downstairs server and my development workstation.

27.0.0.1       localhost.localdomain   localhost
::1             localhost6.localdomain6 localhost6

192.168.1.123   dahifi.internal
192.168.1.123   homeboy.dahifi.internal   homeboy
192.168.1.102   oberyn.dahifi.internal    oberyn
192.168.1.123   elder.dahifi.internal   berkley

After saving changes, I need to restart dnsmasq: systemctl restart dnsmasq. From there I was able to validate the configuration on the server and external machines using nslookup. Once I was comfortable that things were working, I added my internal server’s IP to my router’s DHCP DNS scope and refreshing the client leases on a couple devices to make sure they would work.

Note about .local domains

I’ve never had issues with domains ending in .local among my Windows business networks, but Ubuntu may have a multicast DNS service called Avahi running, which hijacks anything FQDN ending in .local. Interestingly this service was missing off of the actual Ubuntu server install, which interfered with my troubleshooting. The simplest thing to do to get us up and running was just to change our internal domain from dahifi.local to dahifi.internal. Any other non-routable TLD should work as well.

Additionally, Ubuntu ships with resolved, a network name manager service. It runs a caching service at 127.0.0.53, and interfered with my troubleshooting as well. My internal domain kept getting routed to my ISP’s search page, until I ran sudo service systemd-resolved restart to clear the cache.

Multisite Docker setup using Nginx Proxy

The SSD Nodes site has a nice write up of how to run multiple websites with Docker and Nginx that I was able to use to get our WordPress site up and running. I prefer putting everything in a docker-compose file. The only prerequisite is creating the network:

docker network create nginx-proxy

docker-compose.yml:

version: "3"
services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro

networks:
  default:
    external:
      name: nginx-proxy

And a second file, blog-compose.yml for the blog itself:

version: "3"

services:
   db_node_blog:
     image: mysql:5.7
     command: --default-authentication-plugin=mysql_native_password
     volumes:
       - ./blog_db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: root_password
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress_user
       MYSQL_PASSWORD: wordpress_user
     container_name: blog_wp_db

   wordpress:
     depends_on:
       - db_node_blog
     image: wordpress:latest
     volumes:
       - ./blog_wp_data:/var/www/html
     expose:
       - 80
     restart: always
     environment:
       VIRTUAL_HOST: dahifi.internal
       WORDPRESS_DB_HOST: db_node_blog:3306
       WORDPRESS_DB_USER: wordpress_user
       WORDPRESS_DB_PASSWORD: wp_password
     container_name: blog_wp
volumes:
    blog_db_data:
    blog_wp_data:


networks:
  default:
    external:
      name: nginx-proxy

You’ll notice that the site that the blog is published to is identified by the VIRTUAL_HOST environment variable. In this case we’re still pointing to the “top level” domain, dahifi.internal, and not blog.dahifi.internal. This is due to issues we were having with subdomain resolution on the Nginx proxy, and is something we’ll have to work on later. Originally, we had our internal GitLab instance running on this host at port 80, and had to take it down for Nginx to work. My next step is to make sure that subhosts work properly, and then reconfigure GitLab and this blog to run under something like git.dahifi.internal.

Image uploads

One additional change that I needed to make was to change the default file size limit of 2M. Following along with this setup tutorial, I added - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini line to the WordPress container, then added the following to the uploads.ini file:

memory_limit = 64M
upload_max_filesize = 64M
post_max_size = 64M

Then I rebuilt the container with docker-compose down and up, making sure to specify my blog-compose.yml file.

I still encountered errors trying to upload. WordPress kept throwing

Unexpected response from the server. The file may have been uploaded successfully. Check in the Media Library or reload the page.

I couldn’t find any errors in WordPress’s Apache instance, and PHP looked fine. I eventually found a message in the Nginx container log: client intended to send too large body. It seems that Nginx has it’s own limits. I added client_max_body_size 64M this directly in the /etc/nginx/nginx.conf file, then reloaded it with service nginx reload. Problem solved! Not only can I upload files directly through the web interface, but I was also able to add the internal site to the WordPress app running on my phone, and can upload images directly from my phone.

Elder is already working on writing a story in it now, and I’m looking forward to using this site as an internal bulletin board for the family. Let’s see what happens!

Up before dawn

car on highway during golden hour

Getting it together, turning an inadvertent alarm into opportunity.

It is going to be a long day.

My Eldest, bless her heart, was using my iPad yesterday to film herself and her sister play with Legos, and afterward started playing with the stopwatch. She somehow wound up setting the alarm on my device for 4:35AM, so I got roused way early this morning. I tried to go back to sleep, but I think I woke myself up too much trying to disable the alarm. Que sera, here I am.

I must have spent at least eight hours working on the WordPress project yesterday. I can’t remember the last time I was that focused on anything for that long. A good half of that was trying to figure out why the header slider I was working on wouldn’t show up on the page I was creating. Turns out it was a sidebar setting. Lesson learned: WordPress’s page template hierarchy is quite complicated.

My internal GitLab server is already proving it’s worth, and has proved the need for some reengineering of the way things are currently laid out around here. I don’t have the development database fully under source control, so I was doing most of my work yesterday through a Google Remote Desktop session. And last night I was forced to edit images on Photoshop, check them into to version control, then import them into WordPress on the guest VM on the same machine, because I never properly setup guest to host file sharing and network communication. Well, I have a task for today.

Today’s Thursday, so tonight is the night I’m supposed to write tomorrow’s Substack. I’m having a bit of anxiety since I don’t really know what I’m going to write about. Maybe something about improving oneself during this time of self-isolation, with some mini-reviews of some of the books I’ve read recently? I hope I get a better idea before tonight. I haven’t checked my subscription stats since last week, so maybe I’ll see if anyone’s responded.

I am also expecting a delivery in sometime today. I ordered a new mesh wifi router, and am looking forward to setting that up. The wifi here has been garbage for a long time, and it is time for my old Netgear to go. I went all out and got an ASUS ZenWifi AC with all the bells and whistles, so we should be good to go. I just have to promise myself that I won’t set it up until after I finish my Substack, otherwise I’ll wind up distracting myself.

And I am going to start brewing beer! I made some preparations to use my Mr. Beer kit yesterday, and we should be good to start today. I also discovered that I did not need to order extra bottles, since the rest I needed were actually inside the brewing vat. Alas, now I’ll have some special ones I can use for gifts or something. The vat is assembled, the water is chilling in the fridge, and we’ll be ready to do this one with the kids as a project for today.

I must say that removing Twitter off of my phone may turn out to be another one of those life-changing steps, like when I dumped Facebook. I took a look at it yesterday after posting the blog for the day, and then looked at it once briefly during the day. I didn’t even feel the urge to pull it up during the evening, so focused I was on working on the WordPress project. My phone has turned into this strange, useless device now. I pick it up and look at it out of habit, but nothing on it has the same draw that flipping open Twitter and scrolling through it. Certainly not LinkedIn, that’s for sure.

And it has been several days since I filled out a job application. I’ve been somewhat discouraged by the requirements of some of the positions that I’ve been looking at, and my lack of experience in certain areas. For example, Twilio had a whole slew of postings up over the area recently, and there were several that I thought I would be a good fit for. One of the application questions asked “give an example of something you built using Twilio”. Ummm…. well, I put an Airtable base together that used Zapier to blast text messages during one of my campaigns, but I don’t think that’s quite what they’re looking for. I’m probably selling myself short.

I think the problem is two-fold. One, finding out from Boss that my future with Zombie, LLC was mostly secure for the near term, and that I’m not in any danger of losing my job. That has definitely reduced the sense of urgency. But secondly, I’m really so focused on finishing this damn WordPress project that I don’t want to risk abandoning it. It sound stupid really, that I’m holding back on finding that $100,000 job because I think it might take me away from this project that might lead to recurrent income.

Well, now I have my orders for the day: fill out that application for Twilio; write tomorrow’s Substack; and reconfigure my development VM so I can see it on my local network. That’s on top of doing whatever’s on my list for Zombie, and taking care of the kids and house today.

I’d better get started.

Git-ing it done

black green and blue coated wires

Roll your own GitLab

I had trouble falling asleep last night, Younger crawled in our bed just as I was dozing off and kept squirming as I was falling asleep, so I slept in her bed. It faces East, so I woke up at five and tried to go back to sleep. I heard Elder up, so I got up and started the day. She’s sitting across the room from me, looking up “Valentine’s Day” gifts ideas for the boy in our quarantine bubble down the street. Her sister has been ribbing her about it for days now.

One of our Zombie, LLC clients wants help standing up an internal GitLab server. It got me thinking, so I went ahead and set up a GitLab docker instance on my downstairs Ubuntu server. I figure it’s good practice. Do the job you want has always been good practice, so setting it up was worth the time. Plus it only took about fifteen minutes. The main problem I ran into was an SSH conflict with the existing service on the host. And it doesn’t appear that modifying the config on an existing container requires stopping the Docker daemon, so I just deleted the container and started over. I’ll probably move SSH if I ever do a real deployment, but here at the house the HTTP functionality is enough.

There’s also the mail issue. I didn’t want to use the root account to setup my repos, but the workflow around new accounts wants to send an activation email. I tried installing sendmail on the host, but the password reset didn’t work. I doubt it will work without a publicly routable dynamic DNS entry back to it or SMTP services, which I don’t want to mess with right now. Thankfully I found a password change form in the admin interface that didn’t require knowing the old password and got up and running.

I am nowhere near as strong with my Linux management skills as I am with Windows, where everything is pre-packaged and is somewhat unified. I can stand up domain.local services lickety split, and have a library of PowerShell scripts to setup AD, DNS, DHCP services within a domain. I have never actually taken the time to set one up at home though, but that point may soon be approaching. I’ve been wanting to investigate the use of Ubuntu server as an alternative or supplement to Windows based AD services, but part of me is skeptical that such a setup is even viable for workstation authentication and services. But I digress. The point I’m trying to make here is that I’ve always been in awe of Unix sysadmins ever since I worked at an internet service provider back in the late 90’s and watched our systems guy pop in and out of terminal shells like a wizard. I’ve never felt adequate in that regard.

I made some good progress yesterday working on the WordPress project, and have started converting the client’s site over to the new theme. I’m going over the demo site, examining the Bakery build they’ve got set up, and recreating it using the client’s assets. This allows me to get a bit more familiar with the framework that the theme author is using, and hopefully gleam some best practices at the same time. It’s a two step forward, one step back process. There are some strange bugs that popped up. Activating Woocommerce seems to bring the site down completely, as does changing the theme back to the original. Then at one point, while I was working on the new header, the previews stopped working completely and would only throw 404 errors. They work in the actual site, so I had to make do while I made edits.

Usual best practices for WordPress development and git repos are to exclude the entire WordPress directory except for whatever theme and custom plugin that you’re developing, but since in this case we’re working on an entire site, I’ve added the entire WordPress directory and associated SQL database files. The wp-content/uploads directory is mounted outside the container, along with plugins and themes. I haven’t yet pulled this directory on another machine yet, so I don’t know if it’s going to work. My main concern is how I’m grabbing the database. Managing PostgreSQL during my Django projects has always been a bit of a pain as I never learned how to incorporate it into my source control. I’ll have to spend some time correcting this deficiency.

Here is a look at the Docker Compose file I am using for my development setup. The SQL mount /docker-entrypoint-initdb.d/backup_to_load.sql get’s imported when the container is created; I assume that it’s ignored when pulling the SQL data from source. We shall soon find out. Also, I haven’t solved the file permissions issues that happen when trying to edit things like the wp-config.php file. I’ll have to save that for a later time.

version: '3.8'
services:

  wordpress:
    container_name: 'local-wordpress'
    depends_on:
      - db
    image: 'wordpress:latest'
    ports:
      - '80:80'
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress_user
      WORDPRESS_DB_PASSWORD: wordpress_password
      WORDPRESS_DB_NAME: wordpress_db
    volumes:
      - "./Wordpress:/var/www/html"
      - "./plugins:/var/www/html/wp-content/plugins"
      - "./themes:/var/www/html/wp-content/themes"
      - "./uploads:/var/www/html/wp-content/uploads"

  db:
    container_name: 'local-wordpress-db'
    image: 'mysql:5.7'
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - './data/mysql:/var/lib/mysql'
      - './data/localhost.sql:/docker-entrypoint-initdb.d/backup_to_load.sql'
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress_db
      MYSQL_USER: wordpress_user
      MYSQL_PASSWORD: wordpress_password

  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080

Phishers step up their game

man standing on building rooftop during nigh time

This attack is not new, but the tactics are evolving, and some people are still behind the curve

I’ve been managing business networks for some time, and I’ve witnessed phishing attacks, where attackers attempt to steal a victim’s email login information, evolve the last few years. Yesterday I was alerted to a new variation on this traditional attack that I thought was worth sharing and dissecting, as you’ll see why.

Almost all of the attacks that I’ve seen stem from an email that a victim receives. Usually it’s someone that the victim has corresponded with in the past. The subject line and body vary, but there’s usually an external link where the victim is directed to in order to download some secure file. Normally, the victim arrives at a page that looks like a Google or Microsoft landing page, but of course they’re a fake, setup to steal the victim’s credentials.

If the phishers are successful, they’ll have gained access not only to the victim’s mailbox, but also any associated document storage systems like Google Drive, or Microsoft OneDrive or SharePoint. From there it’s all over, the attackers can download whatever they need, or if they discover that they’ve infiltrated a high value target, they might lurk, and prepare additional attacks.

In one particular case that I was involved in a few years ago, attackers managed to phish the CEO of a company. They discovered that they were going to be travelling from the East coast to the West, and waited until they were thirty thousand feet in the air to launch a fake CEO attack, requesting that their finance director wire tens of thousands of dollars to the perpetrators bank account as soon as possible. In this case, there were enough red flags that the attack was thwarted, but not before the attackers had used the CEOs mailbox to resend the phishing attack to everyone in their contact history.

And so the cycle repeats.

How not to be a victim

Normally, there are numerous red flags when phishing attempts happen, but it still surprises me the number of requests I get from people asking me to inspect an email for legitimacy.

Sometimes it’s as easy as examining the email recipient, or the actual link in the email, and finding that they don’t match. If Jane Doe’s corporate email is jdoe@corp.com, and you see your email client only displays “Jane Doe“, you might need to hover your mouse over it to see that the email is really from a different address altogether. (Hover over the link above to see what I’m talking about.) Most modern email clients have updated the way they display emails, making sure that the actual address is “Jane Doe <jdoe@corp.com>” or something similar.

However, there are still a number of businesses that haven’t taken precautions to protect their own email systems from being spoofed. That’s to say, there may not be anything stopping from someone from setting up a rogue email server and sending an email from anyone at that company. There are several methods to protect from this, known as SPF, DKIM and DMARC, that protect from this happening, so you may want to make sure that your domains are protected.

The flag that I look for is where the link is pointing. Just like email addresses, these URLs can be spoofed. Modern rich-text or HTML mail clients which allow special formatting can be used to try and trick users with links that misdirect users to hacked sites. So always check the URL. That official looking login page for your Office365 account might just be a fake sitting behind someone’s hacked WordPress site. CHECK. THE. URL.

These tips alone should prevent most people from falling victim to one of these attacks. If I’ve been drawn into investigating at this point, I usually go a step further and try to get the fake landing page taken down. Sometimes it’s easy to find the company who’s site has been hijacked, and usually a courtesy call is enough for me to consider my good deed done for the day. Sometimes the site is set up by the hackers themselves. A ten dollar web domain with a three dollar hosting account, paired with a free WordPress template is enough to start with. In these latter cases, I have to do a bit more work to find where the domain is registered and where the site is hosted. Then, an email to the company’s abuse department, and I’m done.

How you can stop it

And in almost every case that I’ve seen, it’s been a WordPress site that has been hosting the fake landing page. As it’s the software behind more than a third of all websites on the internet, it’s not surprising. But if you’ve got a business website running on WordPress and you’re not maintaining it or paying someone to manage it for you, then not only are you exposing yourself, your firm, and your clients to hacks, but you’re also partially responsible for any victims that fall prey through your site. Update your site, at least quarterly, or purchase a product or hire a firm that can check it on a regular basis for you.

How Chrome marked the site with the fake landing page. Firefox has no such warning.

Making sure email the security protocols mentioned earlier, (SPF, DKIM and DMARC) are enabled on your domains will prevent hackers from faking your domain and using it in an attack.

Using updated email software and security applications are also an effective way to mitigate these attacks. Make sure that your email client software is a recent version, or use a cloud-based one to make sure that you have access to the latest anti-phishing tools. And make sure you use them! It still astonishes me how many small firms haven’t enabled two factor authentication for their employees, or even looked at the protection services that are available from their email providers.

And one of the most important things you can do is train your staff how not to fall victim to these attacks. There are a number of firms that can deploy phishing attempts against your staff, and provide training to those who fail to avoid it.

Attackers upping their game

What concerned me with the attack I witnessed was the way that the attackers changed their tactics to evade some of the more advanced mitigation techniques that are in place to stop these cybercrimes. A number of enterprise level email security services have the ability to filter out these malicious links and block them from the recipient. They usually rely on some sort of whitelist or blacklist to allow certain domains through. In the case this week, the victim was sent to Live.com, which is Microsoft’s ID portal for Outlook.com and OneDrive accounts. To the casual observer, it looked like a legitimate OneNote notebook, and there was no breach at this point. No doubt most organization administrators would have no problem with users going there.

Of course within this OneNote page was the real trap, a link to the fake landing page. Thankfully the mark in this case, noting that the OneNote page was addressed from a person different than the original email, was suspicious enough not to fall for it. That said, when I was alerted to it and took a look at the OneNote page without the context of the original email, my initial thought was that it was legit. I almost cleared it! A second read turned up some irregular grammar, which is when I noticed the external link and the O365 landing page. Even then I still had to look up the domain registration on the site, two months earlier using an Asian registrar, before I was convinced it wasn’t some sort of Single Sign On configuration.


Technology changes fast, and cybersecurity is a cat and mouse game between attackers and the security professionals that protect your personal and business assets from these dangerous breaches. If you need help with managing your infrastructure or mitigation strategy against these attempts, let’s discuss it. Whether it’s email and network infrastructure, securing your website, or doing mock infiltration testing or employee training. I can help.

Baby slaps

person's left hand wrapped by tape measure

Inch by inch, life’s a cinch

Well I sure did step up my game. I guess I was anxious about writing a big long post for today’s Substack post, so I wrote it last night. Someone put out a message on the company Slack yesterday about a suspicious email, and I almost fell for it. I figured it warranted an exposition, so I spent an hour or so last night writing it up, after everyone went to bed. The experience writing at night, undisturbed, is quite different from my morning writing, when the kids are getting up and wandering in the room every five minutes. I’m not sure I like having a deadline every night like that though, so we’ll keep it limited to Thursday nights. I think I’ll even put it on my calendar just to keep it routine. Done.

I didn’t make any progress on my WordPress client last night, instead, I’ve started reading through the Docker documentation so that I can figure out what the hell I’m doing with my setups. I know a couple commands; it feels like I’m an infant failing my limbs trying to grab a rattle but I keep hitting myself in the head instead. I don’t understand half of the stuff I’m reading when I look at some of the image notes in Docker Hub, and trying to read through some of the discussions on GitHub issues is even worse. So I’m just reading through the best practices documentation to try and get a sense of how things run between Dockerfiles and Docker Compose, so that I can load a SQL backup automatically, add access my PHP files in both my development environment and in the container’s web services.

And the Docker documentation is pretty interesting. It’s scattered with little goodies like links to Twelve-Factor Apps, and here documents, which is something I didn’t even know about. And if there’s one place I need to step up, it’s my bash skills.

Anyways, I get to keep this post short since today’s a double post day. I thought about writing something for an off day, but figured the ritual of writing morning pages was more important than taking a day off. I’m starting to gather ideas faster, and my writing output has stepped up quite a bit. So I’m going to wrap it up, make some changes to today’s big post before I blast it out to several hundred unknowing Substack subscribers.

Now, time to go grab that rattle by the horns.

Morning pages

Yesterday I spent most of my time trying to migrate a production WordPress site to my development environment. Normally, I’ve used Infinite WordPress’s site migration tools to move them, which does the trick of moving all the files and updating the database references to the site URL, but I don’t think it works when the site’s not public. I’m doing a lot of hacks with my Docker setup, importing databases, messing with file permissions, and duplicating a lot of my work since I like to sit downstairs at my desk during the day, and upstairs at night. So part of my challenge is trying to find a setup that works well for me.

I might have to make some sacrifices. JetBrains IDEs don’t like to work over the network, so I’ve got to add a directory sync if I want to keep the files on my network server and work from both workstations. At least I can run Docker from the remote machine, but it’s not supported by the IDE, so I’ll have to figure out how to fit that into my workflow.

The girls were good. Elder did everything I asked her, and got her extra screen time. She did Typing, piano, and two sessions of math in Khan’s, and we managed to keep the house tidy. So that’s a big parenting win. She’s already up and on her laptop right now, ostensibly doing typing, but I don’t hear too much of it going on over there. Maybe she’s doing math.

We had a bit of excitement yesterday when bitcoin went on a little bit of a tear. I noticed it shot up to touch ten thousand and got excited. Elder came over and said “it went UP,” excitedly. We watched the fight for a few minutes, before it dumped, and then went on a bike ride.

I moved my entire Ethereum stash over to BlockFi. There’s always a moment of horror after publishing a large transaction to the blockchain when the doubt sets in. Wondering whether the address was copied correctly or if my opsec failed and some hacker changed the receiving address while it was in my clipboard. Did I check the address. I usually do a small test transaction before sending over the big one, but it still makes me nervous. Especially after reading about the mining firm that said someone sent a $144 Eth transaction with $131 million in gas fees.

So now I have a fair chunk of my assets up on BlockFi. I haven’t touched but a fraction of my BTC; it’s just too much risk for me to do that. I’ve got a roughly even spit on there between BTC, ETH, and USD stablecoins, and I’m considering whether to put more USD there. I’ve still got the girl’s BTC accounts, but I don’t want to mix them with mine, and I’m not yet sure if I can open an account in their name or if I’ll have to do like I did for lending club and make multiple ones in my name.

Due to the coronavirus, the IRS is allowing 2019 IRA contributions up until July 1. I’m considering whether I want to do this, or throw some more cash into BlockFi. My IRA is on fire right now, I calculated 70% realized gains off of this market rally, and my unrealized gains for the year are much higher than when I calculated them a couple of weeks ago. I’ve still got active value average positions that are in play, and I’m probably going to be short on cash before they complete, so I need some powder. I just doing know whether I should sell some of my other positions, or put more cash into play. All of my current plays are under risk-adjusted position sizes, but my long term holdings are just sitting without any stops on them. With everyone going crazy on RobinHood these days, I should probably put some protections in place in case there’s another lockdown related pullback.

Yesterday, a client’s laptop failed, and I’m waiting on a vendor to go out there and swap a motherboard or something. The drive is encrypted, and while I’m certain I have the keys, I felt a shot of adrenaline course through my body when I remembered that I neglected to reinstall a backup program on her machine after replacing it. So I know what I’m doing today. What I don’t know is what I’m posting tomorrow for my newsletter. This post has been the type of rambling morning pages post that’s of no use to anyone but myself, and which is not the type of quality content that I want to be sending out to my LinkedIn network, or to the email list which I just salvaged from an old CSV file.

I’m going to let that one mull in my head today, and let it stew.

What is work?

two white rabbits

Down one rabbit hole after the other

I spent most of yesterday really digging into WordPress in a way that I really haven’t before: theme files. My current project has a customized version of the Twenty Seventeen theme, with lots of custom templates, fields, and functions that I need to move over to a new template. It’s taken me weeks to finally understand what the previous developer was doing, and there’s a fatal bug in the system somewhere that is deleting post data that I’m trying to uncover so I can clean things up. I figure my best course of action is to migrate everything to a staging site, start with a new theme, and start going through the plugins one by one to rebuild the content on the site. There are multiple pages and types of posts with custom fields that need to be displayed properly. I’m not really looking forward to having to debug someone else’s stylesheets, though.

Doing this kind of development isn’t ideal even on a staging site, given that the WordPress native code editor isn’t really suited to real work. I haven’t done PHP work in over ten years, but I downloaded PHPStorm and got started setting up a development environment. I was hoping to setup some sort of Git workflow for the site, but I didn’t find any options that were production ready, so I grabbed the files via FTP and quickly set to work.

WordPress has an official Docker image, so I set about configuring a Compse file for my local environment. There I ran into problems. I was trying to map my theme directory to the container’s, but I ran into issues with file permissions. I haven’t quite figured it out. I can change the permissions within the container to allow the container to use the files, but then they’re locked on my development host. So that’s my challenge for today, and one that will no doubt lead down many more rabbit holes.

This is just an example of the kind of stuff I do, that most people call work. Now this doesn’t have anything to do with my regular day job responsibilities, it’s for a client. And even if it wasn’t, it’s still the same type of activity that I would be doing for fun anyways. Although if you asked my wife if she thought I was having fun last night, she would have said that all the cursing and muttering I was doing under my breath would indicate otherwise. This particular project is a challenge for me because it involved a level of technical expertise that I don’t have, that I am forced to pick up in order to understand the issue — and hopefully solve it! It’s this area, right outside my current capabilities, that puts me in the zone and makes time fly.

It’s a drive that has gotten me where I am today, and has served me very well. Unfortunatley, it’s not something I find in my current day job, and is one of the main reasons why I’m looking else where these days. Part of the problem is the fact that the company constantly hovers on the edge of sustainabily and closure, but I have trouble reconciling that situation with my responsibility for it. Perhaps it’s that I don’t have any stake in the company, other than my current minimum viable salary. It’s allowed me to pursue other projects, including school and political activities, but has not offered anything for me in the way of growth in several years. I am not in sync with my boss in the way of the direction of the company or even the type of customers that we take on. The challenges are rote, and therefore not interesting to me. And they haven ‘t changed in years. Neither has my salary.

I’ve started reading Designing Your Life, by Bill Burnett and Dave Evans, and one of the first exercises that they ask readers to write a workfview reflection, defining how work relates to their life, money and others. This is my response to that, of course. Work has such a broad meaning to me. It’s not just your job, it’s also the things you do for your family and friends, chores around the house or the yard, spending time with family, and yes, helping your dad or whoever with their laptop from time to time. And one thing my dad taught me, that I’m trying to impress upon my girls, is that when there’s work to be done you just have to suck it up and do it.

Work is rewarding also, and can be fun. That’s not to say it can’t be repetitive or stressful,, the most panic-inducing heart attack moments I’ve had have been related to failures at work. But I’ve helped a lot of people, and it’s often fulfilling. That’s not to say that I haven’t had horrible, dirty jobs that I had to take because I was unemployed and living on couches, but most of them have been knowledge work, and pretty chill. These days it pays the bills, but it’s the work I do outside of work that is where I continue to learn and grow.

Hopefully my girls will be as lucky as I am, and be able to make a living doing what they love. Actually, it’s not luck, it’s by design. Obviously I am not where I want to be right now. Sure, my work life is probably better than ninety percent of the world’s population right now, and I have no room to complain about anything, but it’s it the human condition to want more, to want to be more? And to me, that’s what work is, the drive to improve, to become better. Constant improvement. Refine, iterate, repeat, repeat, repeat.

Leave it better than you found it

blue plastic trash bins on forest during daytime

Taking over abandoned or mismanaged projects

Taking over a project is a much different beast than starting from scratch. I think everyone knows that it’s easier starting from a blank slate most of the time. What separates the amateurs from the professionals though is the documentation that they leave for those that come after. Most of my recent work I’ve been the solo technical resource on a small team, and coming into a new project is often a mess, and trying to decipher someone else’s work without any form of documentation is a challenge. I make sure not to leave it that way.

I’ve been doing small business networks for well over a decade, and taking on a new client almost always starts with a network assessment, inventorying the equipment, and running some kind of network or system scanning tool to catch what else we might have caught and put it into a report. Internally, we’ve been using ITGlue to keep track of all our documentation, and it really comes in handy when handing off a client. In the past, taking over an account from another IT management firm has involved sitting down for an interview with the technical resources on the other team, making lots of notes, and then rebuilding the documentation in our system. And it usually involves some sort of roughly drawn up document with passwords and other critical information.

Lately, it seems we’ve been sending off runbooks left and right, containing all the documentation, checklists and SOPs that we’ve developed for a client. I remember the first time we handed off one to another firm, seeing the surprise in their eyes when we handed over a professional, looking document. It made a real good impression, and I almost considered jumping ship with them. That was over a year again, and here I am, finding myself going through the same situation again.

My recent consultation work has mostly involved taking over a stable of WordPress sites. I’ve been using WordPress for years for this blog and others, but I’ve usually kept things very simple. Just download a nice theme, and start writing. The sites I’ve been taking on recently are much more complicated. There’s usually two or three dozen plugins deployed, and some sort of complicated theme system in place that has some particular arcane way of adding a page or making changes to a header or footer.

Since my focus here is just about writing, I intentionally decided not to spend any time on presentation. I’m literally still using the default Twenty Seventeen theme that came with WordPress out of the box. I’ve looked at some premium themes for it to give it some zazz, but ultimately decided that the effort wasn’t a priority for me. Not so with the other projects. I’ve been using an Envato Elements subscription to source my themes and templates, but each one seems to carry it’s own set of required plugins and design methodology. Figuring out how to tweak them is its own challenge.

I recently took over a site for a client. It was mostly in good shape, but had been neglected for several years. I wanted to make some changes to it, but without understanding how everything was put together, it’s proven difficult. On top of that the original designer used a modified version of one of the default WordPress templates, so the choice was to start delving into the source code or start building from scratch. And again, there were about forty plugins being used, and I’m yet unaware of a simple way to trace an elment in a rendered WordPress site to its source. Plugins will often add elements to the Dashboard UI, or the document editor, and figuring out what goes with what is a slog.

So far, the choice for me has usually been to tear it all down and start from scratch. Cloning production to a staging site and deactivating all the plugins, to see what we’ve got, content wise, is usually the first step. Then I can all the pages and posts to see which elements are missing from the original site. “There’s a shortcode for a slideshow plugin, so let’s note that and re-enable that.” “Why is half of our content missing?” It’s because they used some post taxonomy plugin to put certain content in a separate blog. And so on and so on.

There’s one thing I picked up in the last year or so, called Architectural Design Records, or ADRs. It’s basically a decision making artifact that details the reasoning behind taking a particular design approach to something. They’re closely tied to user stories, and can be placed right in a Git repo with the rest of the source code. I’ve been trying to carry some of the ideas behind ADRs into my own projects, and not just software ones. It’s a good practice for any sort of system design, whether that is technical, business, or personal. Leaving these little artifacts behind for future you or for others seems that it can be a valuable practice, and will come in handy when the time come to tweak something months or years down the line. “Why on Earth did we decide to do x again? Oh yeah, here’s the ADR…”

I am defintely not a WordPress ninja. As the old saw goes, “the more you learn, the more you realize that you don’t know anything.” Give or take. Managing a web host reseller account and using a dedicated tool to keep WordPress installations and their related plugins up to date is simple enough, but taking over these sites and trying to redesign them with an eye toward user design, ecommerce and SEO is a completely different set of skills than I had hoped to working on. And I don’t know how far I want to develop it. Most likely I’ll be doing what I can to salvage the projects I’m working on and get them to the state where it can start generating some revenue, then I’ll start bringing in other resources to hand off tasks to. And when I do, I’ll have supporting documentation to hand off to them so that they can quickly get up to speed, a history of how things operate and why they were setup the way they are.