Creating a Development Virtual Machine – Part One: Ubuntu, Apache, MySQL, PHP

No Comments


If you do web development on Windows, you’re probably used to making do. XAMPP can go a long way, as can Cygwin, but once you want to start playing around with anything state-of-the-art, you’ll start feeling left behind. The solution? Set up a virtual machine running Linux, so you can take advantage of the latest and greatest in their native environments.

Set up Ubuntu

For this purpose, we’re going to be using VirtualBox – originally by Sun, recently(ish) purchased by Oracle. For my money, it still has the best mix of ease-of-use, features, and price (free). You can download the latest version here.

And while you’re at it, go download the latest version of Ubuntu Server. For this article, we’re using 11.10 (Oneiric Ocelot), which you can download here. Grab the 64-bit version.

Install VirtualBox. Before you run it the first time, you’ll want to right-click the icon and choose “Properties”. Then go to the “Compatability” tab and click the checkbox next to “Run this program as an administrator”. If you want any symlinks you create in Ubuntu to be recognized by Windows, you MUST be running the program as an administrator. Windows is funny like that.

Launch VirtualBox, then create a new virtual machine and set the Ubuntu ISO as the CD/DVD drive. (Under the Storage menu in Settings, click on the CD-looking thing under the IDE controller). Also, make sure to set up Networking as “Bridged”. Start up the virtual machine, then follow Ubuntu’s really slick install process. The only application you’ll want to install during setup is the OpenSSH server. We’ll install the rest ourselves.

When all is said and done, restart it and log in. Now the fun begins!

Set up your networking

Let’s set up a static IP address so we don’t have to keep figuring out what dynamic IP the machine obtained.

$ sudo nano /etc/network/interfaces

Edit the last part to look like this:

# The primary network interface
auto eth0
iface eth0 inet static
        address 192.168.0.151
        netmask 255.255.255.0
        network 192.168.0.0
        broadcast 192.168.0.255
        gateway 192.168.0.1

You’ll have to fiddle with those numbers a bit depending on your networking configuration. Ensure primarily that the address you supply isn’t taken by anyone else on your network, and that the gateway matches the one you get when you type “ipconfig” in Windows. Restart your network to get the changes recognized.

$ sudo /etc/init.d/networking restart

Once that’s working, start up Notepad as Administrator in Windows (right-click and “Run as administrator”). Then open up “C:\Windows\System32\drivers\etc\hosts” (no extension) and add your new machine’s IP address. Now you can do things like SSH directly to the hostname or type the hostname in your browser instead of remembering the IP address.

Install Apache

This is easy, and can be handled entirely through automated utilities built-in to Ubuntu.

$ sudo apt-get install --reinstall language-pack-en
$ sudo dpkg-reconfigure locales
$ sudo apt-get install gcc make wget cron curl
$ sudo apt-get install apache2 apache2-mpm-prefork apache2-prefork-dev apache2-utils apache2.2-common

One quick thing, to avoid getting the error “Could not reliably determine the server’s fully qualified domain name, using 127.0.1.1 for ServerName” every time we restart, we need to make a small change.

$ sudo nano /etc/apache2/httpd.conf

Add the following line and save.

ServerName localhost

Install MySQL

Nearly as easy. Start with the automated utilities.

$ sudo apt-get install mysql-server-5.1

No need to give MySQL a root password on your development box. Then edit the MySQL config file.

$ sudo nano /etc/mysql/my.cnf

Change the “bind-address” line in that file to point the the local server IP. (192.168.0.151 in the example above.)

Then, it’s worthwhile allowing root to log in from machines other than localhost. That way you can use whatever Windows GUI tool you like to log in to your virtual machine’s MySQL installation.

$ mysql -u root
GRANT ALL ON *.* TO 'root'@'%';
exit;
$ sudo service mysql restart

Install PHP

Now we could just use the built-in version of PHP, if we felt like taking the easy road. But that’s no fun. Let’s install PHP 5.4 RC2, so we can play around with all the new features. As an added bonus, if you get comfortable with compiling PHP now, you can recompile with whatever version and options you want later for when there’s a new release of PHP, and you don’t have to wait for your package maintainers to update.

First we need a bunch of build tools.

$ sudo apt-get build-dep php5
$ sudo apt-get install libxml2 libxml2-dev libzip-dev libbz2-dev curl libcurl4-openssl-dev libcurl3 libcurl3-gnutls libjpeg62 libjpeg62-dev libpng12-0 libpng12-dev libmcrypt-dev libmcrypt4 libxslt1-dev libxml2-dev

