Apache and Nginx are two popular open source web servers often used with PHP. It can be useful to run both of them on the same virtual machine when hosting multiple websites which have varied requirements. The general solution for running two web servers on a single system is to either use multiple IP addresses or different port numbers.
Droplets which have both IPv4 and IPv6 addresses can be configured to serve Apache sites on one protocol and Nginx sites on the other, but this isn’t currently practical, as IPv6 adoption by ISPs is still not widespread. Having a different port number like 81
or 8080
for the second web server is another solution, but sharing URLs with port numbers (such as http://example.com:81
) isn’t always reasonable or ideal.
This tutorial will show you how to configure Nginx as both a web server and as a reverse proxy for Apache – all on one Droplet. Depending on the web application, code changes might be required to keep Apache reverse-proxy-aware, especially when SSL sites are configured. To avoid this, we will install an Apache module named mod_rpaf which rewrites certain environment variables so it appears that Apache is directly handling requests from web clients.
We will host four domain names on one Droplet. Two will be served by Nginx: example.com
(the default virtual host) and sample.org
. The remaining two, foobar.net
and test.io
, will be served by Apache.
sudo
privileges. You can set up a standard account by following Steps 2 and 3 of the Initial Server Setup with Ubuntu 16.04.Optional References
This tutorial requires basic knowledge of virtual hosts in Apache and Nginx, as well as SSL certificate creation and configuration. For more information on these topics, see the following articles.
In addition to Apache and PHP-FPM, we must also install the PHP FastCGI Apache module which is named libapache2-mod-fastcgi.
First, update the apt repository to ensure you have the latest packages.
Next, install the necessary packages:
Next, let’s change Apache’s default configuration.
In this step we will change Apache’s port number to 8080 and configure it to work with PHP-FPM using the mod_fastcgi module. Edit the Apache configuration file and change the port number of Apache.
Find the following line:
Listen 80
Change it to:
Listen 8080
Save and exit ports.conf
.
Note: Web servers are generally set to listen on 127.0.0.1:8080
when configuring a reverse proxy but doing so would set the value of PHP’s environment variable SERVER_ADDR to the loopback IP address instead of the server’s public IP. Our aim is to set up Apache in such a way that its websites do not see a reverse proxy in front of it. So, we will configure it to listen on 8080
on all IP addresses.
Next we’ll edit the default virtual host file of Apache. The <VirtualHost>
directive in this file is set to serve sites only on port 80
, so we’ll have to change that as well. Open the default virtual host file.
The first line should be:
<VirtualHost *:80>
Change it to:
<VirtualHost *:8080>
Save the file and reload Apache.
Verify that Apache is now listening on 8080
.
The output should look like the following example, with apache2 listening on :::8080.
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1086/sshd
tcp6 0 0 :::8080 :::* LISTEN 4678/apache2
tcp6 0 0 :::22 :::* LISTEN 1086/sshd
Once you verify that Apache is listening on the correct port, you can configure support for PHP and FastCGI.
Apache serves PHP pages using mod_php
by default, but it requires additional configuration to work with PHP-FPM.
Note: If you are trying this tutorial on an existing installation of LAMP with mod_php, disable it first with:
We will be adding a configuration block for mod_fastcgi
which depends on mod_action
. mod_action
is disabled by default, so we first need to enable it.
These configuration directives pass requests for .php
files to the PHP-FPM UNIX socket.
Add the following lines within the <IfModule mod_fastcgi.c> . . . </IfModule>
block, below the existing items in that block:
AddType application/x-httpd-fastphp .php
Action application/x-httpd-fastphp /php-fcgi
Alias /php-fcgi /usr/lib/cgi-bin/php-fcgi
FastCgiExternalServer /usr/lib/cgi-bin/php-fcgi -socket /run/php/php7.0-fpm.sock -pass-header Authorization
<Directory /usr/lib/cgi-bin>
Require all granted
</Directory>
Save the changes you made to fastcgi.conf
and do a configuration test.
Reload Apache if Syntax OK is displayed. If you see the warning Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message.
, that’s fine. It doesn’t affect us now.
Now let’s make sure we can serve PHP from Apache.
Check if PHP works by creating a phpinfo()
file and accessing it from your web browser.
To see the file in a browser, go to http://your_ip_address:8080/info.php
. This will give you a list of configuration settings PHP is using.
At the top of the page, check that Server API says FPM/FastCGI. About two-thirds of the way down the page, the PHP Variables section will tell you the SERVER_SOFTWARE is Apache on Ubuntu. These confirm that mod_fastcgi
is active and Apache is using PHP-FPM to process PHP files.
Let’s create Apache virtual host files for the domains foobar.net
and test.io
. To do that, we’ll first create document root directories for both sites and place some default files in those directories so we can easily test our configuration.
First, create the root directories:
Then create an index
file for each site.
Then create a phpinfo()
file for each site so we can test PHP is configured properly.
Now create the virtual host file for the foobar.net
domain.
Place the following directive in this new file:
<VirtualHost *:8080>
ServerName foobar.net
ServerAlias www.foobar.net
DocumentRoot /var/www/foobar.net
<Directory /var/www/foobar.net>
AllowOverride All
</Directory>
</VirtualHost>
Note: AllowOverride All
enables .htaccess
support.
These are only the most basic directives. For a complete guide on setting up virtual hosts in Apache, see How To Set Up Apache Virtual Hosts on Ubuntu 16.04.
Save and close the file. Then create a similar configuration for test.io
.
<VirtualHost *:8080>
ServerName test.io
ServerAlias www.test.io
DocumentRoot /var/www/test.io
<Directory /var/www/test.io>
AllowOverride All
</Directory>
</VirtualHost>
Now that both Apache virtual hosts are set up, enable the sites using the a2ensite
command. This creates a symbolic link to the virtual host file in the sites-enabled
directory.
Check Apache for configuration errors again.
Reload Apache if Syntax OK is displayed.
To confirm the sites are working, open http://foobar.net:8080
and http://test.io:8080
in your browser and verify that each site displays its index.html file.
You should see the following results:
Also, check that PHP is working by accessing the info.php files for each site. Visit http://foobar.net:8080/info.php
and http://test.io:8080/info.php
in your browser.
You should see the same PHP configuration spec list on each site as you saw in Step 4. We now have two websites hosted on Apache at port 8080
In this step we’ll install Nginx and configure the domains example.com
and sample.org
as Nginx’s virtual hosts. For a complete guide on setting up virtual hosts in Nginx, see How To Set Up Nginx Server Blocks (Virtual Hosts) on Ubuntu 16.04.
Install Nginx using the package manager.
Then remove the default virtual host’s symlink since we won’t be using it any more. We’ll create our own default site later (example.com
).
Now we’ll create virtual hosts for Nginx using the same procedure we used for Apache. First create document root directories for both the websites:
As we did with Apache’s virtual hosts, we’ll again create index
and phpinfo()
files for testing after setup is complete.
Now create a virtual host file for the domain example.com
.
Nginx calls server {. . .}
areas of a configuration file server blocks. Create a server block for the primary virtual host, example.com. The default_server
configuration directive makes this the default virtual host which processes HTTP requests that do not match any other virtual host.
Paste the following into the file for example.com:
server {
listen 80 default_server;
root /usr/share/nginx/example.com;
index index.php index.html index.htm;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
include snippets/fastcgi-php.conf;
}
}
Save and close the file. Now create a virtual host file for Nginx’s second domain, sample.org
.
The server block for sample.org should look like this:
server {
root /usr/share/nginx/sample.org;
index index.php index.html index.htm;
server_name sample.org www.sample.org;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
include snippets/fastcgi-php.conf;
}
}
Save and close the file. Then enable both the sites by creating symbolic links to the sites-enabled
directory.
Do an Nginx configuration test:
Then reload Nginx if OK is displayed.
Now acccess the phpinfo()
file of your Nginx virtual hosts in a web browser by visiting http://example.com/info.php
and http://sample.org/info.php
. Look under the PHP Variables sections again.
[“SERVER_SOFTWARE”] should say nginx
, indicating that the files were directly served by Nginx. [“DOCUMENT_ROOT”] should point to the directory you created earlier in this step for each Nginx site.
At this point, we have installed Nginx and created two virtual hosts. Next we will configure Nginx to proxy requests meant for domains hosted on Apache.
Let’s create an additional Nginx virtual host with multiple domain names in the server_name
directives. Requests for these domain names will be proxied to Apache.
Create a new Nginx virtual host file:
Add the code block below. This specifies the names of both Apache virtual host domains, and proxies their requests to Apache. Remember to use the public IP address in proxy_pass
.
server {
listen 80;
server_name foobar.net www.foobar.net test.io www.test.io;
location / {
proxy_pass http://your_server_ip:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Save the file and enable this new virtual host by creating a symbolic link.
Do a configuration test:
Reload Nginx if OK is displayed.
Open the browser and access the URL http://foobar.net/info.php
in your browser. Scroll down to the PHP Variables section and check the values displayed.
The variables SERVER_SOFTWARE and DOCUMENT_ROOT confirm that this request was handled by Apache. The variables HTTP_X_REAL_IP and HTTP_X_FORWARDED_FOR were added by Nginx and should show the public IP address of the computer you’re using to access the URL.
We have successfully set up Nginx to proxy requests for specific domains to Apache. Next, let’s configure Apache to set the REMOTE_ADDR
variable as if it were handling these requests directly.
In this step we will install an Apache module named mod_rpaf which rewrites the values of REMOTE_ADDR, HTTPS and HTTP_PORT based on the values provided by a reverse proxy. Without this module, some PHP applications would require code changes to work seamlessly from behind a proxy. This module is present in Ubuntu’s repository as libapache2-mod-rpaf
but is outdated and doesn’t support certain configuration directives. Instead, we will install it from source.
Install the packages needed to build the module:
Download the latest stable release from GitHub.
Extract it with:
Change into the working directory.
Then compile and install the module.
Create a file in the mods-available
directory which loads the rpaf module.
Add the following line to the file:
LoadModule rpaf_module /usr/lib/apache2/modules/mod_rpaf.so
Create another file in this directory. This will contain the configuration directives.
Add the following code block, making sure to add the IP address of your Droplet.
<IfModule mod_rpaf.c>
RPAF_Enable On
RPAF_Header X-Real-Ip
RPAF_ProxyIPs your_server_ip
RPAF_SetHostName On
RPAF_SetHTTPS On
RPAF_SetPort On
</IfModule>
Here’s a brief description of each directive. See the mod_rpaf
README file for more information.
HTTPS
environment variable based on the value contained in X-Forwarded-Proto
.SERVER_PORT
environment variable. Useful for when Apache is behind a SSL proxy.Save rpaf.conf
and enable the module.
This creates symbolic links of the files rpaf.load
and rpaf.conf
in the mods-enabled
directory. Now do a configuration test.
Reload Apache if Syntax OK is returned.
Access one of Apache’s websites’ phpinfo()
pages in your browser and check the PHP Variables section. The REMOTE_ADDR variable will now also be that of your local computer’s public IP address.
In this step we will configure SSL certificates for both the domains hosted on Apache. Nginx supports SSL termination so we can set up SSL without modifying Apache’s configuration files. The mod_rpaf
module ensures the required environment variables are set on Apache to make applications work seamlessly behind a SSL reverse proxy.
Create a directory for the SSL certificates and their private keys.
For this article we will use self-signed SSL certificates with a validity of 10 years. Generate self-signed certificates for both foobar.net
and test.io
.
Each time, you will be prompted for certificate identification details. Enter the appropriate domain for the Common Name
each time.
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DigitalOcean Inc
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:foobar.net
Email Address []:
Now open the Apache virtual host file that proxies requests from Nginx to Apache.
Since we have separate certificates and keys for each domain, we need to have separate server { . . . }
blocks for each domain. You should delete the file’s current contents and replace it with the following contents:
server {
listen 80;
listen 443 ssl;
server_name test.io www.test.io;
ssl on;
ssl_certificate /etc/nginx/ssl/test.io-cert.pem;
ssl_certificate_key /etc/nginx/ssl/test.io-key.pem;
location / {
proxy_pass http://your_server_ip:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
listen 443 ssl;
server_name foobar.net www.foobar.net;
ssl on;
ssl_certificate /etc/nginx/ssl/foobar.net-cert.pem;
ssl_certificate_key /etc/nginx/ssl/foobar.net-key.pem;
location / {
proxy_pass http://your_server_ip:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
We split apart the original server block into two separate blocks, and we also told Nginx to listen on Port 443, the default port for secure sites.
Save the file and perform a configuration test.
Reload Nginx if the test succeeds.
Now, access one of Apache’s domains in your browser using the https://
prefix. First, visit https://foobar.net/info.php
and you’ll see this:
We used a self-signed certificate for this tutorial, and so the browser may warn us that the connection might not be trusted. You can safely proceed by trusting the site.
Look in the PHP Variables section. The variable SERVER_PORT has been set to 443 and HTTPS set to on, as though Apache was directly accessed over HTTPS. With these variables set, PHP applications do not have to be specially configured to work behind a reverse proxy.
Since Apache is listening on port 8080
on the public IP address, it is accessible by everyone. It can be blocked by working the following IPtables command into your firewall rule set.
Be sure to use your Droplet’s IP address in place of the example in red. Once port 8080
is blocked in your firewall, test that Apache is unreachable on it. Open your web browser and try accessing one of Apache’s domain names on port 8080
. For example: http://example.com:8080
The browser should display an “Unable to connect” or “Webpage is not available” error message. With the IPtables tcp-reset
option in place, an outsider would see no difference between port 8080
and a port that doesn’t have any service on it.
Note: IPtables rules do not survive a system reboot by default. There are multiple ways to preserve IPtables rules, but the easiest is to use iptables-persistent
in Ubuntu’s repository. Explore this article to learn more about how to configure IPTables.
When Nginx proxies requests for Apache’s domains, it sends every file request for that domain to Apache. Nginx is faster than Apache in serving static files like images, JavaScript and style sheets. So let’s configure Nginx’s apache
virtual host file to directly serve static files but send PHP requests on to Apache.
First, open the apache
virtual host file.
You’ll need to add two additional location blocks to each server block, and modify the existing location blocks. (If you have just one server block from the earlier step, you can completely replace the contents of your file so it matches the content shown below.) In addition, you’ll need to tell Nginx where to find the static files for each site. These changes are shown in red in the following code:
server {
listen 80;
server_name test.io www.test.io;
root /var/www/test.io;
index index.php index.htm index.html;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
proxy_pass http://your_ip_address:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ~ /\. {
deny all;
}
}
server {
listen 80;
server_name foobar.net www.foobar.net;
root /var/www/foobar.net;
index index.php index.htm index.html;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
proxy_pass http://your_ip_address:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ~ /\. {
deny all;
}
}
If you also want HTTPS to be available, preserve the listen 443 ssl;
line and the other SSL settings from Step 9.
The try_files
directive makes Nginx look for files in the document root and directly serve them. If the file has a .php
extension, the request is passed to Apache. Even if the file is not found in the document root, the request is passed on to Apache so that application features like permalinks work without problems.
Warning: The location ~ /\.
directive is very important; this prevents Nginx from printing the contents of files like .htaccess
and .htpasswd
which contain sensitive information.
Save the file and perform a configuration test.
Reload Nginx if the test succeeds.
To verify this is working, you can examine Apache’s log files in /var/log/apache2
and see the GET requests for the info.php
files of test.io
and foobar.net
. Use the tail
command to see the last few lines of the file, and use the -f
switch to watch the file for changes.
Visit http://test.io/info.php
in your browser and then look at the output from the log. You’ll see that Apache is indeed replying:
test.io:80 your_server_ip - - [01/Jul/2016:18:18:34 -0400] "GET /info.php HTTP/1.0" 200 20414 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36"
Then visit the index.html
page for each site and you won’t see any log entries from Apache. Nginx is serving them.
When you’re done observing the log file, press CTRL+C
to stop tailing it.
The only caveat for this setup is that Apache will not be able to restrict access to static files. Access control for static files would need to be configured in Nginx’s apache
virtual host file.
You now have one Ubuntu Droplet with Nginx serving example.com
and sample.org
, along with Apache serving foobar.net
and test.io
. Though Nginx is acting as a reverse-proxy for Apache, Nginx’s proxy service is transparent and connections to Apache’s domains appear be served directly from Apache itself. You can use this method to serve secure and static sites.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
I can see that you have used 4 domains. How can I install LAMP + Nginx to work with magento. EX : LEMP + magento and Apache use for reverse proxy or as a load balancer.
Do you want to Apache as the reverse proxy or Nginx as the reverse proxy?
I need apache as a reverse proxy and Nginx as the main server. However I need to run magento store ( only one domain ) so how can I use it. What is the best for magento ? Can I use Varnish with Nginx ? As far as I can see above , it is for 4 domains or 2 domains. How can I run one domain with same configuration?
I there a way to make it work with one domain name instead? :(
Of course you can, just use one virtual host file for that one domain name.
which one is the single domain that i can use if i want to work nginx as reverse proxy server. I just need to install wordpress on apache and use nginx speed to work better. I saw that so many people didn’t recommend with varnish ? is there any problem with it?
This comment has been deleted
hey Jesin,
Your tutorials are top notch and i have learned so much from them, thank you. I want to ship this setup to local install with docker – do you if one already exists over at docker?
also - i read about the httpoxy vulnerability and i noticed that you stressed the location directive was important to keep passwords, htaccess, etc secure – so even though the article linked states unsetting the proxy header in client requests or using different enviro variables as simple fixes – does this apply to this tutorial or have you already allowed for security with the directive?
Even though I am learning loads from you – I am still simple minded, lol. thanks for any advice.
re: recent do newsletter article: https://www.digitalocean.com/community/tutorials/how-to-protect-your-server-against-the-httpoxy-vulnerability?utm_medium=newsletter&utm_source=newsletter&utm_campaign=072116
To clarify – i want the docker on local install to match this setup when deployed to digital ocean via docker – is this correct idea? very new to docker – just got a laptop that will allow me to use it, lol.
Hi @caramiame,
Glad you find my articles helpful!
The severity of the httpoxy vulnerability depends on how your web application is coded. At the web server level it is best to add that line of config to remove the
HTTP_PROXY
variable.I’m also new to Docker :) You could try these articles:
https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04 https://developer.rackspace.com/blog/dev-to-deploy-with-docker-machine-and-compose/
thanks very much! I appreciate you!
Is php-fpm better than mod_php?
Yes because mod_php is loaded for every HTTP request including requests for static files (images, CSS, JS etc). So it takes up more resources. On the other hand PHP-FPM load only when PHP files are requested.
Thanks for this @jesin it’s great. I did everything exactly like you explained and it worked. Except for step 9 where instead of creating my own certificates i used let’s encrypt certbot. This certificates are super easy to install, they are valid, and best of all free.
Certbot for Nginx on Ubuntu 16.04(xenial)
After installing with:
sudo apt-get install letsencrypt
you can create a valid cert using something like:
letsencrypt certonly --webroot -w /var/www/foobar.net -d foobar.net
Just remember that if you also want the cert for the www.foobar.net you will have to do something like this instead:
letsencrypt certonly --webroot -w /var/www/foobar.net -d foobar.net -d www.foobar.net
So now, the NGINX virtual host named apache will look like something like this:
How about installing MYSQL is it the same as in a LAMP/LEMP installation?
Yes @luismuzquiz, steps for MySQL remain unchanged.
Thanks!
Owncloud users: seems that when you install ownlcoud using this tutorial and then the How to Install Owncloud on Ubuntu 16.04 tutorial, it resets Apache to use mod_php but if you do again:
ando reload apache
php-fpm it’s again enabled.
Maybe owncloud does not support php-fpm?
That is because the OwnCloud repository lists mod_php as a dependency and installs it along with the owncloud package. If you open this file from the repo there is a package named
owncloud-deps-php7.0
which installslibapache2-mod-php7.0
. OwnCloud does work with php-fpm, but it is just trying to install a wholesome LAMP package all by itself.All right, thanks for your explanation. I did use OwnCloud with mod_php first and then when i switched to to php-fpm noticed a much faster upload. Did the test with 15gb of files each time.
I think this is weird, dont know if its standard behavior but i am suspecting that a droplet’s name affects the configuration of an apache virtual host.
Let say you have created a droplet and finished step 5 of your tutorial @jesin
If the A record of one of your domains points to your droplet’s IP with a name or value of @, (if you pointed your domain to your droplet) and your droplet’s name happens to match that of your domain, then you will get the apache default page even if your virtual host includes the ServerName directive and points the domain a different folder.
Conditions:
1.- Lets say you have a domain on namecheap called whataday.com 2.- You point that domain with a value of @ to your droplet’s IP (pointed the domain to your droplet) 3.- Your droplet is named whataday.com
Then you will get this result. Or at least that what happened to me. I have ereased my cache many times, tried 4 different browsers on two different computers. I alway get the apache default page for the domain that matches my droplet’s name. The other 2 domains i created are fine, just like your tutorial teaches. (i did step 5 with 3 domains instead of two).
I am aware from the apache docs that if you omit the ServerName directive from any name-based virtual host, the server will default to a fully qualified domain name (FQDN) derived from the system hostname.
But did not expect the droplet’s name to affect the vhost configuration even if the ServerName directive is included within the vhost.
Home some expert could enlighten me
When browsing my app through the Nginx proxy pass (served by apache) all i got was a blank screen full of gibberish and strange charsets. Nothing else at all. No PHP Errors, no clues, no nothing.
It took me more than 8 hours to finally come up with the solution, turns out the nginx vhost for apache needed this line:
Can one remove mod_rpaf-stable the folder after make install?
Yes, it can be removed.
Is there a way to use a floating IP with this whole setup and then block port:8080 with an ip table?
If like me, you are using a Floating IP pointing to your Droplet and accordingly you used it as a substitution for your droplet’s ip in the proxy pass, and for the mod_rpaf configuration, like this:
Then either of the following iptables (i tried both) configurations will block both port:8080 and also NGINX port 80 for your app (which of course is an undesired behavior).
@luismuzquiz Can you provide more details about the setup? Are you having multiple Apache Droplets with a floating IP and configuring Nginx reverse proxy on a separate Droplet?
It’s Nginx as a Reverse Proxy on Ubuntu 16 with apache as the upstream Server @jesin. Just like your tutorial explains. Everything is on the same droplet. I use a floating ip because that way i can spin up a new droplet from a snapshot or a backup in case my production server gets killed and just point the floating ip to the new droplet instead of having to point all my domains to the new droplet.
One could see the implications of not being able to use the floating ip for the proxy_pass and the RPAF module on this setup (and block port 8080 with the ip tables)
For example, now actually i want to migrate from mysql to maria db. Obviously i wont do it on the production server. But if i snapshot my droplet at night (when no one is using my app) and then create a new droplet from that snapshot (with a different ip), and make the migration to MariaDB within that new droplet. It is not as simple as pointing my floating ip to the new droplet with the mariaDB, i will have to go and change as well the droplets ip on the mod rpaf and the proxy_pass wich is easy but kind of annoying.
How can I block access to http://$serverIP/ and ONLY allow to access to the domains?
Thanks!!
Hi @xdiglett,
You could create a separate virtual host file for
$serverIP
and set it deny all.Here’s an example:
If anyone is using Wordpress and has a redirect loop on the front page…
After a few hours I found out it was caused by the
$_SERVER["REQUEST_URI"]
being set toindex.php
by Nginx instead of the actual url and Wordpress was trying to removeindex.php
by redirecting to the url withoutindex.php
inwp-includes/canonical.php
.The solution for me is using something like this,
proxy_pass http://111.111.111.111:8080$request_uri;
So adding the
$request_uri
fixed it.I don’t know if you are male female or alien but I want to reach out and kiss you right now!!!
I have literally been banging my head against a brick wall for days doubting everything I did in this whole process and temporarily redirecting a clients site back to a dev domain while I figured this out. This was THE KEY!!!
Brilliant :-D
Hi there,
I’m having trouble with this. I’ve followed the instructions above with just one virtual host, as i am only using one domain. I also have SSL setup.
However nothing is showing in the apache log using sudo tail -f /var/log/apache2/other_vhosts_access.log
when I use the info.php, although the php info is shown correctly. However the index.html doesn’t display, and I get the message ‘The requested URL /index.php was not found on this server.’ note the error message is for .php even though the request was for .html
Any ideas please?
Ok, I solved this.
My website is installed in var/www/html/example.com However there was another info.php in the var/www/html folder which I’d left there by accident - this was throwing me off course for finding the solution.
When I realised that and removed it and left the info.php in the correct location (var/www/html/example.com/info.php) it was clear that info.php wasn’t being accessed at all, although the static set index.html in var/www/html/example.com/ was working correctly. This led me to check the apache configuration.
I ran sudo nano /etc/apache2/sites-available/000-default.conf to amend ‘DocumentRoot’ from /var/www/html to /var/www/html/example.com
it now works just fine! - hope this helps somebody out there
I was checking my web app score on Google’s PageSpeed Insights (you enter your url and they give you insights about the quickness of your web app). And they recommend Leverage browser caching meaning i need to set an expiry date or a maximum age in the HTTP headers for static resources such as .css files; .js files; images (png’s and jpg’s) etcetera.
The way to do this when you are using NGINX as a backend is just to add this lines to your NGINX virtual host file:
But in this case, i guess cause we’re using NGINX as front and APACHE as backend (NGINX as Reverse Proxy with Apache), it’s not working. Any ideas?
********** Set nginx as reverse proxy to apache server **********
( *** Change the default port of apache2 80 to 8080 *** )
Listen 8080;
( **** add the apache2 site code here must be phpinfo(); page **** )
This is my apache server <?php phpinfo(); ?>
( **** add the apache2 server virtualhost block here ****)
namevirtualhost <your I.P address here>:8080 <VirtualHost <your I.P address here>:8080> ServerName myapache.com DocumentRoot /var/www/myapache.com directoryindex index.php </VirtualHost>
( **** add the nginx site html code here **** )
</html>
( *** add the nginx server virtualhost block here *****)
}
Hello @jesin
How can I configure one domain to set up my cloud. When I check the blog again and again, i see that i have to use at least 2 domains ; one for apache and one for nginx. How can I use nginx as reverse proxy over apache for just one domain?
Hi Jesin,
I have used this configuration to setup digitalocean loadbalancer (two droplets added to the loadbalancer) but it is not working. Loadbalancer is fetching the details from /usr/share/nginx/example.com instead of /var/www/example.com.
As a single droplet, reverproxy is working with no problems. However, when it comes to load balancer this is not working.
Could you please help me in sorting this out.
Thanks in advance.
You Missed an important step to modify file /etc/php/7.0/fpm/pool.d/www.conf delete: listen 127.0.0.1:9000 and add listen = ‘/run/php/php7.0-fpm.sock’
Hello!
Forgive me if my questions seem obvious. This looks like a great setup for me, I have 1 domain and a subdomain and I’m looking to be able to run both Node.js applications as well as php applications in separate environments. Nginx seems to be the preferred solution for node, and I’d like to use that for my primary domain (let’s say example.com.) Is it possible to set up nginx/apache such that one could serve node projects at example.com/projects/node/ and php at example.com/projects/php/, or do I need a separate domain for each (or would a sub-domain work for my apache/php content?) I’m guessing that the sub-directory approach is either impossible or unadvisable, but thought I’d ask.
Thanks for the great tutorial I’m looking forward to getting started!
if I set up my droplet with Apache and Nginx as a reverse proxy it works also with CDN services like cloudflare or incapsula? If I’m not wrong, they already doing the reverse proxy job for you. Could someone help me to understand better this point?
Installation is quick on local computer but is wrong on Digital Ocean droplet at Step 4 — Verifying PHP Functionality. Page don’t open: This site can’t be reached
xx.xx.xx.xx took too long to respond. Search Google for 156 8080 info ERR_CONNECTION_TIMED_OUT
@jesin many users are having this same problem in step 4 verifying the php functionaity “This site can’t be reached” It wud be very kind of you if you can please enlighten us here. We are using the droplet IP here like http://my_droplet_ip:8080/info.php"
Afer 2days I found that it is the UFW firewall (installed from this article https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04 ) was blocking the request of 8080 after I disabled the UFW firewall by this command
sudo ufw disable
and restarting the apache and php-fpm againsudo service apache2 restart
sudo service php7.0-fpm restart
and the step 4 works OK. If you want to keep using firewall allow the port 8080 by this commandsudo ufw allow 8080
check this for allowing more https://www.digitalocean.com/community/tutorials/ufw-essentials-common-firewall-rules-and-commands If you want to completely remove UFW https://askubuntu.com/questions/275998/can-i-uninstall-ufw-completely Hope this helps, if anybody is looking out there.Hi Jesin, Nice How To tutorial!
I configured apache to listen 127.0.0.1:8080 and nginx to pass requests to 127.0.0.1:8080, and RPAF_ProxyIPs has my public IP 188…
apache: <VirtualHost 127.0.01:8080> nginx: proxy_pass http://127.0.0.1:8080;
So, with this conf RPAF looks does not work and phpinfo show remote addr 127.0.0.1! Any idea how can I fix that?
Hello Jesin, i have a general question:
Why using apache as well ? Wouldnt it be possible to use nginx as webserver and reverse proxy ? On light weight systems without that much CPU & RAM wouldnt that be an advantage in terms of performance ?
Dont understand me wrong - i like this solution. Just try to understand the benefit using both webservers.
Greetings -C.-
This is a great writeup - Thanks.
I have tried to use these steps on an existing LAMP setup.
Everything seems to be working except for the last step : Step 11 — Serving Static Files Using Nginx
I get no output after visiting my_domain/info.php in the file: /var/log/apache2/other_vhosts_access.log
I have gone through most of the steps posted apart from:
Step 6 - The last part for Creating an NGINX Virtual Host Step 9 - SSL (optional) as not needed (yet)
Do I need to create an nginx vhost in addition to the one already set-up for apache?
Hi jesln,
Your tutorial is really awesome! congrats for this, I’ve learn so much with it.
Still I have a problem:
On the very end of the Step 7, The variables HTTPXREAL_IP and HTTPXFORWARDED_FOR don’t show anywhere in the phpinfo. I already googled it, stackoverflowed it (I even opened a question) but nothing solved that.
I tried changing the OS, repositories, packages. Also tried with differents Apache’s mods/libs, but still nothing.
I’m so out of clues on this issue so maybe you can help me figure it out.
Thank you!
Excellent tutorial Jesin, thank you for sharing such relevant information. Does this step-by-step work well in Debian??
What would be the recommended firewall configuration using ufw? (I’m a newbie and most tutorials here use ufw, so I prefer to stick with it if possible)
How should I set RPAF_ProxyIPs if I have DO Load Balancer enabled as well as NGINX as a reverse proxy for Apache??? These settings DO NOT work if I use DO Load Balancer
Could you please show the support for ipv6 in ssl configuration. I use letsencrypt for the same configuration above (nginx as reverse proxy for apache) but the test site: https://www.ssllabs.com shows “No secure protocols supported” in ipv6 row. The ipv4 is grade A, while.
I need help with writing the server block for Step 11 “Serving Static Files Using Nginx”. I would like to redirect non_www to www and http to https.
I tried the following server block, but receive a redirect too many times error when entering the url in a browser.
Any help will be appreciated?
I need help. I got stuck on Step 4 Now when I type my IP (45.55.186.6) doesn’t go through http://45.55.186.60:8080/info.php
Says time out because waited to much.
I have nginx right now running and I’m directing all the http to https. I turned off and and turned on apache and doesn’t work
Nice tutorial.
I would suggest use mod_remoteip apache module instead of prehistoric mod_rpaf.
Hello,
I tried to do with LXD conteiners but without success!
I installed nginx in the root and each apache in conteiners, each container being a domain but I could not, how can I do?
I’m as far as “http://your_ip_address:8080/info.php”
I replaced “your_ip_address” with MY IP, Chrome Gives me this message:
While Firefox says:
I’m not really sure what to do, as I’m just following the directions, no programming skills at all!
Amazing blog. Explained in details :)
I follow your tutorials. But how can I access database by using phpmyadmin as my interface? I try to install mysql, php and phpmyadmin as usual. But i cannot access phpmyadmin by using www.ipaddress/phpmyadmin. Please help to guide me.
This tutorial is very helpful. I am a newbie for VPS. I want to ask you some questions below:
How can we access to database by using phpmyadmin? I try to install it as usual. But I cannot access it by go to: ipaddress/phpmyadmin. It is great if you have tutorial video.
This tutorial is tested with info.php. After following this tutorial, I try to install php script for both sites on nginx and apache, but only one of two sites on nginx and one of two sites on apache work. How can I config for both sites on nginx and apache?
The optional instructions gave me several issues.
First, I had to remove the extra files in /etc/nginx/sites-available, so that it only contains one server block (“apache”).
The instructions never stipulated that the other server blocks have to be deleted, which is what I had to (including the “default” one that is added automatically).
Next, I got the following error:
To fix this, I had to comment out “ssl on;” so that it looks like the following in my server block: #ssl on;
I also replaced the following directive: listen 443 ssl;
With this: listen 443 default ssl;
Lastly, this wasn’t showing new clicks to “info.php”:
The issue was default-ssl.conf setting the path to “/var/www/html” (rather than “/var/www/html/example.com”). I discovered this by searching for all files containing references to “/var/www/html”, since the correct “info.php” file (in “/var/www/html/example.com/info.php”) was clearly not executing as per “other/vhosts/access.log”.
I found the files containing “/var/www/html” with this command: