Monday, January 09, 2012

NGINX With MediaWiki Over SSL

Some of this was inspired by the Ars Technica article here:  <http://arstechnica.com/business/news/2011/11/a-faster-web-server-ripping-out-apache-for-nginx.ars>.

Fire up a Fedora 16 instance on Amazon EC2 --I've been using 'ami-88f37eb8' as the beginning of all my images lately-- and log in via SSH.  Install necessary packages using yum (there may be more than I've listed here):

> yum install -y nginx
> yum install -y mysql mysql-server mysql-libs
> yum install -y php php-mysql
> yum install -y mediawiki

Follow this other wonderful article on how to get free SSL certs[Ars Technica].  Install your new certs into /etc/nginx/certs/.

Create a symlink to the wiki directory:

> ln -s /usr/share/nginx/html/wiki/ /var/www/wiki/

Edit the following files to match these outputs (adjusting for your own installation, of course):


> cat /etc/nginx/conf.d/default.conf
server {
    listen       80;
    rewrite ^(.*) https://$host$1 permanent;
}

> cat /etc/nginx/conf.d/ssl.conf
server {
  listen 443;
  server_name domain.com;


  ssl on;
  ssl_certificate certs/domain_com-class1.cert;
  ssl_certificate_key certs/domain_com-private.key;
  ssl_session_timeout 5m;
  ssl_protocols SSLv2 SSLv3 TLSv1;
  ssl_ciphers ALL:!kEDH:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
  ssl_prefer_server_ciphers on;


  gzip on;
  gzip_static on;
  gzip_min_length 512;
  gzip_http_version 1.1;
  gzip_vary on;
  gzip_comp_level 6;
  gzip_proxied expired no-cache no-store private auth;
  gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript
  gzip_buffers 16 8k;
  gzip_disable MSIE [1-6].(?!.*SV1);


  location / {
    root html;
    index index.html;
    try_files $uri $uri/index.html @wiki;
  }


  location @wiki {
    rewrite ^/wiki/index.php/(.*)$ /wiki/$1 permanent;
    rewrite ^/wiki/(.*)$ /wiki/index.php?title=$1&$args;
  }


  location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME  /usr/share/nginx/html$fastcgi_script_name;
    fastcgi_param HTTPS on;
    include fastcgi_params;
  }


  error_page 404 /404.html;
  location = /404.html {
    root html;
  }


  error_page 500 502 503 504 /50x.html;
  location = /50x.html {
    root html;
  }
}


Go through the motions on setting up MediaWiki with the MySQL database through the web interface at https://domain.com/wiki/.

Add this to the end of /var/www/wiki/LocalSettings.php:

### PRIVATE WIKI SETTINGS ###
# Disable anonymous reading/editing
$wgGroupPermissions['*']['read'] = false;
$wgGroupPermissions['*']['edit'] = false;


# Allow logins
$wgWhitelistRead = array ("Special:Userlogin",
    "MediaWiki:Common.css",
    "MediaWiki:Common.js",
    "MediaWiki:Monobook.css",
    "MediaWiki:Monobook.js",
    "-");


# Prevent new user registrations except by sysops
$wgGroupPermissions['*']['createaccount'] = false;


### NGINX SETTINGS ###
$wgUsePathInfo = true;


Friday, July 29, 2011

Compiling latest MAME for Intel Atom processors

This is more of a note to myself, but I'm putting out there for anybody else that might need it.

Download the following:

Change to the source directory and ensure that the proper path is set to find `make`:

> e:
> cd mame\mame0143

Apply all of the patches in the proper order:

> unzip ..\0143u1_diff.zip
> unzip ..\0143u2_diff.zip
> patch -p0 -E < 0143u1.diff
> patch -p0 -E < 0143u1.diff
> patch -p0 -E < hi_143.txt

Build it with optimizations for the atom processor.  For 64-bit builds ensure you're using the 64-bit version of the build environment, and add the parameter "PTR64=1".  The "-j6" specifies the number of threads to build with --set this to the number of cores/threads your processor(s) can support.  A simple -j should figure out what is optimal, but I had issues on my workstation.