Next, grab and extract PHP 5.4.

$ cd ~/
$ mkdir tmp
$ cd tmp
$ wget http://downloads.php.net/stas/php-5.4.0RC2.tar.gz -O php-5.4.0RC2.tar.gz
$ tar xvfz php-5.4.0RC2.tar.gz

Now, we configure and compile. This takes a while. Feel free to grab a sandwich or something.

$ cd php-5.4.0RC2
$ ./configure --with-apxs2=/usr/bin/apxs2 --with-config-file-path=/etc/php5 --with-mysql=mysqlnd --enable-inline-optimization --disable-debug --enable-bcmath --enable-calendar --enable-ctype --enable-force-cgi-redirect --enable-ftp --with-gd --enable-memory-limit --disable-sigchild --enable-trans-sid --with-ftp --with-jpeg-dir=/usr --with-png-dir=/usr --with-zlib=yes --with-zlib-dir=/usr --with-openssl --with-xsl=/usr --with-gd --with-mcrypt=/usr --with-mhash=/usr --enable-mbstring=all --with-curl=/usr/bin --with-curlwrappers --enable-mbregex --enable-zend-multibyte --with-bz2=/usr --with-mime-magic --with-iconv --with-pdo-mysql=mysqlnd --enable-fileinfo --with-pear --enable-exif
$ make
$ sudo make -i install

Of course, now we have to ensure that Apache knows about PHP.

$ sudo ln -s /usr/local/bin/php /usr/bin/php
$ sudo nano /etc/apache2/mods-available/php5.conf

Add the following lines and save.

AddType application/x-httpd-php .php .phtml .php3
AddType application/x-httpd-php-source .phps

Now enable PHP (and mod-rewrite, while we’re at it).

$ sudo a2enmod php5
$ sudo a2enmod rewrite

It wouldn’t hurt to ensure that PHP is configured how we like it, either.

$ cd /etc
$ sudo mkdir php5
$ cd php5
$ sudo cp ~/tmp/php-5.4.0RC2/php.ini-production php.ini
$ sudo nano php.ini

Ensure the following are set:

date.timezone = America/Toronto (Or whatever is closest to you.)
short_open_tag = On
error_reporting = E_ALL
display_errors = On
log_errors = On
error_log = /var/log/php.log
max_execution_time = 30
memory_limit = 128M
mysql.default_socket = /var/run/mysqld/mysqld.sock

Now make sure that the logfile we specified exists and is writable.

$ sudo touch /var/log/php.log
$ sudo chmod a+rw /var/log/php.log

Finally, restart Apache!

$ sudo service apache2 restart

You should be able to visit the address of your new virtual machine (or the alias you set up in hosts) now and get your basic Apache display.

Extra step – VirtualHosts

I presume you’re going to want to develop multiple projects without having to create separate virtual machines for them all. That’s easy! We’ll just set up an Apache VirtualHost for each one.

$ sudo nano /etc/apache2/sites-available/{development url}

Add the following, then save.

