
Nginx for Developers: An Introduction - jenius
http://carrot.is/coding/nginx_introduction
======
sergiotapia
If you like this article, I wrote a similar one called Devops for Dummies.

[http://tech.pro/tutorial/1335/devops-for-dummies-vps-
configu...](http://tech.pro/tutorial/1335/devops-for-dummies-vps-
configuration-from-scratch-rails-nginx-postgresql)

It teaches you how to setup a DigitalOcean (or any other) VPS from scratch to
host N amount of Rails applications using Nginx and Passenger. It took me some
time to get things working properly and I distilled it into this short article
that holds your hand and takes you from A to Z.

~~~
gnosis
One thing I would recommend is searching for deals on LowEndBox[1] blog. Most
of the popular VPS's are ridiculously overpriced compared to what you can find
on LowEndBox. It's a good site to get advice and reviews of various VPS
providers, too.

[1] - [http://www.lowendbox.com/](http://www.lowendbox.com/)

~~~
driverdan
LowEndBox is great for non-mission critical servers. You aren't going to find
many top tier providers on there, mostly smaller companies. I got a dedicated
box (quad Xeon, 24GB RAM, 500GB) for $49/m.

~~~
sergiotapia
I would love to get my hands on one of those. What provider did you get it
from?

------
TallboyOne
Good article. Be wary of the well documented zero-day exploits if you're using
php.

This is one of my other favorite articles:
[http://docs.ngx.cc/en/latest/topics/tutorials/config_pitfall...](http://docs.ngx.cc/en/latest/topics/tutorials/config_pitfalls.html)

Some good introductory stuff here as well:
[http://pineapple.io/resources/tagged/nginx](http://pineapple.io/resources/tagged/nginx)

~~~
emillon
How can a zero-day be well documented? By definition it's not yet public.

~~~
meritt
It sounds scarier than saying: "If you use PHP, remember to set the following
in your .ini"

    
    
        cgi.fix_pathinfo = 0

~~~
jonknee
So not zero day and not an exploit. A terrible idea for a feature though, PHP
seems to be rich with those.

~~~
meritt
Not really a terrible idea at all. They are simply conforming to the CGI
specification. In realizing the potential security issues associated with
doing so, they offer a way to disable that behavior.

------
thu
I think the sites-available is a debianism, not present on all distros. One
nice thing that nginx supports is include directives with wildcards so you can
e.g. have /srv/example.com/nginx.conf and /srv/api.example.com/nginx.conf and
include them in the main configuration file with include /srv/*/nginx.conf.

~~~
merlincorey
Today You Learn that is because the original package maintainer of the NginX
package in Debian (and thus later, Ubuntu) simply copied the structure of the
Apache package. It's most useless because _there is no script to manage the
sites available like with apache_.

I have been complaining about this for years!

On FreeBSD and all my client's sites (whether they run Linux or what), I
always set mine to include sites/*.conf and delete those apache-isms.

~~~
vacri
It's especially bizarre given how trivial such a script is - as far as I am
aware, it's a glorified symlink-maker.

Hrm, looking now, a2ensite is 340 lines long...

~~~
merlincorey
Quite the glorified symlink maker!

It is my experience from years of administration that `ln` and `rm` (or
perhaps `mv`) are the only commands necessary to work with the directories
without the scripts.

------
tszming
For starter nginx's configuration, the h5bp nginx config [1] is pretty
awesome, e.g. sending correct mime types, protecting hidden files, cross
domain webfont, expires, gzip, server tunings all included.

[1] [https://github.com/h5bp/server-
configs/tree/master/nginx](https://github.com/h5bp/server-
configs/tree/master/nginx)

~~~
jenius
Great suggestion, thanks @tszming!

------
286c8cb04bda
_> The default port for the internet is 80, so if there’s no port in a url,
that means it’s 80._

The Internet has no default port; 80 is for HTTP. If the port is omitted, then
the default for the scheme[1] is assumed.

</pedant>

[1]:
[https://en.wikipedia.org/wiki/URI_scheme](https://en.wikipedia.org/wiki/URI_scheme)

~~~
jenius
haha fair enough, if I changed "the internet" to "http" would that satisfy
you?

~~~
danyork
Yes, that would be good to change it to "http" to be clear about the protocol
you are talking about. :-)

------
warmwaffles
I am a little hesitant on restarting nginx. When you do that, it drops the
connections that are currently attached. Instead, you may want to do `nginx
reload`

~~~
timroman
I can't imagine there are many connections to worry about if you're
configuring a new server.

~~~
warmwaffles
Right but if you are modifying and existing server, then this needs to be
taken into account. We have several servers who are constantly serving
connections and we can't have any of them drop otherwise it will result in a
poor user experience.

I just wish the article talked about using reload as well as restart and when
to use them.

~~~
MatthewPhillips
Me as well. I always use reload but I don't really know how it works. Does it
maintain the old and new configs and drops the old after the last connection
using it is complete?

~~~
merlincorey
When NginX's master process receives the HUP signal[1], NginX will process and
test the new configuration. If it is correct, the new configuration will be
loaded into new worker processes. The old worker processes will stop receiving
connections, but finish their current work. Eventually (within milliseconds
usually), all the old processes will be gone and only new processes with new
configuration will be working on requests.

[1] On FreeBSD, we just use `killall -HUP nginx` to reload; your distro will
probably send HUP to the master process' PID

------
callmeed
One of my favorite nginx features I just discovered is that you can use a
regex in the server_name and then you can use the capture as a variable later
[1] ... this lets you serve domains or subomains from completely different
directories without a new conf file or a reload.

I'm using it at [http://www.utterson.me](http://www.utterson.me) to serve up
static Jekyll blogs on a subdomain.

I may be wrong, but I don't think Apache can do this (it can do regex but you
don't get a variable).

[1]
[http://nginx.org/en/docs/http/server_names.html#regex_names](http://nginx.org/en/docs/http/server_names.html#regex_names)

~~~
ericclemmons
I've done something similar in Apache with mod_vhostalias, where you set a
VirtualDocumentRoot that specifies the pattern to match against and the
dynamic directory path to serve up.

------
lowboy
I like just keeping a single "etc/nginx/sites" folder, including "sites/*.ON"
in my main nginx.conf and then appending .ON to the sites that are enabled:

    
    
        active.site.com.ON
        another.active.com.ON
        not.active.com

~~~
dkokelley
That's clever. Coming from Apache I was disappointed not to see something
equivalent to: a2ensite (site)

~~~
stayclassytally
Wouldn't it be kind of trivial to right a function to would take a directory
name as a parameter and symlink it from site-available to site-enabled?

~~~
dkokelley
It would be. That's exactly what a2ensite does. That's what I ended up doing.

------
chuhnk
For some strange reason I was expecting an article on nginx module
development. [http://www.evanmiller.org/nginx-modules-
guide.html](http://www.evanmiller.org/nginx-modules-guide.html)

~~~
merlincorey
You aren't at all alone. I was really hoping for updated module development
information from someone currently in the trenches.

------
samsnelling
Completely off-topic: Is that a custom WP theme? I love the look and feel of
this article.

On-topic: Thank you for this. I am going to purchase a DO box this weekend and
play around with nginx instead of apache. For some reason when I last tried to
use nginx, I could not get location {} to work. Granted it was some time ago.

Does anyone have any resources on nginx as a load balancer?

~~~
pajju
Avoid using Digital Ocean(DO).

We had very very bad experience with them, file-system corruption, hardware
failures.

And we are still unable to recover all our data. And so far, no hope!

They don't answer any of the questions properly, my team is very upset. We
felt, they don't have much technical expertise in managing servers.

DO might be okay for testing and learning, but never use them for any
production setups.

Update: we are still struggling to get our data back. No hopes so far.

We shall write a detailed blog post on the whole experience with Digital
Ocean.

~~~
jenius
On the contrary, if you just need a box to tinker with sysops stuff and learn,
digital ocean is a fantastic solution. Cheap and I've never had a bad
experience or anything unreliable.

I can't speak to using it to store lots of not-backed-up files or running a
gigantic production server, but for learning about syops it works great, to
get back to the purpose of this article.

~~~
samsnelling
That's kind of where I'm at right now. Normally all of my side projects are
hosted on PAAS (Appfog is my current choice, but we will see since their
acquisition).

I really just want to practice setting up and tearing down configurations. I
think DO will be a good choice for this.

~~~
jenius
Was in that exact same spot a couple months ago and did the same thing. I was
eyeing DO for a while and one day folded and paid the (really no brainer) $5.
I've learned a ton since then and it has been absolutely worth it for me.

I actually transitioned all my apps off any other PAAS platforms (mostly
nodejitsu, timed nicely with their 3x price increase) and am now hosting
everything I run off a single $5 digital ocean box, which actually is saving
me a bit of money, and deploys are a lot smoother. The company I work at,
Carrot, is also hosting all of carrot.is on a $5 DO box, including this
article, which has had no issues coping with the 600+ people on site at a time
that have come with this HN blitz.

------
mfjordvald
It's kinda depressing that this article is basically just a copy of one I
wrote in 2010 and it's still something that gets attention as interesting
stuff. Nginx documentation obviously still has a long way to go.

~~~
forgotAgain
I've actually had your article bookmarked for some time. I got it from the
nginx wiki page at
[http://wiki.nginx.org/Configuration](http://wiki.nginx.org/Configuration).

I was more surprised than depressed about the upvotes for the current article.
It really makes me wonder if the technical level of the audience here hasn't
declined substantially. The current article is well written but it's aimed at
a "Dummies" rather than developer level.

~~~
zalew
yeah, you got to checkout the number of twitter bootstrap tutorials.

------
seclorum
I've always wanted to use nginx to build web apps in Lua .. does anyone
know/can recommend any great tutorials with this in mind? It'd be nice if I
could learn how to use nginx+lua to build a blog, and so on .. I'll use
google, but on the off chance someone on HN knows of something already, I'm
all ears ..

~~~
merlincorey
You might be interested to know that NginX can even embed Lua internally as a
scripting language in the configuration[1].

As for your goals of connecting NginX to serve your Lua project, well that's
quite simple really. Unlike Apache or Lighttpd, _NginX is not an application
server_. NginX is only a _reverse_ proxying HTTP server that speaks HTTP,
FastCGI, and UWSGI. To connect your Lua application to NginX, your Lua
application will either need to speak HTTP, FastCGI, or UWSGI. I don't know
anything about Lua so I can't really help you figure out which is best, but in
terms of setting up with NginX, it mostly just changes which flavor of pass
you will use.

[1]-
[http://wiki.nginx.org/HttpLuaModule](http://wiki.nginx.org/HttpLuaModule)

~~~
seclorum
Thanks for the reply - I am definitely learning a lot from this feedback, and
appreciate the effort.

------
ChikkaChiChi
This article is just fine for IDE-side development, but I would not recommend
for anyone to use the version of nginx in the standard Ubuntu package manager.
It traditionally is several version back missing important key features that
you might want to take advantage of.

~~~
nsmartt
Generally, it's installed using apt, but from a source maintained by nginx.
It's just a quick modification of sources.list.

[http://nginx.org/en/linux_packages.html#stable](http://nginx.org/en/linux_packages.html#stable)

------
raylu
Slightly off-topic, but I'm sad that people still use apt-get. aptitude is
pretty much just better[1].

Also, if you're reading this article you probably don't need the slightly
better performance/throughput of nginx. Nginx's configuration is just
terrible. You can cause segfaults and all sorts of unexpected behavior with
the If directive[2]. And who came up with the idea that rewrite[3] should
sometimes redirect instead of rewriting?

 _If the replacement string begins with[http://](http://) then the client will
be redirected, and any further rewrite directives are terminated._

Apache's configuration might be ugly and unwieldy and the community might be
horribly infested, but at least the configuration makes sense. Lighttpd has
none of the above problems, though.

[1]
[http://superuser.com/questions/93437/](http://superuser.com/questions/93437/)

[2] [http://wiki.nginx.org/IfIsEvil](http://wiki.nginx.org/IfIsEvil)

[3]
[http://wiki.nginx.org/HttpRewriteModule#rewrite](http://wiki.nginx.org/HttpRewriteModule#rewrite)

~~~
merlincorey
I'm extremely biased as I have been using NginX for many years now; however,
I've got to _completely_ disagree with you.

NginX's configuration is beautiful, elegant, and concise. It kicks the ever
living crap out of configuring Apache or Lighttpd (the two other HTTPd's I
have extensive experience with). It seems so strange, because it's
_different_.

NginX's configuration language is _declarative_. If is _imperative_ and
actually using if inside locations in NginX creates an inner location and
executes a mini language to process.

    
    
        14:42 <+merlincorey> !ifisevil
        14:42 < ngxbot> please see above
    

Please see [http://wiki.nginx.org/IfIsEvil](http://wiki.nginx.org/IfIsEvil)
for more about that in particular.

Finally, I have to disagree with OP... NginX has great documentation, written
by Igor himself initially (and edited by the community) available here:
[http://nginx.org/en/docs/](http://nginx.org/en/docs/)

~~~
raylu
Yes, I linked to IfIsEvil. The fact that you need a page to document the
horrible behavior because it's too late to fix it is a sign that something is
very wrong with the config syntax.

~~~
merlincorey
The fact that you think it is a problem with the configuration syntax is an
indication that you didn't read the wiki page, or the important part of my
comment.

NginX's configuration is _declarative_.

The reason the _imperative_ if was given powers beyond its means was because
people clamored for the feature.

The reason it's still there is because _removing it would break some working
configurations that use if_.

If you don't have experience with declarative programming and you think in
terms of imperative programming, it might seem "horrible behavior", but
actually, it's what is to be expected from mixing the two paradigms in the way
it is being mixed.

The real wart is under the hood where-in location based if's are converted to
sub-locations. This is where many problems related to IfIsEvil stem from.

~~~
raylu
I'm rather annoyed that you're not reading anything I've said.

No, the problem is not that I haven't read the page. I have. It can cause
segfaults. Your configuration can cause segfaults. Your _configuration_ can
cause _segfaults_. _Your configuration can cause segfaults._

And yes, I acknowledged that they can't remove it because it's too late, using
those exact words. That doesn't mean it's not a problem. It means you should
jump ship to something saner, like lighttpd, which also doesn't have the
rewrite-sometimes-redirects problem.

~~~
merlincorey
> Your configuration can cause segfaults.

 _MY_ configuration never causes segfaults, because I understand the
_declarative nature_ of the configuration language, and I don't _mistakenly
attempt to shoehorn imperative constructs_ into it.

By your logic, software should not be written in C/C++, because _it can cause
segfaults_!

> It means you should jump ship to something saner, like lighttpd,

Ah, you're a lighttpd guy. I'll stick with not having the http server also be
an application server, and we'll agree to disagree.

Have a nice day.

~~~
raylu
I was using "your" in the third-person, a quirk of the English language that
is too late to fix.

 _Configuration_ should not be able to cause your software to segfault.
Configuration shouldn't be software. And, in case it's not clear,
configuration should not be written in C/C++.

------
GibbyBorn
Guys, don't link to the community wiki, it contains a lot of obsolete or just
wrong information. Always use official documentation:
[http://nginx.org/en/docs/](http://nginx.org/en/docs/)

------
falsedan
I like this article because it reaffirms the demand for competent devops
who've taken an afternoon to read all of
[http://wiki.nginx.org/DirectiveIndex](http://wiki.nginx.org/DirectiveIndex).

------
geuis
Just a note on readability. You have a font color of #555 against #fff; Its a
light grey against white background and _very_ hard to read.

------
saravk
Very nice article useful for Nginx newbies. While we are on that subject, can
anyone please let me know if we can use Nginx for page cache busting purposes.

It is easy to configure Nginx to check if the cached version of the requested
URL exists and serve it. But i would like to know if the configuration can be
extended bit further to serve the cached file only if is less than a few days
old?

------
diminoten
This is fantastic, thank you! The way it's written is great because it doesn't
treat me like an idiot (I get why books do that, but it can grow tiresome). I
wish more tech books were written like this.

While we're picking nits, I thought this might be worth mentioning:

> The default port for the internet is 80

I'd change that to:

> The default port for the web is 80

Again, wonderful guide!

------
dergachev
If you liked this, consider checking out Mastering Nginx by Dimitri
Aivaliotis. I was quite surprised how helpful this book was.

[http://www.amazon.com/Mastering-Nginx-Dimitri-
Aivaliotis/dp/...](http://www.amazon.com/Mastering-Nginx-Dimitri-
Aivaliotis/dp/1849517444)

------
matthieupiguet
Nice introductory article. Maybe it should have included a word about SSL
support, especially the fact that you need to build nginx with ssl support, it
doesn't come out of the box, so make sure you plan for when you'll need it

------
ryandotsmith
If you are interested in running NGINX on Heroku, checkout my buildpack:
[https://github.com/ryandotsmith/nginx-
buildpack](https://github.com/ryandotsmith/nginx-buildpack)

------
DanielBMarkham
Been thinking about nginx for some time. If I could get an easy Mono/F#
implementation working with it, I'd jump on it in a heartbeat.

~~~
mixmastamyk
If it can talk to a socket, nginx can talk to it. Is there something I'm
missing?

------
klearvue
In the example given "listen 80;" is completely unnecessary since it's a
default.

~~~
jenius
If you had read carefully, you would notice that it said that right under ; )

------
w0ts0n
" nginx (pronounced engine-x). "

I have literally never heard anyone call it that.

~~~
oneeyedpigeon
How on earth else would you pronounce it? Now, lighttpd, on the other hand ...

~~~
jlgreco
I've always pronounced it "en gee eye en ecks".

Not the most elegant, but it rolls of the tongue relatively well and nobody
who was familiar with nginx has ever been confused.

------
antocv
What makes this "for developers"? Whats the difference if a sysadmin is
reading this, or a Linux user?

Im surprised to see this on the frontpage, it is less than basics in anything
any hacker worth its name can do.

~~~
srhngpr
I think it should read "Web Developers" \- those who may be less experienced
in setting up a web server like nginx.

~~~
oneeyedpigeon
Why would a _Web_ Developer be less experienced in setting up a _Web_ server
than a Developer? \- a touchy Web Developer :)

