Why Ulysses is Awesome
I started writing my last post on my iMac but because Apple Photos is a bit ... finicky with the iCloud syncing a screenshot I had taken on my iPad wasn’t there.
No fear, just keep writing in Ulysses, then move from the iMac to the iPad and drop the image in. It worked, no problems no fuss. It just works.
Now, if only iCloud would just work ...
Setting the Timezone on my server
When I scheduled my last post on December 14th to be published at 6pm that night I noticed that the schedule time was a bit … off:
I realized that the server times as still set to GMT and that I had missed the step in the Linode Getting Started guide to Set the Timezone.
No problem, just found the Guide, went to this section and ran the following command:
sudo dpkg-reconfigure tzdata
I then selected my country (US) and my time zone (Pacific-Ocean) and now the server has the right timezone.
Setting up the site with SSL
I’ve written about my migration from Squarespace to Wordpress earlier this year. One thing I lost with that migration when I went to Wordpress in AWS was having SSL available. While I’m sure Van Hoet will “well actually” me on this, I never could figure out how to set it up ( not that I tried particularly hard ).
The thing is now that I’m hosting on Linode I’m finding some really useful tutorials. This one showed me exactly what I needed to do to get it set up.
Like any good planner I read the how to several times and convinced myself that it was actually relatively straight forward to do and so I started.
Step 1 Creating the cert files
Using this tutorialI was able to create the required certificates to set up SSL. Of course, I ran into an issue when trying to run this command
chmod 400 /etc/ssl/private/example.com.key
I did not have persmision to chmod on that file. After a bit of Googling I found that I can switch to interactive root mode by running the command
sudo -i
It feels a bit dangerous to be able to just do that (I didn’t have to enter a password) but it worked.
Step 2
OK, so the tutorial above got me most(ish) of the way there, but I needed to sign my own certificate. For that I used this tutorial. I followed the directions but kept coming up with an error:
Problem binding to port 443: Could not bind to the IPv4 or IPv6
I rebooted my Linode server. I restarted apache. I googled and I couldn’t find the answer I was looking for.
I wanted to give up, but tried Googling one more time. Finally! An answer so simple it couldn’t work. But then it did.
Stop Apache, run the command to start Apache back up and boom. The error went away and I had a certificate.
However, when I tested the site using SSL LabsI was still getting an error / warning for an untrusted site.
🤦🏻♂️
—
OK ... take 2
I nuked my linode host to start over again.
First things first ... we need to needed to secure my server. Next, we need to set up the server as a LAMP and Linode has this tutorial to walk me through the steps of setting it up.
I ran into an issue when I restarted the Apache service and realized that I had set my host name but hadn’t update the hosts file. No problem though. Just fire up vim
and make the additional line:
127.0.0.1 milo
Next, I used this tutorial to create a self signed certificate and this to get the SSL to be set up.
One thing that I expected was that it would just work. After doing some more reading what I realized was that a self signed certificate is useful for internal applications. Once I realized this I decided to not redirect to SSL (i.e. part 443) for my site but instead to just use the ssl certificate it post from Ulysses securely.
Why go to all this trouble just too use a third party application to post to a WordPress site? Because Ulysses is an awesome writing app and I love it. If you’re writing and not using it, I’d give it a try. It really is a nice app.
So really, no good reason. Just that. And, I like to figure stuff out.
OK, so Ulysses is great. But why the need for an SSL certificate? Mostly because when I tried to post to Wordpress from Ulysses without any certificates ( self signed or not ) I would get a warning that my traffic was unencrypted and could be snooped. I figured, better safe than sorry.
Now with the ssl cert all I had to do was trust my self signed certificate and I was set1
- Mostly. I still needed to specify the domain with www otherwise it didn’t work. ↩︎
Installing fonts in Ulysses
One of the people I follow online, Federico Viticci, is an iOS power user, although I would argue that phrase doesn’t really do him justice. He can make the iPad do things that many people can’t get Macs to do.
Recently he posted an article on a new font he is using in Ulysses and I wanted to give it a try. The article says:
Installing custsom fonts in Ulysses for iOS is easy: go to the GitHub page, download each one, and open them in Ulysses (with the share sheet) to install them.
Simple enough, but it wasn’t clicking for me. I kept thinking I had done something wrong. So I thought I’d write up the steps I used so I wouldn’t forget the next time I need to add a new font.
Downloading the Font
- Download the font to somewhere you can get it. I chose to save it to iCloud and use the
Files
app - Hit Select in the
Files
app - Click
Share
- Select
Open in Ulysses
- The custom font is now installed and being used.
Checking the Font:
- Click the ‘A’ in the writing screen (this is the font selector) located in the upper right hand corner of Ulysses
- Notice that the Current font indicates it’s a custom font (in This case iA Writer Duospace:
Not that hard, but there’s no feedback telling you that you have been successful so I wasn’t sure if I had done it or not.
Switching to Linode
Switching to Linode
I’ve been listening to a lot of Talk Python to me lately ... I mean a lot. Recently there was a coupon code for Linode that basically got you four months free with a purchase of a single month, so I thought, ‘what the hell’?
Anyway, I have finally been able to move everything from AWS to Linode for my site and I’m able to publish from my beloved Ulysses.
Initially there was an issue with xmlrpc which I still haven’t fully figured out.
I tried every combination of everything and finally I’m able to publish.
I’m not one to look a gift horse in the mouth so I’ll go ahead and take what I can get. I had meant to document a bit more / better what I had done, but since it basically went from not working to working, I wouldn’t know what to write at this point.
The strangest part is that from the terminal the code I was using to test the issue still returns and xmlrpc faultCode error of -32700 but I’m able to connect now.
I really wish i understood this better, but I’m just happy that I’m able to get it all set and ready to go.
Next task ... set up SSL!
Migrating from Square Space to Word Press
This weekend I migrated my site from Square Space to WordPress. I had been planning to do this for a while (ever since a Hover ad read on ATP earlier this summer). This weekend was the last weekend before my Square Spacesubscription was set to expire so I finally made the switch.
Why I did it
Square Space offers a beautiful interface and great templates to get you started. They make everything about setting up a blog, portfolio or online store as easy as it can get. But ... that’s kind of where it ends for me. While the set up is amazingly easy, the actually content posting (for me this means my writing) was more difficult than I would have liked.
In order to get something posted to my Square Space site I would write something in anyone of a number of Plain Text Editors (BBEdit, Drafts, Editorial, Ulysses). Then I would preview the generated HTML
to verify it looked the way I wanted it to. Finally, I would post my MarkDown
to the Square Space Blog App on iOS and do it All. Over. Again.
To say that it was frustrating is a bit of an understatement. I looked really hard to see what API
s existed and found that there used to be an API but that Square Space removed them for some reason. So no direct posting to my blog by my favorite text editors.
So, with Hover having a discount on domains, and me getting an AWSaccount where I could host WordPress and a rich set of WordPress API
s to post directly from some of my favorite text editors, it seemed like a no brainer to make the switch.
How I set up my Wordpress Install
The AWS ecosystem has some amazing documentation on how to do just about anything that you want. So, instead of laboriously taking screenshots and writing up what I did, I’ll just link to Amazon’s Launch a WordPress Website tutorial
Exporting from Square Space to Wordpress
For all the pain it was to get content into SquareSpace, it was a breeze to get it out. Again, no need to get screenshots or write it up if I can just link to it instead!
What I hope to gain from it
As I wrote earlier my main reason for leaving Square Space was the difficulty I had getting content in. So, now that I’m on a WordPress site, what am I hoping to gain from it?
- Easier to post my writing
- See Item 1
Writing is already really hard for me. I struggle with it and making it difficult to get my stuff out into the world makes it that much harder. My hope is that not only will I write more, but that my writing will get better because I’m writing more.
Ulysses integration
With all of that, what has my experience been with writing my first post to my WordPress site?
This entire post was written and edited in Ulysses. I was able to preview my post in Ulysses. I was able topost my content to the site with Ulysses. Basically, Ulysses is a kick ass app and on day one of the conversion, I’m about as happy with a decision that I can be given the short amount of time since I’ve made it.
Podcasts I like
Podcasts I like:
Making Background Images
I'm a big fan of podcasts. I've been listening to them for 4 or 5 years now. One of my favorite Podcast Networks, Relay just had their second anniversary. They offer memberships and after listening to hours and hours of All The Great Shows I decided that I needed to become a member.
One of the awesome perks of Relay membership is a set of Amazing background images.
This is fortuitous as I've been looking for some good backgrounds for my iMac, and so it seemed like a perfect fit.
On my iMac I have several spaces
configured. One for Writing
, one for Podcast
and one for everything else. I wanted to take the backgrounds from Relay and have them on the Writing
space and the Podcasting
space, but I also wanted to be able to distinguish between them. One thing I could try to do would be to open up an image editor (Like Photoshop, Pixelmater or Acorn) and add text to them one at a time (although I'm sure there is a way to script them) but I decided to see if I could do it using Python.
Turns out, I can.
This code will take the background images from my /Users/Ryan/Relay 5K Backgrounds/
directory and spit them out into a subdirectory called Podcasting
from PIL import Image, ImageStat, ImageFont, ImageDraw
from os import listdir
from os.path import isfile, join
# Declare Text Attributes
TextFontSize = 400
TextFontColor = (128,128,128)
font = ImageFont.truetype("~/Library/Fonts/Inconsolata.otf", TextFontSize)
mypath = '/Users/Ryan/Relay 5K Backgrounds/'
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
onlyfiles.remove('.DS_Store')
rows = len(onlyfiles)
for i in range(rows):
img = Image.open(mypath+onlyfiles[i])
width, height = img.size
draw = ImageDraw.Draw(img)
TextXPos = 0.6 * width
TextYPos = 0.85 * height
draw.text((TextXPos, TextYPos),'Podcasting',TextFontColor,font=font)
draw.text
img.save('/Users/Ryan/Relay 5K Backgrounds/Podcasting/'+onlyfiles[i])
print('/Users/Ryan/Relay 5K Backgrounds/Podcasting/'+onlyfiles[i]+' successfully saved!')
This was great, but it included all of the images, and some of them are really bright. I mean, like really bright.
So I decided to use something I learned while helping my daughter with her Science Project last year and determine the brightness of the images and use only the dark ones.
This lead me to update the code to this:
from PIL import Image, ImageStat, ImageFont, ImageDraw
from os import listdir
from os.path import isfile, join
def brightness01( im_file ):
im = Image.open(im_file).convert('L')
stat = ImageStat.Stat(im)
return stat.mean[0]
# Declare Text Attributes
TextFontSize = 400
TextFontColor = (128,128,128)
font = ImageFont.truetype("~/Library/Fonts/Inconsolata.otf", TextFontSize)
mypath = '/Users/Ryan/Relay 5K Backgrounds/'
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
onlyfiles.remove('.DS_Store')
darkimages = []
rows = len(onlyfiles)
for i in range(rows):
if brightness01(mypath+onlyfiles[i]) <= 65:
darkimages.append(onlyfiles[i])
darkimagesrows = len(darkimages)
for i in range(darkimagesrows):
img = Image.open(mypath+darkimages[i])
width, height = img.size
draw = ImageDraw.Draw(img)
TextXPos = 0.6 * width
TextYPos = 0.85 * height
draw.text((TextXPos, TextYPos),'Podcasting',TextFontColor,font=font)
draw.text
img.save('/Users/Ryan/Relay 5K Backgrounds/Podcasting/'+darkimages[i])
print('/Users/Ryan/Relay 5K Backgrounds/Podcasting/'+darkimages[i]+' successfully saved!')
I also wanted to have backgrounds generated for my Writing space, so I tacked on this code:
for i in range(darkimagesrows):
img = Image.open(mypath+darkimages[i])
width, height = img.size
draw = ImageDraw.Draw(img)
TextXPos = 0.72 * width
TextYPos = 0.85 * height
draw.text((TextXPos, TextYPos),'Writing',TextFontColor,font=font)
draw.text
img.save('/Users/Ryan/Relay 5K Backgrounds/Writing/'+darkimages[i])
print('/Users/Ryan/Relay 5K Backgrounds/Writing/'+darkimages[i]+' successfully saved!')
The print
statements at the end of the for
loops were so that I could tell that something was actually happening. The images were VERY large (close to 10MB for each one) so the PIL
library was taking some time to process the data and I was concerned that something had frozen / stopped working
This was a pretty straightforward project, but it was pretty fun. It allowed me to go from this:
To this:
For the text attributes I had to play around with them for a while until I found the color, font and font size that I liked and looked good (to me).
The Positioning of the text also took a bit of experimentation, but a little trial and error and I was all set.
Also, for the brightness
level of 65 I just looked at the images that seemed to work and found a threshold to use. The actual value may vary depending on the look you're doing for.
The why of a decision
As a a manager no one will ever agree with every decision you make. Not the people you manage, and not the people that manage you. But if you always know why you made a decision and you can articulate that decision, then you’ll be on a good footing when someone asks you, “How did you know to do that?” or “How did you know to make that decision?”
One of the best lessons I learned from my boss LB is that the decision is less important than the why of the decision. Make no mistake, bad decisions are bad decisions, but they are much less likely to be made if you know why you made it.
Once I was able to internalize that lesson, it freed me to actually make decisions.
When faced with a decision, I tend to ask these questions:
- What do I know?
- How do I know it (i.e. how confident am I in the information I know)?
- What do I gain by waiting for more information?
- What’s the worst that happens if I make the wrong decision?
- What’s the worst that happens if I make no decision now?
- Who can I talk to about this decision?
Having answers to these questions doesn’t guarantee that my decision will be right, but it does help me to understand why I’m making the decision that I’m making. It will also help me to explain the decision later on if needed.
One of the things I try to tell the people I work with is this:
The decision itself is less important than why you made the decision. If you don’t know why you made a decision, then you shouldn’t be making the decision yet.”
Know why you made a decision and you’ll be better equipped to make the decision.
Making the Right Choice, or How I Learned to Live with Limiting My Own Technical Debt and Just Be Happy
One of the things that comes up in my day job is trying to make sure that reports that we create are correct, not only from a data perspective, but from an architectural perspective. There are hundreds of legacy reports with legacy SQL code that has been written by 10’s of developers (some actual developers and some not so actual developers) over the last 10+ years.
Today a request came in to update a productivity report to include a new user. The request included their user ID from the application where their productivity is being tracked from.
This request looked exactly like another report and request that I’ve seen that involved running productivity from the same system with the same aspects (authorizations work).
I immediately thought that the reports were the same and set out to add the user id to a table ReferralsTeam
which includes fields UserID
and USerName
.
I also thought that documenting what needed to be done for this would be a good thing to be done.
I documented the fix and linked the Confluece
article to the JIRA
issue and then I realized my mistake. This wasn’t the same report. It wasn’t even the same department!
OK, so two things:
- There are two reports that do EXACTLY the same thing for two different departments
- The report for the other department has user ids hard coded in the
SQL
What to do?
The easy way is to just update the stored procedure with the hard coded user ids with the new one and call it a day
The right way:
- Update the table
ReferralsTeam
to have a new column called department ... or better yet create a second table calledDepartments
with fieldsDepartmentID
andDepartmentName
and add theDepartmentID
to theReferralsTeam
table. - Populate the new column with the correct data for the current team that has records in it
- Update the the various stored procedures that use the
ReferralsTeam
table in them to include a parameter that is used to filter the new column that was added to keep the data consistent - Add the User IDs from the report that has the user IDs hard coded, i.e. the new department
- Update the report that uses the hard coded user ids to use the dynamic stored procedure
- Verify the results
- Build a user interface to allow the data to be updated outside of
SQL Server Management Studio
- Give access to that user interface to the Department Managers so they can manage it on their own
So, which one would you do?
In this case, I updated the hard coded stored procedure to include the new user id to get that part of the request done. This helps satisfy the requester and allows them to have the minimum amount of down time.
I then also create a new JIRA
issue so that we can look at doing steps 1 - 6 above and assigned to the report developer. Steps 7 & 8 are in a separate JIRA
issue that is assigned to the Web Developers.
Doing things the right way will sometimes take longer to implement in the short run, but in the long run we’ve removed the need for Managers in these departments to ask to have the reports updated, we prevent bad/stale filters from being used, and we can eliminate a duplicative report!
One interesting note, the reason I caught the duplication was because of a project that we’ve been working on to document all of the hundreds of reports we have. I searched Confluence
for the report name and it’s recipients were unexpected for me. That lead me to question all I had done and really evaluate the best course of action. While I kind of went out of order (and this is why I started documented one process that I didn’t mean to) I was still able to catch my mistake and rectify it.
Documentation is a pain in the ass in the moment, but holy crap it can really pay off in unexpected ways in the long run.
Page 20 / 24