I am trying to configure a simple wordpress site in nginx on Ubuntu. I'm no linux expert, but I usually manage between following tutorials online and tweaking a few bits myself. I've also had this very site running on a previous server with nginx, which I configured myself. I've migrated to a new server but I'm setting things up slightly differently this time round, so starting from scratch.
I've got nginx, php, and mysql installed and configured. I know php is working as I have checked it with domain.com/php.info. However, when I try to access domain.com or domain.com/index.php I get 403 forbidden. If I point the server block to index.html, that is served correctly.
I have set folder permissions to 755 and files to 644, and the owner to www-data.
If I rename index.php to index2.php, I can access the page at domain.com/index2.php but if I then point the server block to index2.php, I still get error 403.
I thought my server block config must be wrong, so I used the generator at digitalocean but the result is the same. I've tried almost every suggestion I can find on google and nothing has worked. Config below, can anyone help? Thanks!
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
set $base /var/www/example.com;
root $base/;
# SSL
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# security
include nginxconfig.io/security.conf;
# logging
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log warn;
# index.php
index index.php;
# index.php fallback
location / {
try_files $uri $uri/ /index.php?$query_string;
#also tried the alternatives below
#try_files $uri /index.php;
#try_files $uri /index.php?$args;
}
# additional config
include nginxconfig.io/general.conf;
include nginxconfig.io/example.com.wordpress.conf;
# handle .php
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
include nginxconfig.io/php_fastcgi.conf;
}
}
# non-www, subdomains redirect
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name .example.com;
# SSL
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
return 301 https://www.example.com$request_uri;
}
# HTTP redirect
server {
listen 80;
listen [::]:80;
server_name .example.com;
return 301 https://www.example.com$request_uri;
}
Related
I have a Nginx webserver (I'm very new at Nginx). This is my Nginx config file:
server {
listen 80;
listen [::]:80;
server_name example.com *.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_timeout 5m;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name example.com *.example.com;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
}
I have a DNS-record set to allow wildcard subdomains. My question now is: how can I "catch" the current subdomain in PHP?
For example: if the subdomain is http://demo.example.com, I want to go to
http://example.com?subdomain=demo.
Thanks in advance!
The host header will already contain the client requested domain. You could just grab that in php
$domain = $_SERVER['HTTP_HOST'];
However, unless you have a wildcard SSL certificate then you are going to have a bad time.
SSL negotiation takes place before any HTTP exchange so if the subdomain and the SSL cert don't agree the connection will fail.
Also, changing the subdomain to a query string is a bad idea:
You'll lose the ability to configure each subdomain separately within
Nginx and force lots of redirects and rewrites for every client
connection.
Your SEO will suck.
What will your page links look like?
If I have one.example.com and you have two.example.com the requests will become:
example.com?subdomain=one
example.com?subdomain=two
Both of those requests are now being handled by the same index page on example.com. Is that really what you want?
Add the following server to your Nginx. don't forget to restart Nginx service
server {
server_name demo.example.com;
rewrite ^(.*) http://example.com?subdomain=demo;
}
Update
according to the comment, for dynamic redirection, you should get the subdomain name by regex
server {
listen 80;
server_name ~^(?<name>.+)\.example\.com$;
return 301 http://example.com/?subdomain=$name;
}
Also, you can rewrite it instead of 301 redirects by
rewrite ^(.*) http://example.com/?subdomain=$name;
See this document for more info.
when i add another nginx-php site,this site was redirected to another php site,i didn't write the redirect in .conf file. what happend?
this is my new site : y2b.casvot.com
site above was redirected to this domain : www.casvot.com
//=======================my nginx config file=================
//
//You should look at the following URL's in order to grasp a solid understanding
//of Nginx configuration files in order to fully unleash the power of Nginx.
//http://wiki.nginx.org/Pitfalls
//http://wiki.nginx.org/QuickStart
//http://wiki.nginx.org/Configuration
//Generally, you will want to move this file somewhere, and start with a clean
//file but keep this around for reference. Or just disable in sites-enabled.
// Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
// Default server configuration
//================================================
server {
// SSL configuration
//
// listen 443 ssl default_server;
//listen [::]:443 ssl default_server;
// Note: You should disable gzip for SSL traffic.
// See: https://bugs.debian.org/773332
// Read up on ssl_ciphers to ensure a secure configuration.
//See: https://bugs.debian.org/765782
//Self signed certs generated by the ssl-cert package
//Don't use them in a production server!
//include snippets/snakeoil.conf;
root /home/casvot;
//Add index.php to the list if you are using PHP
// Index file path
index index.php index.html index.htm index.nginx-debian.html;
server_name casvot.com www.casvot.com;
location / {
//First attempt to serve request as file, then
// as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
//pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
root /home/casvot/;
include snippets/fastcgi-php.conf;
// With php7.0-fpm:
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
//SSL configuration
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/www.casvot.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.casvot.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
//Virtual Host configuration for example.com
//
// You can move that to a different file under sites-available/ and symlink that
//to sites-enabled/ to enable it.
server{
listen 80;
root /home/;
index index.php index.html index.htm ;
server_name y2b.casvot.com;
location / {
// First attempt to serve request as file, then
// as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
location ~ \.php$ {
root /home;
include snippets/fastcgi-php.conf;
// With php7.0-fpm:
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
}
server {
if ($host = www.casvot.com) {
return 301 https://$host$request_uri;
} //managed by Certbot
if ($host = casvot.com) {
return 301 https://$host$request_uri;
} // managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name casvot.com www.casvot.com;
return 404; //# managed by Certbot
}
/home directory:
An issue doesn't stick out at me, but is it possible that your server and your ISP support IPv6? Maybe it's connecting via IPv6 and www.casvot.com is the only vhost listening. I don't see a listen [::]:80; for y2b.casvot.com, but I see it for the other.
On Ubuntu 16.04 with Bash I've established LEMP and I can't access a WordPress app from browser although DB data is according (as I recall), and document root app dir has the right permissions (see below).
Nginx conf
nginx.conf (all default).
nginx default (all default).
Nginx app conf (seven first lines are mine - the rest is Certbot).
WordPress app wp-config.php
This is the only part I changed in wp-config.php:
define('DB_NAME', 'example.com');
define('DB_USER', 'example.com');
define('DB_PASSWORD', 'example.password');
My resets before testing
chown -R www-data:www-data /var/www/html/
chmod -R a-x,a=rX,u+w /var/www/html/
systemctl restart nginx.service
/etc/init.d/php*-fpm restart
Nginx logs
I checked all three Nginx logs (-t,access and error). The first two logs output no error, but error outputs this:
directory index of "/var/www/html/example.com/" is forbidden
My question
Why is the entrance forbidden, given the above data? What I miss?
Notes:
This problem is unique to the WordPress app. It doesn't happen with the non-HTTPS, PHPmyadmin app.
The DB user and the DB name of the WordPress app are identical to one another and also identical to the app's dir name.
The server root at your Nginxapp.conf should be:
root /var/www/html;
Not:
root /var/www/html/example.com/;
BTW, this setting has been defined in the Nginx virtual machine default.conf, it is kind of redundant to redefine it again at the app conf file.
Update
With your comment of not working after changing the root to root /var/www/html;, I further check your setting, and notice that you do not have a location directive for handling the root directory, try to change this line in your virtual host setting from:
try_files $uri $uri/ =404;
to:
location / {
try_files $uri $uri/ /index.php?$args;
}
I was able to solve it with this conf:
server {
root /var/www/html/judith-law.co.il;
server_name judith-law.co.il www.judith-law.co.il;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
location ~* \.(jpg|jpeg|png|gif|ico|css|js|ttf|woff|pdf)$ {
expires 365d;
}
# managed by Certbot
listen 443 ssl http2; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
return 404; # managed by Certbot
}
I have several virtual hosts configured with nginx. They are very simiral to each other and for most of them, everything seems to be working fine.
However,
If I hit the server through a url that does not have any virtual host configured, nginx always redirects to one of the existing virtual hosts (seems to be the first one in the list.
Same happens if I simply go there using IP address.
Most of the virtual hosts look like this:
server {
server_name iibs.co;
return 302 $scheme://www.iibs.co$request_uri;
}
server {
server_name www.iibs.co;
root /var/www/iibs.co;
index index.php;
include global/restrictions.conf;
client_max_body_size 64M;
# Additional rules go here.
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi.conf;
fastcgi_intercept_errors on;
fastcgi_pass php;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
# Only include one of the files below.
# include global/wordpress.conf;
# include global/wordpress-ms-subdir.conf;
# include global/wordpress-ms-subdomain.conf;
}
I just tried adding another one, very similar just with different domain and root. And that particular one, also getting redirected to the same first vhost on the list.
At this point, I have no idea where and what should I looks for.
This is an example of default NGINX config for prevent redirects to the first of the existing virtual hosts .
### Block all illegal host headers. Taken from a discussion on nginx
### forums. Cf. http://forum.nginx.org/read.php?2,3482,3518 following
### a suggestion by Maxim Dounin. Also suggested in
### http://nginx.org/en/docs/http/request_processing.html#how_to_prevent_undefined_server_names.
server {
listen 80 default_server; # IPv4
#listen [::]:80 default_server ipv6only=on; # IPv6
server_name _;
server_name "";
return 444;
}
I am trying to attach a promo subdomain to my site which is already on https, and then use a redirect url to redirect to another page in the site. For eg., basically if my site were https://example.com and had a page https://example.com/xyz/xyz/promo then I want a browser redirect when I type in https://promo.example.com to this page. I have set up all the relevant AWS route 53 settings.
My nginx server blocks have this
server {
listen 80 default_server;
listen [::]:80 default_server;
return 301 https://example.com$request_uri;
}
server {
server_name www.example.com;
return 301 https://example.com$request_uri;
}
server {
server_name example.com;
return 301 https://example.com$request_uri;
}
server {
server_name promo.example.com;
return 301 https://example.com/xyz/xyz/promo;
}
ssl_certificate /..path/..;
ssl_certificate_key //..path/..;
ssl_dhparam /..path/...;
ssl_trusted_certificate /..path/..;
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
ssl_prefer_server_ciphers on;
ssl_ciphers .......; //hidden
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_buffer_size 1400;
spdy_headers_comp 0;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=86400;
resolver_timeout 10;
server {
listen 443 ssl spdy;
server_name example.com;
include /etc/nginx/helper.conf;
root /var/www/example/ ;
index index.php index.html;
charset utf-8;
location / {
add_header "Access-Control-Allow-Origin" "*";
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
Current behaviour:
It redirects correctly when I type in promo.example.com directly without the https. But if I type in https://promo.example.com it just shows me example.com, with the url being https://promo.example.com
Expected behaviour:
If I type in https://promo.example.com, it should redirect to https://example.com/xyz/xyz/promo
I can't put https://promo.example.com and then redirect with the server blocks, because nginx throws an error.
How can I redirect https://promo.example.com to go to https://example.com/xyz/xyz/promo
Due to use Strict-Transport-Security header the browser provides 301 redirect automatically by itself so this server block has never been used:
server {
server_name promo.example.com;
return 301 https://example.com/xyz/xyz/promo;
}
Port redirection 80->443 happens before even browser connected to server, so Nginx always serves latest server block based on port 443. This should help you:
server {
listen 443 ssl;
listen 80;
server_name promo.example.com;
return 301 https://example.com/xyz/xyz/promo;
}
Try this:
server {
server_name promo.example.com;
rewrite ^ https://example.com/xyz/xyz/promo permanent;
Each Server can have a single instance of https, which in this case is example.com, thus when https is prefixed to any of the url, irrespective of the urls, the user is redirected to the example.com.
To have the user redirected to the intended url with https, you need to have a separate port or a separate IP for that site.
As per http://nginx.org/r/listen, the default for the listen directive is listen *:80 | *:8000;.
If the directive is not present then either *:80 is used if nginx runs with the superuser privileges, or *:8000 otherwise.
As such, the snippets you've provided have no effect on https connections at all, since they don't apply to port 443 over ssl.
You haven't provided your ssl configuration snippets, nor the certificate details, for us to provide you with a complete answer, but once the above is understood, the answer would likely avail itself.
You can refer to http://nginx.org/en/docs/http/configuring_https_servers.html#single_http_https_server in regards to configuring a single server to handle both HTTP and HTTPS requests.
P.S. In general, HTTPS itself doesn't plan nicely with subdomains, and unless you've paid extra, your certificate likely doesn't cover any of the subdomains, which means that it'll result in browser warnings should you or your users attempt to access such sites via the https:// address scheme.
There are two ways to work around this:
Have a wildcard certificate for *.example.com, so all subdomains can share the same certificate.
Run each SSL site at a different IP address. This way, the webserver knows which SSL certificate it can send to the browser. - by inspecting the IP address which received the incoming connection.