Why is nginx complaining of an unknown directive? - nginx

I'm trying to direct all HTTP requests resembling /<uuid4> to a specific HTTP server running on the localhost. Below is the relevant location line in my nginx.conf:
# nginx.conf
upstream django {
server unix:///app/django.sock; # for a file socket
}
server {
access_log /var/log/access.log;
error_log /var/log/error.log;
listen 80;
server_name 127.0.0.1;
charset utf-8;
client_max_body_size 75M;
# Django media
location /media {
alias /app/media;
}
location /static {
alias /app/static;
}
location ~* "[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$" { # matches UUIDv4
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass localhost:8000;
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /app/conf/uwsgi_params;
}
}
When starting nginx, I get the following error: nginx: [emerg] unknown directive "8}-([0-9a-f]" in /etc/nginx/sites-enabled/nginx.conf:30
What gives?

Actually you have another error. I've checked your server block and got following:
$ sudo nginx -t
nginx: [emerg] invalid URL prefix in /etc/nginx/sites-enabled/test:23
nginx: configuration file /etc/nginx/nginx.conf test failed
This is error about missing protocol in proxy_pass localhost:8000; line. After fixing it to proxy_pass http://localhost:8000; configs test passed.
Probably you're looking into old (or wrong) error log.

Related

How to setup NGINX proxy for Jenkins?

