In the early days we ran the Ruby code through an obfuscator (which came along with its own set of problems), since we offered a downloadable free trial and didn't know how paranoid we needed to be. Still, much of the codebase remained unobfuscated (CSS, scripts, etc). The hardest part was trying to discourage legit customers not to mess directly with the code, as it made upgrades nearly impossible to manage. To avoid this, we focused on building extensibility APIs into the product that would be useful for all customers. Our licenses, of course, also stipulated the things you mentioned, but hackers will be hackers, so we had to deal with some interesting circumstances from time to time.