<VirtualHost *:80>
    ServerName {development url}
    DocumentRoot /home/{user}{/{development url}/

    <Directory /home/{user}/{development url}/>
        AllowOverride All
    </Directory>
</VirtualHost>

Now enable your site and reload Apache.

$ sudo a2ensite {development url}
$ sudo service apache2 reload

Extra step – Shared folders

I bet you’re wondering how you’re supposed to get files on and off that machine, huh? Well, since you installed OpenSSH, you have options there, but there’s an easier way. You can just share that folder you were referencing above with a specific folder on your host machine. Make changes in Windows, and it will (usually) be reflected in the virtual machine. I’ve noticed a few times that when I’ve created a file, the Ubuntu host flips out and doesn’t properly recognize it, but a quick restart fixes it, and machine restarts are usually like ten seconds, max.

First, make sure that folder above exists on your virtual machine, then click on the “Devices” menu in VirtualBox, then click “Install Guest Additions”. This makes a virtual CD available to your virtual machine that contains the actual guest additions we’re going to install.

$ sudo mount /dev/cdrom /media/cdrom
$ cd /media/cdrom
$ sudo ./VBoxLinuxAdditions.run

Ignore the crap about x.org failing – we don’t have any GUI installed on the server, so whatever. Now shut down the machine (“sudo shutdown -h now”), and open up the Settings menu and click on Shared Folders. Click the little Folder/Plus icon on the right, and choose a Folder Path from your Windows box, and remember the Folder Name it gives you (or make up your own). Hit “OK” and start that machine back up.

We’re going to set up this machine to automatically mount that folder every time it boots up.

$ sudo nano /etc/init.d/rc.local

Add the following just after “do_start() {“:

    mount -t vboxsf {Folder Name} /home/{user}/{development url}

Now restart to check it out.

$ sudo restart -r now
# After restarting...
$ cd /home/{user}/{development url}
$ ls

You should see all the files from your Windows machine. If you don’t, well… ugh. Okay, I got this fixed by re-running the VBoxLinuxAdditions.run script, the re-mounting. No clue why that worked, but it worked, so… yeah. Not questioning it.

What Else Could We Possibly Do?

Hot damn, that’s a lot of stuff, isn’t it? Well, we still have Memcache, Memcached (yes, both), and Redis to install. These are all optional, but super-neat tools, and practically essential if you want to write anything that scales well these days.

For now though, you should have a good base to work from. If anything doesn’t work, let me know, but I followed along with my own VM while I was writing this, so I’m pretty confident I didn’t skip anything.

The Curious Case of The Missing Memcached::casMulti()

No Comments

I understand I’m a little late to the game, but Memcached is friggin’ awesome.

(No, I’m not talking about Memcache, I’ve known about that for a while. I’m talking about Memcached, the younger, beefier, stupidly-named cousin of Memcache. Crazy new features, but named in a way that’s sure to guarantee dozens of Google search mismatches. Nice.)

Previously, if you wanted to be sure that your cache writes weren’t clobbering each other, you had to implement some form of locking system, which introduces the very healthy chance of deadlocks and locking timeouts. This kills the concurrency.

But with Memcached, you can do this really sweet thing called “cas()” which stands for “compare and set”. (Maybe. Depending on who you’re talking to.)

Simple usage:

$cas = null;
$m = new Memcached();
do {
    // Get user, get cas token byref
    $user = $m->get('user::4099', null, $cas);

    // Do something with your user
    $m->cas($cas, 'user::4099', $user);
} while ($m->getResultCode() != Memcached::RES_SUCCESS);

So when you’re getting your $user, you’re also getting a $cas token. This token is updated every time the cache entry is changed. When you go to write your user later, instead of calling set(), you call cas() and pass in your $cas token. Memcached will only update the user if $cas is equal to the cas token in memory for that cache entry. If it fails, it sets Memcached’s internal result code to RES_DATA_EXISTS.

Now obviously you’ll want to limit that do-while loop there to prevent infinite looping, and if you really wanted to be a speed demon, you could change that “null” in there to a callback function so this function would block less, but still – it’s pretty goddamn quick, and no need to wait for locks.

There’s just one problem. What if you need to work with MULTIPLE objects?

See, there’s a getMulti() and a setMulti(), but no casMulti(). This is even weirder, because getMulti() even passes back an array of $cas tokens. Googling for it produces complaints about its lack, or worse, people confused about the difference between Memcache and Memcached. Apparently it’s not even IN the Memcached server, which sort of blows my mind. I can think of all kinds of situations where you’d want two or more objects to be updated in-step.

So anyway, since this thing doesn’t exist natively, I wrote it.

Memcached::casMulti()

/**
 * Set an array of Memcached keys with cas tokens, fail on all if any don't match.
 *
 * @param array   $items      An array of items to store.  All items require "key", "value", and "cas" entries.
 * @param integer $expiration The expiration time, defaults to 0.
 */
function casMulti(array $items, int $expiration = 0) {
    $newCasToken = null;
    $successfullySet = array();

    // First load old versions of data, ensure cas values remain sound
    foreach ($items as $item) {
        $item['old_value'] = $this->get($item['key'], null, $newCasToken);

        // If any tokens have changed since we loaded them, WHOOPS
        if ($newCasToken !== $item['cas']) {
            throw new DataChangedException("Data changed while we were messing about.");
        }
    }

    foreach ($items as $item) {
        // On successful set
        if ($this->cas($item['cas'], $item['key'], $item['value'], $expiration)) {
            // Get new cas token
            $this->get($item['key'], null, $item['cas']);

            // Keep track of our successes
            $successfullySet[] = $item;

        // Failed set?
        } else {
            // Data has been modified, crap
            if ($this->getResultCode() === Memcached::RES_DATA_EXISTS) {
                // Loop through "successful" sets
                foreach ($successfullySet as $item) {
                    // Get new cas token
                    $this->get($item['key'], null, $newCasToken);

                    // If this item hasn't changed on us
                    if ($newCasToken !== $item['cas']) {
                        // Undo our changes
                        $this->cas($newCasToken, $item['key'], $item['old_value'], $expiration);
                    }
                }

                throw new DataChangedException("Data changed while we were messing about.");

            // Some other reason?
            } else {
                // Do something appropriate
                throw new Exception("Something else messed up.");
            }
        }
    }
}

Some caveats:

  • This function assumes it’s part of a Memcached library, ideally one that extends PHP’s Memcached object, and thus $this is equal to a valid Memcached instance.
  • Since I don’t have access to Memcached’s Result Object (there’s no setResultObject), it relies on Exceptions to report failures, and those pretty obviously haven’t been fleshed out.
  • This is the biggie: I haven’t tested it yet. Like, not at all. I’m busy trying to set up a Virtual Machine to replace the shitty XAMPP-on-Windows thing I’ve been fighting with for years, but it’s a slow process. This will of course be updated once I get a chance to test it out, but I had an itch one evening and just had to scratch it and write this code. (I’ll also be updating this blog with the process used to create said Virtual Machine, should you choose to try it out yourself.)

With that said, let’s walk through it quickly.

You’re going to be passing in an array of items to compare-and-set, and that array should look something like:

array(
    [0] => array(
        "key" => "user::4099",
        "value" => "json-user-data-goes-here",
        "cas" => "big-long-cas-token-taken-from-get-or-getMulti",
    ),
    [1] => array(
        "key" => "user::4105",
        "value" => "json-user-data-goes-here",
        "cas" => "big-long-cas-token-taken-from-get-or-getMulti",
    )
)

I could have put $expiration in each of the items too, and maybe that’s a good idea? I figured keeping as close to Memcached’s existing methods was worthwhile, and how often are you going to need to have different expirations for everything?

Next, we get the old values of everything we’re changing, just in case we need to roll back. If any values have changed since before this function was called, SHUT DOWN EVERYTHING.

Then we try to cas each key individually. If a key is successfully set, we save it for later. If they’re all successfully set, no biggie. If any fail though, we go into recovery mode.

In recovery mode, we examine every previously-set item. If it hasn’t changed, we use cas() again to change it back to the way we found it before we tried anything. If it HAS changed, we just leave it – no sense in messing with anyone else’s work.

Yeah, so…

Now like I said, this is absolutely untested. And not in an “untested under load” kind of way – I mean I haven’t even run it yet. It might not even friggin’ compile. I’ll update this blog post once I have tested it sure, but for now, exercise caution.

And even if it does compile and seems to work, exercise caution. I wrote this late at night after a day of frustratedly poking at the Memcached docs and Google. There could be all kinds of situations where this Just Doesn’t Work.

And even if it does work in all situations as expected? It may not even be a good idea. There’s a LOT of cache reads going on here, and I really don’t know what that does to concurrency. There may very well be much more efficient ways of doing this.

So be warned. Have fun playing around with this, but try not to use it in production code.

Nope.

1 Comment

Alternate title: “Welp”.

Alternate, actually informative title: “Indie Stone Still Doesn’t Get It”

Or at the very least, Lemmy still doesn’t get it.

Barely hours after I posted, hoping that Indie Stone would learn from this latest disaster, developer Lemmy has posted an apology, and announced that he’s removing himself from further community involvement.

But while that may or may not represent a good idea, the big news in the article is the following excerpt:

No one put ‘must have thick skin’ (or ‘must make nightly off-site backups, for that matter) in my game programmer job description.

Really? Really?

First, I mean, you went indie. You made your own job description, so you can’t really complain that you’re required to do more than you were told – it was your job in the first place to find out what was required, and if it was acceptable.

Second – and this is the killer – it’s pretty obvious that “nightly off-site backups” are still a distasteful, onerous thing to him, that the entirety of the development has been a hack job from the start, and will continue to be so until yet another slapdash solution fails catastrophically. And when that happens, all the people who supported him and supported PZ’s development can expect is more hand-wringing, and more “in hindsight, it’s obvious I shouldn’t have stored credit cards unencrypted on our web server” responses.

If they ever finish Project Zomboid, I might buy it (if I’m convinced my payment information isn’t being handled by them) because it looks like it’ll be a really cool game on completion. But I’m certainly not going to invest in a pre-order, given that they can’t be arsed to exhibit a bare minimum level of professionalism.

Hell, my college homework was in source control.

There’s Professionalism, and then there’s Professionalism.

No Comments

So Project Zomboid was stolen last night. Literally. Someone broke into the developer’s flat, stole two laptops containing the source code, and booked it. And these two laptops contained the ONLY recent copies of the code. All other backups are at least a month old.

Seriously.

Reddit got angry about this, and Lemmy got angry back over Twitter (account since removed, wisely).

So far, this was all something of an unfortunate morality play, but then another PZ developer popped up this morning to elucidate on the subject of Professionalism and Indies.

In as much as he is talking about people being angry because Lemmy raged at Reddit over Twitter, he’s right. (Hypocritical, of course, since they pulled his Twitter account, but whatever.) One of the differences between indies and commercial studios is that you get a closer relationship with the developers than you would if you had a PR department between you. If that relationship exposes a personality you don’t like, well, tough. Don’t invest in that game, simple.

But he also draws an arbitrary line in the sand in that article, declaring that some indies would rather just be commercial studios. Here, in his words:

There’s the type of studio that really, if they were honest, they’d like to be the first type of indie [independent studios, working for commercial clients] – everything they do is onwards an upwards to this goal. Legitimacy. A proper company. And then there’s the other type.

This type of indie never pretends to be professional. The “company” is probably just a name. It technically exists, but really what it boils down to is a guy in his underpants making a daft game. Sometimes that guy has a day-job, sometimes he’s taken a whoppping gamble and is working full-time from home.

The point is, if you’re going to throw your money at one of these indies, it’s important to know who you’re throwing money at and why. You can’t necessarily have your cake and eat it too.

You can just hear the derision there. Ugh, commercial studios, right? All that process and overhead and accountability, bleh. When PZ was first getting popular, I read a blog post from one of their developers about how he left the commercial games industry because it was the most miserable period of his life. Which is cool – we’ve all heard the gory details exposed by EASpouse and others. Fleeing that environment is a positive, healthy step. But there was always something about the way it was written that never sat well with me.

I guess last night I figured out what it was. At Indie Stone, “professionalism” is a dirty word.

But being a professional doesn’t mean having to give up your indie cred, or bow to the demands of marketing folk or whatever. It just means that you treat this shit like Your Job, which it now is. It means taking all the appropriate precautions to prevent shit like this from sinking you. Every instance of “bad luck” that’s struck Indie Stone so far has been entirely preventable with just the bare minimum of professionalism. If they’d read the PayPal terms that said they didn’t accept pre-orders, they wouldn’t have lost all those money and orders. Ditto for Google Checkout. And ditto for backing up your code appropriately.

You wouldn’t hire an independent caterer who didn’t wash their kitchen first. You wouldn’t hire an independent electrical contractor who wasn’t certified. These are just little one or two-person outfits, without any dreams of gaining “Legitimacy”. But they take the time to know their craft and be professionals about it.

And the dirtiest, scariest part of this all is that setting up an offsite backup in this day and age isn’t hard. At all. It’s almost harder NOT to, actually. See, source control tools were invented way back in the dark ages, and you have a million options nowadays. CVS. Subversion. Git. Mercurial. Veracity. And the interesting thing is, they all make development EASIER, not harder. First, if you ever made a mistake, you can roll your code back to ANY POINT in the development history to figure out what went wrong. Second, when working with more than one developer, it makes it really difficult to accidentally clobber changes that they’ve been working on. Finally, if your computer ever catches on fire, your source control is generally safe on another server somewhere in another city, and even that’s backed up in case that server catches on fire.

The fact that Indie Stone was charging people for pre-orders for a game, and then not expending the requisite effort to protect people’s investment is absolutely, completely unprofessional. And not in the “Commercial Studio” sense that these guys seem to dread, but in the “Basic Respect For Your Customers And For Your Trade” sense.

Now, they’re planning on continuing on (good for them!), and hopefully they’ll be able to. I know personally that losing a month’s worth of work would be devastating – moreso than the theft itself. But hopefully they learn from this, and not just to back up their code remotely. They’ve had three serious hits due to a lack of professionalism. This is the time to start looking into all their shit that they’ve been giving short shrift. Check their security for XSS, SQL injection, change every password (because you now have people who own their laptops, and a whole bunch of people on the internet upset at them). Ensure payments are still flowing properly, ensure refunds are processed immediately (because there’s going to be a bunch of those, and having their payment processing yanked on them now is going to suck BIGTIME) – double-down on this stuff.

I’d love to see Project Zomboid survive, because it’s a thrilling, ambitious project. But I hate how they’re badmouthing professionalism. You can be a professional indie without succumbing to all the soul-deadening crap that happens in a commercial studio. Long-term, it’s even easier to do, because then you don’t have to worry about having your payment processing yanked twice and having months of work stolen from you. Swear all you want on Twitter, but respect your craft, and respect your customers.

Slave Leias Get No Respect!

No Comments

This is a reaction to this post: “Geek girls” and the problem of self-objectification

I guess my biggest problem with this article is the following:

Too often, women in geek cultures are only welcomed if they are decoration, sexy versions of the things geek men love, not equal participants or fellow fans.

Maybe I live in a weird, tiny bubble, but with the folks I hang around with, this just ain’t so. My group of friends in Oakville is fully of nerdy girls, and I hang around with them because they are smart and fun and into awesome nerdy things, not because they are “decoration.” Fully half the awesome friends I made at PAX Prime last year were nerdy girls – at no time dressed up or flaunting themselves. We met on the Harry Potter Pubcrawl and talked about nerdy shit and exchanged numbers and hung out for the rest of the con.

Of all of the nerdy girls I am friends with, the emphasis is on the “nerdy” – they’re into comic books, or games, or loose-leaf tea, or reading. That they’re girls makes no more difference than their hair colour, or height. Are other nerdy dudes so fucking shallow that ladies are shunned if they’re not eye candy? For shame.

Yup. Definitely cold.Now on the flip side of that – if you are dressed in costume AT ALL, you are emphasizing yourself as decoration and shouldn’t be surprised when you’re treated as such. I’ve never been able to have a meaningful conversation with a lady dressed as Leeloo, BUT the same goes for dudes dressed as Master Chief or whatever. The most I ever get out is “Oh hey, sweet costume, you look great/badass/cold” and then I mosey on. Seriously, I can’t connect with you when you’re kitted out like that, it’s intimidating.

If you want to connect with and gain acceptance within a community, be as you are. Sure, there will be some sexist assholes (and perhaps the nerd community has more than its fair share due to natural high levels of social anxiety in its members), but as with all things, the cream will rise to the top and you will be welcomed. There’s no need to lower yourself to fit in.

Node.js and CoffeeScript on Windows, Redux

10 Comments

Remember back when we installed Node.js on a Virtual Machine just to get it working on Windows 7? Well there’s a better way.

1) Install Cygwin

Grab Cygwin from here and install that puppy. Make sure you install the following modules:

  • Devel -> gcc4-g++ [Builds v0.4.2 and earlier use gcc-g++]
  • Devel -> git
  • Devel -> make
  • Devel -> openssl-devel
  • Devel -> pkg-config
  • Devel -> zlib-devel
  • Editors -> nano
  • Libs -> openssl-devel
  • Python -> python

Ensure you allow Cygwin to install required packages as well, otherwise these things just won’t work.

2) Download and build Node.js

