How to alter existing nginx config into a reverse proxy for multiple local machines with working lets-encrypt certificate - lets-encrypt

Let me preface this by saying most of my "experience" comes from blindly copypasting config lines from various blogs and sites like this and hoping for the best.
Currently I have a setup like this:
Dynamic ddns hostname pointed at my public IP redirecting incoming traffic from ports 80 and 443 to a LXC container with nextcloud + certificate from letsencrypt for the same ddns hostname. So far so good.
this is the relevant nginx config:
server {
server_name stats;
listen 9753 default_server;
listen [::]:9753 default_server;
location /nginx-status {
stub_status on;
access_log off;
allow 127.0.0.1;
allow ::1;
deny all;
}
location ^~ /.well-known/acme-challenge {
proxy_pass http://127.0.0.1:81;
proxy_set_header Host $host;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name nextcloud;
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
client_max_body_size 10240M;
root /var/www/nextcloud/;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location = /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
location / {
rewrite ^ /index.php;
}
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
deny all;
}
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ^~ /apps/rainloop/app/data {
deny all;
}
location ~ \.(?:flv|mp4|mov|m4a)$ {
mp4;
mp4_buffer_size 100M;
mp4_max_buffer_size 1024M;
fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
set $path_info $fastcgi_path_info;
try_files $fastcgi_script_name =404;
include fastcgi_params;
include php_optimization.conf;
}
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+).php(?:$|\/) {
fastcgi_split_path_info ^(.+?.php)(\/.*|)$;
set $path_info $fastcgi_path_info;
try_files $fastcgi_script_name =404;
include fastcgi_params;
include php_optimization.conf;
}
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
try_files $uri/ =404;
index index.php;
}
location ~ .(?:css|js|woff2?|svg|gif|map|png|html|ttf|ico|jpg|jpeg)$ {
try_files $uri /index.php$request_uri;
access_log off;
expires 30d;
}
}
My original vision for altering this was to use nextcloud.ddns.net to access my nextcloud as before, but also be able to reverse proxy to different local machines via nextcloud.ddns.net/whatever, nextcloud.ddns.net/something etc. Why? Because in my absolute failure of understanding the underlying technology I envisioned this would keep using the already valid ssl certificate for nextcloud.ddns.net without me having to obtain a new certificate for each destination. Does it work like this? I still do not know, but that didn't stop me from trying. I tried including a new location /whatever directive in various places, but all I achieved was a) it not working at all, b) redirecting me to the original nextcloud, c) only working while connected to local lan.
Seeing as I wasn't getting anywhere I went the other way and registered another ddns hostname, pointed that at the same public IP and included this block at the top of the nginx.conf:
server {
listen 443 ssl;
server_name other_hostname.ddns.net;
location / {
proxy_pass http://different_local_machine.lan/;
}
}
This works but obviously complains about the certificate being issued to nextcloud.ddns.net not to other_hostname.ddns.net
Onto my questions then:
Is it at all possible to set it up as I originally thought of with using 1 ddns hostname with different /suffixes or is this not how it works at all?
How would I go about getting multiple lets-encrypt certificates in the working scenario with multiple ddns hostnames? I'm worried if I follow the same instructions as I did to get the cert for the nextcloud I'll end up messing that, as that is still the only internet-facing nginx.
How "safe" would I be in just ignoring the warning? I mean I know the certificate is for different hostname, but I actually know it's still a valid certificate.
Again I apologise for my technical shortcomings, it took me few days to find out that what I want to achieve is called reverse proxy and it didn't improve much from there, but I think what I want to achieve should be possible with help from internet strangers without me having to complete a semester of Computer Science
Thanks for any help!

Here is an example that can be used to handle this ... you may need to tweak the setup for your own needs ...
I use this in an nginx docker that is networked to two containers
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
In the /etc/nginx/conf.d/ directory resides the configuration files for each container ..
-- in site1.conf --
upstream production{
server container_name1:80;
}
server {
server_name site1.com;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
add_header Access-Control-Allow-Origin *;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://production/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/site1.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/site1.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 = site1.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name site1.com;
listen 80;
return 404; # managed by Certbot
}
-- in site2.conf --
upstream production_admin{
server container_name2:80;
}
server {
server_name admin.site1.com;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
add_header Access-Control-Allow-Origin *;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://production_admin/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/site1.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/site1.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 = admin.site1.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name admin.site1.com;
listen 80;
return 404; # managed by Certbot
}
Upstream will set the name that is used in the proxypass and just serve off port 80 for server. This should get you started

