Main Site

This is Gem Newman's blog. Return to the main site.

Quotation

Showing posts with label networking. Show all posts
Showing posts with label networking. Show all posts

20 February 2015

Configuring Flask, uWSGI, and Nginx (Updated!)

This is an updated version of a previous post, which is preserved here.


In a departure from what I often write about, I'm going to talk a little bit about something that is tangentially related to what I actually do for a living: running a web server. So I'm going to give a brief tutorial on setting up uWSGI (in Emperor mode) and Nginx so that you can run one or more Python Flask instances on a server.

Installation
Flask
uWSGI
Nginx
Port Forwarding
Sources

Why? Well, I'm far from a pro at anything related to networking or web development, but I have been writing a few web tools lately just for fun. Initially, I had several different Flask/Werkzeug instances running in what was essentially a dev mode on different ports on my server, and I had each of these ports forwarded. But...


...this was ungainly, running multiple Werkzeug instances was inefficient, I didn't want to have to forward all of those ports, and damn it, I wanted to do things right. But, as this isn't my area of expertise, it took me a while to put all of these pieces together, because many of the examples that I was able to find were light on the details. I'm putting this here in the hope that someone else in my situation might find it useful.

Installation

So here are the relevant details. I'm running Ubuntu 14.04 and I'm using Python 3.4 (and 2.7.9), Flask 0.10, uWSGI 2.0.9, and Nginx 1.1.19. If you are missing any of these, you'll want to install them with your package manager of choice.* For example:

$ sudo apt-get install python
$ sudo apt-get install uwsgi
$ sudo apt-get install nginx
$ pip3 install flask

Some caveats: First, if you're running Python 2.x, you'll want to ensure that Flask is available for it, as well. (You can try pip install flask, depending on your configuration.) Second, if you're planning to run multiple Flask applications using multiple versions of Python, you may have to build uWSGI core from source and specify which Python plugin to use for each application. Building uWSGI from source isn't the worst thing in the world; instructions for building the application and the necessary plugins are available here.

The goal here is to run multiple Flask servers on one machine without having to worry about port numbers and the like. We'll start with just one, and I'm sure that you can figure the rest out from there.

Flask

First you need a Flask application to run. How about this one? I wrote it a few months ago because I wanted to translate GET requests to POST requests. (At the time that I'm writing this, that particular application hasn't been updated to use Python 3.)

Navigate to the directory you'd like to install it to (probably /opt/ or /var/www/), then clone it. You'll want to verify that it runs locally on its own first.

$ cd /opt
$ git clone https://github.com/spurll/post.git
$ post/run.py

In a web browser on the same server, navigate to http://localhost:9999 and verify that the application is accessible. If you're running headless (as I am) you can always spawn the process to the background with post/run.py & and then curl localhost:9999 and verify that you don't get an error back. You can now kill the Python process.

Flask is now set up!

uWSGI

First, test that uWSGI will run your application correctly on its own:

$ cd /opt/post
$ uwsgi --socket 127.0.0.1:9999 --protocol=http -w run:app

In this case, run is the name of the Python source file that contains our application (/opt/post/run.py) and app is the name of the Werkzeug/Flask application object contained in that file. Verify that the application is accessible again from http://localhost:9999 as above.

If everything is working correctly, kill the uWSGI instance. It's now time to configure uWSGI's Emperor mode. This allows us to essentially have one master process that oversees all of our web applications, starting (and restarting) them when needed and logging as appropriate. You will probably have to install a few plugins, too, using your package manager of choice. (Note that if you want to support multiple Python versions, you may need to build these plugins from source, as mentioned above.) Assuming you want to use the standard plugins:

$ sudo apt-get install uwsgi-plugin-python
$ sudo apt-get install uwsgi-plugin-http

