Question

Which one to use for my App back-end: Nginx or Apache?

Posted March 4, 2017 26.8k views
NginxApacheApplicationsUbuntu 16.04

I have this app/social network i’m about to launch.
The back-end uses PHP+ MySQL to serve the Mobile app (iOS and Android)
I read a lot of things but they are very confused. They are not CLEAR if an application using APACHE (get data from database receiving in json, load images, load and send messages, post text, etc) will really be faster just because it’s a dynamic content WHEN we’re scaling (like many people using at the same time).
Some say it’s the same, some say apache is faster, some test i saw showed nginx faster than apache even for dynamic content when there’s more than 10 requests at the same time.
Anyone would tell me if an API (php+mysql) for a mobile app would be faster on APACHE or NGINX? (DEFAULT installation, im not talking about ninja tricks)
??

1 comment

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

×
Submit an Answer
16 answers

@MrCruz
Apache with mod_php is a bit faster than Nginx with php-fpm.
I love the simplicity of Nginx and would always go with that. And I find it much easier setting up multiple Nginx in load balancing, which is great for scaling.

But talking about speed and serving dynamic content, then it really hasn’t much to do with Apache or Nginx.
Since you need to make sure your application will respond as fast as possible, so it doesn’t hold up one of the connections in Apache/Nginx.
So this leads us to PHP and MySQL.

You’ll get much more difference in what version of PHP you’re running. Nothing below version 7.0 is worth looking at, since it’s almost twice as fast as earlier versions.

You might want to switch from MySQL to MariaDB, since it has some extra features.
And remember to create correct indexes in your database, since that can easily make 10x the speed difference.
Actually you should be using PostgreSQL with it’s JSON storage, but that would be a big change, so let’s skip that.

Make sure everything is cut to the bone and optimized. Optimization/tweaking/tuning actually makes a huge difference. If you’re not interested in that, then just spend more on CPU/RAM and that’ll “fix” it.

I would do a Nginx, php-fpm, MariaDB, and cache with memcached or Redis. All of these can be setup on the same server or each on their own server and multiplied for scale.

Dang, just reloaded and saw the typical great answer from @jtittle :-)

  • And even though .htaccess and .htpasswd might be convenient in Apache, they’re actually one of the main reasons Apache is slower than Nginx.
    And the mod_rewrite in Apache is terrible compared to the simplicity of Nginx location regular expressions.

    • @hansen - Thanks – much appreciated :-).

      That’s definitely one reason Apache is normally slower than NGINX (.htaccess). Another is because of how mod_php works with Apache. Since it’s a module, it’s loaded in at runtime so if, for example, you’ve set PHP’s Memory Limit to something such as 128-256M, each of the processes spawned by Apache can use up to that much – it’s not collective.

      So you could end up spawning a dozen processes each using 256M, which is 3GB of RAM – that may be just enough to cause a crash/failure.

      Beyond that, configuring the MinServers, MaxSevers, ChildServers, etc is a pain. Yes, it’s true that PHP-FPM has similar settings, but they are far easier to work with and much easier to troubleshoot.

      A little basic math (which is actually detailed in the configuration file that’s used by default) and you’re set. I can’t say the same for Apache. What works one day may crash on you another :-). With PHP-FPM, if you configure it wrong, it probably won’t even start – which is better than running with configuration that may inevitably crash on you.

      Don’t get me wrong, I’m not an NGINX snob. I use Caddy too – though it’s configuration is much like NGINX, so it was a easy transition.

      • Sorry for piggy bagging on your thread @MrCruz but think you’ll learn even more from our geeky talk :)

        @jtittle
        I totally agree. mod_php is heavy on resources, but it does make requests faster than php-fpm, since everything is in memory. But it’s few milliseconds of difference. And I too prefer the way php-fpm is configured and managed.

        I looked at Caddy a couple of months ago, but didn’t know why I should use it compared to Nginx.
        One thing I’ve really been wanting to play with is HTTP/2 Server Push, which Nginx currently doesn’t want to implement even though CloudFlare has provided some code.
        Caddy don’t have that either - until 12 days ago! Now it supports Push - awesome!
        https://github.com/mholt/caddy/pull/1215