For what it's worth if anybody is as hopeless as I am and has this exact same problem, I managed to discover solution on another forum. 1 freaking line, that was it. proxy_set_header Referer $http_referer; What does it do? How should I know? It makes my stuff work as I want though and that's all I care about.
So the full working location block looks like:
location ~ /something {
proxy_pass http://somehost.lan:someport;
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
discussion that led me to the "discovery" : https://unix.stackexchange.com/questions/290141/nginx-reverse-proxy-redirection Bottom post, 1st comment.

Related

Is there a way to specify hostname in laravel octane

When i start octane it always use this host http ://127.0.0.1:8000 , which is usable in local development, but in production environnement i use domain name instead of localhost
Is there a way to change the hostname like http ://domain.com:8000 when we start octane.
Update:
I'm using apache
Update:
I switched to Nginx so, it works better than apache. But if someone managed to resolve this in Apache feel welcome to leave your configuration.
You need Nginx or Apache. It's already on Octane Documentation.
In the Nginx configuration example below file, Nginx will serve the site's static assets and proxy requests to the Octane server that is running on port 8000:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80; // or 8000
listen [::]:80; // or 8000
server_name domain.com;
server_tokens off;
root /your/octane_path/public;
index index.php;
charset utf-8;
location /index.php {
try_files /not_exists #octane;
}
location / {
try_files $uri $uri/ #octane;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/domain.com-error.log error;
error_page 404 /index.php;
location #octane {
set $suffix "";
if ($uri = /index.php) {
set $suffix ?$query_string;
}
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Scheme $scheme;
proxy_set_header SERVER_PORT $server_port;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://127.0.0.1:8000$suffix;
}
}
You can change the hostname by passing the option --host=your-host to the octane command.

JFrog Artifactory OSS displaying port in "Set me up"

