Reviews of M1 Macs for Development

So far, the key interest for me have been the potential drastic improvement in battery life. I’m almost willing to sacrifice a bit of short term productivity to get there. I don’t know that the experiences sound any worse that trying to get my favorite development environments productive on Windows or a non-Debian flavor of Linux:

JetBrains and Xcode-centric perspective (11/23/2020):
https://medium.com/before-semicolon/is-m1-mac-worthy-or-good-for-developers-developer-review-3ed832f4105e

Rubyist perspective (11/25/2020):

https://www.driftingruby.com/episodes/a-rubyist-s-apple-m1-review

macOS 11 Big Sur compatibility on Apple Silicon · Issue #7857 · Homebrew/brew · GitHub (closed as of 12/26/2020):

https://github.com/Homebrew/brew/issues/7857

TypeScript/JavaScript/Rust (12/3/2020):

https://dev.to/redhoodjt1988/how-to-setup-development-environment-on-new-macbook-pro-m1-3kh

Rails’ DHH’s own experience (12/28/2020):

DriftingRuby tweet:


How to Cancel Humble Choice

I tried to cancel Humble Choice a couple of months ago, after getting sucked in to a membership a few months ago, but either I didn’t complete the cancellation, or I didn’t have enough time to completely follow-through. I had a little bit of a challenge finding the cancellation link this time, so I wrote it up here just in case anyone else experienced the frustration. No idea if it works on mobile, I went to the desktop this time to make sure that I could see the entire menu.

  • Manage Your Plan
  • Scroll down to [Cancel Your Subscription] button
  • Scroll down to [Cancel My Membership]
  • Select a reason and [Cancel My Membership]
  • Click [Cancel My Membership] on the popup.

Fuji EnviroMAX AA vs. Sunbeam Batteries

So we have a battery hungry front door lock that requires 4-AA batteries to power. I noticed that the Sunbeam batteries purchased from Dollar Tree (3 pack for $1, or $1.33 per replacement) were getting replaced every month or so, so I was curious if that was normal as well as how much I was really paying for them.

Tracking in a spreadsheet, the Sunbeam batteries lasted from 23 to 36 days, with an average of 28.8 days. At $1.33 per replacement / 28.8 days… that door cost 4.61¢ per day with the Sunbeam batteries.

Thinking maybe I could do better, I bought a 96 pack of EnviroMAX Batteries (affiliate link) on Woot (but for 25¢ each instead of being similar in price to the Sunbeam… so it was $1 per replacement instead of the $1.42 at the current moment for that link.) The batteries lasted 13-25 days, with a generous average of 21 days, or about 4.7¢ per day… The last replacements were more like 2 weeks and I stopped tracking them, but there were sets in the middle that made it 3 weeks or better, but it was horribly inconsistent.

I just bought a large pack of Kirkland batteries, so I’ll be sure to track the performance of those and see how it lines up with the other batteries.


Sylvania vs. Amazon Basics LED bulbs

I’ve been tracking the Sylvania 60W 2700K Equivalent A29 (affiliate link) vs. the AmazonBasics 60W Soft White Non-Dimmable (affiliate link) over the past year and a half after noticing that I was replacing bulbs a lot. With 40+ bulbs in the house, it’s not as uncommon as I would have initially expected to be replacing a bulb on any given day.

I have a limited amount of data so far, but definitely have an apples to apples (same socket in same fixture) comparison, and it looks like the Amazon Basics bulb lasted 242 days vs. the Sylvania’s 308. While I have no other apples-to-apples comparisons, the remaining Sylvania bulbs have lasted at least ten months.

The above links have a 24-pack of AmazonBasics at $27.99, or 0.48¢ per day vs. the Sylvania at $22.88, or 0.31¢ per day.


ASCII/Punycode TLDs for Internationalized Domains

IANA has a list of TLDs alphabetically by domain. One thing notable are domains of in the following format:

XN--VERMGENSBERATER-CTB
XN--VERMGENSBERATUNG-PWB
XN--VHQUV
XN--VUQ861B

These are internationalized TLDs, specified in a Punycode encoding for the unicode domain name. Some of these representations are just for non-ascii characters:

XN--VERMGENSBERATER-CTB,vermögensberater,wealth consultant

Others are representing fully non-Latin alphabets:

XN--FPCRJ9C3D,భారత్,India

Most of these non-Latin representations are either country designations, brand names, or a telecom-centric term.

If you want to experiment on your own, install simpleidn gem and sign up for a Rapid API key and the Microsoft Translator API (it’s a little simpler interface than navigate individual vendor APIs)