@MrCruz

Personally, I’d recommend NGINX over Apache. I find that configuring + optimizing NGINX is far less a chore than it is with Apache, it works out of the box with fastcgi using PHP-FPM (without having to use a module), and it’s also very simple to configure as a web server, reverse proxy, or even a load balancer.

That being said, while the default configuration may work short-term, at some point, to achieve a level of performance needed for your application to scale, you will have to modify configuration and begin tweaking configuration files. There’s really no way around that. The default configuration with NGINX and Apache is meant to get you started, but it’s not really intended for full-on production usage.

The same can be said of PHP/PHP-FPM, MySQL/MariaDB/Percona, etc. Base or stock installations are just a means to get you started. At some point, you’ll have to dive in or hire a sysadmin to do the work for you if you plan on scaling as there’s only so many cases where you can throw hardware at an issue before it no longer works. In doing so, you’ll also end up spending more trying to cope with load than you would hiring a sysadmin to manage it for you (if you’re not comfortable or capable of working from the CLI on your own).

@MrCruz

LTS = Long-Term Support Release. This means that Ubuntu 16.04 will continue to receive updates for a period of 5 years from the date of release. A non-LTS release, such as 16.10, will not.

As far as Ubuntu 16.04 goes, the commands to add the MariaDB repository would be:

sudo apt-get install software-properties-common
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.1/ubuntu xenial main'
sudo apt-get update
sudo apt-get -y install mariadb-server

@MrCruz

In regards to creating an API, neither NGINX or Apache would be handling any more than the initial request made by the user, which is then passed on to PHP (mod_php) or PHP-FPM (NGINX).

Your application would be responsible for handling everything else, such as encoding or decoding a JSON GET or POST request using PHP’s json_encode() or json_decode() functions, differentiating the requests (i.e. GET, POST, HEAD, etc), querying MySQL using PDO or MySQLi, etc.

NGINX and Apache simply function as web servers. They accept an incoming request and route it to a location depending on your configuration, if possible, else they throw an error. That error can be one that is setup to be handled by NGINX or Apache using configuration, or your application can handle it by using native PHP functions.

NGINX, in my experience, uses far less CPU and RAM to serve requests than Apache does, which is also one reason I prefer and use it myself, as well as on client websites that I manage or am hired to setup.

If you have any other specific questions, feel free to ask, I’m always happy to help!

@jtittle and @hansen
Yeah i agree with booth of you.
My concerns really were if by choosing NGINX (over Apache), it would perceptibly affect the performance of the overall response of requests, “using standards at the beginning for nginx or apache” in case i get like 40k new users per week, for example.
I never used NGINX before, so i don’t know.
And i really already know that most of the work is done by my code as you guys mentioned. I have scaled other apps with different servers, but in different scenarios. (i didn’t have to setup all servers myself)
I pay the most attention to my codes than to anything else. And have created my own techniques over time.
I barely rely (or never) on the chosen platform, database or anything like that to deal with the logic, data processing, security, etc.

