tutorial

How to focus stack a set of images in Photoshop

I recently rented a Nikon 105mm VR Macro lens for a weekend, and wanted to experiment with different types of macro photography.

One of the things I was most interested in was focus stacking. See, there's a problem with macro photography in that you're dealing with a depth of field measured in millimeters when reproducing images at a 1:1 ratio, even stopped down to f/8 or f/11. And, wanting to avoid diffraction at higher apertures, there's no way to take a straight-out-of-camera picture of a 3D object that's sharp from front to back.

One frequent subject of my close-up photography is the Raspberry Pi single board computer. You can see the problem when taking just one photo:

How to upgrade the SSD hard drive in a Dell XPS 13 (9360)

June 6, 2018 Update: I've also posted a video of the SSD replacement process, embedded below:

I recently purchased a used Dell XPS 13 (model 9360), and I chose to purchase the base option (with 128 GB SSD) since it was cheaper to do that and upgrade the SSD to a larger model (500 GB) aftermarket than to buy a higher model XPS (I bought this model: WD Blue 3D NAND 500GB PC SSD).

Reboot and wait for reboot to complete in Ansible playbook

September 2018 Update: Ansible 2.7 (to be released around October 2018) will include a new reboot module, which makes reboots a heck of a lot simpler (whether managing Windows, Mac, or Linux!):

- name: Reboot the server and wait for it to come back up.
  reboot:

That's it! Much easier than the older technique I used in Ansible < 2.7!

One pattern I often need to implement in my Ansible playbooks is "configure-reboot-configure", where you change some setting that requires a reboot to take effect, and you have to wait for the reboot to take place before continuing on with the rest of the playbook run.

For example, on my Raspberry Pi Dramble project, before installing Docker and Kubernetes, I need to make sure the Raspberry Pi's /boot/cmdline.txt file contains a couple cgroup features so Kubernetes runs correctly. But after adding these options, I also have to reboot the Pi.

Converting a non-Composer Drupal codebase to use Composer

A question which I see quite often in response to posts like A modern way to build and develop Drupal 8 sites, using Composer is: "I want to start using Composer... but my current Drupal 8 site wasn't built with Composer. Is there an easy way to convert my codebase to use Composer?"

Convert a tarball Drupal codebase to a Composer Drupal codebase

Unfortunately, the answer to that is a little complicated. The problem is the switch to managing your codebase with Composer is an all-or-nothing affair... there's no middle ground where you can manage a couple modules with Composer, and core with Drush, and something else with manual downloads. (Well, technically this is possible, but it would be immensely painful and error-prone, so don't try it!).

Use Ansible's YAML callback plugin for a better CLI experience

Ansible is a great tool for automating IT workflows, and I use it to manage hundreds of servers and cloud services on a daily basis. One of my small annoyances with Ansible, though, is it's default CLI output—whenever there's a command that fails, or a command or task that succeeds and dumps a bunch of output to the CLI, the default visible output is not very human-friendly.

For example, in a Django installation example from chapter 3 of my book Ansible for DevOps, there's an ad-hoc command to install Django on a number of CentOS app servers using Ansible's yum module. Here's how it looks in the terminal when you run that task the first time, using Ansible's default display options, and there's a failure:

Ansible 2.5 default callback plugin

...it's not quickly digestible—and this is one of the shorter error messages I've seen!

Re-partitioning and reinstalling a newer version of Fedora on my laptop

Fedora 26 Installer - Installing software progress bar

I wanted to document this process on my blog, since it's the second time I've had to do it, and it always takes me way longer to figure it out than it should... basically, here's how you can take a laptop with a hard disk that's running an older version of Fedora (in my case, Fedora 23), use the Fedora install media to re-partition the drive, then install a newer version of Fedora (in my case, Fedora 26):

Quick way to check if you're in AWS in an Ansible playbook

For many of my AWS-specific Ansible playbooks, I need to have some operations (e.g. AWS inspector agent, or special information lookups) run when the playbook is run inside AWS, but not run if it's being run on a local test VM or in my CI environment.

In the past, I would set up a global playbook variable like aws_environment: False, and set it manually to True when running the playbook against live AWS EC2 instances. But managing vars like aws_environment can get tiresome because if you forget to set it to the correct value, a playbook run can fail.

So instead, I'm now using the existence of AWS' internal instance metadata URL as a check for whether the playbook is being run inside AWS:

Reverse-proxying a SOAP API accessed via PHP's SoapClient

I'm documenting this here, just because it's something I imagine I might have to do again someday... and when I do, I want to save myself hours of pain and misdirection.

A client had an old SOAP web service that used IP address whitelisting to authenticate/allow requests. The new PHP infrastructure was built using Docker containers and auto-scaling AWS instances. Because of this, we had a problem: a request could come from one of millions of different IP addresses, since the auto-scaling instances use a pool of millions of AWS IP addresses in a wide array of IP ranges.

Because the client couldn't change their API provider (at least not in any reasonable time-frame), and we didn't want to throw away the ability to auto-scale, and also didn't want to try to build some sort of 'Elastic IP reservation system' so we could draw from a pool of known/reserved IP addresses, we had to find a way to get all our backend API SOAP requests to come from one IP address.

The solution? Reverse-proxy all requests to the backend SOAP API.

Pages

Subscribe to RSS - tutorial