$ cd ~
$ git clone git://github.com/joyent/node.git
$ cd node
$ git fetch --all
# if the above fails complaining --all is not recognised, try: git fetch origin
$ git tag
$ git checkout [latest stable tag from previous command, e.g., v0.2.5]
$ ./configure
$ make
$ make install

If, during the “configure” step, you get the following error: “error: could not configure a cxx compiler!” Do the following:

  1. Close your Cygwin terminal.
  2. Start -> Run -> ash
  3. /bin/rebaseall
  4. Close ash, re-open your Cygwin shell, and try again.

3) Configure Node.js

Node.js tries to use /etc/resolv.conf for domain name resolution, all pretending like its on Linux. Simple enough to get around though, just “nano /etc/resolv.conf” to create it. Slap the following in there:

nameserver 8.8.8.8
nameserver 8.8.4.4

Hit Ctrl-O to save. Now Node.js will route DNS requests through Google’s free DNS service.

4) Install NPM

This one’s easy. Run this:

curl http://npmjs.org/install.sh | sh

5) Install CoffeeScript

This is easy because we installed npm:

npm install -g coffee-script

6) Configure your system’s PATH

Open up Control Panel and search for PATH. Click on “Edit the system environment variables”, then click the “Environment Variables” button. Scroll through the “System Variables” list until you find “Path”, then add this to the end:

