SSL Certificate for Apache

I just renewed the certificate for a client web store. This is a task that drives me crazy because I do it so infrequently that I can never remember the details. It's made worse by the fact that I use InstantSSL, a company whose documentation and practices are incredibly confusing. Also, cheap.

Here's what happened.

I followed the usual instructions for generating a Certificate Signing Request. This generated two files, a .csr and a .key (for later).
I used a command line like this:

openssl req -new -newkey rsa:2048 -nodes -keyout myDomainName.key -out myDomainName.csr

It is entirely unclear to me if the name of the files makes any difference. Also, in the dialog that openssl conducts to construct the CSR, it asks for "your name". It means 'your domain name'. May be obvious but I thought that maybe it was picking up the domain name from the command line.

The purchase process for InstantSSL is pretty easy. They are really good at taking money.

Since I screwed up the domain name thing, I had to interact with tech support and give them a new CSR. This was annoying since it just said I needed to do it, not how. Eventually I had looked around long enough that I felt like I had to call. Turns out you have to construct a support account and treat send it through the support website along with your order number.

The next step was validation. It does two things. It looks up the company phone number (in this case using Dunn & Bradstreet). I had to work with the client to be there to answer the phone and gather the 'validation code'. Entering this into the phone call tool triggers another email (this came to me, as the email address on the purchase) with another, longer validation code. This had to be put into the order control panel.

While there, I saw that it still wanted to send email to admin@, an address that does not exist, for additional validation. Turns out that, in the order control panel, you can change this to one of several other options. I don't know where they come from but, one of them was me. That sent another validation code to put into the order control panel.

And then I got an email with a .zip full of certification. Expanding this got me two files, a .crt and a .ca-bundle. I also needed the .key file made along with the CSR.

These were put into folders specified in the Apache config file. In my case, this was a virtual host file for that site.

There are three files and they need three entries for Apache configuration:

    SSLCertificateFile /etc/ssl/certs/sales/myDomain.crt
    SSLCertificateChainFile /etc/ssl/certs/sales/myDomain.ca-bundle


    SSLCertificateKeyFile /etc/ssl/private/myDomain.key

