Edit: I realise that this may not be clear from the answer below... but from the point of view of your application, it doesn't really make any difference whether you run the PKI/CA yourself or whether you use one or more third-party CAs. Even if you choose to run your own PKI, you really don't want to code it yourself - so you'd use one of the existing ones, which would be logically separate from the application, and any interaction with the CA would be via the usual protocols. End of edit
Should I really be operating a PKI and issuing the certs myself?
As a general rule, unless you already know how to run a PKI, you shouldn't be doing it. It's a lot more complicated than you'd think, and a lot more ways that things can go wrong. Even companies that do PKI as their core business get it wrong sometimes; see Diginotar who had their certificate infrastructure hacked and eventually went bankrupt.
Allowing third-party certificates, especially by multiple CAs, has its own pitfalls. I have a smartcard that contains my electronic ID that I use to access my bank and several government sites. But I might also have a "soft" certificate that I use to access other things. If your site would accept both those certificate authorities, would you have any way to know that those two certificates refer to the same person (or user)? Would you want to have one user per certificate, or would you want one user to be able to use more than one certificate? What happens when a certificate expires - how would you know that my new certificate still refers to me? These questions need to be considered carefully when you design your applications and chains of trust.
Is there a way of making them behave just like SSH keys, the user
presents any key during signup and that key is bound to the account?
This is just a Small Matter Of Programming... (In other words, not so small, but not impossible.) You'd probably want some way for the user to add/remove certificates, too.
About verifying them in my app, most documentation I've found makes
the web server check the certs against a CA (my own CA in this case,
which brings us back to the PKI problem) and setting an environment
variable if the cert is trusted ... that wouldn't work in my case as
I'd like to get rid of the CA and have the clients provide their own
certs, so based on the fact that I can't rely on checking them against
a CA, what can I check them against? Do client certs have the
equivalent of the SSH public key I can just store in my DB and check
You wouldn't save the entire certificate, you'd just save enough information that you can verify the certificate the next time the user presents it. This would usually be the certificate serial number, the CN and the issuing CA. You might also want to store the expiry date, so that you can remind users to renew their certificates before they expire. (This could of course be done when you check their certificates at login time, but it might be wise to store the data so you can email a reminder in case they don't login during the time they would have got the warning.)
Even when a certificate is issued by a third-party CA, the certificate will contain information about how you can verify its validity. This will usually be by OCSP (Online Certificate Status Protocol), which is a real-time check against the issuing CA's database. There's also CRL, a Certificate Revocation List, which contains information on which certificates are revoked by the CA. This is not real-time; the CRL will be re-issued at intervals.
Finally, how would a new customer go about signing up to my website;
he's asked to present a cert and he doesn't have any, how does he
If you choose to use third-party CAs, you should give them a link to one or more of the CAs you trust.
If you run your own CA, you'd give them a link to that CA, which would have to be configured to allow (previously) anonymous users, as well as existing users, to request a new certificate.
Finally, if you want to have a look at setting up a PKI, you could try out EJBCA, an open-source CA/VA. It will give you a basic idea of the complexities involved.
passwords.txtbut with even worse usability"? The certs can be completely public.
passwords.txtfile -- the server can send a list of authorized CAs for the client cert, and the browser can then only offer the user a choice of certificates signed by those CAs. If the server sends itself as the only CA allowed, then the browser will only offer the user the certificate from that site -- more like a password manager than