(I know most [99% are average] programmers will be like* “your code won’t ever be better than theirs, don’t re-invent the wheel”* but that i disagree)
Yet i know the importance of taking the advantages from whatever we’re using, from hardware and low-level programming for performance. I started coding with c, c++ and Assembly. But i’m not a Masochist and like evolution too lol
It’s cool that you guys mentioned MariaDB. I say MySQL but in fact i ALWAYS used MariaDB. So i’m happy you guys made it easier for me to decide keeping using it.
PHP 7 i saw some people saying devs should wait it gets older and more stable. But looks like it’s a 100% GO, right? I will go for the PHP7.
So..
This time i want to set up the server myself for the beginning and only the essential for now.
IF my plan works, more money will be injected and of course, someone will be doing advanced settings modifications, etc as you guys wisely pointed out.

  • @MrCruz
    Just go with Nginx - if you bump into any problems, we’re here to help.
    If you don’t like it after first setup, it’s fairly easy to change to Apache or another web server.

    You say, you expect 40k users per week. But is that the amount of requests to your app? Because that’s the important thing, when talking loads/speeds/connectivity/etc.
    With a $20 single server, unless your app is extremely heavy, you should easily be able to serve 2-4 million requests per month.
    That’s about 1-2 request per second. But if you have peak periods, then you might need to tweak, scale or add cache/etc.

    Cool with MariaDB - when you have time, look into PostgreSQL - it’s JSON feature might be something you want to play with. And use MariaDB 10.1 (it’s highly stable - I’m using it in many high load projects, but looking forward to 10.2)
    After a few days with high activity, try running this tuner - and see what it recommends - and run it again on a weekly basis for a month or every time you make big schema/query changes.
    https://github.com/major/MySQLTuner-perl

    About PHP - it’s BS to say version 7 is not stable. It’s very stable. There has just been some changes, which did so older code didn’t work, so that’s why people didn’t like it in the beginning. Compared to HHVM, it’s a lot more stable. And it’s even faster.
    I’m running 7 and 7.1 in high production and I find it just as stable as 5.6
    Since you control all your code, then I would recommend 7.1 - you’ll see instantly if anything is failing, by going through the logs - and your app not working :)

    @jtittle Anything you think I missed - or you want to give your take on?

@jtittle @hansen
I need some help.
While trying to install the NGINX i got this error:

Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.
invoke-rc.d: initscript nginx, action "start" failed.
dpkg: error processing package nginx-core (--configure):
 subprocess installed post-installation script returned error exit status 1
dpkg: dependency problems prevent configuration of nginx:
 nginx depends on nginx-core (>= 1.10.0-0ubuntu0.16.04.4) | nginx-full (>= 1.10.0-0ubuntu0.16.04.4) | nginx-light (>= 1.10.0-0ubuntu0.16.04.4) | nginx-extras (>= 1.10.0-0ubuntu0.16.04.4); however:
  Package nginx-core is not configured yet.
  Package nginx-full is not installed.
  Package nginx-light is not installed.
  Package nginx-extras is not installed.
 nginx depends on nginx-core (<< 1.10.0-0ubuntu0.16.04.4.1~) | nginx-full (<< 1.10.0-0ubuntu0.16.04.4.1~) | nginx-light (<< 1.10.0-0ubuntu0.16.04.4.1~) | nginx-extras (<< 1.10.0-0ubuntu0.16.04.4.1~); however:
  Package nginx-core is not configured yet.
  Package nginx-full is not installed.
  Package nginx-light is not installed.
  Package nginx-extras is not installed.

dpkg: error processing packagNo apport report written because the error message indicates its a followup error from a previous failure.
                                   e nginx (--configure):
 dependency problems - leaving unconfigured
Processing triggers for systemd (229-4ubuntu16) ...
Processing triggers for ureadahead (0.100.0-19) ...
Processing triggers for ufw (0.35-0ubuntu2) ...
Errors were encountered while processing:
 nginx-core
 nginx
E: Sub-process /usr/bin/dpkg returned an error code (1)

What should i do?

  • @MrCruz
    How did you install it? apt install nginx ? It should say it needs to install a handful of other things, which you should say yes to.

    • yes i used:
      sudo apt-get update
      sudo apt-get install nginx

      From the site’s tutorial lol

      • That’s the first time ever I’ve seen that fail - it’s like it doesn’t try to install the dependencies.
        Can you try with sudo apt-get install nginx-full

        • @hansen

          Preparing to unpack .../nginx-full_1.10.0-0ubuntu0.16.04.4_amd64.deb ...
          Unpacking nginx-full (1.10.0-0ubuntu0.16.04.4) ...
          Processing triggers for man-db (2.7.5-1) ...
          Setting up nginx-full (1.10.0-0ubuntu0.16.04.4) ...
          Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.
          invoke-rc.d: initscript nginx, action "start" failed.
          dpkg: error processing package nginx-full (--configure):
           subprocess installed post-installation script returned error exit status 1
          dpkg: dependency problems prevent configuration of nginx:E: Sub-process /usr/bin/dpkg returned an error code (1)
          

          This is weird. Maybe my droplet already has Apache, is it possible to be the problem?
          The only thing i picked pre-installed for Ubuntu was the PHPMyAdmin.

