I am setting up etherpad-lite in a subdirectory at this location.
Unfortunately the files in 'static' aren't being loaded:
Clearly something is going on in my nginx, which (partially) looks like this:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name _
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name www.whitewaterwriters.com;
ssl_certificate /etc/letsencrypt/live/www.whitewaterwriters.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.whitewaterwriters.com/privkey.pem;
return 301 https://whitewaterwriters.com$request_uri;
}
server {
listen 443 ssl;
server_name whitewaterwriters.com;
ssl_certificate /etc/letsencrypt/live/whitewaterwriters.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/whitewaterwriters.com/privkey.pem;
root /usr/share/nginx/html;
index index.html index.php;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~/watchtower/.*/live/pdfs/ {
autoindex on;
}
location /watchtower {
root /usr/share/nginx/html/;
}
location /etherpad {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
proxy_read_timeout 300;
proxy_pass http://localhost:9001/;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location /{
root /usr/share/nginx/html/whitewaterwriters-site/_site/;
}
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers PROFILE=SYSTEM;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
My question is: how do I configure nginx so that the missing files appear?
There are some other questions on this topic both in the github issues and SE, but they, in general, are solved by moving from etherpad to etherpad-lite, which I already use, or are both unanswered and approaching a decade old...
Short answer: if you add a trailing slash to your prefixed location, everything would work as expected.
map $http_upgrade $connection_upgrade {
'' close;
default upgrade;
}
server {
...
location /etherpad/ {
proxy_buffering off; # recommended by etherpad nginx hosting examples
proxy_set_header Host $host;
# optional headers
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr; # EP logs to show the actual remote IP
proxy_set_header X-Forwarded-Proto $scheme; # for EP to set secure cookie flag when https is used
# recommended with keepalive connections
proxy_http_version 1.1;
# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# upstream
proxy_pass http://127.0.0.1:9001/;
}
}
If you want /etherpad URI to work too, add the following location if you won't get HTTP 301 redirect from /etherpad to /etherpad/ with the above configuration:
location = /etherpad {
return 301 /etherpad/;
}
For me it wasn't necessary, but it can depend on your server environment.
To preserve query string, if any, you can use return 301 /etherpad/$is_args$args; or rewrite ^ /etherpad/ permanent instead.
Long answer (and what happened undercover).
There are many question on SO about "how can I host a webapp under an URI prefix". Here is one on my answers and here is a ServerFault thread on the similar topic.
The only right way to do it is to made your proxied app request its assets via relative URIs only (consider assets/script.js instead of /assets/script.js) or using the right URI prefix (/etherpad/assets/script.js).
Luckily, etherpad requests its assets using a relative paths (e.g. <script src="static/js/index.js"></script>) making it suitable to be hosted under any URI prefix. The problem is, when your origin URI is /etherpad, browser considers the current remote web server directory as the root one, and requests above script from server as scheme://domain/static/js/index.js. That request won't even caught by your location /etherpad { ... } (since it isn't starts with /etherpad). On the other hand, when your origin URI is /etherpad/, browser considers the current remote web server directory as the /etherpad/ and correctly requests above script from server as scheme://domain/etherpad/static/js/index.js.
Now let's see what happened with the proxied request /etherpad/<path> using your original configuration. Since you are using a trailing slash after the upstream address (http://localhost + /), nginx cut the location /etherpad prefix from the request URI and prepend it with that slash (or any other URI used in a proxy_pass directive after the upstream name) resulting in //<path>. You can read A little confused about trailing slash behavior in nginx or nginx and trailing slash with proxy pass SO threads for more details. Anyway that URI won't served by etherpad giving you Cannot GET //<path> error.
Changing location /etherpad { ... } to the location /etherpad/ { ... } you'll made both of the aforementioned problems gone.
A few words about the etherpad wiki examples, especially this one.
Both
location /etherpad/ {
proxy_pass http://127.0.0.1/;
...
}
and
location /etherpad/ {
rewrite ^/etherpad(/.*) $1 break;
proxy_pass http://127.0.0.1;
...
}
do the same string - stripping the /etherpad prefix from the request URI before passing it to the upstream. However the first one do it in a much more efficient way. It is a good practice to avoid regular expressions whenever possible. Using
location = /etherpad {
return 301 /etherpad/;
}
is also more efficient than
rewrite ^/etherpad$ /etherpad/ permanent;
Second and third location blocks from the above wiki example completely duplicate functionality from the first one. Moreover, that example breaks WebSocket support (whoever wrote it, he can at least add that support to the location /pad/socket.io { ... } block).
And never do the thing used at this example:
location ~ ^/$ { ... }
Use exact matching location instead:
location = / { ... }
Here is one more configuration I've tested in order to check if I can serve etherpad static assets directly via nginx. It seems to be workable, although I didn't tested it a lot. It uses an uncompressed js/css assets versions (which should not impact performance when you are using gzip or some other compression). It is also a good example of a configuration where you can't avoid using rewrite directive to strip a prefix from the request URI.
location /etherpad/static/ {
# trying to serve assets directly via nginx
# if the asset is not found, pass the request to the nodejs upstream
rewrite ^/etherpad(/.*) $1 break;
root /full/path/to/etherpad-lite/src;
try_files $uri #etherpad;
}
location /etherpad/ {
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:9001/;
}
location #etherpad {
proxy_redirect / /etherpad/;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:9001;
}
Update
As being suggested on the GitHub, URIs started with /etherpad/static/plugins/ prefix should always be passed to the nodejs upstream since there are no corresponding assets would exists under the /path/to/etherpad/src/static/ directory. Despite there is already defined fallback to the nodejs upstream (try_files $uri #etherpad), to eliminate an extra stat system call produced by the try_files directive we can modify the above configuration to this one:
location ~ ^/etherpad/static/(?!plugins/) {
# trying to serve assets directly via nginx
# if the asset is not found, pass the request to the nodejs upstream
rewrite ^/etherpad(/.*) $1 break;
root /full/path/to/etherpad-lite/src;
try_files $uri #etherpad;
}
location /etherpad/ {
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:9001/;
}
location #etherpad {
proxy_redirect / /etherpad/;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:9001;
}
(using negative lookahead regex, better readability) or to this one:
location /etherpad/ {
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:9001/;
}
location /etherpad/static/ {
rewrite ^/etherpad(/.*) $1 break;
root /full/path/to/etherpad-lite/src;
try_files $uri #etherpad;
}
location /etherpad/static/plugins/ {
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:9001/static/plugins/;
}
location #etherpad {
proxy_redirect / /etherpad/;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:9001;
}
(only prefix locations, better performance). The repetitive part
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
and probably other optional headers (X-Real-IP, X-Forwarded-For, X-Forwarded-Proto) setup mentioned at the very beginning of the answer, can be used as a separate file, e.g. etherpad-proxy.conf, and included into the main nginx config with the include directive.
You can try to navigate the static content to the correct folder with:
location /static {
root root /usr/share/nginx/html/whitewaterwriters-site/_site/static;
}
# or something like:
location /etherpad/static {
root root /usr/share/nginx/html/whitewaterwriters-site/_site/;
}
since this is working: https://whitewaterwriters.com/etherpad/static/js/vendors/html10n.js?v=869d568c
It's my first time deploying an application on a deployment environment so I am a complete beginner at this, I have an nginx proxy server (call it server1) on an instance with an exposed IP to the internet & it routes requests to another server on a different instance (call it server2) that hosts my Django application, the conf file for server1 goes like this :
`server{
server_name _;
location / {
proxy_pass_header Authorization;
proxy_pass http://10.156.0.4:80;
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_http_version 1.1;
proxy_set_header Connection “”;
proxy_buffering off;
client_max_body_size 0;
proxy_read_timeout 36000s;
proxy_redirect off;
}
listen 443 ssl;
listen [::]:443 ssl;
include snippets/self-signed.conf;
include snippets/ssl-params.conf; }
server{
listen 80;
listen [::]:80;
server_name _;
return 302 https://35.246.244.220;}
and the second server:
server{
listen 80;
listen [::]:80;
server_name _;
location / {
proxy_pass_header Authorization;
proxy_pass http://10.156.0.4:8880;
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_http_version 1.1;
proxy_set_header Connection “”;
proxy_buffering off;
client_max_body_size 0;
proxy_read_timeout 36000s;
proxy_redirect off;
}
location /static/ {
alias /opt/app/mydjangoapp/staticfiles/;
autoindex off; }
}
I am running my django application using this command python manage.py runserver 0.0.0.0:8880 & I also did collectstatic before running the application.
Everything works fine when i edit proxy_pass in server1 to http://10.156.0.4:8880 directly but i needed the second nginx server so i can serve the static files for my application.
I feel like I am doing something obviously wrong here, but for the life of me i can't figure it out.
I figured out the problem, there was a firewall rule between those two instances that didn't allow ingress or egress from port 80, only port 8880. Didn't think of this at all!
I'm trying to deploy a web application to my server. I have put the html files in one folder and I have a django server running on the same server. I am using nginx to set up reverse proxy for the backend but for some reason I'm not able to route to backend urls.
Here is my nginx configuration:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://example.com$request_uri;
}
server {
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
server_name example.com example.com;
root /var/www/html/;
index index.html;
# Let's Encrypt parameters
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
try_files $uri $uri/ = index.html;
}
location /api {
proxy_pass http://unix:/run/gunicorn.sock;
proxy_redirect off;
proxy_set_header Host $http_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 https;
}
}
In the first block..I'm setting fallbacks to index.html because it is an angular app.
The angular app runs fine.
But I'm not able to access the routes of the reverse proxy server, whenever I hit a route with /api/something it takes me back to the angular app i.e index.html
It was very simple, I had to modify the path block like this
location ~^/(admin|api) {
proxy_pass http://unix:/run/gunicorn.sock;
proxy_redirect off;
proxy_set_header Host $http_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 https;
}
Im learning nginx and jenkins by setting up a build server on ec2. Setting up jenkins was easy and I was able to even create a test job. I now want to move on to nginx config and mighty confused as to how to set it up. I have hosted zone with my domain, lets call it domain.com . I created an A record for jenkins.domain.com and in the value box put it the IP of the ec2 instance.
Then added this to the /etc/nginx/site-enabled/default
server {
listen 80;
server_name jenkins.domain.com;
return 301 https://$host$request_uri;
}
server {
listen 80;
server_name jenkins.domain.com;
location / {
proxy_set_header Host $host:$server_port;
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;
# Fix the "It appears that your reverse proxy set up is broken" error.
proxy_pass http://127.0.0.1:8080;
proxy_read_timeout 90;
proxy_redirect http://127.0.0.1:8080 https://jenkins.domain.com;
# Required for new HTTP-based CLI
proxy_http_version 1.1;
proxy_request_buffering off;
# workaround for https://issues.jenkins-ci.org/browse/JENKINS-45651
add_header 'X-SSH-Endpoint' 'jenkins.domain.com:50022' always;
}
}
However when I go to jenkins.domain.com:80 I get the site cannot be reached page...
proxy_redirect is not needed here. You can use below site configuration. You should create file jenkins in /etc/nginx/site-available(for ubuntu) or /etc/nginx/conf.d/ (centos or rhel) & copy the configuration in that file. You have to create the soft link on Ubuntu in site-enabled.
ln -s /etc/nginx/site-available/jenkins /etc/nginx/site-enabled/jenkins
Jenkins conf file
server {
listen 80;
server_name jenkins.domain.com;
access_log /var/log/nginx-access.log;
error_log /var/log/nginx-error.log;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_read_timeout 150s;
proxy_next_upstream error;
proxy_pass http://127.0.0.1:8080;
# Add HTTP Strict Transport Security for good measure.
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains;";
}
}
I have following problem, i'm trying to put a Django app with an gunicorn server on my VPS running Nginx. My nginx config looks like this:
upstream app_name {
server unix:/path/to/socket/file.sock fail_timeout=10;
}
server {
listen 80 default_server;
listen[::]:80 default_server ipv6only=on;
root /webapps/;
server_name my_hostname.com;
location / {
proxy_set_header Host $http_host;
}
location /appname/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_name;
}
}
However when i navigate to my_server.com/appname/ i constantly get 404 error. I'm still new to Nginx, could someone point me in the right direction on how to set the proxy_pass for /appname/ path? I should point out that when location for /appname/ is replaced with / the django app is running fine.
You just need a trailing slash for proxy_pass:
proxy_pass http://app_name/;
it helps you to cut the "appname" prefix so the config looks like:
upstream app_name {
server unix:/path/to/socket/file.sock fail_timeout=10;
}
server {
listen 80 default_server;
listen[::]:80 default_server ipv6only=on;
root /webapps/;
server_name my_hostname.com;
location /appname/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_name/;
}