What Microsoft’s new EES licensing model means for Primary Schools

Today is the first day of Microsoft’s EES licensing and this has massive implications if your school uses Microsoft Products.

I am not going to cover the student licensing model because I’m relatively confident this model wont fit for most Primary Schools.
The new licensing model we will look at covers Microsoft Windows and Microsoft Office licensing.  We are also ignoring Exchange and Sharepoint CALs(CAL Suite).

What does this all mean in real terms?

  1. You pay Microsoft per year for licensing
  2. Teachers can use Microsoft Office at home
  3. An average 2 form entry will be paying for 30 members of staff
  4. Updates to latest versions of products without any extra cost (Software Assurance).

When might EES not be appropriate?

  1. EES may also not be cost effective if you purchase OEM licenses or don’t use Microsoft Office.
  2. EES may not be useful if your school does not have a high quantity of devices (netbooks/laptops) running Microsoft Office.
  3. If your school intends to NOT purchase new hardware or new Microsoft products.
  4. If you don’t want to get into an annual rolling contract with Microsoft due to funding uncertainties or due to a requirement of a grant etc.

Time for some maths…

All of these figures are based on a 2 form entry school buying new Microsoft Office licenses every 5 years.
Standard licensing model:
Cost per office license per machine, £32
Average # of devices with office installed, 80
*Windows License — Excluded because is OEM (Roughly £50 per device)
Average cost every 5 years — £2560
Ergo cost per year on Non EES per device license model — £512

EES:
Average cost per EES Office license per member of staff — £20
Average # of staff members per 2 form entry: 30
Ergo cost per year for office on EES: £600
Ergo cost per year for Windows on EES: £600
Note that I haven’t covered any Server CALS.

To summarize

EES breaks even at roughly 100 devices in a 2 form entry school but the advantage is that staff can use Microsoft Office at home so don’t need their own copy.
It is unlikely EES will be cheaper than OEM as buying a device without windows lately is difficult however XP Pro upgrades are roughly £50 per device so if you buy 15 devices per year then EES Windows Licenses work out better value. A smart hardware manufacturer should see this opportunity and provide OS free hardware so that schools can leverage this new licensing model.

Hopefully someone from Microsoft can respond with some information about CAL licensing and any mistakes in this post. Word on the street is CAL pricing will be staying relatively similar for Server CALS, this pricing isn’t due to be released till May.

I quickly bashed up an EEE license cost calculator so you can see if it’s cost effective for your school to move or not

If you want to know more about EES please get in touch with Primary Technology who will be happy to help.

Updated Varnish WordPress VCL

THIS VARNISH CONFIG HAS BEEN UPDATED AND IS AVAILABLE HERE

I have been tweaking a varnish vcl config for WordPress for quite some time and I wanted to share it..  Thanks to everyone(especially DocWilco)  in #varnish on Linpro IRC for helping

Features:

  1. Load balancing
  2. Probing
  3. Does not cache wp-admin
  4. Puts all uploads/content requests onto one server
  5. Purging
  6. Long timeout for file uploads
  7. XML RPC support
  8. Custom 404 and 500 message
  9. Forwards user IP address for comments

First of all.. Let’s define some backends..

// BACKEND CONFIGS
backend server1 {
  .host = "server1.example.com";
  .port = "8080";
  .probe = {
                .url = "/";
                .interval = 5s;
                .timeout = 1 s;
                .window = 5;
                .threshold = 3;
  }
// we include time outs so uploads don't time out
 .connect_timeout = 600s;
 .first_byte_timeout = 600s;
 .between_bytes_timeout = 600s;
}

backend server2 {
  .host = "server2.example.com;
  .port = "8080";
  .probe = {
                .url = "/";
                .interval = 5s;
                .timeout = 1 s;
                .window = 5;
                .threshold = 3;
  }
// we include time outs so uploads don't time out
 .connect_timeout = 600s;
 .first_byte_timeout = 600s;
 .between_bytes_timeout = 600s;
}

// define round-robin for backends
director cluster round-robin {
        {.backend = server1;}
        {.backend = server2;}
}

// set the servers wordpress can purge from
acl purge {
        "server1.example.com";
        "server2.example.com";
}

sub vcl_fetch {
 if (req.http.host ~ "ourdomain.com"
     || req.http.host ~ "ourotherdomain.com"
// don't cache wp-admin ever cause that's not cool
     && req.url !~ "wp-admin")
{
// we cache these domains for 8 hours unless they are purged.
        set beresp.ttl = 8h;
        set beresp.grace = 600s;
// don't cache 404 or 500 errors
        if (beresp.status == 404 || beresp.status >= 500) {
                  set beresp.ttl = 0s;
        }
}
// tell all of the files to use server1
if (req.url ~ "files") {set req.backend = server;set beresp.ttl = 8h;}
}

sub vcl_recv {
// Purge WordPress requests for purge
  if (req.request == "PURGE") {
                if (!client.ip ~ purge) {
                        error 405 "Not allowed.";
                }
                purge("req.url == " req.url " && req.http.host == " req.http.host);
                error 200 "Purged.";
        }

// forward the client IP so comments show up properly
set req.http.X-Forwarded-For = client.ip;

// let server2 handle all feeds
    if (req.url ~ "/feed/")
    {set req.backend = server2;}

// server1 must handle file uploads
    if (req.url ~ "media-upload.php"
    || req.url ~ "file.php"
    || req.url ~ "async-upload.php")
    {set req.backend = server1;return(pass);}

// server1 can serve all files.
    if (req.url ~ "/files/")
    {set req.backend = server1;}

// do not cache xmlrpc.php
    if (req.url ~ "xmlrpc.php")
    {return(pass);}

// strip cookies from xmlrpc
    if (req.request == "GET" && req.url ~ "xmlrpc.php")
    remove req.http.cookie;return(pass);}

// caching these files is fine
if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|lzma|tbz)(\?.*|)$") {
            remove req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
            set req.http.Accept-Encoding = "deflate";
        } else {
            remove req.http.Accept-Encoding;
        }
}

// Remove cookies and query string for real static files
    if (req.url ~ "^/[^?]+\.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)(\?.*|)$") {
       unset req.http.cookie;
       set req.url = regsub(req.url, "\?.*$", "");
    }

// Remove cookies from front page
    if (req.url ~ "^/$") {
       unset req.http.cookie;
    }

// if the request is for our domain and not for wp-admin then load balance it to a server that is responding or send it to server1
if (req.http.host ~ "ourdomain.com"
    || req.http.host ~ "ourotherdomain.com"
    && req.url !~ "wp-admin")
{
        set req.http.X-Forwarded-For = client.ip;
        set req.backend = cluster;
        } else {
        set req.http.X-Forwarded-For = client.ip;
        set req.backend = server1;
}

// Custom error message
sub vcl_error {
if(obj.status == 404) {
        set obj.ttl = 0s;
  set obj.http.Content-Type = "text/html; charset=utf-8";
    synthetic {" <!--?xml version="1.0" encoding="utf-8"?-->

    "} obj.status " " obj.response {"
</pre>
<div style="background-color: white;"><center>
 <img src="http://whatever.com/heavyload.jpg" alt="" width="600px" /></center>
<h1>This page is unavailable</h1>
If you are seeing this page, either maintenance is being
performed or you are trying to access a file that doesn't exist. Please <a href="http://whatever.com/contact.html">contact us</a> if you believe this is an error
<h2>Error "} obj.status " " obj.response {"</h2>
"} obj.response {" on server "} req.backend {"
<address><a href="http://whatever.com/">Us.</a></address></div>
<pre>
  "};
    return (deliver);
error 404 "Not found";
 }
else
{
    set obj.http.Content-Type = "text/html; charset=utf-8";
    synthetic {" <!--?xml version="1.0" encoding="utf-8"?-->  
  
    "} obj.status " " obj.response {"
  

</pre>
<div style="background-color: white;"><center>
 <img src="http://whatever.com/heavyload.jpg" alt="" width="600px" /></center>
<h1>This website is unavailable</h1>
If you are seeing this page, either maintenance is being
performed
 or something really bad has happened. Try returning in a few
minutes. If you still see this error in a few minutes please <a href="http://whatever.com/contact.html">contact us</a>
<h2>Error "} obj.status " " obj.response {"</h2>
"} obj.response {" on server "} req.backend {"
<address><a href="http://whatever.com/">Us.</a></address></div>
<pre>
  "};
    return (deliver);
}
}

How to put the latest CBBC news on your WordPress blog

Step 1. Log into your blog
Step 2. Click Appearance-> Widgets
Step 3. Drag RSS over to your sidebar.
Step 4. Paste http://newsrss.bbc.co.uk/rss/cbbc_news/homepage/rss.xml in where it asks for RSS feed URL
Step 5. Give the widget a title. *optional

Note: PrimaryBlogger users can just drag the CBBC Widget onto their sidebar.