@MrCruz

What I would do is start fresh. Deploy a clean Ubuntu 16.04 64bit image and start off running:

apt-get update
apt-get -y upgrade
apt-get -y install nginx

or copy and paste:

apt-get update && apt-get -y upgrade && apt-get -y install nginx

Once NGINX is installed, you’ll find all the available configuration in /etc/nginx.

The nginx.conf file is the main configuration file for NGINX – this is where you can really tweak and tune NGINX to perform better.

The sites-available directory is the main directory where config files for your website(s) are stored. They are symlinked to the sites-enabled directory (you have to do this by hand, except for the default which is already done for you) and as per nginx.conf, it’ll load all configuration from this directory.

From there, it’s a matter of setting up actual configuration for your website either in the default.conf configuration file, or a new one.

  • Thanks! @jtitle @hansen
    Now my problem is correctly install MariaDB.
    Do you have a step-by-step to install it on DigitalOcean droplet correctly?

    • Make sure you didn’t accidentally add MySQL while installing PHP. But MariaDB should complain if it’s installed during installation (I think).
      I generally install MariaDB first, then Nginx and then PHP-FPM.

      I’m not completely sure if this key is still valid for the general mirror, otherwise go to https://downloads.mariadb.org/mariadb/repositories/ and find the mirror in your data center and scroll down to see the key and repository. It’s official repositories.

      sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 80E7349A06ED541C
      sudo add-apt-repository 'deb [arch=amd64,i386] http://mirrors.digitalocean.com/mariadb/repo/10.1/ubuntu trusty main'
      
      sudo apt-get update
      sudo apt install mariadb-server
      

      If you add the following official repository, then you’ll always get the stable version of Nginx - instead of version 1.10.x included in Ubuntu 16.04

      sudo add-apt-repository ppa:nginx/stable
      
      sudo apt-get update
      sudo apt install nginx
      

      I don’t think you can install PHP 7.1 on Ubuntu 16.04 without the following repository - otherwise you will get 7.0
      But do note that this is an un-official repository. Though it’s massively used by many people and is referenced in almost every PHP tutorial on DigitalOcean.

      sudo LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
      

      Depending on what you need in PHP, you should only install the modules you need. If you are installing 7.1, then replace all 7.0 below. This is a list of common modules, which allows you to use many frameworks (or phpMyAdmin) without them complaining about missing modules. I’ve only tested this list with the ppa:ondrej/php repository listed above.

      sudo apt-get update
      sudo apt install php7.0 php7.0-common php-common php-gettext php-pear php7.0-fpm php7.0-cli php7.0-mysql php7.0-curl php7.0-gd php7.0-intl php7.0-json php7.0-mcrypt php7.0-readline php7.0-opcache php7.0-mbstring php7.0-xml php7.0-zip php7.0-bz2 php7.0-soap
      

      And finally, just for good measures. This will update the index, do upgrades (also kernel upgrades), remove non-used packages, and cleanup old downloaded packages - and finally reboot:

      sudo apt-get update
      sudo apt-get dist-upgrade
      sudo apt-get autoremove
      sudo apt-get autoclean
      
      sudo reboot
      
    • @MrCruz

      MariaDB can be installed using:

      apt-get -y install mariadb-server
      

      Once the installation is complete, you’ll want to run:

      mysql_secure_installation
      

      … from the CLI to set a root password.

      As far as PHP goes, I prefer 7.1.x, and I use the ppa:ondrej/php repo to stay up to date. You can add it using:

      add-apt-repository -y ppa:ondrej/php
      

      You’ll then need to update/sync the packages:

      apt-get update
      

      Once the update finishes, you can run the command below to search for all available packages for that PHP version:

      apt-cache search php7.1 --names-only
      

      At minimum, you’ll want to install php7.1-fpm, php7.1-cli, and php7.1-mysql, though I tend to install quite a few more than that, which you could do by using:

      apt-get -y install php7.1-cli php7.1-dev php7.1-fpm php7.1-bcmath php7.1-bz2 php7.1-common php7.1-curl php7.1-gd php7.1-gmp php7.1-imap php7.1-intl php7.1-json php7.1-mbstring php7.1-mysql php7.1-readline php7.1-recode php7.1-soap php7.1-sqlite3 php7.1-xml php7.1-xmlrpc php7.1-zip php7.1-opcache php7.1-xsl php-yaml
      