> set PATH=e:\mame\mingw64-32w\bin
> make OSD=windows TARGETOS=win32 ARCHOPTS="-march=atom -mtune=atom" -j6

I can build the 32-bit version in less than ten minutes on my workstation... the 64-bit version is a significantly faster build at less than five minutes.

Monday, January 10, 2011

PRObE Test Clusters

Last month I managed (with the help of others) to break-down, upgrade, test and re-assemble two test clusters that were shipped last week to University of Utah and Carnegie-Mellon University.  Both are running two Ethernet and one Infinband network for systems testing using Emulab.

I can't wait until we're doing this with two 1,000 node clusters!

Cluster 'Pillar'; 16 nodes to Utah

Cluster 'Marmot'; 128 nodes to CMU 

Managing DNS from LDAP

At work, we're using Puppet (if you're thinking of using yourself... don't) to manage our computing resources, and we're specifying what modules Puppet runs on each node using a custom LDAP schema for each host resource.  While we were at it, I thought it would be a good idea to manage our DNS zone entries using the schema with a couple extensions.

Complications
Our zones have separate entries for internal and external responses. There are three simplified, general cases where some entries are the same internally and externally, some differ internally from externally and some don't exist externally.

There is also the possibility of an entry being removed from the LDAP database. This entry would then need to then be removed (automatically) from the DNS database.  But not all DNS entries are to be maintained by LDAP --for example we're performing updates from the DHCP server as well.  I would prefer to not store a third database file for easy storage and retrieval (this could cause serious synchronization issues), which means that I would have to actually verify that each entry that has ever been in LDAP can be removed from the DNS in the future.

Solution
I wrote a Python script that used python-ldap and python-dns to compare the entries in ldap with current responses from each DNS server, and updated each out-of-sync entry.

Similar to the dynamic DNS features of the DHCP servers, my solution for the second complication and an optimization for the comparison algorithms, the script creates an additional TXT entry to tag every host and entry type pair with a hash of the values of the entries (i.e. "www TXT 'LDAP_CNAME_1a2b3c4d5e6f7890'").  This allows me to search every host within a zone for a TXT entry with an 'LDAP_' prefix.  Those that don't match an LDAP entry are simply removed.

When I'm finished putting the polish on the script and documenting it a little better, I plan an open-source release.

Other Thoughts
The documentation for dnspython totally sucks.  I've seen many cases where I had to dig through the source for the library to make something work, even though the documentation said it would work differently.  Those that were within earshot of my office that day, heard many a curse word.

Monday, October 04, 2010

Getting the Perceived Brightness from an RGB Value

I used this function as a modification to an AutoHotkey program (don't ask) that was reading pixels from a screen for OCR, and takes into account what the human eye perceives as brightness.  The difference in brightness between the foreground and background being a GUI designer's determining factor in font color selections.

The original implementation was horribly inefficient.  It would simply take the RGB value and convert it to a string and then converting the pairs of characters back to values and comparing against some arbitrary number.  Each pixel went through this process.  There were a few spots where speed mattered, so the original author just did a direct comparison to the RGB value (i.e. `if(RGB > 0x005500)' ) which doesn't work if you have a pixel which has any red in it!

So after reading up on how the human eye perceives color and brightness, and other light reading, I came up with the following function:

GetBrightness(RGB) {
  ;Finds the percieved brightness of an RGB value
  ;Parameter: RGB is the value of the color to be tested
  ;Returns: Integer value of the brightness, which 
            ranges from 0 to 255

  ;Mask out the other colors to get each individual color
  Red := (RGB >> 16) & 0xFF
  Grn := (RGB >> 8) & 0xFF
  Blu := RGB & 0xFF
  return Round( sqrt( (Red**2 * 0.241) + \
                      (Grn**2 * 0.691) + \
                      (Blu**2 * 0.068) ) )
}