Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brianjking/573d88520341a7aa363b to your computer and use it in GitHub Desktop.
Save brianjking/573d88520341a7aa363b to your computer and use it in GitHub Desktop.
RaspberryPi Web Server

Setting up a RaspberryPi Web Server with NginX

WARNING!

I started this guide as I was building my web server but it was never finished. Nonetheless there's some valuable info for anyone starting a web server from scratch.

Steps

  1. download offline raspbian
  2. follow instructions for no screen install of raspbian
  3. setup static ip address, reserve in router, and update hosts file on remote computer
  4. follow secure web server, secure ssh best practices, setup ssh-copy-id in mac
  5. install full stack (nginx, mysql, php)
  6. avoid using sudo and setup directories for nginx /var/www/vhosts/site.tld/
  7. secure your nginx/php installation
  8. use vhost to manage virtual hosts
  9. define your configuration files as needed, h5bp has a good starting point but doesn't include support for php.
  10. php.ini values can be set through fastcgi in the config file. However it produces some questionable results...

On Step 6:

sudo su

# add user to www-data
gpasswd -a user www-data

# change ownership
chown -R user:www-data /var/www/

# find all files, set permissions to rw-r-----
find /var/www -type f -exec chmod 0640 {} \;

# find all folders, set group id and permissions to rwxrwx---
find /var/www -type d -exec chmod 2770 {} \;

Source: Lekensteyn

On step 7:

Consider a situation where remote users can upload their own pictures to the site. Lets say that an attacker uploads an image to http://www.example.com/uploads/sample.gif. What happens, given the server block above, if the attacker then browses to http://www.example.com/uploads/sample.gif/fake.php?

  1. nginx will look at the URL, see that it ends in .php, and pass the path along to the PHP fastcgi handler.
  2. PHP will look at the path, find the .gif file in the filesystem, and store /somefilename.php in $_SERVER['PATH_INFO'], executing the contents of the GIF as PHP.

This issue can be mitigated in a number of ways, but there are downsides associated with each of the possibilities:

  • Set cgi.fix_pathinfo to false in php.ini (it’s set to true by default). This change appears to break any software that relies on PATH_INFO being set properly (eg: Wordpress).
  • Add try_files $uri =404; to the location block in your nginx config. This only works when nginx and the php-fcgi workers are on the same physical server.
  • Add a new location block that tries to detect malicious URLs. Unfortunately, detecting based on the URL alone is impossible: files don’t necessarily need to have extensions (eg: README, INSTALL, etc).
  • Explicitly exclude upload directories using an if statement in your location block. The disadvantage here is the use of a blacklist: you have to keep updating your nginx configuration every time you install a new application that allows uploads.
  • Don’t store uploads on the same server as your PHP. The content is static anyway: serve it up from a separate (sub)domain. Of course, this is easier said than done: not all web applications make this easy to do.

On Step 9:

Here's a sample configuration file. To be improved.

#################################################################
# Fallback site configuration
#################################################################
server {
  listen 80 default_server;
  server_name _;
  error_log /srv/www/vhosts/fallback/log/fallback.error.log;
  return 444;
}

#################################################################
# Pi and PHPMyAdmin configuration
#################################################################
# www.pi.dev
server {
  listen 80;
  server_name www.pi.dev;
  rewrite ^(.*) http://pi.dev$1 permanent;
}

# pi.dev
server {
  listen 80;

  server_name pi.dev;
  root /srv/www/vhosts/pi.dev/public;
  charset utf-8;
  error_log /srv/www/vhosts/pi.dev/log/pi.dev.error.log debug;
  access_log /srv/www/vhosts/pi.dev/log/pi.dev.access.log;

  location / {
    index  index.php index.html;
    try_files $uri $uri/ index.html;
  }
  location ~ \.php$ {
    try_files $uri $uri/ =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass   unix:/var/run/php5-fpm.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME /srv/www/vhosts/pi.dev/public/$fastcgi_script_name;
    fastcgi_param PHP_VALUE "open_basedir =/srv/www/vhosts/pi.dev/public/:/srv/www/vhosts/pi.dev/craft/";
    include        /etc/nginx/fastcgi_params;
  }
}

# www.pma.pi.dev
server {
  listen 80;  
  root /usr/share/phpmyadmin;
  server_name www.pma.pi.dev;
}

# pma.pi.dev
server {
  listen 80;
  root /usr/share/phpmyadmin;
  server_name pma.pi.dev;
  charset utf-8;

  location / {
    index  index.php;
    try_files $uri $uri/ index.php;
  }
  location ~ \.php$ {
    try_files $uri $uri/ =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass   unix:/var/run/php5-fpm.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME /usr/share/phpmyadmin/$fastcgi_script_name;
    fastcgi_param PHP_VALUE "open_basedir =/usr/share/phpmyadmin/:/usr/share/";
    include        /etc/nginx/fastcgi_params;
  }
}

#################################################################
# UNDiario with Craft configuration
#################################################################
# www.undiario.dev
server {
  listen 80;
  server_name www.undiario.dev;
  rewrite ^(.*) http://undiario.dev$1 permanent;
}

# undiario.dev
server {
  listen 80;

  server_name undiario.dev;
  root /srv/www/vhosts/undiario.dev/public/;
  charset utf-8;
  error_log /srv/www/vhosts/undiario.dev/log/undiario.dev.error.log debug;
  access_log /srv/www/vhosts/undiario.dev/log/undiario.dev.access.log;
  index index.php;

  location ~ \.php$ {
    try_files $uri $uri/ =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass   unix:/var/run/php5-fpm.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME /srv/www/vhosts/undiario.dev/public/$fastcgi_script_name;
    fastcgi_param PHP_VALUE "open_basedir =/srv/www/vhosts/undiario.dev/public/:/srv/www/vhosts/undiario.dev/craft/";
    include        /etc/nginx/fastcgi_params;
  }
  location ~ ^(.*)$ {
      try_files $uri $uri/ /index.php?p=$uri&$args;
  }
}

Ok, here's the thing. Wehn using apache you can define values for PHP through the vhost.conf file. I figured it'd be the same in nginx. However it seems that when you set a value like fastcgi_param PHP_VALUE "open_basedir = /my/path/public/:/my/path/app/";; it applies it to every host (!?) and so you have to re-set it in other hosts to override it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment