nginx custom maintenance 503 page with css and image - html

I have a nginx virtual server with a custom 503 used for maintenance.
The html page uses some fonts from google fonts, bootstrap, but also a css and an image from the local server.
When the page is loaded, the linked css is not loaded. Using Firefox web tools I can see for the Error 503.
Trying direclty the css URL, the css is loaded by the browser.
The image is correclty displayed even if has an error 503.
This is my nginx configuration:
if (-f /home/user-site/www/MainWebSite/releases/current/.maintenance) {
return 503;
}
if (!-d /home/user-site/www/MainWebSite/releases/current) {
return 503;
}
# error_page 503 /maintenance.html;
# location = /maintenance.html {
# root /home/user-site/www/MainWebSite/htdocs;
# }
error_page 503 #maintenance;
location #maintenance {
root /home/user-site/www/MainWebSite/htdocs;
#rewrite ^(/css)/(.+?)(\.[^.]*$|$) /stuff/css/$2$3 break;
rewrite ^(/img)/(.+?)(\.[^.]*$|$) /stuff/img/$2$3 break;
rewrite ^(.*)$ /maintenance.html break;
}
I suppose that the css cannot be loaded because of the error 503 returned by the server even if the rewrite roule correctly retunr the css.
How I can prevent error 503 on css and images of landing pages?
tanks.
Update!!
Following this solution the configuration works!
if (-f /home/user-site/www/MainWebSite/releases/current/.maintenance) {
set $err503 1;
}
if (!-d /home/user-site/www/MainWebSite/releases/current) {
set $err503 1;
}
error_page 503 #maintenance;
location #maintenance {
root /home/user-site/www/MainWebSite/htdocs/error503;
try_files $uri /maintenance.html =503;
}
location /static {
root /home/user-site/www/MainWebSite;
}
location /media {
root /home/user-site/www/MainWebSite;
}
location /robots.txt {
root /home/user-site/www/MainWebSite/htdocs/robots.txt;
}
location /sitemap.xml {
root /home/user-site/www/MainWebSite/htdocs/sitemap.xml.txt;
}
location ~* \.(css) {
root /home/user-site/www/MainWebSite/htdocs/error503;
# The file will be returned
}
location ~* \.(png|jpg|jpeg) {
root /home/user-site/www/MainWebSite/htdocs/error503;
# The file will be returned
}
location / {
if ($err503 = 1) {
return 503;
}
uwsgi_pass unix:/tmp/uwsgi_MainWebSite.sock;
include /etc/nginx/uwsgi_params;
}

Related

how to serve xml file as a static content in nginx

I have a test.xml file stored in the location
/deploy/projects/backend/assets. I tried to serve this file as a static content when someone accesses this using link https://xyz/assets/test.xml. However, it gives error "404 Not Found". My nginx config file is as below:
cat nginx/server.conf
http {
include /etc/nginx/mime.types;
client_max_body_size 100m;
server {
listen 80 default_server;
server_name _;
location ~ ^/assets/ {
root /deploy/projects/backend;
}
}
}

How can i change my 404 error page in nginx configuration file?