By default, your uWSGI master configuration file will probably be located at /etc/init/uwsgi.conf. Edit it with your editor of choice (I'm a Vim guy, myself):

$ sudo vim /etc/init/uwsgi.conf

It should look something like this:

description "uWSGI"
start on runlevel [2345]
stop on runlevel [06]
respawn

env UWSGI=/usr/bin/uwsgi
env LOGTO=/var/log/uwsgi/emperor.log

exec $UWSGI --master --emperor /etc/uwsgi/apps-enabled --die-on-term --uid www-data --gid www-data --logto $LOGTO

You can change the location of the Emperor's log file by changing the LOGTO environment variable. You can also modify which user (--uid) and group (--gid) the Emperor will run as.

Now it's time to configure the applications. Your application-specific configuration files (in this case, for the POST program that we installed to /opt/post/) will probably be found at /etc/uwsgi/apps-available/. Create a new file there and call it post.ini. It should like something like this:

[uwsgi]

# Variables
url_mount = /%n
base = /opt/%n
app = run
callable = app

# Plugins
plugins-dir = /usr/lib/uwsgi/plugins
plugins = python,http

# URL Script Mounting
mount = %(url_mount)=%(base)/%(app).py
manage-script-name = true

# Generic Config
pythonpath = %(base)
venv = %(base)/venv            # If using virtualenv
socket = /opt/run/%n.sock
module = %(app)
logto = /var/log/uwsgi/%n.log

Here, url_mount is the mount-point for the application (for example, if you're running the application at http://www.yourserver.com/post, the value would be /post), base is the base directory of our application (the directory that contains the module we want to run), app contains the name of the module to run (in this case run, for run.py), callable is the name of the Werkzeug/Flask callable application object (if you don't supply this, uWSGI will assume that it's called application), and socket defines the location of the socket you'd like Nginx to use when communicating with your uWSGI server. The %n references the name of our file (sans extension) to maintain consistency.

You'll need to ensure that the location of your sockets (in this case, /opt/run/) exists and that the appropriate user (in this case, www-data) has write permissions.

This configuration assumes that you want to run your program using the modules installed on your system's Python. Plugins might prove to be an issue. You'll want to point plugins-dir to the appropriate path, and make sure that you have the appropriate plugin. If you're running Python 3.x (or you want to specify a specific Python plugin for uWSGI for some other reason), you can point plugins at something like python34 (which you may have to build) instead.

To run the application in a virtual environment, you can add a line defining home:

home = %(base)/virtualenv

Where virtualenv is the directory containing the Python virtual environment you'd like to use. (In our case, that would be at /opt/post/virtualenv/, if we were using a virtual environment.)

Once you're ready, create a symbolic link to place the post.ini file you've created in the apps-enabled directory:

$ sudo ln -s /etc/uwsgi/apps-available/post.ini /etc/uwsgi/apps-enabled/post.ini

You can start the uWSGI process (if you haven't already) like this:

$ sudo service uwsgi start

As soon as your Emperor process sees an application configuration file in apps-enabled it will start up a uWSGI instance to serve requests for that application. If you'd like to set up additional Flask applications at this time, simply install them and create uWSGI configuration files for each (and don't forget to link them to apps-enabled!). If you're having trouble, take a look at the logs (which are probably in /var/log/uwsgi/).

The uWSGI Emperor is now set up!

Nginx

We're almost there!

The default configuration file for Nginx should be located at /etc/nginx/sites-available/default. Feel free to edit this one, or create your own. By default, Nginx will point requests on port 80 (the default HTTP port) to /usr/share/nginx/www. If you'd like to point them somewhere else (such as /var/www/) you can change that here. Here's a brief Nginx configuration file that you can use to run connect your uWSGI server to the outside world:

# server unix:///path/to/your/site.sock; # For a file socket.
# server 127.0.0.1:9999;                 # For a port.

upstream post {
    server unix:///opt/run/post.sock;
}

server {
    listen 80;
    server_name your.server.url;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    root /var/www;
    index index.html index.htm;

    # GET to POST
    location /post {
        include uwsgi_params;
        uwsgi_pass post;
    }
}

Replace your.server.url with the URL for your server (you can use localhost for testing purposes). This configuration assumes that you'd like your application to be accessible at http://your.server.url/post. If you'd like it to take the place of the main page at http://your.server.url/, modify the location appropriately.

Note that current versions of uWSGI no longer support the (long-deprecated) uwsgi_modifier1 30; to pass this mount information on to uWSGI, so if you're running multiple applications (or don't want to host your application on /) you will probably want to pay attention to the script mounting information for uWSGI above.

Once you're done, create a soft link to /etc/nginx/sites-enabled/ for each of the entries in /etc/nginx/sites-available/. Now you can start your Nginx service.

$ sudo service nginx start

Every time you modify the Nginx configuration file, you'll have to restart the it.

Port Forwarding

If you're running this server from your home or office and you need external access, don't forgot to forward port 80 so that Nginx is accessible. Instructions for your router are probably available here.

Sources

I used several sites while putting this all together. If you're stuck, they may contain additional information that I neglected to include here. Here are the most helpful of the bunch:

Deploying Flask on uWSGI
Multiple Django and Flask Sites with Nginx and uWSGI Emperor
How to Setup Nginx
uWSGI Example Configuration

I also had some help from my friends and colleagues BCJ and Curtis when I was initially setting up Nginx. Thanks, gents!


* Since you're probably not going to be running uWSGI under your own user account, you'll probably want to either use a virtual environment or satisfy any package requirements via sudo pip3. Otherwise, you will probably end up with errors like:

Traceback (most recent call last):
  File "/opt/post/run.py", line 9, in 
    from post import app
  File "/opt/post/post/__init__.py", line 1, in 
    from flask import Flask
ImportError: No module named 'flask'

21 January 2015

WiFi and Cell Phones: Should You Really Be Worried?

Until recently, several of the talks presented at SkeptiCamp Winnipeg 2013 were missing from the SkeptiCamp Winnipeg archives. Although I have previously posted a transcript of my 2013 talk, which discussed electromagnetic hypersensitivity and other fears linked to WiFi and mobile phones, audio of the talk is now available on the Winnipeg Skeptics site. It's also available right here!

SkeptiCamp Winnipeg 2013: WiFi and Cell Phones: Should You Really Be Worried?

SkeptiCamp Winnipeg is a conference for the sharing of ideas. It is free and open to the public: anyone can attend and participate! Presentations and discussions focus on science and free inquiry, and the audience is encouraged to challenge presenters to defend their ideas. You can visit the Winnipeg Skeptics' SkeptiCamp page for information about upcoming events and links to past SkeptiCamp talks.

22 September 2014

Configuring Flask, uWSGI, and Nginx

An updated version of this post, which covers uWSGI 2.0.9 and Python 3.4 is available here.


In a departure from what I often write about, I'm going to talk a little bit about something that is tangentially related to what I actually do for a living: running a web server. So I'm going to give a brief tutorial on setting up uWSGI (in Emperor mode) and Nginx so that you can run one or more Python Flask instances on a server.

Why? Well, I'm far from a pro at anything related to networking or web development, but I have been writing a few web tools lately just for fun. Initially, I had several different Flask/Werkzeug instances running in what was essentially a dev mode on different ports on my server, and I had each of these ports forwarded. But...


...this was ungainly, running multiple Werkzeug instances was inefficient, I didn't want to have to forward all of those ports, and damn it, I wanted to do things right. But, as this isn't my area of expertise, it took me a while to put all of these pieces together, because many of the examples that I was able to find were light on the details. I'm putting this here in the hope that someone else in my situation might find it useful.

Installation

So here are the relevant details. I'm running Ubuntu 12.04 (I know, I know, I should update) and I'm using Python 2.7.2, Flask 0.10, uWSGI 2.0.6, and Nginx 1.1.19. If you are missing any of these, you'll want to install them with your package manager of choice. For example:

$ sudo apt-get install python
$ sudo apt-get install uwsgi
$ sudo apt-get install nginx
$ pip install flask

The goal here is to run multiple Flask servers on one machine without having to worry about port numbers and the like. We'll start with just one, and I'm sure that you can figure the rest out from there.

Flask

First you need a Flask application to run. How about this one? I wrote it a few months ago because I wanted to translate GET requests to POST requests.

Navigate to the directory you'd like to install it to (probably /opt/ or /var/www/), then clone it. You'll want to verify that it runs locally on its own first.

$ cd /opt
$ git clone https://github.com/spurll/post.git
$ post/run.py

In a web browser on the same server, navigate to http://localhost:9999 and verify that the application is accessible. If you're running headless (as I am) you can always spawn the process to the background with post/run.py & and then curl localhost:9999 and verify that you don't get an error back. You can now kill the Python process.

Flask is now set up!

uWSGI

First, test that uWSGI will run your application correctly on its own:

$ cd /opt/post
$ uwsgi --socket 127.0.0.1:9999 --protocol=http -w run:app

In this case, run is the name of the Python source file that contains our application (/opt/post/run.py) and app is the name of the Werkzeug/Flask application object contained in that file. Verify that the application is accessible again from http://localhost:9999 as above.

If everything is working correctly, kill the uWSGI instance. It's now time to configure uWSGI's Emperor mode. This allows us to essentially have one master process that oversees all of our web applications, starting (and restarting) them when needed and logging as appropriate. You will probably have to install a few plugins, too, using your package manager of choice. For example:

$ sudo apt-get install uwsgi-plugin-python
$ sudo apt-get install uwsgi-plugin-http

By default, your uWSGI master configuration file will probably be located at /etc/init/uwsgi.conf. Edit it with your editor of choice (I'm a Vim guy, myself):

$ sudo vim /etc/init/uwsgi.conf

It should look something like this:

description "uWSGI"
start on runlevel [2345]
stop on runlevel [06]
respawn

env UWSGI=/usr/bin/uwsgi
env LOGTO=/var/log/uwsgi/emperor.log

exec $UWSGI --master --emperor /etc/uwsgi/apps-enabled --die-on-term --uid www-data --gid www-data --logto $LOGTO

You can change the location of the Emperor's log file by changing the LOGTO environment variable. You can also modify which user (--uid) and group (--gid) the Emperor will run as.

Now it's time to configure the applications. Your application-specific configuration files (in this case, for the POST program that we installed to /opt/post/) will probably be found at /etc/uwsgi/apps-available/. Create a new file there and call it post.ini. It should like something like this:

[uwsgi]

# Variables
base = /opt/post
app = run
callable = app

# Generic Configuration
plugins = http,python
pythonpath = %(base)
socket = /opt/run/%n.sock
module = %(app)
logto = /var/log/uwsgi/%n.log

Here, base is the base directory of our application (the directory that contains the module we want to run), app contains the name of the module to run (in this case run, for run.py), callable is the name of the Werkzeug/Flask callable application object (if you don't supply this, uWSGI will assume that it's called application), and socket defines the location of the socket you'd like Nginx to use when communicating with your uWSGI server. The %n references the name of our file (sans extension) to maintain consistency.

You'll need to ensure that the location of your sockets (in this case, /opt/run/) exists and that the appropriate user (in this case, www-data) has write permissions.

This configuration assumes that you want to run your program using the modules installed on your system's Python. To run the application in a virtual environment, add a line defining home:

home = %(base)/virtualenv

Where virtualenv is the directory containing the Python virtual environment you'd like to use. (In our case, that would be at /opt/post/virtualenv/, if we were using a virtual environment.)

Once you're ready, create a symbolic link to place the post.ini file you've created in the apps-enabled directory:

$ sudo ln -s /etc/uwsgi/apps-available/post.ini /etc/uwsgi/apps-enabled/post.ini

You can start the uWSGI process (if you haven't already) like this:

$ sudo service uwsgi start

As soon as your Emperor process sees an application configuration file in apps-enabled it will start up a uWSGI instance to serve requests for that application. If you'd like to set up additional Flask applications at this time, simply install them and create uWSGI configuration files for each (and don't forget to link them to apps-enabled!). If you're having trouble, take a look at the logs.

The uWSGI Emperor is now set up!

Nginx

We're almost there!

The default configuration file for Nginx should be located at /etc/nginx/sites-available/default. Feel free to edit this one, or create your own. By default, Nginx will point requests on port 80 (the default HTTP port) to /usr/share/nginx/www. If you'd like to point them somewhere else (such as /var/www/) you can change that here. Here's a brief Nginx configuration file that you can use to run connect your uWSGI server to the outside world:

# server unix:///path/to/your/site.sock; # For a file socket.
# server 127.0.0.1:9999;                 # For a port.

upstream post {
    server unix:///opt/run/post.sock;
}

server {
    listen 80;
    server_name your.server.url;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    root /var/www;
    index index.html index.htm;

    # GET to POST
    location /post {
        include uwsgi_params;
        uwsgi_param SCRIPT_NAME /post;
        uwsgi_modifier1 30;
        uwsgi_pass post;
    }
}

Replace your.server.url with the URL for your server (you can use localhost for testing purposes). This configuration assumes that you'd like your application to be accessible at http://your.server.url/post. If you'd like it to take the place of the main page at http://your.server.url/, things are even simpler:

...
    # GET to POST
    location / {
        include uwsgi_params;
        uwsgi_pass post;
    }
}

Once you're done, create a soft link to /etc/nginx/sites-enabled/ for each of the entries in /etc/nginx/sites-available/. Now you can start your Nginx service.

$ sudo service nginx start

Every time you modify the Nginx configuration file, you'll have to restart the it.

Port Forwarding

If you're running this server from your home or office and you need external access, don't forgot to forward port 80 so that Nginx is accessible. Instructions for your router are probably available here.

Sources

I used several sites while putting this all together. If you're stuck, they may contain additional information that I neglected to include here. Here are the most helpful of the bunch:

Deploying Flask on uWSGI
Multiple Django and Flask Sites with Nginx and uWSGI Emperor
How to Setup Nginx

I also had some help from my friends and colleagues BCJ and Curtis when I was initially setting up Nginx. Thanks, gents!

15 September 2013

WiFi and Cell Phones: Should You Really Be Worried?

What follows is the text of my presentation from the Winnipeg Skeptics' fourth annual SkeptiCamp Winnipeg, an open conference celebrating science and critical thinking.


Some of this presentation is adapted from a 2013 position paper my project team wrote for Bad Science Watch last year as part of our investigation into anti-WiFi activism in Canada. Bad Science Watch is an independent, non-profit science advocacy organization that aims to protect Canadian consumers by countering bad science in media and politics. The organisation is always looking for volunteers (and, of course, donations!). You can find out more at BadScienceWatch.ca.

So, cell phones and WiFi: What seems to be the problem?

Well, the problem is in the last few years we have an increasing number of people who are complaining that radiation generated by our modern conveniences (like computers, cell phones, appliances, and power lines) is responsible for a host of debilitating ailments in certain people who are "electromagnetically hypersensitive". Activists are pushing for stricter government regulation, removal of wireless technology from schools, and radio-free zones.

To make sure that everyone's on the same page, I'll start with a bit of basic science.

First of all, what is radiation?

Well, "radiation" can mean a few different things. Generally, it's the process by which energetic waves or particles travel through space. If you want to classify radiation broadly, there are two main ways you can do it: first, you can ask, "Is it particle radiation or electromagnetic radiation?" and second, "Is it ionizing or non-ionizing?"

Particle Radiation

Particle radiation occurs when large, unstable elements decay into smaller, more stable elements. Particle radiation often comes in the form of alpha particles (groups of two protons and two neutrons), beta particles (which are free electrons or positrons), or free neutrons. This sort of radioactive decay also results in a little bit of electromagnetic radiation (in the form of gamma rays), which we'll talk about in a second. Particle radiation is a form of ionizing radiation (we'll get to that too, but generally speaking that's the bad stuff). We won't be talking much about particle radiation today, but when people talk about stuff being "radioactive" this is often what they mean.

Electromagnetic Spectrum

The second type of radiation is electromagnetic radiation. This is an energetic wave that propagates through space. Visible light is a type of electromagnetic radiation, and so are radio waves. EM radiation is a particular form of the more general electromagnetic field, which is a field produced by the movement of electrically charged objects, and which affects the behaviour of charged particles. Electromagnetic fields can be natural (the Earth and the Sun, for example, have their own EM fields), or they can be artificial. Artificial fields can be produced intentionally (microwaves use them to cook food, computers and phones use them to communicate), or they can be produced as a by-product of technology (pretty much anything that uses electricity will have an EM field).

Non-ionizing Electromagnetic Radiation

Unlike particle radiation (which is generally ionizing), electromagnetic radiation can be either ionizing or non-ionizing. Radiation at non-ionizing frequencies may be sufficiently powerful to cause substances to heat up, but is not powerful enough to strip electrons from molecules (creating ions) and break molecular bonds.

Ionizing Electromagnetic Radiation

The radio, microwave, infrared, and visible spectra are made up of non-ionizing radiation, while x-rays and gamma rays are forms of ionizing radiation, and ultraviolet radiation sort of straddles the line between the two.

High doses of non-ionizing radiation are known to cause thermal effects (think of putting your hand on an incandescent light bulb, or microwaving a pizza pocket), but low doses are not known to have any deleterious effects to living things. By contrast, high doses of ionizing radiation can result in serious burns and radiation sickness, while low, steady doses can result in genetic damage and cancerous tumours.

So that's generally what scientific investigations into radiation has found: ionizing radiation causes direct damage to living systems, and non-ionizing radiation doesn't (although it can heat stuff up). So what's electromagnetic hypersensitivity?

Electromagnetic hypersensitivity (or EHS) is a term used to describe the adverse, subjective medical symptoms that some people report experiencing after exposure to certain frequencies of non-ionizing electromagnetic radiation (generally, the weak fields produced by WiFi hotspots, cell phones, or power lines). The symptoms associated vary from patient to patient, but often include fatigue, inability to sleep, headache, stress, muscle aches, and rashes. Sufferers report that their symptoms are worse in the city than in the country, and that they're especially bad when they're in close proximity to a device (such as a mobile phone) that emits a wireless signal.

Determining the prevalence of EHS is difficult, and estimates vary wildly depending on who's asking the questions, with the World Health Organization reporting a few individuals per million, while surveys conducted by support groups peg the number as high as one in thirty. But the effects of this syndrome are not limited to those who describe themselves as hypersensitive. Because these symptoms can compromise quality of life, parents groups and teachers unions in Ontario and British Columbia are pressuring schools to remove all WiFi installations (with some success), a group called Citizens for Safe Technology is calling for BC Hydro to suspend its Smart Meter program, and according to news reports some sufferers taken to the hills, moving as far beyond the reach of cellular signals and power lines as they can.

So what's the deal? Are these symptoms real or is it "all in their heads"?

First of all: What I just did? Don't do that. While psychogenic illnesses certainly do exist (and we would do ourselves a great disservice to deny that), framing the issue in terms of diseases that are "real" or "all in your head" is, at best, unhelpful, not to mention wildly inaccurate.

So, let's try that again: Are these symptoms really caused by a sensitivity to electromagnetic fields, or is something else going on?

Well, in 2004 the World Health Organization held a workshop on electromagnetic hypersensitivity. The working group proposed that we should no longer refer to "EHS", because "electromagnetic hypersensitivity" implies a causal relationship between the reported symptoms and electromagnetic fields, and that relationship hasn't been established. Because the actual cause of these symptoms isn't known to be EMF, the WHO suggested that the syndrome be referred to as "idiopathic environmental intolerance attributed to electromagnetic fields" (or IEI-EMF) instead. Catchy, isn't it?

So that's where things stood in 2004: causality hadn't been established, and many scientists were skeptical, as there was no known mechanism by which non-ionizing radiation could result in these symptoms. How have things progressed since then?

Well, there's been a fair amount of research: some of it good, some of it not so good. The highest quality papers that we were able to identify involved double-blind, controlled provocation studies in which individuals who identified themselves as "hypersensitive" were exposed either to a source of EMF or to an inactive control. Subjects were asked to report on the severity of their symptoms, which allowed researchers to determine whether symptoms differed depending on whether the source of electromagnetic radiation was turned "on" or "off". While subjects reportedly experienced symptoms of EHS while in the presence of the device, researchers were able to find no consistent correlation between symptom severity and the presence or absence of electromagnetic fields. In addition, while many hypersensitive individuals claimed to be able to perceive the presence of EMF, it turned out that the majority were unable to do so under double-blind laboratory conditions. Is it just me, or does this remind anyone else of the JREF's million-dollar challenge?

While these and similar studies have fared well in replication and peer review, studies do exist purporting to show that EHS symptoms are correlated to EMF. However, they tend to exhibit basic methodological problems not present in the provocation trials. The body of the literature suggests that the symptoms of EHS are not caused by exposure to EMF, and several systematic reviews, including those published by Röosli in 2008 and Rubin et al. in 2010, concluded that the nocebo effect (the placebo effect's evil twin) played a significant role in the onset of EHS symptoms.

A 2006 study investigating several treatments for EHS symptoms, including "shielding" devices, "filters", supplementation, cognitive behavioural therapy, and even acupuncture, found that only cognitive behavioural therapy outperformed placebo. The body of available evidence suggests that electromagnetic hypersensitivity is a psychogenic disorder. EHS is frequently compared to other controversial idiopathic conditions such as chronic Lyme disease.

Rather than addressing the methodological problems identified in their research or investigating plausible alternative causes of EHS, activists in Canada have generally focused on limiting access to WiFi, Smart Meters, and other devices that they claim (without evidence) to be the cause of EHS. One of the most prominent promoters of the link between EHS and EMF in Canada is Dr. Magda Havas, who teaches environmental studies at Trent University. She's published many papers on the subject, including one that claims to show that EMF (somehow) increases blood sugar. Dr. Steven Novella points out that this particular paper is actually nothing more than a four-patient case study (a series of well-documented anecdotes). Additionally, exposure to EMF was often guessed-at instead of measured, and no blinding was employed at all.

Another Havas study (which apparently did not pass peer review) purported to show that use of cordless phones resulted in huge spikes in heart-rate on an EKG; however, when Lorne Trottier and Harvey Kofsky investigated, they were able to replicate the spike on the EKG when it wasn't even hooked up to a patient! The best explanation seems to be that the EKG was experiencing electrical interference from the cordless phone—something that is specifically warned about in the heart rate monitor's user manual.

Okay, enough about EMF. Don't cell phones and WiFi cause cancer? I remember reading about something about the WHO classifying cell phones as a carcinogen a few years ago, don't I?

No. Well, that's not actually true. The International Agency for Research on Cancer has classified radiofrequency electromagnetic fields in Group 2B, which means that they are "possibly carcinogenic". While this puts radio waves in the same category as DDT, it also puts them in the same category as coffee, pickles, and "being a carpenter". It's worth pointing out that beer, wine, and other alcoholic beverages actually fall under group 1 (the "definitely known to be carcinogenic" group).

There's a lot of nuance here, but I'll try to break it down. First of all, the categories aren't divided up by how carcinogenic we think they are; they're divided up by how sure we are that they're at least a little carcinogenic. If we're quite positive that they're a little bit carcinogenic (like alcohol), they go in Group 1. If the evidence shows that something is probably carcinogenic, it goes in Group 2A. If the evidence is quite muddled (as is the case with radiofrequency EMF), regardless of how carcinogenic we think it might be, it goes in Group 2B. So saying that cell phones are in the same category as DDT (or carpentry) can be misleading. It has nothing to do with how dangerous we think it might be, it has to do with how sure we are that it might be dangerous (in this case, not sure at all). Several large, randomized, controlled trials have found no link between cell phone use and cancer, while others have found a correlation. I don't have time to delve deep into the details today, but so far I'm not convinced.

Several companies market products aimed at "protecting" customers from the putative harmful effects of EMF, including "Stetzer" filters and cellphone cases designed to block electromagnetic radiation. These devices offer no demonstrated health benefit, and as for the cases, to the degree that they may indeed block EM radiation, they would also interfere with the functioning of your device: that "radiation" is how mobile phones work. But that won't stop companies from making a quick buck at the consumer's expense.

Smart Meter

I want to talk specifically about Smart Meters for just a moment. Is anyone familiar with these? They record your electricity usage, like any other meter, but they report readings back to the utility automatically. The thing is, they do so wirelessly, which is apparently the chief cause for concern, and the data that they gather is much more temporally specific, opening the door for pricing that differs by time of day or season. I want to point out that there are potential concerns related to these devices that do not relate to health. I think that making this distinction is important, and it's one I harp on quite a bit whenever I'm asked to talk about genetically engineered foodstuffs. Whether or not I sympathize with criticisms of Smart Meters that relate to privacy, market forces, or information security, I want to stress that using bad arguments (like EHS) to support a potentially just conclusion is intellectually dishonest, and it's a good way to alienate potential allies, particularly if those people take critical thinking seriously.

It's important to point out that, given the balance of the available evidence, removing sources of EMF (such as WiFi or Smart Meters) is very unlikely to have any effect on those suffering from this EHS. Not only will these efforts inconvenience many people and incur substantial monetary costs, they're not actually going to get us any closer to helping anyone. And that, in my mind, is the biggest problem.

The WHO released a fact sheet on the subject of electromagnetic fields and health. I'll quote their conclusions here:

"The symptoms [of EHS] are certainly real and can vary widely in their severity. Whatever its cause, EHS can be a disabling problem for the affected individual. EHS has no clear diagnostic criteria and there is no scientific basis to link EHS symptoms to EMF exposure. Further, EHS is not a medical diagnosis, nor is it clear that it represents a single medical problem."

To physicians, they further recommend: "Treatment of affected individuals should focus on the health symptoms and the clinical picture, and not on the person's perceived need for reducing or eliminating EMF in the workplace or home."

So, cell phones and WiFi: Should you be worried? I'm not.

Thanks to Catrina Duffy, Adrian Powell, Ryan Gray, and Jason Locklin, who joined me in spending countless hours poring through the literature on this project.

Links and References
Bad Science Watch
BSW Position Paper on Electromagnetic Hypersensitivity
Skeptic North: Why, WiFi? Why?
Science-Based Medicine: CFLs, Dirty Electricity and Bad Science
IARC Agent Classification Monographs