My Client (next.js) app running at port 3000
My Server (graphql) app running at port 4000
My website is https://example.com, nginx will pass proxy port 3000.
If the user access the site, the page is loaded successfully.
But behind the scene, In my webpage some api requests are sended to graphql server. (http://localhost:4000)
This api requests are failed.
I don't know why, but when I access http://example.com:4000/graphql the graphql playground (graphiql?) loaded successfully and I can send some query and result showed well. But request from webpage is failed.
nginx/sites-enabled/example.com
server {
listen 80;
listen [::]:80;
server_name www.example.com example.com;
return 301 https://example.com$request_uri;
}
server {
listen 80;
listen [::]:80;
server_name example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # 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
}
client app's graphql part
export default function createApolloClient(initialState, ctx) {
return new ApolloClient({
ssrMode: Boolean(ctx),
link: authLink.concat(new HttpLink({
uri: 'http://localhost:4000/graphql', // Server URL (must be absolute)
credentials: 'same-origin', // Additional fetch() options like `credentials` or `headers`
fetch,
})),
cache: new InMemoryCache({ fragmentMatcher }).restore(initialState),
credentials: 'include',
})
}
** What I tried...**
I added below snippets to nginx conf (above listen [::]443 part) and restart the nginx service, but nothing changed.
location /graphql {
proxy_pass http://localhost:4000/graphql;
}
I think I miss something in nginx conf. How do I fix it?
I resolved like below.
createApolloClient
... createApolloClient(initialState, ctx) {
return new ApolloClient({
...
link: createHttpLink({ uri: '/graphql' })
nginx
location /graphql {
proxy_pass http://localhost:4000/graphql;
}
Related
I have got a route in expressjs application with the following code.
...
router.get("/:id", async (req, res, next) => {
try {
// debug(`The req is ${req.params.id}`);
const data = await getSuperHerors(req.params.id);
res.send(data);
} catch (err) {
next(err);
}
});
...
I want to setup my nginx revere proxy to forward on the id.
The conf file for nginx is here
...
server {
root /var/www/html;
server_name example.biz; # managed by Certbot
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:3000;
# proxy_pass http://127.0.0.1:3000/$1$is_args$args;
# set $upstream http://localhost:3000;
# proxy_pass $upstream/$1$is_args$args;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.biz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.biz/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
if ($host = example.biz) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 ;
listen [::]:80 ;
server_name example.biz;
return 404; # managed by CertbotWhat is wrong with my reverse proxy file.
}
...
What is wrong with my reverse proxy file.
For now I have put it back to its original but I have tried to use the configs behind the comments.
Joseph Shanahan
Thanks, you are right all requests were forwarded.
I went back and had a look at my setup and found something else wrong.
Cheers
Joseph Shanahan
I have a nodejs server running with nginx as a reverse proxy. https://example.com and http://example.com run correctly with http://example.com redirecting to https, but http://www.example.com gives an nginx error 404 Not Found. https://www.example.com does work, though.
This is my server block configuration:
server {
root /var/www/partyshare.shop/html;
index index.html index.htm index.nginx-debian.html;
server_name partyshare.shop www.partyshare.shop;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/partyshare.shop/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/partyshare.shop/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 = partyshare.shop) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name partyshare.shop www.partyshare.shop;
return 404; # managed by Certbot
I believe the error is on the second server block, where $host = www.partyshare.shop when requesting the http version, so it skips past the redirect and returns a 404 error. I tried adding an if statement for the www version, but it errored out, and wouldn't recognize my SSL certificate as the http was crossed out in red, so if anybody could help that would be great.
You should update the 2nd server block to do the same for both partyshare.shop and www.partyshare.shop, and not just partyshare.shop.
server {
listen 80;
listen [::]:80;
server_name partyshare.shop www.partyshare.shop;
return 301 https://$host$request_uri;
}
I have a web application which is setup in the following way: the frontend is being served by nginx. The backend is handled by FastAPI. I setup a rule in nginx to proxy all requests with url /api to the backend directly. Now, I also proxy to Grafana. The way I did this was to build a reverse proxy within my FastAPI server. So in nginx, I have a rule to proxy all requests with url /grafana to FastAPI. FastAPI then does some user authentication before proxying to the grafana server. The exception is that any Grafana websocket connection gets proxied directly from nginx to the grafana server.
Here's my nginx conf file
server {
server_name example.com www.example.com;
root /var/www/web-app/html;
index index.html index.htm index.nginx-debian.html;
location / {
try_files $uri $uri/ =404;
}
location /api {
proxy_pass http://localhost:5000;
}
# grafana reverse proxy
location /grafana {
proxy_set_header Origin http://localhost:3000;
# proxy_set_header Origin https://example.com;
proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin $http_origin;
proxy_pass http://localhost:5000;
}
location /grafana/api/live {
rewrite ^/(.*) /$1 break;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $http_host;
proxy_pass http://localhost:3030;
}
listen 443 ssl http2; # managed by Certbot
ssl_certificate /etc/letsencrypt/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/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 = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
Here's my FastAPI proxy
async def _reverse_proxy(request: Request):
url = httpx.URL(path=request.url.path,
query=request.url.query.encode("utf-8"))
new_header = MutableHeaders(request.headers)
if "grafana_session" not in request.cookies:
if "authorization" not in request.headers:
return RedirectResponse("/")
jwt_token = request.headers["authorization"].replace('Bearer ', '')
# user authentication stuff...
current_user = get_current_user_from_token(token=jwt_token, db=some_session)
org = get_org_by_id(current_user.org_id, some_session)
if org is None:
raise HTTPException(
status_code=404,
detail="Organization not found",
)
del new_header['authorization']
new_header['X-WEBAUTH-USER'] = current_user.username
new_header['X-Grafana-Org-Id'] = f"{org.grafana_org_id}"
if "authorization" in new_header:
del new_header['authorization']
rp_req = client.build_request(request.method, url,
headers=new_header.raw,
content=await request.body())
rp_resp = await client.send(rp_req, stream=True)
return StreamingResponse(
rp_resp.aiter_raw(),
status_code=rp_resp.status_code,
headers=rp_resp.headers,
background=BackgroundTask(rp_resp.aclose),
)
app = FastAPI(title=settings.PROJECT_NAME, version=settings.PROJECT_VERSION)
origins = ["http://localhost:3000", "https://example.com"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(api_router, prefix=settings.API_V1_STR)
app.add_route("/grafana/{path:path}", _reverse_proxy, ["GET", "POST", "DELETE"])
If I run this locally on localhost:3000 (with some modifications to nginx to be listening on 3000 instead of 443 ssl), everything works perfectly. If I try in production at example.com, I have to include this hacky bit proxy_set_header Origin http://localhost:3000; to change the origin in a request to my FastAPI proxy to make it work. Why is this happening?
NOTE: I've checked the grafana server logs to make sure that it wasn't the issue. None of the requests make it past the FastAPI server, it is the one returning error 403, origin not allowed.
I'm using certbot to generate a let's encrypt certificate, everything work fine except the http version is not redirected to the https.
Here is my .conf in sites-available :
# the IP(s) on which your node server is running. I chose port 3000.
upstream app_yourdomain {
server 127.0.0.1:3000;
keepalive 8;
}
# the nginx server instance
server {
server_name deussearch.fr www.deussearch.fr;
access_log /var/log/nginx/deussearch.fr.log;
# pass the request to the node.js server with the correct headers
# and much more can be added, see nginx config options
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_set_header X-NginX-Proxy true;
proxy_pass http://app_yourdomain/;
proxy_redirect off;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/www.deussearch.fr/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.deussearch.fr/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.deussearch.fr) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name deussearch.fr www.deussearch.fr;
return 404; # managed by Certbot
}
I really can't find what's wrong here, like I followed tutorial and everything worked fine , anyone know ? I'm using Nginx on ubuntu if it can help !
I have check your website it's OK. Every I try access http://deussearch.fr/ always redirect to https://www.deussearch.fr/
https://i.imgur.com/H7c9dXY.png
You can also check in https://www.sslshopper.com/ssl-checker.html#hostname=deussearch.fr
I using the Nginx configuration below and it works fine.
However, I'm using three paragraphs {...} for redirections, can this be optimized to a single paragraph or set directly in the main paragraph ?
upstream mywebsite_upstream {
server 127.0.0.1:3003;
keepalive 64;
}
server {
server_name www.mywebsite.com;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://mywebsite_upstream;
proxy_redirect off;
proxy_read_timeout 240s;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/www.mywebsite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.mywebsite.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.mywebsite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name www.mywebsite.com;
return 404; # managed by Certbot
}
server {
listen 80;
server_name mywebsite.com;
return 301 https://www.mywebsite.com;
}
server {
listen 443;
server_name mywebsite.com;
return 301 https://www.mywebsite.com;
}
Yes, sure you can:
server {
listen 80;
server_name mywebsite.com www.mywebsite.com;
return 301 https://www.mywebsite.com$request_uri;
}
server {
listen 443;
server_name mywebsite.com;
# SSL config here
return 301 https://www.mywebsite.com$request_uri;
}
I think you'll need to copy all SSL-related configuration from your main server block to the second one.
I think (and I'm not alone, check an answer under the link) that nginx config produced by certbot is a crap and it is better to do nginx config changes manually a leave for certbot only a certificate receiving/renewing:
certbot certonly --webroot -w /var/www -d hostname -d hostname ...
Update
When your server hosts other domains (and even if ins't) it is a good practice to have an additional server block serving requests than does not contain a valid domain name (or does not have Host HTTP header at all - those are typically port scanners, vulnerability searchers etc.) To close suspicious connections on port 443 you'll need minimal SSL config within that block. It's best to use a self-signed key and certificate for that purpose. For generating a pair of self-signed key/cart in one line you can use the following command:
openssl req -nodes -new -x509 -subj "/CN=localhost" -keyout /etc/nginx/server.key -out /etc/nginx/server.crt
You can use special nginx 444 code (close connection without any response) for the suspicious connections:
server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
return 444;
}
To simplify certbot key renewing process with the command like given above, you can add an additional section to all your server blocks for hosted domains (including that ones used for redirection too):
location /.well-known/acme-challenge/ {
root /var/www;
}