c:\cygwin\usr\local\bin

If you installed Cygwin to a different spot, make that modification now.

Ta-daa!

Congratulations! Node.js and CoffeeScript are now installed in Cygwin under Windows 7. You can call node.js from a cmd.exe window now due to that PATH variable, and even calling CoffeeScript is super-easy:

node /usr/local/lib/node_modules/coffee-script/bin/coffee {arguments}

Thanks to the offical guide on how to install CoffeeScript on Windows, and to the authors and maintainers of Node.js and CoffeeScript as well.

Dear Capcom, Pull Your Head Out Of Your Ass

No Comments

It’s beginning to look like the PC version of Street Fighter IV: Arcade Edition is going to be a worse investment than setting your wallet on fire.

The original SFIV was cancelled on PC due to piracy concerns. I don’t even understand that – isn’t the draw for this game fighting other people? Developers have come up with reliable ways to prevent pirated versions of games from going multiplayer for decades now. But Capcom, determined to apply a solution in face of a problem they don’t even really have, has basically guaranteed that pirating SFIV:AE will get you a better game than buying it.

First, make the assumption that if you’re pirating SFIV, you don’t care much about getting online, this being a fairly common restriction on pirated games. So if you pirate SFIV and you have an internet problem or Capcom’s servers go down, you get the following features that paying customers don’t:

  • You can continue your game! Paying customers get kicked out without saving.
  • Your challenge mode works like always! Paying customers lose the ability to save progress in challenge mode.
  • You can change your settings! Paying customers can’t save their settings changes.
  • You can play dress-up! Paying customers lose access to cosmetic DLC while offline.
  • You can play with all 39 characters. Paying customers? Only fifteen.