# http://data.iana.org/TLD/tlds-alpha-by-domain.txt
require 'net/http'
require 'uri'
require 'simpleidn'
require 'openssl'
require 'json'


def translate(source)
  return source if source =~ /^[A-Za-z]+$/
  # using rapidapi for somewhat uniform API access (via a single key!)
  url = URI("https://microsoft-translator-text.p.rapidapi.com/translate?to=en&api-version=3.0&profanityAction=NoAction&textType=plain")
  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Post.new(url)
  request["content-type"] = 'application/json'
  request["x-rapidapi-key"] = ENV['RAPIDAPIKEY']
  request["x-rapidapi-host"] = 'microsoft-translator-text.p.rapidapi.com'
  request.body = "[
      {
          \"Text\": \"#{source}\"
      }
  ]"

  response = http.request(request)
  read_body = JSON.parse(response.read_body)
  [read_body[0]["detectedLanguage"]["language"],read_body[0]["translations"][0]["text"]]
end

puts 'ascii/punycode TLD,Unicode version,language,translation'
File.read(File.open('tlds.txt'))
#Net::HTTP.get(URI('http://data.iana.org/TLD/tlds-alpha-by-domain.txt')) # I saved this locally
  .each_line
  .map { |a| a.strip }
  .reject {|n| n =~ /^#/ }
  .map { |a| [a, SimpleIDN.to_unicode(a), translate(SimpleIDN.to_unicode(a))].flatten }
  .reject {|n| n[1] =~ /^[A-Za-z]/ }
  .sort { |a, b| a[1].length <=> b[1].length }
  .each { |l| puts l.join(',') }


AWS Certified Solutions Architect Associate (SAA-C02) Experience

Prep

Online Exam

  • PearsonVue browserlock kept detecting itself on Catalina on my MacBook Air and exiting, so I ended up using a Windows laptop instead.
  • OnVue app on Windows kept detecting “gamebar”, which I had to disable (and reboot Windows to fully take effect)
  • Make sure the laptop that you’re using can be maneuvered to show all the workspace within reach.
  • Have a phone handy for check-in, but a convenient place to stash out of sight/sound range.
  • Make sure anything with any print or writing is out of view and out of reach of the workspace area before check-in.

Contents That I Could’ve Been More Prepared For

  • SQS vs. Kinesis use cases
  • Priority queueing – I think this requires either AmazonMQ or a separate SQS queues (depending on priority levels)
  • ECS launch types. ECS vs. Fargate vs. EKS
  • Amazon RDS Read Replicas vs Aurora Global Database

Regex testing in test in zsh and launching a browser page

I get so many casual mentions of ticket numbers in our discussions and I keep hacking old URLs for tickets to look them up, or clicking through JIRA boards and views to navigate to the proper ticket, only to have them pull up in a sidebar in JIRA requiring more clicks to get to a useful view.

So, I wrote a quick script in JIRA called gojira to launch a browser window (macOS from the terminal):

open https://jira.example.com/browse/$1

With the above script, I can just invoke gojira PROJECT-1234 to bring up the ticket.

Ok, so that’s great but 90% of the ticket numbers are referencing the same project. So what if I want to only specify a ticket number some times? That’s when I finally looked up if you can test (alias [ ]) a regex in zsh. Turns out that you can.

If regex

The fairly common =~ operator is available for test/[] in zsh. You do have to double the square brackets for it to work (and single quote your regex):

if [[ "$1" =~ '[[:alpha:]]+-[[:digit:]]+' ]]
then
  open https://jira.sdlc.appriss.com/browse/$1
else
  # default to PROJECT if only a number is specified.
  open https://jira.sdlc.appriss.com/browse/PROJECT-$1
fi

Why not a function?

Of course, this can also be handled in a zsh function and added to your .zshrc or .zlogin:

function jira() {
  if [[ "$1" =~ [[:alpha:]] ]]
  then
    open https://jira.sdlc.appriss.com/browse/$1
  else
    open https://jira.sdlc.appriss.com/browse/PROJECT-$1
  fi
}


Deploying a Minecraft Server to EC2 (with some cost analysis)

Caveat… this is likely not the option you want to pursue for a small to medium scale Minecraft server… Lightsail will be more cost-effective due to the amount of data transfer involved. Also, this is partly an exercise it navigating Amazon Linux as a largely Ubuntu user.

Purchase a Domain

I’m going through Namecheap for a .online domain because… well… it’s cheap… and registering revrestfarcenim.online (.online domain through Route 53 would be $39 vs. $1.88 for the first year with Namecheap).

Launch an EC2 instance

If you’re trying to use free-tier resources for this, you’ll want to go for a t2.micro, but you’ll also need to modify the java parameters for the server to fit within those memory limits.

  • Go to Services -> EC2
  • Scroll down in the main window to “Launch instance” and click [Launch Instance]
  • Select Amazon Linux 2 AMI (should be the first option)
  • I’m selecting t3a.small for this to be similar in “virtual” resources as the $10-15/mo virtual server hosting providers (including Amazon Lightsail).
  • Click [Next: Configure Instance Details]
  • You’ll get a default vpc and subnet created and selected… if you don’t want to use these, you can click the available links to create new ones.
  • For “Auto-assign Public IP”, I have “Use subnet setting (Enable)” because I’m going to want to have this publicly accessible.
  • Scroll to near the bottom of the “Step 3” form and find “T2/T3 Unlimited” and uncheck “Enable” unless you want to run up a bill because you forgot about the Minecraft server.
  • Click [Next: Add Storage] to configure your space.
  • Click [Next: Add Tags]
  • Click [Next: Configure Security Group]
  • Click [Add Rule] and add a Custom TCP Rule that allows traffic to port 25565 (the port for Minecraft) from 0.0.0.0/0
  • Click [Review and Launch]
  • Click [Launch] and choose “Create a new key pair” named “minecraftserver”
  • Click on Instances and select your new instance, noting the IPv4 Public IP in the instance details below (leave tab open for reference in the next section)

Create a Hosted Zone in Route 53

  • In a new tab, go to Services -> Route 53 -> Hosted Zones
  • Click [Create hosted zone]
  • Type in your domain name for your server and select “Public hosted zone”
  • Copy the values for the NS record and populate those as the nameservers for your domain (for me, this is on Namecheap
Route 53 NS record
Namecheap Custom DNS settings
  • Now go back to Route 53 and [Create Record]
  • Choose “Simple routing”
  • Click [Define simple record]
  • Leave the record name blank.
  • Under “Value/Route traffic to” select “IP address or another value depending on the record type” and paste your IP in.
  • Be sure “Record type” is “A” and click [Define simple record]
  • Click [Create records] on the “Configure records” screen.

Install and setup Minecraft

  • Using your keypair from instance creation, ssh into your your instance
chmod 400 minecraftserver.pem # or whatever the filename is
ssh -i minecraftserver.pem ec2-user@revrestfarcenim.online
  • Create minecraft server folder and user
sudo mkdir /srv/minecraft-server # assuming EBS mount
sudo adduser --system --home /srv/minecraft-server minecraft
sudo chown minecraft.minecraft /srv/minecraft-service
  • Do updates and install java
sudo yum update
sudo amazon-linux-extras install java-openjdk11
  • Download minecraft server, run for the first time, and set the eula.txt
sudo -u minecraft wget https://launcher.mojang.com/v1/objects/a412fd69db1f81db3f511c1463fd304675244077/server.jar
sudo -u minecraft java -Xmx1024M -Xms1024M -jar server.jar nogui
# you'll get an error, so edit the eula.txt
sudo -u minecraft nano eula.txt # or vi, just set to eula=true
# run minecraft again and try to connect to server at revrestfarcenim.online

Making Minecraft a service

  • Run sudo nano /lib/systemd/minecraft-server.service
  • Paste a config similar to:
[Unit] 
Description=start and stop the minecraft-server 

[Service]
WorkingDirectory=/srv/minecraft-server
User=minecraft
Group=minecraft
Restart=on-failure
RestartSec=20 5
ExecStart=/usr/bin/java -Xms1024M -Xmx1024M -jar server.jar nogui

[Install]
WantedBy=multi-user.target
  • Now, enable the service with sudo systemctl enable /lib/systemd/minecraft-server.service
  • And start the service with sudo systemctl start minecraft-server.service
  • As it’s starting, you can check the status with sudo systemctl status minecraft-server.service.
  • With this systemctl setup, you should also be able to reboot the instance and have the Minecraft server come back up

Troubleshooting

  • If you don’t go with the default gateway and subnets created with the instance, you may find yourself having to explicitly set up an Internet Gateway and a Route Table (0.0.0.0/0 to your igw)
  • Make sure the associated security group is allowing port 25565 to connect (especially if SSH is working)

Teardown

Be sure to delete your hosted zone (you’ll need to delete the A record before deleting the zone) and terminate your instance to avoid running up charges for things you’re not using. I deleted the VPC as well just to avoid clutter and half-baked subnets and security groups, but that’s only because I have nothing of long-term value in the account.

Cost Analysis

There are multiple hits that you’re going to take by hosting this on EC2:

  • egress costs (9¢ per GB after your first GB): In my limited tests, the Minecraft worlds we started up required 100-200MB to initially download per session. It’s unclear if that’s the case for every session, but if you have 20 of your friends use a server, that might be 9¢ x 0.20 GB x 20 for one session each… 36¢ per average number of sessions… that could add up quickly. By contrast, you could get a different hosting provider (including Lightsail) to bundle 2TB of transfer instead.
  • hosted zone cost (50¢ for a distinct domain’s hosted zone)
  • If you use a separate EBS volume, minimum cost there is 80¢.
  • t3a.small cost is 1.88¢ per hour or $13.53/month… you could have the server shut down during off-hours, but then you’re not comparing to “always-on” options.

Monitoring your S3 buckets for #omgcat usage

If you’re serving up a static website from S3, especially if you have larger assets stored there, you may want to put monitoring on the requests or bytes downloaded from S3, just to make sure someone’s not running up terabytes of transfers or millions of requests.

Enabling Metrics on S3

You will have to enable metrics on S3 in order to get CloudWatch alarms on them.

  • Go to Services -> S3 -> Buckets and select the bucket for your static site.
  • Select Management tab and [Metrics] and then click on the pencil icon next to the bucket icon.
  • Once enabled, the metrics will take a bit to populate.

Setting up Simple Notification Service (SNS)

(These are the same instructions as in Monitoring your CloudFront #omgcat usage)

Set up a topic

  • First, you’re going to want to be notified. Go to Services -> Simple Notification Service to set up a pathway for that to happen.
  • Next, click “Topics” and then [Create topic]
  • Name your topic something that adequately describes the purpose (I just used domainname-com)
  • Scroll down to [Create Topic]

Set up a subcription

  • Under “Amazon SNS” left sidebar, click “Subscriptions” and [Create Subscription]
  • Click on the Topic ARN field and you should be able to see an ARN with your topic name as the last part of the ARN. Click that ARN
  • Under Protocol, select your preferred method of notification (I’m going with SMS.
  • Under Endpoint, enter your cell number, including country code (+18005551212 for (800) 555-1212 in the US)

Setting up a CloudWatch Alarm

  • Go to Services -> CloudWatch -> Alarms and [Create alarm]
  • [Select metric] and select S3
  • If you don’t see “Request Metrics per Filter” then the metrics haven’t started populating yet.
  • Check “GetRequests” or “BytesDownloaded” and [Select Metric]
  • Set conditions as you would like to have flag any anomalies and click [Next]
  • Choose “In Alarm” and “Select an existing SNS topic” and click in the box below “Send Notification To…” to get suggestions and select the SNS topic corresponding to the notification method you set up. Click [Next]
  • Name your alarm and click [Next]
  • Review the summary and click [Create Alarm]


Monitoring your CloudFront #omgcat usage

Ok, so you’ve created a lovely static site and/or set up a CloudFront distribution for https for it. But CloudFront bills by the GB. What if somebody decides your assets are perfect to hotlink to or just straight up makes an insane boatload of requests? How do you protect yourself from getting a frightening bill before AWS Budget can even notify you?

Setting up Simple Notification Service (SNS)

Set up a topic

  • First, you’re going to want to be notified. Go to Services -> Simple Notification Service to set up a pathway for that to happen.
  • Next, click “Topics” and then [Create topic]
  • Name your topic something that adequately describes the purpose (I just used domainname-com)
  • Scroll down to [Create Topic]

Set up a subcription

  • Under “Amazon SNS” left sidebar, click “Subscriptions” and [Create Subscription]
  • Click on the Topic ARN field and you should be able to see an ARN with your topic name as the last part of the ARN. Click that ARN
  • Under Protocol, select your preferred method of notification (I’m going with SMS.
  • Under Endpoint, enter your cell number, including country code (+18005551212 for (800) 555-1212 in the US)

Get Notified

  • Go to Services -> CloudFront -> Alarms
  • [Create Alarm]
  • Under Metric, choose the threshold that you want to detect on… maybe it’s Requests, maybe it’s Bytes Downloaded…
  • Select the distribution that you want to watch ( domainname.com should be mentioned in the dropdown)
  • For “Send a notification to”, select the SNS topic that corresponds to the notification method you set up.
  • Since mine is a dev/test site, I don’t expect more than a request/second so
  • Finally, [Create Alarm]

Testing the Alarm

  • If you have a low enough threshold you can probably just hold down F5 (or whatever your refresh key is) for a few seconds. (Word of caution: Don’t do this with a page that downloads a lot of assets!)
  • In bash you can also do the following.
for i in {1..61}
do
  curl https://domainname.com
done
  • If your notifications are working, you should get an message through your preferred notification method.
  • Under Services -> CloudWatch -> Alarms, you should also see your Alarm count be > 0.