The New Web Stack

Just tossing this out there as it's pretty new and exciting for me. Most folks who know what's going on here won't get anything new out of it. I just felt like writing about a new, shiny toy.

I've been writing tons of web code for nearly 20 years now. On the back-end, I started with C and Perl, and graduated to PHP. I've tried a handful of other things (server-side JavaScript, LUA, Java), but PHP always felt like home. It wasn't a general-purpose language trying to plug itself into a web server. It was purpose built for serving HTTP requests.

Behind the PHP, I've always had an Apache web server, and my persistence was either files or MySQL databases.

Lately, though, I've been struggling with PHP in terms of code re-use. I've found I have to exercise a lot of discipline, and spend a fair amount of design effort to get relatively straight-forward chunks of PHP to have a life much beyond the original use case.

For non-web prototyping and tooling, I've been experiencing a bit of programming renaissance with Python. It truly does let me focus on the problem, and not the environment/setup/deployment. I get some amazing cross-platform tools with little effort. I can restrict myself with fewer rules/idioms, and get easily-maintainable and re-usable code. I am always shocked when I find code I wrote for another purpose entirely just plugging directly into a new tool and working like a champ.

I decided it was time to give Python a try on the web server. There is certainly some friction for those of us used to "live" scripts that are immediately available when you make a change. But, on the whole, I might have stumbled onto a more powerful (and re-usable) platform on which to build web back-ends.

While I was at it, I decided to go ahead and yank my entire stack, and start over. Here's where I stand today.

The OS

The host OS is still FreeBSD. After having toyed with Linux for unrelated purposes, and even built an embedded web server on a single-board computer, I absolutely cannot stand Linux for use as a server. It seems the simplest management tasks are hidden behind several, competing tools that are supposed to help you. Why can't everything be text files (in sane locations) and shell scripts? I'm already sick of sym-linking configs as a kind of "switch" to enable things.

That's not to say I'm using FreeBSD like I ever have. The improvements over the last few years are utterly staggering. I started using ZFS, and while I'm nowhere near qualified to describe its benefits, I greatly enjoy the additional data protection. I switched all my externally-accessible services to run inside jails. I always wanted better isolation, and jails have made it so trivially easy, I create and destroy jails all the time just to test things out. I'm also really enjoying the features and clarity of the OpenBSD-derived packet filter (pf) for handling my firewalls. IPFW wasn't necessarily bad, but I was always skittish about making any changes for fear of some silly mistake in the configs causing me to "lose" the server. pf has restored my confidence in my ability to configure a robust and useful firewall. Lastly, I am now a fan of binary distributions. Yeah, building everything from source code is easy (and kinda cool), but I got things to do! The next-generation package management (that integrates with the ports collection) is something that still impresses me. Keeping the entire OS and user-land applications up-to-date has never been easier. FreeBSD is still the king of all server operating systems.

Data Persistence

Okay, so this isn't as big of a change as some of the other things, but I took the plunge, and dropped MySQL like a bad habit. MariaDB works exactly like it is intended to work: as a drop-in replacement for MySQL. I haven't noticed any differences, and the project is now more active than ever.

Web Server

I've always wanted to try something that isn't Apache. Lighttpd and Nginx are very common "lightweight" alternatives to Apache, and Apache seems to be losing its mind lately. Why do I need this cumbersome "Apache Runtime" to install the stupid server? I also get the feeling the Apache devs rather do all their development in Java, and forget they ever had a high-performance, cross-platform web server that grew up from the very creator of the world-wide web.

Going purely based on my knowledge that Netflix (a huge FreeBSD supporter/user) uses Nginx for their high-load systems, I decided to give it a try. So far, I feel like this thing is stripped down to exactly what you need and not a thousand other bells and whistles. The configuration and management feels "tighter" than Apache. It gives me the impression that I'm not herding cats, but tuning a Chevy small-block that's about to fly off the jack stands as soon as I let go. I have yet to do any meaningful bench-marking with it, but my hopes are high that I can do some relatively fair tests between my existing Apache server and a new Nginx server running in separate jails on the same hardware.

Application Environment

This is where I've had to learn the most in the last few weeks. I haven't deployed CGI-like applications in quite a while (read: CGI sucks). When I saw a lot of folks deploying Python over "FastCGI," I always cringed. I know it's 100% better than the old CGI, but why can't they name it something friendlier?

I got a FastCGI container around Python, and was able to serve a few pages from Python code through my old Apache server. It really didn't convince me that I was going to have a great time with the new regime. But, when I moved over to Nginx things changed.

I found that most folks were deploying Python applications behind a new protocol: WSGI. The common WSGI host (I've found) is uWSGI. The documentation appears good, so far, so I spun up a uWSGI daemon in the same jail as my shiny, new Nginx server. That took about five minutes (mostly just to realize I could use the "ini" config alongside the rc.conf switches).

In no time, I was hooking up some existing Python code, and spewing out JSON responses like a pro. For the modern web, the back-end is no longer generating the display (like we all learned to do with PHP). The back-end's greater responsibility is to provide application access over HTTP. This shift in philosophy has only convinced me more that I should have been looking into this stuff a long time ago.

Conclusion

Here are some idiotic acronyms to help put things in perspective for the ADHD crowd that are frequently employed in web development:

I've never (willingly) run a LAMP (Linux + Apache + MySQL + PHP) stack because I don't like Linux on the server. Since PHP 3 was out in the wild, I've been running FAMP (F=FreeBSD) stacks. Some of these systems have over a decade of continuous service (clarification: not to be confused with uptime; I patch my systems). Today, though, I'm looking at a really fancy, new stack: FNMP (FreeBSD + Nginx + MariaDB + Python). I get excited just thinking about all the goofy personal projects that I can spin up or port over from my PHP applications.

In a future post, I hope to post some config files and my benchmark results. I'm also trying to bring up some pretty simple services that could potentially serve a wider audience than myself, so stay tuned!