I have the current jenkins configuration:
server {
listen 80;
listen [::]:80;
server_name server_name mysubdomain.maindomain.com;
# This is the jenkins web root directory (mentioned in the /etc/default/jenkins file)
root /var/run/jenkins/war/;
access_log /var/log/nginx/jenkins/access.log;
error_log /var/log/nginx/jenkins/error.log;
#pass through headers from Jenkins which are considered invalid by Nginx server.
ignore_invalid_headers off;
location ~ "^/static/[0-9a-fA-F]{8}\/(.*)$" {
# rewrite all static files into requests to the root
# e.g /static/12345678/css/something.css will become /css/something.css
rewrite "^/static/[0-9a-fA-F]{8}\/(.*)" /$1 last;
}
location /userContent {
#have nginx handle all the static requests to the userContent folder files
#note : This is the $JENKINS_HOME dir
root /var/lib/jenkins/;
if (!-f $request_filename){
#this file does not exist, might be a directory or a /**view** url
rewrite (.*) /$1 last;
break;
}
sendfile on;
}
location #jenkins {
sendfile off;
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;
# Required for new HTTP-based CLI
proxy_http_version 1.1;
proxy_request_buffering off;
proxy_pass http://127.0.0.1:2021;
}
location / {
# try_files $uri $uri/ =404;
try_files $uri #jenkins;
}
}
which is essentially a copy of this jenkins configuration and my current /etc/default/jenkins file:
NAME=jenkins
# location of java
JAVA=/usr/bin/java
JAVA_ARGS="-Djava.awt.headless=true"
# make jenkins listen on IPv4 address
JAVA_ARGS="-Djava.net.preferIPv4Stack=true"
PIDFILE=/var/run/$NAME/$NAME.pid
JENKINS_USER=$NAME
JENKINS_GROUP=$NAME
JENKINS_WAR=/usr/share/$NAME/$NAME.war
JENKINS_HOME=/var/lib/$NAME
RUN_STANDALONE=true
JENKINS_LOG=/var/log/$NAME/$NAME.log
MAXOPENFILES=8192
HTTP_PORT=2021
HTTP_HOST=127.0.0.1
# servlet context, important if you want to use apache proxying
PREFIX=/$NAME
JENKINS_ARGS="--webroot=/var/cache/$NAME/war --prefix=$PREFIX --httpListenAddress=$HTTP_HOST --httpPort=$HTTP_PORT"
a simple curl requests shows a response of Jenkins running:
$ curl http://localhost:2021/jenkins/
<html><head><meta http-equiv='refresh' content='1;url=/jenkins/login?from=%2Fjenkins%2F'/><script>window.location.replace('/jenkins/login?from=%2Fjenkins%2F');</script></head><body style='background-color:white; color:white;'>
Authentication required
<!--
You are authenticated as: anonymous
Groups that you are in:
Permission you need to have (but didn't): hudson.model.Hudson.Administer
-->
</body></html>
However I am unable to acess the Web UI from the browser. whenever I try to I get a 404. The following are the reevant versions of installed 'wares:
Nginx - 1.13.6
Jenkins - 2.73.2 (using java -jar path-to-warfile --version)
OS - ubuntu 16.04
JDK - openjdk version "1.8.0_131"
An inspection of sudo nginx -T revealed that my site config wasn't being loaded. After correcting the error in my nginx.conf (spelling error in the include directive for the directory), this resolved the issue.
Thanks to SmokedCheese on IRC for his/her help with this issue.

nginx: [emerg] "http" directive is not allowed here in /etc/nginx/sites-enabled/default:1

I'm new to NGINX and I'm trying to setup minimal working thing. So I trying to run aiohttp mini-app with nginx and supervisor (by this example). But I can't configure Nginx right and getting the following error:
nginx: [emerg] "http" directive is not allowed here in /etc/nginx/sites-enabled/default:1
Here is full default.conf file:
http {
upstream aiohttp {
# Unix domain servers
server unix:/tmp/example_1.sock fail_timeout=0;
server unix:/tmp/example_2.sock fail_timeout=0;
server unix:/tmp/example_3.sock fail_timeout=0;
server unix:/tmp/example_4.sock fail_timeout=0;
}
server {
listen 80;
client_max_body_size 4G;
server example.com;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_buffering off;
proxy_pass http://aiohttp;
}
}
}
It looks correct. server directive is in http as it should be. And http is parent directive. What I'm doing wrong?
I am assuming that you have http in your /etc/nginx/nginx.conf file which then tells nginx to include sites-enabled/*;
So then you have
http
http
server
As the http directive should only happen once just remove the http directive from your sites-enabled config file(s)
You may insert a part which should be inside http{} section into your nginx.conf and in /etc/nginx/sites-available/default leave just server{} section.
I've been having similar issue. I needed to include upstream directive but I could't touch the /etc/nginx/nginx.conf file where the http directive is defined. The only thing I could do was to replace /etc/nginx/conf.d/default.conf (cloud/kubernetes automation stuff...)
The solution is quite simple but since it might not be obvious (wasn't to me), here is how you can write your /etc/nginx/conf.d/default.conf file if you need to include upstream spec. (upstream and server directives are not enclosed by anything in this file)
/etc/nginx/conf.d/default.conf
upstream api {
server ...;
}
server {
listen 80;
server_name example.com;
...
location / {
proxy_pass http://api;
...
}
}
So, actually the problem was in the second server keyword. I used an example from aiohttp docs, and looks like they mistyped with "server example.com" instead of server_name example.com.

Docker Nginx stopped: [emerg] 1#1: host not found in upstream

I am running docker-nginx on ECS server. My nginx service is suddenly stopped because the proxy_pass of one of the servers got unreachable. The error is as follows:
[emerg] 1#1: host not found in upstream "dev-example.io" in /etc/nginx/conf.d/default.conf:988
My config file is as below:
server {
listen 80;
server_name test.com;
location / {
proxy_pass http://dev-exapmle.io:5016/;
proxy_redirect off;
##proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
}
server {
listen 80 default_server;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/log/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
I have many servers in the config file, even if one server was down, I need to have running nginx. Is there any way to fix it?
Any suggestion to fix this issue would be appreciated.
Just adding a resolver did not resolve the issue in my case. But I was able to work around it by using a variable for the host.
Also, I guess it makes more sense to use Docker's DNS at 127.0.0.11 (this is a fixed IP).
Example:
server {
listen 80;
server_name test.com;
location / {
resolver 127.0.0.11;
set $example dev-example.io:5016;
proxy_pass http://$example;
}
}
I found the variable workaround on this page.
Include to prevent Nginx from crashing if your site is down, include a resolver directive, as follows:
server {
listen 80;
server_name test.com;
location / {
resolver 8.8.8.8;
proxy_pass http://dev-exapmle.io:5016/;
proxy_redirect off;
...
WARNING! Using a public DNS create a security risk in your backend since your DNS requests can be spoofed. If this is an issue, you should point the resolver to a secure DNS server.
This usually means that the dns name you provided as upstream server cannot be resolved. To test it, log on nginx server and try pinging upstream server provided and see if the name resolution completes correctly, If its a docker container try docker exec -it to get a shell, then try pinging the upstream to test the name resolution. If the contianer is stopped try to use IP address instead of dns name in your server block.
proxy_pass http://<IP ADDRESS>:5016/;
You can also use the resolver directive if you want to use different dns server for this location than the host system:
resolver 8.8.8.8;
When using nginx plus, you can get around this as well by adding a zone to your upstream with resolve. When use this test in your proxypass. When the server some-server starts resolving, it will starting pass traffic to it.
Make sure to as stated above, put a resolver in other parts of your config. For docker, I use
resolver 127.0.0.11 valid=1s;
upstream test {
zone test-zone 64k;
server some-server:1234 resolve;
}

nginx: [emerg] "server" directive is not allowed here

I have reconfigured nginx but i can't get it to restart using the following config:
conf:
server {
listen 80;
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location /robots.txt {
alias /path/to/robots.txt;
access_log off;
log_not_found off;
}
location = /favicon.ico { access_log off; log_not_found off; }
location / {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 30;
proxy_read_timeout 30;
proxy_pass http://127.0.0.1:8000;
}
location /static {
expires 1M;
alias /path/to/staticfiles;
}
}
after running sudo nginx -c conf -t to test the configuration the following error is returned i can't figure out what is really the problem
nginx: [emerg] "server" directive is not allowed here in /etc/nginx/sites-available/config:1
nginx: configuration file /etc/nginx/sites-available/config test failed
That is not an nginx configuration file. It is part of an nginx configuration file.
The nginx configuration file (usually called nginx.conf) will look like:
events {
...
}
http {
...
server {
...
}
}
The server block is enclosed within an http block.
Often the configuration is distributed across multiple files, by using the include directives to pull in additional fragments (for example from the sites-enabled directory).
Use sudo nginx -t to test the complete configuration file, which starts at nginx.conf and pulls in additional fragments using the include directive. See this document for more.
Example valid nginx.conf for reverse proxy; In case someone is stuck like me.
where 10.x.x.x is the server where you are running the nginx proxy server and to which you are connecting to with the browser, and 10.y.y.y is where your real web server is running
events {
worker_connections 4096; ## Default: 1024
}
http {
server {
listen 80;
listen [::]:80;
server_name 10.x.x.x;
location / {
proxy_pass http://10.y.y.y:80/;
proxy_set_header Host $host;
}
}
}
Here is the snippet if you want to do SSL pass through. That is if 10.y.y.y is running a HTTPS webserver. Here 10.x.x.x, or where the nignx runs is listening to port 443, and all traffic to 443 is directed to your target web server
events {
worker_connections 4096; ## Default: 1024
}
stream {
server {
listen 443;
proxy_pass 10.y.y.y:443;
}
}
and you can serve it up in docker too
docker run --name nginx-container --rm --net=host -v /home/core/nginx/nginx.conf:/etc/nginx/nginx.conf nginx
The path to the nginx.conf file which is the primary Configuration file for Nginx - which is also the file which shall INCLUDE the Path for other Nginx Config files as and when required is /etc/nginx/nginx.conf.
You may access and edit this file by typing this at the terminal
cd /etc/nginx
/etc/nginx$ sudo nano nginx.conf
Further in this file you may Include other files - which can have a SERVER directive as an independent SERVER BLOCK - which need not be within the HTTP or HTTPS blocks, as is clarified in the accepted answer above.
I repeat - if you need a SERVER BLOCK to be defined within the PRIMARY Config file itself than that SERVER BLOCK will have to be defined within an enclosing HTTP or HTTPS block in the /etc/nginx/nginx.conf file which is the primary Configuration file for Nginx.
Also note -its OK if you define , a SERVER BLOCK directly not enclosing it within a HTTP or HTTPS block , in a file located at path /etc/nginx/conf.d . Also to make this work you will need to include the path of this file in the PRIMARY Config file as seen below :-
http{
include /etc/nginx/conf.d/*.conf; #includes all files of file type.conf
}
Further to this you may comment out from the PRIMARY Config file , the line
http{
#include /etc/nginx/sites-available/some_file.conf; # Comment Out
include /etc/nginx/conf.d/*.conf; #includes all files of file type.conf
}
and need not keep any Config Files in /etc/nginx/sites-available/ and also no need to SYMBOLIC Link them to /etc/nginx/sites-enabled/ , kindly note this works for me - in case anyone think it doesnt for them or this kind of config is illegal etc etc , pls do leave a comment so that i may correct myself - thanks .
EDIT :- According to the latest version of the Official Nginx CookBook , we need not create any Configs within - /etc/nginx/sites-enabled/ , this was the older practice and is DEPRECIATED now .
Thus No need for the INCLUDE DIRECTIVE include /etc/nginx/sites-available/some_file.conf; .
Quote from Nginx CookBook page - 5 .
"In some package repositories, this folder is named sites-enabled, and
configuration files are linked from a folder named site-available;
this convention is depreā€ cated."
There might be just a typo anywhere inside a file imported by the config. For example, I made a typo deep inside my config file:
loccation /sense/movies/ {
mp4;
}
(loccation instead of location), and this causes the error:
nginx: [emerg] "server" directive is not allowed here in /etc/nginx/sites-enabled/xxx.xx:1
Replace include /etc/nginx/conf.d/*.conf; in nginx.conf with include /etc/nginx/conf.d/includes-optional/cpanel-proxy-vendors/*.conf; or /etc/nginx/conf.d/includes-optional/site-available/*.conf;

How do I get Nginx to return 444 if the request doesn't match a path?

Short version:
I want to use NGINX as a reverse proxy so that a client accessing the public facing URL gets served API data from the internal Gunicorn server sitting behind the proxy:
external path (proxy) => internal app
<static IP>/ABC/data => 127.0.0.1:8001/data
I'm not getting the location mapping correct.
Long version:
I am setting up NGINX for the first time and am attempting to use it as a reverse proxy for a rest api served by Gunicorn. The api is served at 127.0.0.1:8001 and I can access it from the server and get the appropriate responses, so that piece I believe is working correctly. It's running persistently using Supervisord.
I'd like to access one of the API endpoints externally at <static IP>/ABC/data. On the Gunicorn server, this endpoint available at localhost:8001/data. Eventually I'd like to serve other web apps through NGINX with roots like <static IP>/foo, <static IP>/bar, etc. Each of these web apps would be from an independent Python app. But currently, when I try to access the endpoint externally, I get a 444 error code, so I think I am not configuring NGINX correctly.
I put together my first attempt at an NGINX config from the config posted on the Guincorn site. Instead of a single config, I've split it into a global config and a site specific one. My global config at etc/nginx/nginx.conf looks like:
user ops;
worker_processes 1;
pid /run/nginx.pid;
error_log /tmp/nginx.error.log;
events {
worker_connections 1024; # increase if you have lots of clients
accept_mutex off; # set to 'on' if nginx worker_processes > 1
use epoll;
# 'use epoll;' to enable for Linux 2.6+
# 'use kqueue;' to enable for FreeBSD, OSX
}
http {
include mime.types;
# fallback in case we can't determine a type
default_type application/octet-stream;
access_log /tmp/nginx.access.log combined;
sendfile on;
server_tokens off;
server {
# if no Host match, close the connection to prevent host spoofing
listen 80 default_server;
return 444;
}
gzip on;
gzip_disable "msie6";
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Then my site specific configuration that is in /etc/nginx/sites-available (and is symlinked in /etc/nginx/sites-enabled) is:
upstream app_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response
# for UNIX domain socket setups
# server unix:/tmp/gunicorn_abc_api.sock fail_timeout=0;
# for a TCP configuration
server 127.0.0.1:8001 fail_timeout=0;
}
server {
# use 'listen 80 deferred;' for Linux
# use 'listen 80 accept_filter=httpready;' for FreeBSD
listen 80 deferred;
client_max_body_size 4G;
# set the correct host(s) for your site
server_name _;
keepalive_timeout 100;
# path for static files
#root /path/to/app/current/public;
location /ABC {
# checks for static file, if not found proxy to app
try_files $uri #proxy_to_app;
}
location #proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS
# proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
proxy_pass http://app_server;
}
# error_page 500 502 503 504 /500.html;
# location = /500.html {
# root /path/to/app/current/public;
# }
}
The configs pass service nginx checkconfig, but I end up seeing the following in my access log:
XXX.XXX.X.XXX - - [09/Sep/2016:01:03:18 +0000] "GET /ABC/data HTTP/1.1" 444 0 "-" "python-requests/2.10.0"
I think I've somehow not configured the routes properly. Any suggestions would be appreciated.
UPDATE:
I have it working now with a few changes. I commented out the following block:
server {
# if no Host match, close the connection to prevent host spoofing
listen 80 default_server;
return 444;
}
I can't figure out how to get the behavior of returning 444 unless there is a valid route. I'd like to, but I'm still stuck on this part. This block seems to eat all incoming requests. I've also changed the app config to:
upstream app_server {
server 127.0.0.1:8001 fail_timeout=0;
}
server {
# use 'listen 80 deferred;' for Linux
# use 'listen 80 accept_filter=httpready;' for FreeBSD
listen 80 deferred;
client_max_body_size 100M;
# set the correct host(s) for your site
server_name $hostname;
keepalive_timeout 100;
location /ABC {
# checks for static file, if not found proxy to app
try_files $uri #proxy_to_app;
}
location #proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS
# proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
rewrite ^/ABC/(.*) /$1 break;
proxy_pass http://app_server;
}
}
Basically I seem to have had to explicity set server_name and also use rewrite to get the correct mapping to the app server.
This works fine for me, returns 444 (hangs up connection) only if no other server name is matched:
server {
listen 80;
server_name "";
return 444;
}

Resources