Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: administration

  • Mailbag: Curbing Comments By Count

    Mailbag: Curbing Comments By Count

    Someone had a rant in my mailbox about my strong stance on comment moderation, which can be distilled to this question:

    I noticed you really have strong opinions on comment moderation. Do you use anything other than bad words to flag for moderation or outright block?

    Sure do!

    I’m very careful about ‘bad words’ since ‘anal’ will also pick up ‘canal’ and I only moderate for for things that are generally only used as a pejorative. Example? Okay, I have ‘dyke’ and ‘kike’ in my mod list. The first one I get called a lot. Still. The second has fallen out of favor. But because people have a remarkable talent to say words with the sole intent to be hurtful, even under the veneer of “I was just being funny, stop being so sensitive!” I have cherry-picked the popular ones on my sites and tossed them into moderation.

    The only thing I blacklist are people. People’s emails (and user names sometimes) go into the blacklist. That’s why I wrote Sitewide Comment Control, I’m able to blacklist people from the whole network easily. But I only use this for people. People should be blacklisted when they prove themselves to be untrainable.

    That leaves one thing up in the air and that’s moderation. You have three choices with default WordPress: Moderate all, moderate un-approved, moderate none.

    I have “moderate un-approved” which means I have to manually approve all first time comments. To add on to that, I use Comment Probation in order to restrict people I’m not entirely sure about.

    And finally, I moderate by length.

    I month ago, I mentioned on Twitter that I was playing with an idea to have my comments moderated by length. If a comment was over X words long, it should be flagged as needing approval before showing.

    Caspar Hübinger, in the time it took me to get a cup of coffee, wrote Comment Moderation by Word Count. I made one, small, patch to it, and I’m using it now.

    This simple WordPress plugin will send any comment that would otherwise be approved automatically by WordPress to the moderation queue if it contains more than a given number of words.

    The theory I have is this: If your comment is over a certain length, you really may want to consider making it a rebuttal blog post of your own. My limit is currently set to 250 words here, which is half a page of content.

    Mod by comment length is a very basic field on your Comment Settings section

    My one change was this:

    If current_user_can( 'edit_posts' ) then they should be able to leave a comment of any length without moderation.

    My theory here was that admins and editors are trusted users.

    And now you know!

  • Static Content Subdomain

    Static Content Subdomain

    I use a lot of different tools to run my websites, and over time I’ve learned what I want is to have my static content, the files that are uploaded and are images, stored separately from my apps. So while I have the basic folders on my domain (wordpress, wiki, gallery) I have a special subdomain called static.example.com for all those images and videos.

    There are a few reasons I do this. First, I like having my images separate. Second, it allows me to establish a cookie-free subdomain for images and that shuts up YSlow’s check.

    Create The Subdomain

    Do this however your host allows. Keep in mind that some don’t allow you to traverse domain folders. If your host creates your domain as /home/user/example.com and subdomains as /home/user/static.example.com you may have to fight a little more with things depending on your setup. If possible, I prefer to put the subdomain folder inside the main web root.

    If you’re using cPanel, by default you get your static subdomain installed at /home/user/public_html/static which is how I like it. This is perfectly accessible by all things but it’s also browsable at example.com/static/ and we don’t want that. Applying a little .htaccess magic will solve this.

    # CDN
    <If "%{HTTP_HOST} == 'example.com' ">
            RedirectMatch ^/static/(.*)$ http://static.example.com/$1
    </If>
    

    Now we’re ready to go!

    Move WordPress Uploads

    This used to be really easy. Go to Settings -> Media and change things. But we removed that to stop people from blowing themselves up. Now there are a couple ways about it. I jumped right over to editing the options by going to wp-admin/options.php and look for upload_path and upload_url_path.

    Setting image location options

    I change upload_path to /home/example/public_html/static/wordpress which is where I’ve moved all my images. Then upload_url_path becomes http://static.example.com/wordpress and I’m done except for fixing my old posts. It’s actually pretty neat that once I put those paths in, the Media Settings page lists them as editable.

    Fixing the old posts takes a little trick though, and you’ll have to search/replace your posts via the database:

    UPDATE wp_posts SET post_content = REPLACE(post_content,'http://example.com/wp-content/uploads/','http://static.example.com/wordpress/');
    

    Or in wp-cli:

    wp search-replace http://example.com/wordpress/wp-content/uploads http://example.com/wordpress
    

    The gotcha here is that since I use SSL for my administration, I had to set up a new certificate for the static domain. Not a big deal right now since I can set up a self-signed, or use StartSSL until Let’s Encrypt is off the ground. It is something to consider though.

    Move ZenPhoto Uploads

    I have to start by warning you that Zenphoto doesn’t like this. When you install it, it puts your images in an albums folder, in the Zenphoto gallery install. This isn’t so bad, but you actually can move it around. You have to look in your zenphoto.cfg.php file (found in zp-data). The default location for your albums is defined by this:

    $conf['album_folder'] = '/albums/';
    $conf['album_folder_class'] = 'std';
    

    Since I want it in the static location, I tell it my folder path based on ‘web root’ and that its ‘in_webpath’ (which tells ZenPhoto to look in the root and not relative), by changing that section to this:

    $conf['album_folder'] = '/static/gallery/albums/';
    $conf['album_folder_class'] = 'in_webpath';
    

    But that means my URLs for images become http://example.com/static/gallery/albums... and I wanted http://static.example.com/gallery/albums... instead. Thankfully the .htaccess rule I used at the beginning of all this covers me there. Looking into this, I understand this is the case because unlike MediaWiki or WordPress, ZenPhoto only has one ‘location’ setting. The other two have path and URL.

    MediaWiki

    This was … weird. Technically all you have to do is set up the folders and change the following values in LocalSettings.php:

    $wgUploadPath       = "/static/wiki";
    $wgUploadDirectory  = "/home/example/public_html/static/wiki/";
    

    The thing that’s weird is that the documentation says you can do this:

    $wgUploadPath       = "http://static.example.com/wiki";
    

    And when you do, the image URLs properly call from the domain name. They just won’t load. When you dig deeper, it turns out that it’s caused by the settings for responsive images. The way it puts in srcset doesn’t seem to like this. So for now I’ve disabled it and my setup is this:

    $wgUploadPath       = "http://static.example.com/wiki";
    $wgUploadDirectory  = "/home/example/public_html/static/wiki/";
    $wgResponsiveImages = false;
    

    End Result?

    All my uploaded content is on my ‘static’ subdomain, separate from everything else, which makes version control even easier. Also now if I ever decide to move things off to a CDN, I’m pretty well set up.

    The real reason I do this is that while some of my content is uploaded via the content management systems I use (WordPress, ZenPhoto, etc), the majority is not. ZenPhoto, for example, is faster to FTP up a gig of images than it is to use a PHP tool. Ditto videos. And because of them, it’s nice to have a separate location I can give access to without allowing someone full rights on all my tools.

  • Make or Break Yourself

    Make or Break Yourself

    How you react to adverse situations is what makes or breaks your business, not the fact that you had one in the first place.

    Taylor Swift recently penned an open letter to Apple Music. To Apple, Love Taylor lets us all in on a fact of the new Apple Music (their streaming service, coming soon for free for 3 months) that a lot of us didn’t know.

    I’m sure you are aware that Apple Music will be offering a free 3 month trial to anyone who signs up for the service. I’m not sure you know that Apple Music will not be paying writers, producers, or artists for those three months. I find it to be shocking, disappointing, and completely unlike this historically progressive and generous company.

    Three months where we get free music is great, but the cost of that free music was astronomical. As Taylor points out, it doesn’t hurt her, she has money. But the indie people will be terribly hurt by this, to the point that many of my indie friends pulled out of the trial too.

    Apple kowtowed in under 24 hours from that post. Eddie Cue (who’s the Apple mogul in charge of this project) replied on Twitter:

    I see a lot of people take criticism in some pretty appalling ways. I’ve been threatened with legal action for not deleting a one-star review of a plugin on WordPress.org. I’ve been vilified, called a Nazi or worse, and had my reputation blasted because I stood up for a user who didn’t like a product and left a bad review. I get insulted daily because I tell people “If someone misunderstood what your documentation said, you need to review your docs and consider updating them.”

    I’m glad I have a thick skin, because some days the things people say and accuse me of would make me cry. Sometimes they do, and those are the days I walk away and let someone else handle that person, or just take a break.

    In general, I believe in the inherent capability of goodness in humanity. I assume good faith. I presume that people who are leaving reviews aren’t generally doing it to attack me personally, but because they’re having a terrible day. Maybe they’re having the worst day of their life. And I, as an experienced support tech, know that they’re pretty much always going to be irrational.

    That’s the thing. People aren’t usually intentionally misleading, nor do they plan to make my life miserable. They’re having a bad day and it’s perceived to be my fault, so I’m sorry, but let me try to understand things better. How I reply to them depends on how they come to me with their issues, though. If they say ‘it’s broken!” (a common complaint, right?), I tell them I’m sorry and ask them if they can explain what, exactly, is broken. I may spend time clarifying with them “Do you mean X?” and I may ask “Why are you trying to do Y?” so I can understand the big picture.

    And then… those people who come at me and say “This person is lying and gave me a bad review!” I’m often inclined to side with the users, since a bad review is something that makes people overreact. But that doesn’t mean I dismiss the complaint out of hand. I check if the reviewer is a fake account (we have ways), and I check their history and their information and validate they’re real people before I reply. If they’re fake, I remove the reviews. If they’re not, I leave them be.

    Leaving them be is where most (if not all) of the hate comes from. You see, leaving them be is hurting businesses and ruining reputations.

    No. No they’re not.

    What ruins your reputation is how you reply to them. If you accuse them of being spammers or harassers, you make yourself look bad. If you lay into them because you disagree with their review, you make a fool of yourself. A review is a ‘how I feel’ from a user, and even though you may not agree with their conclusions, that doesn’t make their experience invalid. It means there was a breakdown in communication somewhere between you and them.

    This is why I tell people to check their documentation. If they’re getting a lot of bad reviews that are plain wrong, and they’re wasting a lot of time talking to people and correcting them, then the issue has to be, in part, the information they’ve presented up front. If its not there, add it. If it’s there, point them to it. “Actually I answered this in the FAQ where it says this plugin is Multisite only.” True story, I have to use that a lot.

    But when that question comes up time and again, I may ask “The FAQ covers this here LINK. Do you think there’s a better place I can put that? Where were you looking so I can make it more obvious for the next guy?”

    Maybe they never reply and fix that one-star review, but when people go and look at the reviews and see a one-star, and read it, they’ll see my mature, reasonable, honest reply. And that will do far more for my reputation than anything else.

  • Mailbag: Wrong Robots

    Mailbag: Wrong Robots

    I got an odd email from ‘Yan’ who, amidst the odd hate and sexist filled remarks that apparently I don’t like people in the WP community, had a legit question:

    Seen your post:

    But… Your actual robots.txt does not reflect the content of the article. Hmmm…

    Well. That was almost 2 years ago. And it never reflected the content of this site. I don’t care if this site has it’s images snagged. I have anti-hotlinking protection in my .htaccess anyway. It’s my other site, my massively major huge gallery with 10G of photos that I protect.

    That brings up a point that many people miss about this site. I’m not always talking about what I do here. For example, I talked about making a slide-up bit of code that duplicates WordPress.com’s follow tab. That email setup isn’t here and it never will be. I’m not particularly worried about my followers’ ability to find the sidebar email registration box there. This is a site for slightly more technical people.

    However, the site that code is on is a site visited by luddites, primarily. They want their news about their thing in a way that is simple, straightforward, and easy. They need a reminder. Also they share links on social media a lot, so making a slide-up that auto-pops when you come from Facebook or Tumblr or Twitter was the right choice to make sure people knew what was going on and how to sign up. It’s had amazing results.

    There are lessons I learn from running multiple sites and I bring them all back here to people who would appreciate them.

    Now if people wonder, yes I do think that Google’s still evil for how they hotlink images. Of course, I’d think them equally evil for copying my images. Image search is just a really messy thing. The two options you get for it is that either Google has a copy of all the images on the planet or they hotlink. Even assuming they’re clever enough to protect themselves from duplicate images using some sort of super powerful algorithm, you get those options and each has a problem. If you’ve copied everything, you have to have a file server the likes of which would make the pyramids look teeny tiny, and in both cases you need a database with enough speed to stop us all from running Google Pagespeed tests on Google.

    Am I the only one who does that? Oh. Sorry.

    We’re talking about Google being evil and robots.txt files. The site that I do block Google Images on has a very large robots:

    User-Agent: *
    # My stuff
    Disallow: /cgi_bin/
    
    # WordPress
    Disallow: /trackback/
    Disallow: /blog/
    Disallow: /wp/
    Disallow: /wordpress/wp-admin/
    Disallow: /wordpress/wp-includes/
    Disallow: /wordpress/xmlrpc.php
    Disallow: /wp-admin/
    Disallow: /wp-content/
    Disallow: /wp-includes/
    Disallow: /xmlrpc.php
    Disallow: /wp-
    
    # Gallery
    Disallow: /gallery/albums/
    Disallow: /gallery/themes/
    Disallow: /gallery/zp-core/
    Disallow: /gallery/zp-data/
    Disallow: /gallery/page/search/
    Disallow: /gallery/uploaded/
    Disallow: /gallery/rss.php
    Disallow: /gallery/rss-comments.php
    Disallow: /gallery/README.html
    Disallow: /gallery/rss-news-comments.php
    Disallow: /gallery/rss-news.php
    
    # Wiki
    Disallow: /wiki/images/
    Disallow: /wiki/bin/
    Disallow: /wiki/cache/
    Disallow: /wiki/config/
    Disallow: /wiki/docs/
    Disallow: /wiki/extensions/
    Disallow: /wiki/languages/
    Disallow: /wiki/maintenance/
    Disallow: /wiki/math/
    Disallow: /wiki/public/
    Disallow: /wiki/serialized/
    Disallow: /wiki/tests/
    Disallow: /wiki/skins/
    Disallow: /wiki/t/
    Disallow: /wiki/index.php
    
    User-agent: Mediapartners-Google
    Allow: /
    
    User-agent: Adsbot-Google
    Allow: /
    
    User-agent: Googlebot-Image
    Disallow: /
    
    User-agent: Googlebot-Mobile
    Allow: /
    
    User-agent: Browsershots
    Allow: /
    
    User-agent: Dotbot
    Allow: / 
    

    So yes, actually, I am still using that code. There you are.

  • Learning nginx

    Learning nginx

    I’m an nginx rookie. In fact, I moved a site specifically to nginx so I could sit and learn it. While this site, today, is ‘on’ nginx, it’s actually an nginx proxy that sits in front of Apache 2.4, not because I think Apache is necessarily better, but because after all this time, I still can’t stand the loss of the dynamism of my .htaccess.

    When I was experimenting, though, one of the things I started to do was recreate my ‘tinfoil hat’ .htaccess rules in nginx. What are ‘tinfoil hat rules’? They’re things I’ve tweaked in .htaccess to make it harder for nefarious people to look at my code and get into my servers. They’re also general ‘stop being from being jerks’ rules (like preventing hotlinking).

    This isn’t complete, but it’s everything I’d started to compile and test.

    Header

    ######################
    # TinFoil Hat Rules
    

    This is pretty basic, I like to document my section before I get too far into this.

    Directory Listing

    # Directory Index Off
    location  /  {
      autoindex  on;
    }
    

    Directory listing is like when you go to domain.com/images/ and you get a list of all their images. This is just a bad idea, as people can also use it to list PHP files you might have (many plugins lack an index.php, and no, this isn’t a bad thing). This simple rule will protect you.

    Hotlinking

    # Hotlinking
    location ~* (.jpg|.png|.jpeg|.gif)$ {
        valid_referers blocked elftest.net *.elftest.net;
        if ($invalid_referer) {
            return 444;
        }
    }
    

    Ah. Hotlinking. This is in-line using images from someone else’s server, like <img src="http://example.com/images/yourimage.jpg" /> – If I’m on example.com, that’s fine. If I’m not then that’s bad. Never ever hotlink images unless the site provides you a hotlinking URL. I cannot stress this enough.

    This code comes straight from the nginx wiki, and works great.

    Protecting wp-config.php

    This is pretty straightforward. I want to block anyone from hitting that directly, any time, any where.

    location /wp-config.php {
        deny all;
    }
    

    Done.

    Brute Force Protection

    If you have ngx_http_limit_req_module module then you can rate-limit how many requests an IP can give to a file.

    location /wp-login.php {
        limit_req zone=one burst=5;
    }
    

    And that’s all I got to…

    And that is, sadly, as far as I got before I started playing with Apache 2.4 and enjoying the ifs of that, over nginx. What about you? What are your nginx security tweaks?

  • Switching The Main Blog on Multisite

    Switching The Main Blog on Multisite

    Previously I’d only ever posted this in my ebook, WordPress Multisite 110.

    What people mean by this is the site they originally set to be seen at domain.com is no longer the one they want to use, but the one at (say) domain.com/temp or temp.domain.com. If this is what you’re wanting to due, it’s not impossible, but it is annoying and a little tricky. If you’re using the trick to give WP it’s own directory, these are not the directions you’re looking for. I haven’t written those out yet.

    First you have to go to Network Dashboard > Sites and edit the site you want to be the main site.

    Example.com using two

    This you want to to look like this:

    Changing the subset two to no folder name

    Make certain you leave ‘Update siteurl and home as well’ checked! If you forget that, you’ll be sad. You no longer need to check the box (it’s gone in newer versions of WP), but if you DO have it, check it.

    Now you’d think you go to edit the main site and change it, but you can’t.

    Default main site is not editable

    By default, the main site is not editable. This makes sense when you think about how messy this might be, so in order to edit it you have to go to your wp-config.php file and look for this line:

    define('BLOG_ID_CURRENT_SITE', 1);

    Change it to the site ID you want to use as your main site. In this example, I want site , aka, two, to become my main site.

    define('BLOG_ID_CURRENT_SITE', 2);

    Save the file and then you have to go back to your Sites and edit the old main site.

    Main site can now be edited

    Give its path a new name and press save, making sure you keep that checkbox checked if it’s there.

    Change the original main site to new

    In this example, I’ve picked a new URL for my formerly main site becuase I don’t want any conflicts, but there’s nothing stopping me from picking ‘two’ again and just totally swapping things.

    The last step is to change your post content. Using a plugin like Velvet Blues Update URLs, you will need to search each site separately and replace the URLs. If you have wp-cli, you can do that too like this:

    wp search-replace 'example.com' 'example.com/new' wp_posts wp_postmeta --dry-run
    wp search-replace 'example.com/two' 'example.com' wp_2_posts wp_2_postmeta --dry-run
    

    If those look good, rerun without dry run and call it a day!

    An interesting quirk is that you may need to edit the Fileupload URL if you’re using blogs.dir for your images. I noticed that on one site it was set to http://example/two/files which clearly is wrong. To fix that, go to Network Admin, click on Sites, and click on edit for the site. From there, click on the dangerous “Settings” tab and look for “Fileupload URL” and edit as needed to match things.

    Cool tricks like this can be found in WordPress Multisite 110.