I have recently setup JFrog Artifactory OSS and I have it running behind a nginx reverse proxy with a Lets Encrypt SSL certificate.
I can access the site fine (without inputting the port etc). However; when I click the "Set me up" button on a repository; it has the port in the <url> field. It's displaying like this;
https://sub.domain.net:443/artifactory/maven-releases/
I have set Artifactorys base URL to https://sub.domain.net/
I have included my configuration for nginx.
server {
server_name www.sub.domain.net sub.domain.net;
if ($http_x_forwarded_proto = '') {
set $http_x_forwarded_proto $scheme;
}
rewrite ^/$ /ui/ redirect;
rewrite ^/ui$ /ui/ redirect;
chunked_transfer_encoding on;
client_max_body_size 0;
location / {
proxy_read_timeout 2400s;
proxy_pass_header Server;
proxy_cookie_path ~*^/.* /;
proxy_pass http://xxx.xx.xxx.xx:8082;
proxy_next_upstream error timeout non_idempotent;
proxy_next_upstream_tries 1;
proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host:$server_port;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location ~ ^/artifactory/ {
proxy_pass http://xxx.xx.xxx.xx:8081;
}
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/sub.domain.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sub.domain.net/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
if ($host = www.sub.domain.net) {
return 301 https://$host$request_uri;
}
if ($host = sub.domain.net) {
return 301 https://$host$request_uri;
}
listen 80 ;
server_name www.sub.domain.net sub.domain.net;
return 404;
}
Any help you can provide will be greatly appreciated. Thanks.

Unable to set nginx with Nuxt + Laravel API with HTTPS

My application is split as:
Nuxt frontend website in a repository
Laravel backoffice AND API in a different repository (same server)
What I'm trying to achieve is setting up nginx into two server blocks, so that:
Nuxt is served via port 3000 (reverse proxy)
Laravel's backoffice is served as a regular php webpage on port 80
The API is served on port 8000 so that the website can fetch data
These are my HTTP configs:
API and backoffice
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
root /var/www/api/public;
server_name api.website.com;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location /api {
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;
proxy_pass http://localhost:8000;
proxy_read_timeout 90;
proxy_redirect http://localhost:8000 https://api.website.com;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}
location ~ /\.ht {
deny all;
}
ssl_certificate /etc/letsencrypt/live/api.website.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.website.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
Website
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name website.com www.website.com;
location / {
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;
proxy_redirect off;
proxy_read_timeout 1m;
proxy_connect_timeout 1m;
proxy_pass http://127.0.0.1:3000;
}
ssl_certificate /etc/letsencrypt/live/www.website.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.website.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
With these settings on nginx I'm getting a 403 when I try to reach the backoffice, and while the website works, I'm getting a gateway timeout ("Error occured while trying to proxy to") in any request I make.
How can I have it so that I can:
Browse to api.website.com and have the Laravel + Vue.js website open up
Browse to website.com and have the compiled Nuxt website open and fetching API data from api.website.com:8000
Both of these while under HTTPS
Any help would be greatly appreciated.

"Naked domain" unexpectedly closed the connection on my computer

I am experiencing ERR_CONNECTION_CLOSED on all web browsers for the naked domain of my website in my computer. I don't find this issue in any other device other than my computer. The www version loads fine as well.
I have tried clear browser history for last 24 hours, deleted the cache and cookies. It didn't make any difference.
This is my nginx configuration.
upstream app_server {
server unix:/run/gunicorn.sock fail_timeout=0;
}
server {
server_name mydomain.com www.mydomain.com;
location = /favicon.ico { access_log off; log_not_found off; }
location /assets/ {
root /home/djangoadmin/v/myappname;
}
location /media/ {
root /home/djangoadmin/myapp/myappname;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https; # <-
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://app_server;
break;
}
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain.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.mydomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = mydomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name mydomain.com www.mydomain.com;
return 404; # managed by Certbot
}
Is this a device issue or something related to my nginx configuration? How to fix this?
Finally figured it out! The reason was my computer's /etc/hosts had a entry for the naked domain pointing to 127.0.0.1. Removing it fixed the issue.

Rundeck reverse proxy behind Nginx

I have configured reverse proxy for Rundeck behind Nginx. Below is the Rundeck.conf which is placed in the path /etc/nginx/sites-enabled
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_session_cache shared:SSL:1m;
ssl_prefer_server_ciphers on;
## server configuration
server {
listen 443 ssl;
listen 80 ;
server_name ~(?<repo>.+)\.pilot1 pilot1;
if ($http_x_forwarded_proto = '') {
set $http_x_forwarded_proto $scheme;
}
## Application specific logs
## access_log /var/log/nginx/pilot1.ci1.peapod.com-access.log timing;
## error_log /var/log/nginx/pilot1.ci1.peapod.com-error.log;
# rewrite ^/$ /rundeck/menu/home redirect;
rewrite ^/rundeck/?(/rundeck)?$ /rundeck/menu/home redirect;
chunked_transfer_encoding on;
client_max_body_size 0;
location ^~ /rundeck/ {
proxy_pass http://localhost:4440;
proxy_read_timeout 900;
}
}
Reverse proxy works fine when I browse and login to Rundeck.But when I click log out the redirection to the login page exposes the port:4440
as below
LOGIN----> pilot1/rundeck redirects to pilot1/rundeck/menu/home (works fine)
Logout---> pilot1:4440/rundeck/user/loggedout
I do not want the port to be exposed. How do i fix this issue?
Here is what I had to do:
In NGINX config under an appropriate 'server' section set up a location:
location /rundeck/ {
proxy_pass http://localhost:4440;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Rundeck config:
sed -i "/^grails.serverURL/c grails.serverURL = ${RUNDECK_URL}" /etc/rundeck/rundeck-config.properties
sed -i "/^framework.server.url/c framework.server.url = ${RUNDECK_URL}" /etc/rundeck/framework.properties
sed -i '/^RDECK_JVM="$RDECK_JVM/ s/"$/ -Dserver.web.context=\/rundeck"/' /etc/rundeck/profile
where RUNDECK_URL should point to you NGINX ip (dns name) so http://my-nginx.com/rundeck

Resources