That’s an impressively broken game. But here’s a good question. Why bother at all?

Recently, Lionhead has come out and said that second-hand game sales cost them more than piracy. I’ve long suspected this to be the case for a while, but it’s interesting to see a publisher come out and say it. Given this, wouldn’t it make more sense for Capcom to try to make money from second-hand sales instead of battling uphill against pirates? And come on, Street Fighter is the perfect game for this. Check it:

You buy SFIV:AE for $10. That’s right. Ten dollars. Cheap, simple, easy. (Knock on: So cheap that it may tempt some pirates to buy it.) However, this is only the single-player version of the game. Most people are buying this game for the multiplayer anyway, which you sell a key for direct from your website for $30. The benefits are enormous:

  • From customers who would have paid you anyway, you make the same $40 you would have charged at retail.
  • From pirates who only want to play single player, you make the same $0. But you can’t stop that anyway.
  • From pirates who want to play multiplayer, you make $30 instead of $0!
  • From second-hand buyers who want to play multiplayer, you make another $30 instead of $0!

You’ve now converted some pirates to paying customers, and recovered most of the money you lose on second-hand sales. What do you think Capcom?

Capcom?

Wait, what are you doing? Why are you selling the retail version for less than the digital version?

Didn’t you listen to a thing I just said?

Best Error Message Ever