On my system, these are root files with permission 644. I do not know if this is ideal. There might be some more secure arrangement. (That's what comments are for.)

After a server restart, the browser security violation went away and things look pretty good.

Now you know.





Debugging a Web Type Font Served from a Different Domain

A client came up with a type face that she found on some site. The supplied file type was .ttf (truetype).

Because I treat my public_html folder as source code, I always keep a third level domain for static file server, eg, static.someDomain.com, to hold files that need to be directly served. I expect that this might have worked more easily if I had been able to/chosen to serve the type file from the site's public_html folder instead of the different domain.

I put the .ttf on the static domain and added this coding to the web page:

@font-face {
  font-family: 'demoFont';
  src: local('demoFont'), url(http://static.someDomain.com/demoFont.ttf) format('ttf');
}

Even though the internet said that Firefox wants .ttf , it didn't work.

I have used Google fonts before so I checked that out for comparison.
@font-face {
  font-family: 'demoFont';
  font-style: normal;
  font-weight: 400;
  src: local('demoFont'), url(http://static.someDomain.com/demoFont.woff) format('woff');
}

I find a site that does ttf-woff conversion ([1] below). It works great but, after I copy it in and edit to use the google version of @font-face. No dice.

Reading the internet ([2] below), I got the idea to look at the headers ('curl -I domain.com') coming back from google and my static domain specifically to see about 'Access-Control-Allow-Origin'. I found that google's header included "Access-Control-Allow-Origin: *" and mine did not.

The website suggested using .htaccess to add the goodies to the header:

<FilesMatch "\.(ttf|otf|eot|woff)$">
    <IfModule mod_headers.c>
        Header set Access-Control-Allow-Origin "*"
    </IfModule>
</FilesMatch>

(Actually, I added the '|woff')

Checking the header... No dice. The line does not appear.

I notice mod_headers.c and check my Apache config. Not there. Navigate to /etc/apache2/sites-enabled:

ln -s ../mods-available/headers.load headers.load

service apache2 restart

Bada Bing. Bada Boom!

The header is there and the the typeface shows. Win! And, for good measure, it works in Chrome, Safari and late model Internet Explorer.


[1] - http://everythingfonts.com/ttf-to-woff
[2] - http://stackoverflow.com/questions/2856502/css-font-face-not-working-with-firefox-but-working-with-chrome-and-ie










SSH fails to use RSA valid RSA key because the account is not owned by correct user

For various reasons, there are three accounts on this Linux server that I want to access with SSH using my RSA key pair. I generate them and copy my key into each account, tune up the authorized keys file and prepare for satisfaction. What I got was much less. Only one of the accounts logged in using the RSA key. The other two ignored the key and insisted on a password.

The first thing I did was install the key on a couple of other servers and demonstrated that the keys were good.

Then I had my SSH client show me the transcript and did one million things. I now know a ton about the sshd file. I changed permissions, did careful reinstallations, I spent hours to no avail. I consulted my genius son. At the end, I was still getting this:

debug1: Next authentication method: publickey
debug1: Offering RSA public key: /Users/tqwhite/.ssh/id_rsa
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: password

That's right, it was actually trying to use the key and it was being rejected. Then, it would ask for a password. I was stuck and gave up. Actually, I ran out of time.

Some time later, I was building a new Linux server at my day job and, damned if I don't run into the same problem. So, I dig in and try again.

This time I'm in a slightly different context and, I'm not sure how I got there but found out about this:

sshd -d

It turns on debugging on the server side. (It's a little bit annoying because, after one try, it breaks something and I had to reboot to get everybody cleaned up and working again for another try. I'm sure there's a better way but I don't really care. Rebooting was ok on this server.)

To use it, I logged in with one terminal window, turned on debugging, then tried to log in with another window. The debug window showed a transcript of the server side of the experience.

I didn't grab a complete transcript but it did include this phrase:

bad ownership or modes for directory

So, I cycle back and make sure that my .ssh directory is set correctly:

chmod go-w ~/
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Still no dice.

I'm thrashing about, feeling desperate and miserable and, suddenly, Voila!, I notice that the freaking account (root, in this case) is not owned by its correct user. I know, wtf?, but there it is. For some reason, the image used to create the server has weirdness on the ownership of account directories. I reflect on "bad ownership or modes" and, moments later,

sudo chown root:root /root

and, bada bing, it works. I go to the server that was killing me previously and, who knows why, the accounts that fail are not owned properly. More chown and life is good.

Awesome Experience with DigitalOcean

[UPDATE2]

DigitalOcean solved the problem and made life good again. We achieved understanding of the specifics of my need and that it is a valid one. Their preferred solution will require changes to their system that might be made in the future. In the meantime, they have agreed that I can have more than one account. That means that I can use DigitalOcean in the way that suits my needs.

Almost more importantly, it means that I can love DigitalOcean again. I told the guy that I feel silly because I actually had hurt feelings and was sad at the prospect of not feeling the DigitalOcean love. I guess I feel even sillier at my elation at having them not only satisfy my need but actually exert the effort to go through conflict to a happy resolution.

The title of this post has been changed from "Rough Experience" to "Awesome Experience with DigitalOcean".

[/UPDATE2]


[UPDATE]

I heard from a different Digital Ocean guy this morning. He was incredibly nice, clearly had read and paid attention to what was said last night and made suggestions for ways to solve my problem. I don't know what the resolution will be but, I'm leaving this post up both so he can read it to understand what I'm trying to do and so that the rest of the world can know that these guys are not only trying to provide an awesome service but are willing to reverse course when they see that they are injuring a customer relationship. I think that might even be more important than getting it right the first time.

[/UPDATE]

Digital Ocean kicked me out last night when I tried to start a new client account using my own credit card. They told me that they are "not comfortable" with me using my credit card for more than two accounts (I have another client I put there already). Huh? Not comfortable using my 100% valid credit card to pay for multiple accounts?

My Situation

It turns out that there are lots of people who want a minimal website and have no way of getting it. When a friend or family member knows one of those people, I sometimes end up making a small website for them. For years, I've just hosted the site on one of my servers. They never have any real traffic so it doesn't cost me anything.

But, I hate it. I have some sites that have been in my life for years and, if I want to change servers, I know I have to move those sites, too. What I really want is to be able to quickly fire up the site and then hand it off to the person. Most of them are happy to pay a few bucks to keep it alive. (I don't take the money because I don't want to do the paperwork.) I'm happy to help again if they need it, but I really would like to have it be their responsibility.

I've thought about just pushing them to a shared host, but, I've not seen one that didn't require a whole other learning curve. More importantly, I manage my software with git and no command line is a problem. And, I put parameters in my virtual host file to drive my software. Putting these sites a virtual host that would support how I want to work is too expensive for them.

Enter Digital Ocean.

These guys offer a very straightforward system to generate a virtual private server on the web. Their smallest instance comes out to about $5.00 a month. I can have a website based on my software up and running there in about twenty minutes.

Aha! A solution to my problem. I can quickly generate the new, tiny site. Because it's cheap, I can afford to host it as a gift for awhile or I can pass the account on to the person or I can invoice them and manage it myself. In all cases, if the client wants to use some other web guy, I can just hand over the password. Or, if I don't want to mess with it any more, I can just hand over the password. Or, as is the case with one more substantial client, I can fire them – and just send them the password.

The point is that I can, in an email, give the site to the client and be done with it. I do not have to do a whole project to change their DNS, initialize a server, blah blah blah. Send the password. Be done.

Opportunity Arrives!!

This notion came to me this summer. Having my own Digital Ocean account, I fired up a new account for a new client and started to work. This one is a little larger than the main use case but, the principal of being able to turn the whole thing over to them when appropriate still applies. Then a friend asked me if I could help out one of her friends.

Sure!, says I. I have this awesome new service available. I'll fire it up tonight. He can send me sixty bucks for this first year of service and Bingo!, we will have his little site working before sunup.

Disappointment Follows

So, I hit Digital Ocean and create the account. I enter my credit card and, Bam!, the site tells me their fraud detector has found me wanting. The messages are all nice and unthreatening. Almost immediately, I get an email asking why I made more than one account with the same credit card. I think, "oh! I can understand that", and explain my situation.

Imagine my surprise when that's not enough. (No! You can't buy three things from me using the same credit card.)

I engage with some customer service guy. He tells me that they have "standard procedures". He asks how we should resolve this. Thinking, "Really, your standard procedures say, 'don't let TQ give you an extra five bucks a month?"

Instead, I tell him that it makes sense to have his software detect my anomalous behavior but, having investigated me and found me to be a real person, it seems like the 'standard procedure' should be to green light my account and let me get to work.

"We are not comfortable"

But, he ignores what I wrote (It's weird. when I reviewed the emails this morning, it's like I was talking to an automated system. He never actually responded anything I said.) and, after asking me to repeat my earlier explanation (was he really paying that little attention?), tells me that they are "not comfortable moving forward" with more than two accounts.

Where I come from, "not comfortable" is the same as "we don't feel like it." He offers no real reason. In my ire, I assume that he doesn't really care how I feel about, at least not enough to tell me the real reason – or, more likely, there isn't one. It really is that they value their procedures over my business.

I told him that I was bummed out about his discomfort and that he could delete the account I made but won't be able to use. He told me that he wasn't going to do the deleting. I have to do it. He explained the procedure I should go through.

I believe the real meaning of that was, "I just told you we are not going to work with you because we don't feel like it. What makes you think we are going to do anything for you. Now, you go clean up our server."

Be Cautious

I have come to really value companies that want to have a good, supportive relationship with me. I send email to the Bare Bones software (make of bbedit, my code editor) and get a response from the principal guy. My main server host, Server Grove, tries to help me out when I contact them. Their main guy sometimes gets involved. There have been occasions when he actually did stuff that I know he didn't have to do to help me. I feel good about those companies and tell everyone how much I like them.

Digital Ocean has such a nice website and a good service. I thought I had found another company to solve a problem that has been bugging me forever.

Not. Bummer.



Internet Sales Tax

In case you were wondering, I have decided that I am opposed to the current proposal to tax internet sales transactions.

I am, generally, sympathetic to the problem of lost revenue and competitive advantage given to online vendors over bricks and mortar. It's a distortion in the market that could encourage a death spiral where anyone in my neighborhood has to be driven out of business because they have a structural price disadvantage - at least if you ignore shipping.

However, I note that sales tax is considered to be the most regressive way to get revenue. It makes me a little suspicious when we have Republican support for a tax increase. If they support it, I figure it's going to turn out badly for me.

But, more important is the part where it makes it so that we are all at risk of being involved with any tax authority in the country whenever we do business on the internet. This seems to me a little like searches at airports. Sure, there's a 'reason' but it is actually a checkpoint where you have to ask the government for permission to travel.

I suspect that adding sales tax to the internet will be another way that we put an instrument on the net that will put more of us in a position to be troubled by the government. Unlike a garage sale, the internet keeps a record. That means that the piece of Craig's list crap you sell to someone in Alabama, well, that means the Alabama Dept of Revenue owns a piece of your ass.

If the sums were huge, I might still be swayed in support but, this tax will produce something like $23 billion. That's 5% of the defense budget, not including wars.

That tells me that there is something else going on. I don't know what it is but, when the corporatists in Washington get together to add a tax that will affect everyone that ever wants to sell something using the internet, I am very suspicious.


The Nasty Case of Two Bugs

Here's are the two bugs: The declaration of private was made one of the child classes but not in the parent.

Here's the behavior: A parent class makes an assignment to a property

$this->routeName=$incomingParameter;

when accessed by class A, it works fine, by class B, the assignment is not made.

It turns out that, I had tried doing this work in class B before I decided that the better strategy was to put it into the base class (for both A & B). When I abandoned that effort, I inadvertently left the property declaration (private $routeName) in class B. It never was in class A.

The base class already had a property of that name. What I did not know is that, despite the long list of declarations that prove my intention to declare all properties, $routeName was not, in fact, declared.

That means that, from the base class perspective, the property could not be assigned. Incredibly, though I have PHP set to complain about everything, it did not complain about this attempt to assign to a private property. It failed silently and, since I was focused on the base class, inscrutably.

Once I noticed that the property wasn't declared in the base, I did so and it worked.

I experimented and found that, if I removed the declaration from the child class B, it worked. If I changed the declaration to protected, it worked just fine, too. (Much to the consternation of a co-worker who considers it blasphemy to have a declaration in a child class be available to a parent.)

Of course, the correct solution was to remove the declaration from the child, add it to the parent, and get back to work.

Testimonial: SpamSieve Is Awesome!

(I usually focus on programming topics here but, having recently built a new computer and watched the miracle that is SpamSieve's Bayesian filtering, I wanted to make my enthusiasm available to the internet in the hopes that the SpamSieve people enjoy greater success and that some people will stop living in spam hell. It makes more sense here than on any of my other blogs.)
Macintosh using friends, if you are not using SpamSieve, your life can be better.

I have been using the same email address since the middle nineties. I have never concealed it either. I use it to sign up for stuff, on blog posts, everywhere. As a consequence, I get spam. Lots of it. Yesterday, I got 104 spam email messages and that's pretty much every day for me.

But, I use SpamSieve so I never see any of them. Well, almost never. I see one or two every couple of days. Then, I tell SpamSieve that I don't like them and they disappear. Actually, a whole other category of spam disappears. It's amazing.
 
It's kind of fun, actually. All of a sudden the spamsters will get a new idea and I will see a bunch of spam. Eeek! I say to myself and I will point out their spammyness to SpamSieve. The next day there might still be a couple. Then, none. I'll check the SpamSieve discard folder and, there they are, out of sight.

I review the discard folder every once in awhile to see if it is mad at anyone I like. It does happen. Well, by "does happen", I mean, I can recall some incidents. Like, five times in my life after the first few weeks of a new installation.

Here's another amazing thing. If you set up your email right (imap!), SpamSieve running on your main Mac will remove the spam from your iPhone, too. And your iPad. And you iPod Touch. And your other Macintosh. It is a miracle.

SpanSieve costs thirty bucks but it is the best thirty bucks you will ever spend. If you ever wanted to know if something was worth it, here's one occasion where you can actually know the answer: TQ White II, computer ace, has used this software for years and says, "It works like a miracle."

And that information, my friends, is a gift. Enjoy!

http://j.mp/UtDhdi

Screwy qTip2 Behavior Bug Report

The qtip is supposed to be pointing to the top left of the word, Terms. Instead it's pointing to the bottom left:

But right next to it, set up in the same way, the word Delivery has it's tooltip correctly placed at the top left of the target:

And if I reorder the display without changing anything else, the tooltip moves to its proper place:


The bad tooltip also flickers, though I suspect that's because the tooltip is placed over the target.

Here is the html table visible in the screenshot:

<table style='width:690px;text-align:center;'><tr>

<td style='width:200px;text-align:center;'><span class='tooltipAbove' title='Call us at xxx/xxx-xxx and we will set you up.'>Refund</span> &bull; <span class='tooltipAbove' title='Information entered is only used to fulfill this order.<br/>It is never shared with anyone. Period.'>Privacy</span></td>

<td id="copyright">&#169; 2012 Ten Sigma. All Rights Reserved.</td>

<td style='width:200px;text-align:center;'>
<span class='tooltipAbove' title='This product is activated using our website<br/>at http://TenSigma.org'>Delivery</span>
&bull;
<span class='tooltipAbove' title='If you do not wish to pay immediately by credit card,<br/>please contact us at xxx/xxx-xxxx and we will work something out.'>Terms</span>
</td>

</tr></table>

(Be quiet. I like to make it look good and move the styles to class later.)

Here is how the qTip is activated:

$('.tooltipAbove[title]').qtip({
position: {
my: 'bottom left',
at: 'top left'
}
});
}

Any thoughts?


C# Scope

This makes no sense to me. 

The situation:

public OutputType functionName(){

MyDataType myVarName; // <-- proper declaration here

foreach (something in something){ 
if (some condition){
myVarName=blah;
}
else{
myVarName=bloop;
}
}
return f(myVarName); // <-- uninitialized local variable error here
}

I get an error that myVarName on the last line is uninitialized. Stepping through shows that the variable is being assigned correctly in the foreach block. 

I read the web and it says that variables are scoped to the block in which they are declared. Since that's exactly what I have, I am very confused.

For no real reason, I try this:

public OutputType functionName(){
MyDataType myVarName;

myVarName=doodle; // <-- frivolous assignment

foreach (something in something){
if (some condition){
myVarName=blah;
}
else{
myVarName=bloop;
}
}
return f(myVarName); // <-- no error
}

And it works fine.

This tells me that local variables are scoped to the block in which they are first assigned

Even thought that specifically contradicts microsoft.com.

Ouch!

Safari Screws Up Dates!

I just spent an annoying hour dealing with the fact that Safari's Javascript engine does not correctly parse standard (ECMA-262) date strings.

Here is a valid date string (coming from my database server):

2012-01-01T00:00:00

Creating a date object is simple:

dateObj=new Date('2012-01-31T00:00:00');

and this works great in every browser except Safari. Safari tells you you have an "invalid date".

After screwing around way too much, I found that this works:

dateObj=new Date('2012/01/31');

And so, I changed my code to:

dateString='2012-01-31T00:00:00'.replace(/t.*$/, '').replace(/-/g, '/'); //ie, '2012/01/31'
dateObj=new Date(dateString);

I'm guessing that, if you needed the time, you'd have to split that off the string and use:

dateObj.setHours(blah);

but I don't have time, or need, to figure that out now.