@hansen @jtittle
Guys, i found from MariaDB website.
16.10 “yakkety”
16.04 LTS “xenial”
I have Ubuntu 16.04 .. Should i get the MariaDB 16.10 ?
What’s the LTS stand for here?

  • No!
    You should only install packages that matches your operating system. And you’ve installed Ubuntu 16.04 Xenial.
    LTS means Long Term Support, which in Ubuntu terms means that they’ll support the system with security updates for 5 years. For 16.04 it’s supported until April 2021.
    https://wiki.ubuntu.com/Releases

@hansen @jtittle
Guys, THANK YOU VERY VERY MUCH..
IT IS WORKING LIKE A CHARM.. Everything
MariaDB, PHP, Nginx, HTTPS .. my app connected using secure connection.. pretty cool..
Now, there’s only one thing bothering me.. the Mailing from PHP.. idk if i installed the sendmail wrong.. idk.. but it isn’t working as it does at my old server.
My PHP signup script has to send an email to the user.. The MX records are already set and working with gmail account.
But currently the PHP mailing isn’t working
Do you guys have anything for me to allow my PHP script to send emails?

  • @MrCruz Awesome!
    I can only recommend using Postfix, and having it relay the mail to Google Apps, Mailgun, Amazon SES, or another quality provider you’re using. Postfix is also a drop-in-replacement to sendmail (just like MariaDB is to MySQL).

    @jtittle Do you agree?

    I would not recommend sending mails from your droplet directly to the receiver, since there would be a high chance of the mail ending up in their spam-folder.

    Mail is difficult. In one of my companies, we send about 200k mails per day. That has taken me countless days to get it right and to make sure we weren’t marked as spam. And I still use an external provider for relaying.

    By the way, when you think you’ve setup everything, I would actually recommend that you take a snapshot of the server and re-install a clean Ubuntu and start all over. Just to make sure you’ve nailed everything and written everything down (in case of disaster). I know you probably don’t have time, but it’s a life saver to have good notes. And please, please, please remember to have multiple backups.

    • @hansen @MrCruz

      I would definitely recommend using Google Apps (G Suite), MailGun, SendGrid, or Amazon for mail over trying to setup up a mail server. While their are bash scripts and various other applications that will do it for you, it’s not the setup that’s the hard part – it’s management.

      Keeping up with SPF, DKIM, DMARC, and whatever new tech that comes out in the not too distant future can be a lot to manage when coupled with tweaking spam filters, IP blocks, preventing bounces/delays, etc.

      The services above manage the majority of those for you. You’ll have to add a few entries to your DNS zone, though beyond that, you’ll use their SMTP server(s), IP ranges, etc. If you’re actually developing your own application, I would recommend getting familiar with one of the API’s and using it over SMTP. You’ll have far more control over how mail gets sent and received than you do with just SMTP.

      MailGun has a very simple API, probably the most simplistic of them all. I’ve worked with it in the past (PHP) and it really wasn’t all that hard to setup and run.

@hansen @jtittle
Boy i feel dumb. EVERYTHING works fine but the damn PHP mailing (using smtp trying to login to google account - G Suite)
I tried Postfix and Sendmail many times, installing and re-installing, one or the other or both.
None get my PHP code to work. With sendmail using terminal it says it works (it shows sent mails) but it doesn’t send emails to anybody. And i need it to be done through PHP code.
But using gmail.com the account i created using my domain, it works just fine. It receives emails and it sends emails.
But can’t even use any Mail.php or anything similar to connect to via smtp using PHP.
I feel like it’s something very small and stupid that i missed.

Previous 1 2 Next