No Comments

Time Vortex Malfunction.

YES.

Let’s talk about Anonymous

2 Comments

So there’s been some hullaballoo recently about how Anonymous might turn out to actually be responsible for the PSN hack, but I think that honestly goes to show how poorly understood Anonymous actually is. Let’s break it down.

History

So there’s this website, eBaum’s World, where members can – and usually do – post anonymously. When you don’t provide a handle to go with your posting over there, you show up as “Anonymous”. On any other website, when someone would provide an answer to a question you posed, you’d say something like “Thanks, JimmyJim255!”. On eBaum’s World, you’d instead say “Thanks, Anon!” And so it grew to be A Thing.

It was funny, to pretend that Anonymous wasn’t some anonymous person, but a giant Hive-Mind of people. You send a question out, and it gets Answered. You request the source for a particular image, and it is provided to you not by a single person, but by the Great Anonymous Itself. The Hive-Mind has spoken.

What Anonymous Isn’t

Anonymous isn’t a tightly-controlled net of hackers. There’s no “Boss Anon”. No “Anon Bin Laden”. There’s no single member of Anonymous that you can arrest that will cause a “crippling blow” to “the network”. Because let’s be honest here, “the network” is generally a bunch of bored dudes, killing some time by browsing eBaum’s World and taking part in whatever looks fun.

Sure, some members are incredibly more talented in the whole Black Hat stuff. Sure, some are better at persuading the herd, through use of clever rhetoric, reverse psychology, and hilarious memes. But they don’t make up the bulk of Anonymous, and if they left and never returned, it would remain the same.

What Anonymous Is

Anonymous remains the same even through the loss of its members, largely because Anonymous is ever-changing. From one moment to the next, the “member list” is different. Some bored college student in California hits up a well-crafted webpage to join in on a DDOS attack on Friday night, and leaves on Saturday morning, bored. A talented hacker joins in the fight against Scientology because she has a friend she lost to the group, but leaves when they start attacking Sony, because she’s a hyuuuuge fan. Any “leaders” are at best temporary and individually-motivated. Participants are even more amorphous and random. Pinning down “Anonymous” is pretty much impossible.

It’s made even worse by statements from “inside” the group as well. From the linked article, a “veteren member of Anonymous” says:

“If you say you are Anonymous, and do something as Anonymous, then Anonymous did it,” said Kayla. “Just because the rest of Anonymous might not agree with it, doesn’t mean Anonymous didn’t do it.”

While technically correct, going back to the old-school definition of Anonymous as the Hive-Mind, it doesn’t help clear things up to the media. This point of view correctly places Kayla as a veteran member of Anonymous, at least, given the fact that she still thinks of Anonymous as the Hive-Mind across the internet, where thanking or blaming one member thanks or blames the Hive-Mind. But as far as news organizations are concerned, it really muddies the waters.

Kayla is not confirming that there is a well-controlled and organized cyberterrorist group called Anonymous. She’s not confirming that Anonymous is behind the PSN network attacks. There’s no confusion inside the Anonymous community about this.

She’s just saying, with the same playful, let’s pretend attitude as members of Anonymous have always regarded themselves, that if you thank Anonymous for giving you sauce, then you can curse Anonymous for taking down PSN.

Welcome to the Hive-Mind.

An open letter to voters in Kingston and the Islands

No Comments

I’ve been following this election pretty closely, and honestly, it’s pretty scary. The Conservatives are within spitting distance of a majority, and with that comes massive change for Canada. Change I’m not comfortable with.

A few quick examples of things Harper’s Conservatives have done while they’ve held a minority position:

  • He created an Agency for Crime Victims that was only used to support a “tough-on-crime” position to get superprisons funded, doing nothing for victims at all. Canada’s crime rate is falling, why do we need more prisons? http://bit.ly/iqP47m
  • In 2007, Harper cut $1.2 Billion in spending for the establishment of quality national childcare. However, he never kept his promise to cut the $1.4 billion in tax breaks he gives to oil companies (the wealthiest corporations in history). http://bit.ly/mdj61J
  • At the 2010 G20 summit in Toronto – a summit to discuss what to do about the terrible economic hardships befalling the world – Harper spent $1.9 million building a fake lake and nearly $1 Billion on security for the 3 day event. 1,105 arrests were made – the largest mass arrest in Canadian history. Only 99 criminal charges were laid. http://bit.ly/mPxqBo
  • And let’s not forget the fact that he prorogued parliament early to prevent threats to his government. http://bit.ly/jZp251

With that happening while he only holds a minority government, I honestly fear what might happen if he got the majority mandate he’s seeking.

What does this have to do with you though? Well, for the first time that I can remember, a whole hell of a lot might be resting on the shoulders of Kingston and the Islands.

Peter Milliken stepped down this election, deciding not to run again after a long and successful career in Federal politics. The Liberal who replaced him is not faring as well this election. In 2008, Milliken won by 7% of the vote. In 2011, Ted Hsu is projected to be ahead by 0.1%.

0.1% is an INCREDIBLY small number. There’s only 97,000 registered electors in Kingston and the Islands, which means 0.1% is only 97 people. But it’s smaller than that. In 2008, only 58,000 electors turned out, which means 0.1% is only 58 people. But it’s smaller than that. Voter turnout has been falling year-over-year.

Which means that Kingston and the Islands hinges on maybe 50 people. Maybe less.

With Harper within spitting distance of a majority government, that could mean that the fate of Canada hinges on maybe 50 people.

Or less.

So if you haven’t voted yet, please, PLEASE get out there on May 2 and cast your vote. If you’re considering voting NDP or Green, please consider Liberal candidate Ted Hsu. If you’re considering voting Conservative, please consider anybody else.

There’s a website set up to educate people about everything the Harper government has done during its term. All the slimy, inconsiderate, nasty things done in our name. It’s called “ShitHarperDid.com“. Reading it is informative, so please go give it a look before you head out to the polls. Hopefully it will only be an historical record going forward, not a breaking news source.

If you’re still not convinced, please humour me by reading this incredibly poignant article, published in The Star in 2010: “Changing Canada, One Backward Step At A Time“. This was written back when there was no immediate election on the horizon, and nobody had an axe to grind, except to point out the terrible things being done to Canada.

Thanks for listening.

Older Entries