i need help about my Nginx configuration file. I coded my html file. This is the config file:
server
{
listen 888;
server_name phpmyadmin;
index index.html index.htm index.php;
root /www/server/phpmyadmin;
location ~ /tmp/ {
return 403;
}
#error_page 404 /404-error.html;
location ~ /*-error.html {
try_files $1-error.html #error;
internal;
}
location #error {
root /var/www/wwwroot/umutisik.com/error_docs;
}
Also sorry for my bad English, not my main language.

nginx error pages based on accept header do not work for json requests

I'm trying to build a nginx-based maintenance mode application, that catches all requests to my applications and returns a predefined response as a 503.
I currently have applications requesting json responses as well as users accessing the pages with their browsers. So in case the request contains the header Accept: application/json, I want to respond with the content of a json file maintenance.json, otherwise with an html file maintenance.html.
My current nginx config looks like this:
server {
listen 8080;
root /usr/share/nginx/maintenance;
server_tokens off;
error_page 503 = #unavailable;
location ^~ / {
return 503;
}
location #unavailable {
set $maintenanceContentType text/html;
set $maintenanceFile /maintenance.html;
if ($http_accept = 'application/json') {
set $maintenanceContentType application/json;
set $maintenanceFile /maintenance.json;
}
default_type $maintenanceContentType;
try_files $uri $maintenanceFile;
}
}
For browser requests to any path this works out fine: "https://maintenance.my-domain.local/some-path". I get the response code and the html content.
But for requests with header Accept: application/json I get a 404 html page. And the nginx log shows [error] 21#21: *1 open() "/usr/share/nginx/maintenance/some-path" failed (2: No such file or directory), client: 10.244.2.65, server: , request: "GET /asd HTTP/1.1", host: "maintenance.my-domain.local".
It seems like json requests are ignoring my location for some reason. When I remove the directive to set the appropriate file and just always return the html this also works for json-requests.
Anyone any idea?
I'm not necessarily looking for a fix for this specific config, but rather for something that fits my needs of responding with different "error pages" based on the Accept header.
Thanks in advance!
EDIT: For some reason this now results in an HTTP 200 instead of a 503. Don't know what I changed..
EDIT2: Managed to fix a part of it:
server {
listen 8080;
root /usr/share/nginx/maintenance;
server_tokens off;
location ^~ / {
if ($http_accept = 'application/json') {
return 503;
}
try_files /maintenance.html =404;
}
error_page 503 /maintenance.json;
location = /maintenance.json {
internal;
}
}
With this config I now get the maintenance page when using the browser and the maintenance json, when defining the header Accept: application/json. The browser response code is 200 now though...
Ok, I found the solution to my problem.
# map the incoming Accept header to a file extension
map $http_accept $accept_ext {
default html;
application/json json;
}
server {
listen 8080;
root /usr/share/nginx/maintenance;
server_tokens off;
# return 503 for all incoming requests
location ^~ / {
return 503;
}
# a 503 redirects to the internal location `#maintenance`. the
# extension of the returned file is decided by the Accept header map
# above (404 in case the file is not found).
error_page 503 #maintenance;
location #maintenance {
internal;
try_files /maintenance.$accept_ext =404;
}
}
Key was the map on the top. I just added application/json there and mapped everything else to the html file by default. But you could add multiple other files/file types there of course.

Angular 8 + Nginx - failed to load resource

I have an application written in Angular 8 that I'm serving on nginx. After the deployment I get an following error:
Failed to load resource: the server responded with a status of 404 ()
Additionally in the Dev Tools we can see such a message:
error: "404 Not Found404 Not Foundnginx/1.12.0
message: "Http failure response for https://myUrl/app/assets/config/endpoints.json: 404 OK
name: "HttpErrorResponse" ok: false status: 404 statusText:
"OK" url: "https://myUrl/app/assets/config/endpoints.json"
What I didn't understand why is the response stating "OK"? But it's not the main problem. The main problem is that I can't load this endpoints.json file neither access any file located under the assets dir.
When I directly go to the URI:
https://myUrl/app/someFile.png
then it's visible, but if I try to reach
https://myUrl/app/assets or https://myUrl/app/assets/logo.png
then i get an 404 error page.
It's served from a docker container and I saw that all files are there so the structure is as follows in
/usr/share/nginx/html/
-/
-index.html
-assets/
-------config/
-------------endpoints.json
-------images/
-------------logo.png
-polifills.js
-favicon.ico
The app was build with the --prod flag and the base href flag --base-href ./
As I see the favicon is loading and all the scripts in the main dir work fine. The problem is related to the assets dir...
Here are my files:
* nginx.conf
server {
listen 8888;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
}
}
Enpoints service (which is trying to get this endpoints.json
private enpoints$: Observable<Endpoint>;
private readonly ENDPOINT_URL = './assets/config/endpoints.json';
constructor(private http: HttpClient) {}
public loadEndpoints(): Observable<Endpoint> {
if (!this.enpoints$) {
this.enpoints$ = this.http.get<Endpoint>(this.ENDPOINT_URL).pipe(shareReplay(1));
}
return this.enpoints$;
}
Any suggestions?
Just figured it out. The issue was related to my nginx configuration.
I had to take the root path out of the location block so it's applicable to all locations. The official nginx pitfalls doc helped me here a lot.
Now my config file looks like that:
server {
listen 8888;
server_name localhost;
root /usr/share/nginx/html;
location / {
index index.html index.htm;
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
}
location /assets {
try_files $uri $uri/ /index.html;
}
}
Although I think the second block isn't needed at all. I have to check it, and will reply.

ISPConfig Vhost allowing clean URLs in Laravel

I have an existing server which is working well hosting a number of sites using nginx and ISPconfig. However I have created a new site and wish to use Laravel.
I've installed Laravel successfully via composer and have got as far as seeing the familiar welcome blade displayed when I visit mywebsite.com/public
What I want to do next is make some clean urls. My experience with vhost files is somewhat limited and I'm having a bit of trouble with the config.
My routes file looks like this
Route::get('/', function () {
return view('welcome');
});
Route::get('/test', function () {
return view('test');
});
and I'd hoped to see mywebsite.com/test display the contents of test.blade.php
I'm aware I need to do some work with the vhost file before I can expect this to work but my experience with vhosts is limited and I'm at a bit of a loss.
My current file looks like this
server {
listen *:80;
server_name mywebsite.com ;
root /var/www/mywebsite.com/web;
index index.html index.htm index.php index.cgi index.pl index.xhtml;
error_page 400 /error/400.html;
error_page 401 /error/401.html;
error_page 403 /error/403.html;
error_page 404 /error/404.html;
error_page 405 /error/405.html;
error_page 500 /error/500.html;
error_page 502 /error/502.html;
error_page 503 /error/503.html;
recursive_error_pages on;
location = /error/400.html {
internal;
}
location = /error/401.html {
internal;
}
location = /error/403.html {
internal;
}
location = /error/404.html {
internal;
}
location = /error/405.html {
internal;
}
location = /error/500.html {
internal;
}
location = /error/502.html {
internal;
}
location = /error/503.html {
internal;
}
error_log /var/log/ispconfig/httpd/mywebsite.com/error.log;
access_log /var/log/ispconfig/httpd/mywebsite.com/access.log combined;
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location /stats/ {
index index.html index.php;
auth_basic "Members Only";
auth_basic_user_file /var/www/clients/client1/web5/web/stats/.htpasswd_stats;
}
location ^~ /awstats-icon {
alias /usr/share/awstats/icon;
}
location ~ \.php$ {
try_files /5e26a1d85cb98f7191261e023385e60d.htm #php;
}
location #php {
try_files $uri =404;
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/lib/php5-fpm/web5.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors on;
}
}
Now on another server I have this working with this simple directive
server {
root /var/www/public;
index index.php index.html index.htm;
server_name localhost;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
}
But I am limited to what I can do with the vhost on the current server as ISPconfig writes most of it for me and it refuses to write the above config that worked elsewhere. Also I feel editing the file directly will be bad practice, I'd always be on edge that ISPconfig will rewrite the file for me, so I'm not really sure how best to proceed with this.
My options would be to just go ahead and edit the vhost and hope for the best, but if I do that how would I ensure ISPconfig could not overwrite the file without resorting to "hacky" methods?
Alternatively, is there a config I can enter via ISPconfig that will allow rewrites to happen properly in a way that suits Laravel? In this instance, any directive entered would need to take precedence over the ~ .php$ clause as that is written by ISPconfig before any directives entered via the control panel.
I just had the same problem recently. Digging the ISPConfig's sources, I understood it can insert/ merge/ delete location blocks of that default vhosts file. So i did the following:
Sites' menu > choose website > Options
Then I inputed the following on the "nginx Directives" field:
# redirect stuff to the public inner folder
location / {
root {DOCROOT}/public;
try_files /public/$uri /public/$uri/ /public/index.php?$query_string;
}
# merged the stuff people suggests for laravel inside the php block
# mind the 'merge' keyword that did the trick
location ~ \.php$ { ##merge##
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
}
There is a slight problem with Danilo's answer. Php ran but assets like js/css/images stopped loading. Adding the following to nginx directives inside ISPConfig works for me:
location / {
root {DOCROOT}/public;
try_files $uri public/$uri/ /public/index.php?$query_string;
}
I am not expert with this but from my past experience if I have two domains I would define server blocks for each in two different files and place them in /etc/nginx/sites-available/site1.com and /etc/nginx/sites-available/site2.com
but it looks like you already have a website that you access using mywesite.com which is located at /var/www/mywebsite.com/web; (see the root value of your configuration file)
Now you install Laravel in test folder in /var/www/mywebsite.com/test location.
To access this you need can try adding following at the end of your ispconfig file.
Note how I used the relative path to laravel's public folder from the root of the server block.
location /../test/public {
try_files $uri $uri/ /index.php$is_args$args;
}
For more detailed tutorial try Nginx Server Block Setup.
Hope this helps,
K