Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: php

  • Apache 2.4 Kiboshed SPDY

    Apache 2.4 Kiboshed SPDY

    I have a store running on SSL for security reasons. I mean, you kind of have to, right? The problem is you don’t really want to cache SSL pages, as I reminded myself lately. At best, I was able to work around PageSpeed’s idiosyncrasies and compress the HTML and JS somewhat, but still I know that there has to be a better way.

    Everyone told me to look at SPDY. Now… this came with some issues. I needed Apache 2.2.4 (I was on 2.2.2):

    	httpd >= 2.2.4 is needed by mod-spdy-beta-0.9.4.1-397.x86_64
    	mod_ssl >= 2.2 is needed by mod-spdy-beta-0.9.4.1-397.x86_64
    

    race car driving very fastWhat’s an elf to do? Well… what about Apache 2.4? After all, it’s the latest and greatest. This is when my eyebrows jumped. There’s no support for Apache 2.4. And the mod release is only on SPDY 2 when the release is on SPDY 3.1? What on earth is Google doing!? Apparently giving up on mod_spdy which is horrible. Love the open source community though. Patrick Buckley forked it. I cannot stress enough the requirements in life to check into some random stranger before you just download and use their code. Especially when we’re talking servers! Sadly, looking into his code I saw it would upgrade apache and SSL.

    Well. No. It’s not that I don’t trust this guy, the code looks okay. It’s trying to install HTTPD 2.4.7 which is not the latest and greatest for my server’s OS (currently 2.4.9). Not to mention some research on cPanel showed issues with mod_spdy and CentOS (including the note that Patrick’s code caused random coredumps). However. The odds are that when, eventually, the stars align and there is mod_spdy (or some alternative) for Apache, it’ll be for 2.4.x so I may as well put the effort into updating today.

    Sidebar. Yes I know about nginx. Yes I’m aware of the package for CentOS. Yes I know it’s faster for static files and CSS and JS (and arguably even for PHP). Yes I know it’s easier to use default nginx than to tune Apache. But. I like having my .htaccess file to edit, and I’m not ready to do a total switch yet since this is not my server for me alone. Eventually yes, I will. Today is not that day.

    So Apache 2.4! There aren’t a lot of Apache 2.4 issues, but what they have are major enough for me to sit up and pay attention. For example, MPM-itk is no longer provided as an easy install from cPanel, they wanted me to use mod_ruid2, which isn’t compatible with memcache. I really hate that. However. Many people informed me you can still use memcached, and besides which, Apache 2.4 doesn’t support Memcache. I still find it amusing that Cpanel outright says mod_ruid2 is just as dangerous as MPM-itk, but would rather use the one that’s less compatible. It’s not that I can’t install it on my own, of course, it’s as the amount of effort put into working around a problem gets large, the less pleased I am with that as a solution. Work smarter. By the way, mod_ruid2 is available on Apache 2.4. I learned a lot when I installed it myself, now I’ll learn more.

    There was a catch in things of course. I’d set up mpm.conf files in /usr/local/apache/conf/userdata/std/2/ and had to roll those back, as they borked deployment. Took me an hour to sort out that. Remember to read the complete errors, folks. Of course I tested things once Apache 2.4 was up, before starting to make sure all my modules etc were still running. I was lucky, I only had to configure pagespeed for Apache 2.4. Everything else worked out of the box. Since I was using MPM Prefork already (worker is not available due to mod_ruid2) I didn’t have to edit anything there.

    Devil food cakeWhat did I notice? Memory and load stayed the same. And you’d think that meant this was for nothing. I should mention this happened to be on the same day I got nailed by a 60% bump in traffic on my busiest site. So … that would be better then.

    I’m bummed that SPDY isn’t being actively developed for Apache right now, though. For folks who are pushing the HTTP 2.0 world, they seem intent on ignoring or not committing to getting others up to speed. While nginx is awesome, there will always be a reason for people to use other server types. I hope to either see mod_spdy get picked up and loved again, or for someone else (Microsoft’s HTTP S&M?) to pick up the thread and remember that abandonment doesn’t move things forward as fast as you’d think.

  • Polyphemus Problem Pans Out

    Polyphemus Problem Pans Out

    I use PHP in DSO mode, which is (woefully) insecure because it lives to save files as ‘nobody.’ Now, previously I found a ‘fix’ to this with WordPress, by tweaking some file permissions and a define in my wp-config.php file, and all was well. But if you know me, you know I’m polyamorus with my CMS, and WordPress ain’t the only game in town.

    I love, love, love Zenphoto for a gallery that is larger than my thumbdrive. But I’ve been having an annoyance that acrylian and sbillard have been really patient with me ranting about for a while now. See, when you upgrade Zenphoto, it narked at me that I had bad permissions:

    zenphoto-perms

    Oh how I cried. My work-around became to make those 777, upgrade, and change ’em back to 755, because that did work for nobody, but when Zenphoto moved the config file and had it be writable by the upgrader, I had to make that owned by nobody and the slippery slope was happening. This was not good. I brought it up again, but we all agreed this was very much a me-problem.

    A new PHP

    Now my choices were to deal with it, or change to a new PHP. Well there are problems with that, and neither suPHP nor FastCGI met my needs for speed and memory consumption. Also I tend to get error 500s when I try any of them on this server, which means I would have to do a total overhaul which I don’t have time for. Instead, I decided to look into why mod_php (aka DSO) likes to have nobody own this stuff. In my research, I stumbled across mod_ruid2, which is included in EasyApache.

    Gruppo_di_polifemo,_sperlonga_0In reading up on cPanel’s notes on mod_ruid2, I hit the incompatibilities list and winced. Right there near the top was MemCache. When I switched over to ZendOptimizer, I also switched to MemCache, and I really was not ready to give it up and go to XCache. Worse? It’s not compatible with mod_security. Epic fail. I absolutely cannot use this. Back to the drawing board until cPanel figures out a way to force it to work with those.

    More searching introduced me to MPM-itk. This was something categorically not supported by cPanel (they backed mod_ruid2), but they still had some directions on how to do this in their forums: Using MPM ITK as a Custom Opt Module

    I need to stress two very important things here:

    1) This is NOT supported by cPanel.

    They do include it in their Custom Mods, but they don’t support it’s use, and won’t include it by default because of issue number 2 (see below). Mind you, I’m no stranger to unsupported installs. I have ImageMagick in a higher version than they do, I installed wp-cli, and I have Pagespeed. So I pretty much run around always upgrading what I need. I am smarter than I used to be, and I have all this documented in a Word Doc called “Custom Installs on my server” which lives on Dropbox, for emergencies. Everything is written with code examples and as much copy/pasta as I can.

    2) There is a security risk with mpm-itk because it runs as root.

    I will quote the author:

    Since mpm-itk has to be able to setuid(), it runs as root (although restricted with POSIX capabilities and seccomp v2 where possible) until the request is parsed and the vhost determined. This means that any code execution hole before the request is parsed will be a potential root security hole. (The most likely place is probably in mod_ssl.) This is not likely to change in the near future, as socket passing, the most likely alternative solution, is very hard to get to work properly in a number of common use cases (e.g. SSL).

    Obviously this is a choice you need to make yourself. Perhaps ironically, by using setuid(), you’re protected from users cross-contaminating but this is not really a perfect fix for everyone. And frankly, this is not my preferred long term fix. My long term fix is this: Build a brand new server, from scratch, with FastCGI, and move sites over one at a time, testing as I go. That’s not today. Instead, it took me about an hour to figure this stuff out and install. And it worked out of the box. Well, except for one thing which I’ll get to.

    Installing mpm-itk

    These directions are pretty easy for cPanel/WHM. You install:

    cd ~/tmp
    wget http://docs.cpanel.net/twiki/pub/EasyApache3/CustomMods/MPMitk.tar.gz
    tar -C /var/cpanel/easy/apache/custom_opt_mods -xzf MPMitk.tar.gz
    

    Then you run EasyApache (/scripts/easyapache) and select mpm-itk from the Exhaustive Options list for PHP (it will give you a warning about the dangers, Will Robinson). Once the update is done, make sure all your normal settings are back in place, if you have anything special, and now you have to actually tell every virtual host what ID to use.

    mkdir -p /usr/local/apache/conf/userdata/std/2/username
    echo "AssignUserID username username" >> /usr/local/apache/conf/userdata/std/2/username/mpm.conf
    /scripts/ensure_vhost_includes --user=username
    

    Replace ‘username’ with your user name (you saw that coming, right?) and off you go. Of course, I had 10 users, so instead I scripted it:

    #!/bin/bash
    for user in `ls /var/cpanel/users`; do
        mkdir -p /usr/local/apache/conf/userdata/std/2/${user}
        echo "AssignUserID ${user} ${user}" >> /usr/local/apache/conf/userdata/std/2/${user}/mpm.conf
        /scripts/ensure_vhost_includes --user=${user}
    done
    

    Huzzah!

    Cleanup, Aisle PHP

    Once I had it installed, and it really was painless, I tested uploads on WordPress and everything worked. But I remembered what I had done back in 2011:

    The last step I had was chowning the folder for uploads and 2011 to nobody:nobody.

    This time I did it in reverse and chowned everything back to my user IDs. I did this for all sites, for all users, and all cache folders. Then I decided to look for all files and folders that were 777 (which I do at work when scanning for hacks) just in case I’d been stupid. I try to not be, but…

    find . -type d -perm 0777
    

    That listed all directories, and I was appalled to find some! That’s right. Up until recently, there were folders permission’d as 777 on my server. I bow my head in shame and embarrassment. Please forgive me, as I run this command to fix that:

    find . -type d -perm 777 -print -exec chmod 755 {} \;
    

    I also ran find . -group nobody to see if I had anything left over, and it happily came up empty. Then I went to double check everything worked. When I’d tested before, I did it on my single install of WP, my wiki, my gallery, another blog, and it worked. So I came here to post and I couldn’t upload images. Horror! Shock! I decided to scan my error log, and right away got a warning on cPanel: Out of disk quota.

    Well that was an easy fix!

    Now everything’s owned by the user it runs for, and nobody owns anything. Everything is secure (except for that ‘running setuid as root for a millisecond’ issue, and yes I’m keeping tabs on that), and everyone is happy. Especially me.

    Bonus Internet points if you get the joke with the title.

  • Customizing Author’s Comments on Genesis

    Customizing Author’s Comments on Genesis

    commentsI like Genesis, but I wanted to make some tweaks to how comments looked.

    1) Bigger Avatar Size
    2) ‘Mark’ post authors and site admins

    This was pretty easy, since they have a filter in for comments, so all I had to do what tell it to replace their avatar size with mine, and then to use my callback. It’s in my callback that I did an extra check. If the commenter is an admin, they’re labled ‘Site Admin’ and if they’re the post author, it’s ‘Post Author.’

    The end result looks like this (I’m commenting on a CSI episode where someone’s hiding in the walls):

    Example Comment

    The only hard part of the code was finding I can’t filter the comment callback, but I have to totally replace it with my own. Bummer, but not insurmountable. StudioPress has a nice document on comment filters which explained how I could override settings like avatar size and callback, which lead me to my next step, the filter:

    // Customize Comments for avatar size and MY callback
    add_filter('genesis_comment_list_args', 'mysite_comment_list_args');
        function mysite_comment_list_args($args) {
            $args['avatar_size'] = '90';
            $args['callback'] = 'mysite_comment_callback';
            return $args;
    }
    

    Once I have the filter, I have to create the mysite_comment_callback. This is something I basically copied from the source of my theme, taking the whole function for genesis_comment_callback and changing what I wanted.

    /** replace comment callback with my own **/
    function mysite_comment_callback( $comment, $args, $depth ) {
    
    	$GLOBALS['comment'] = $comment; 
    	global $post; 
    	?>
    
    	<li <?php comment_class(); ?> id="comment-<?php comment_ID(); ?>">
    
    		<?php do_action( 'genesis_before_comment' ); ?>
    
    		<div class="comment-header">
    			<div class="comment-author vcard">
    				<?php echo get_avatar( $comment, $size = $args&#91;'avatar_size'&#93; ); ?>
    				<?php echo ( user_can( $comment->user_id, 'administrator' ) ) ? '<span class="mysite-title">Site Admin</span>' : (
    						( $comment->user_id === $post->post_author ) ? '<span class="mysite-title">Post author</span>' : '' ) ; ?>
    				
    				<?php printf( '<cite><span class="fn">%1$s</span></cite> <span class="says">%2$s:</span>',
    						get_comment_author_link(), 
    						apply_filters( 'comment_author_says_text', __( 'says', 'genesis' ) ) ); ?>
    		 	</div><!-- end .comment-author -->
    
    			<div class="comment-meta commentmetadata">
    				<a href="<?php echo esc_url( get_comment_link( $comment->comment_ID ) ); ?>"><?php printf( __( '%1$s at %2$s', 'genesis' ), get_comment_date(), get_comment_time() ); ?></a>
    				<?php edit_comment_link( __( '(Edit)', 'genesis' ), '' ); ?>
    			</div><!-- end .comment-meta -->
    		</div>
    
    		<div class="comment-content">
    			<?php if ( $comment->comment_approved == '0' ) : ?>
    				<p class="alert"><?php echo apply_filters( 'genesis_comment_awaiting_moderation', __( 'Your comment is awaiting moderation.', 'genesis' ) ); ?></p>
    			<?php endif; ?>
    
    			<?php comment_text(); ?>
    		</div><!-- end .comment-content -->
    
    		<div class="reply">
    			<?php comment_reply_link( array_merge( $args, array( 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?>
    		</div>
    
    		<?php do_action( 'genesis_after_comment' );
    
    	/** No ending </li> tag because of comment threading */
    
    }
    

    Finally it was a simple CSS to make it look snazzy.

    .bypostauthor span.mysite-title {
    	padding: 2px 5px;
    	padding: 0.15rem 0.4rem;
    	font-size: 11px;
    	font-size: 0.785714286rem;
    	line-height: 1;
    	font-weight: normal;
    	color: #7c7c7c;
    	background-color: #FFFFCC;
    	background-repeat: repeat-x;
    	background-image: -moz-linear-gradient(top, #ffc, #fc3);
    	background-image: -ms-linear-gradient(top, #ffc, #fc3);
    	background-image: -webkit-linear-gradient(top, #ffc, #fc3);
    	background-image: -o-linear-gradient(top, #ffc, #fc3);
    	background-image: linear-gradient(top, #ffc, #fc3);
    	border: 1px solid #d2d2d2;
    	border-radius: 3px;
    	box-shadow: 0 1px 2px rgba(64, 64, 64, 0.1);
    	float: right;
    }
    

    I should point out that I have no experience with editing comments.

  • Kick PageSpeed Up A Notch

    If you’re using Apache and PHP 5.3 on your DreamHost domain, you have the magical power to enable Google PageSpeed. Just go and edit your domain and make sure you check the box for “Page Speed Optimization”:

    PageSpeed Option

    But what does that even mean, I hear you ask?

    partnersPageSpeed is Google’s way to speed up the web (yeah, that was redundant), and it serves as a way for your server to do the work of caching and compressing, taking the load off your webapps. Like WordPress. Anyone can install this on their apache server, and it’s free from Google Developers: PageSpeed Mod. Since you’re on DreamHost, you lucky ducky you, we did it for you. Now you can sit back and relax.

    The first thing to notice when you turn on PageSpeed is that it minifies your webpage. That means it takes your pretty formatted source code and gets rid of the extra spaces you don’t use. This is called by using the PageSpeed filter “collapse_whitespace.” Another filter we use is “insert_ga” which is how we’re magically able to insert your Google Analytics for you from your panel. That filter automatically inserts your GA code on every page on your domain. That’s right! No more plugins!

    If you’re like me, you may start to wonder what other filters you should use, and that entirely depend on what you want to remove. I knew I wanted to remove code comments like the following:

    <!-- #site-navigation -->
    

    That’s easy! There’s a filter for “remove_comments” so I can just use that. They have a whole mess of filters listed in the Filter Documentation and reading through it took a while. If you read each one, at the bottom they talk about how risky a certain filter is. Taking that into account, I went ahead and added some low and some high risk filters, since I know what I’m using.

    The magic sauce to add all this is just to edit your .htaccess and put in the following near the top:

    <IfModule pagespeed_module>
        ModPagespeed on
        ModPagespeedEnableFilters remove_comments,rewrite_javascript,rewrite_css,rewrite_images
        ModPagespeedEnableFilters elide_attributes,defer_javascript,move_css_to_head
        ModPagespeedJpegRecompressionQuality -1
    </IfModule>
    

    Really, that’s it.

    The ones I picked are:

    • remove_comments – Remove HTML comments (low risk)
    • rewrite_javascript – minifies JS (med. to high risk, depending on your site)
    • rewrite_css – parses linked and inline CSS, rewrites the images found and minifies the CSS (med. risk)
    • rewrite_images – compresses and optomizes images (med. risk)
    • elide_attributes – removing attributes from tags (med. risk)
    • defer_javascript – combines JS and puts it at the end of your file (high risk AND experimental!)
    • move_css_to_head – combines CSS and moves it to the head of your file (low risk)

    Now keep in mind, not all of the features will work. While DreamHost is on a pretty cutting edge version of PageSpeed, they’re constantly innovating over there and improving. The best thing about these changes is, if you do it right, you can speed your site up faster than any plugin could do for you. And that? Is pretty cool right there.