CapRover serving static files from host - nginx

I want to serve static files located on the host server using CapRover.
What I did:
Created directory structure /srv/foo/bar.
Ensured bar permission is drw-rw-r-- and all files inside it are -rw-r--r--.
Created new app in CapRover dashboard called app.
Modified its Nginx config (scroll all the way down to see my changes):
<%
if (s.forceSsl) {
%>
server {
listen 80;
server_name <%-s.publicDomain%>;
# Used by Lets Encrypt
location /.well-known/acme-challenge/ {
root <%-s.staticWebRoot%>;
}
# Used by CapRover for health check
location /.well-known/captain-identifier {
root <%-s.staticWebRoot%>;
}
location / {
return 302 https://$http_host$request_uri;
}
}
<%
}
%>
server {
<%
if (!s.forceSsl) {
%>
listen 80;
<%
}
if (s.hasSsl) {
%>
listen 443 ssl http2;
ssl_certificate <%-s.crtPath%>;
ssl_certificate_key <%-s.keyPath%>;
<%
}
%>
client_max_body_size 500m;
server_name <%-s.publicDomain%>;
# 127.0.0.11 is DNS set up by Docker, see:
# https://docs.docker.com/engine/userguide/networking/configure-dns/
# https://github.com/moby/moby/issues/20026
resolver 127.0.0.11 valid=10s;
# IMPORTANT!! If you are here from an old thread to set a custom port, you do not need to modify this port manually here!!
# Simply change the Container HTTP Port from the dashboard HTTP panel
set $upstream http://<%-s.localDomain%>:<%-s.containerHttpPort%>;
# THIS IS WHAT I CHANGED
location / {
root /srv/foo/bar;
}
# Used by Lets Encrypt
location /.well-known/acme-challenge/ {
root <%-s.staticWebRoot%>;
}
# Used by CapRover for health check
location /.well-known/captain-identifier {
root <%-s.staticWebRoot%>;
}
error_page 502 /captain_502_custom_error_page.html;
location = /captain_502_custom_error_page.html {
root <%-s.customErrorPagesDirectory%>;
internal;
}
}
I even set persistent directory mapping for the app, /srv/foo to /srv/foo.
But when I open https://app.caprover.mydomain.com/test.jpg from a browser:
404 Not Found
nginx
So I checked Nginx log (docker service logs captain-nginx --follow):
... *4773 open() "/srv/foo/bar/test.jpg" failed (2: No such file or directory), client: 1.2.3.4, server: app.caprover.mydomain.com, request: "GET /test.jpg HTTP/1.1", host: "app.caprover.mydomain.com"
... "app.caprover.mydomain.com" "GET /test.jpg HTTP/1.1" 404 548 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" "-"
What do I miss?

Nginx is looking inside the container for the path to /srv/foo/bar
I you have created the directory outside of the caprover nginx container, then it has to be mapped into the container to enable nginx to access it.

Related

How can I reference a variable set by lua in nginx?

I am using nginx lua docker image firesh/nginx-lua:alpine-3.4. And i tried to use environment variable in nginx.config file. Below is the configuration in /etc/nginx/nginx.conf.
user nginx;
env ES_USERNAME;
env ES_PWD;
worker_processes 1;
events {
worker_connections 10240;
}
http {
server {
listen 8080;
server_name localhost;
set_by_lua $es_username os.getenv("ES_USERNAME");
set_by_lua $es_pwd os.getenv("ES_PWD");
location /health {
proxy_pass http://$es_username:$es_pwd#elk-es-http:9200/_cluster/health;
}
...
After launching the container, I see this error in the log:
2021/11/18 01:07:14 [error] 6#6: *6 failed to load inlined Lua code: set_by_lua:1: unexpected symbol near '"http://"', client: 10.0.4.122, server: localhost, request: "GET /health HTTP/1.1", host: "10.0.2.170:8080"
The problem is that the url after proxy_pass is not reading the variable from lua. It treats the ${es_username} as a string rather than read its value. What is the correct way to use that?
That sounds strange. I rather expect both $es_username and $es_pwd variables will have an empty value. set_by_lua expects a function that should return a value, and your returns nothing. The correct usage is
set_by_lua $es_username 'return os.getenv("ES_USERNAME")';
set_by_lua $es_pwd 'return os.getenv("ES_PWD")';

NGINX virtual hosts with seperate lua_package_path variables

I'm trying to serve two (Openresty) Lua web applications as virtual hosts from NGINX which both require their own unique lua_package_path, but have a hard time getting the configuration right.
# Failing example.conf
http {
lua_package_path = "/path/to/app/?.lua;;"
server{
listen 80;
server_name example.org
}
}
http {
lua_package_path = "/path/to/dev_app/?.lua;;"
server{
listen 80;
server_name dev.example.org
}
}
If you define the http twice (one for each host), you will receive this error: [emerg] "http" directive is duplicate in example.conf
If you define the lua_package_path inside the server block, you will receive this error: [emerg] "lua_package_path" directive is not allowed here in example.conf
If you define the lua_package_path twice in a http block (which does not make any sense anyway), you will receive this error: [emerg] "lua_package_path" directive is duplicate in example.conf
What is the best practise of serving multiple (Openresty) Lua applications with their own lua_package_path, being virtual hosts on the same IP and port?
I faced this issue several month ago.
I do not recommend no use debug and release projects in the same server. For instance, you launch the one nginx application for both (debug and release) key may lead to unexpectable behaviour.
But, nevertheless, you can setup:
package.path = './mylib/?.lua;' .. package.path inside lua-script.
You can setup your own local DEBUG = false state and manage inside the app.
Obviously, use the other machine for debug. Imo, the best solution.
Execute different my.release.lua or my.debug.lua file:
http {
lua_package_path "./lua/?.lua;/etc/nginx/lua/?.lua;;";
server{
listen 80;
server_name dev.example.org;
lua_code_cache off;
location / {
default_type text/html;
content_by_lua_file './lua/my.debug.lua';
}
}
server{
listen 80;
server_name example.org
location / {
default_type text/html;
content_by_lua_file './lua/my.release.lua';
}
}
}
Fixed it removing the lua_package_path from the NGINX configuration (since the OpenResty bundle already takes care of loading packages) and pointing my content_by_lua_file to the absolute full path of my app: /var/www/app/app.lua
# example.conf
http {
server{
listen 80;
server_name example.org
location / {
content_by_lua_file '/var/www/app/app.lua';
}
}
server{
listen 80;
server_name dev.example.org
location / {
content_by_lua_file '/var/www/app_dev/app.lua';
}
}
}
After that I included this at the top of my app.lua file:
-- app.lua
-- Get the current path of app.lua
local function script_path()
local str = debug.getinfo(2, "S").source:sub(2)
return str:match("(.*/)")
end
-- Add the current path to the package path
package.path = script_path() .. '?.lua;' .. package.path
-- Load the config.lua package
local config = require("config")
-- Use the config
config.env()['redis']['host']
...
This allows me to read the config.lua from the same directory as my app.lua
-- config.lua
module('config', package.seeall)
function env()
return {
env="development",
redis={
host="127.0.0.1",
port="6379"
}
}
end
Using this I can now use multiple virtual hosts with their own package paths.
#Vyacheslav Thank you for the pointer to package.path = './mylib/?.lua;' .. package.path! That was really helpful! Unfortunately it also kept using the NGINX conf root instead of my application root. Even with prepending the . for the path.

nginx upstream does not be recognized by proxy_pass

I want my nginx to pass different uri's to different backends,so I thought I do that:
server {
listen 8090;
access_log /var/log/nginx/nginx_access.log combined;
error_log /var/log/nginx/nginx_error.log debug;
location /bar {
proxy_pass http://backend2;
}
location /foo {
proxy_pass http://backend2;
}
location / {
proxy_pass http://backend1;
}
}
upstream backend1 {
server 10.33.12.41:8080;
server 127.0.0.1:8080 max_fails=3;
}
upstream backend2 {
server 10.33.12.41:8080;
server 10.33.12.43:8080;
}
If I call wget http://mynginxserver:8090/ i get the following:
wget http://mynginxserver:8090/
--2015-09-18 11:58:21-- http://mynginxserver:8090/
Connecting to mynginxserver:8090... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://backend1/
[following]
--2015-09-18 11:58:21-- http://backend1/
Resolving backend1 (backend1)... failed: Temporary failure in name resolution.
wget: unable to resolve host address ‘backend1’
Why does it try to resolve backend1? I don't get it. Please help ;)
Regards,
Snooops
My Fault:
1st it should have been postet here: serverfault.com
and 2nd its already solved here:
https://serverfault.com/questions/590044/nginx-proxy-pass-config

Only one NGINX Server Context works at a time for NGINX sites-enabled

I have the following structure I am working with for NGINX
/etc/nginx
- nginx.conf
- conf.d
- a.conf-disabled (I appended 'disabled' so it wont be used)
- b.conf-disabled (I appended 'disabled' so it wont be used)
- sites-available
- a
- b
- sites-enabled
- a (sym link to sites-available/a)
- b (sym link to sites-available/b)
The nginx.conf file looks like the following:
worker_processes 4;
events {
worker_connections 1024;
}
http {
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
The a file in sites-available looks like the following:
server {
listen 80;
server_name a;
location /a/ {
proxy_pass http://172.17.0.20:5678/;
}
}
and the b file in sites-available looks like the following:
server {
listen 80;
server_name b;
location /b/ {
proxy_pass http://172.17.0.20:5678/;
}
}
I am aware these pointing at the same address, I am just using it because I want to be able to test /a and /b separately.
The problem I am having is that only /a will work and /b fails. If I remove a, then /b works fine.
For example:
curl -X GET http://container-ip/a/ -> WORKS FINE
curl -X GET http://container-ip/b/ -> DOESN'T WORK
I ran logs and its not complaining about anything, but does fail with this when I try to hit /b.
2015/07/13 04:51:59 [error] 235#235: *58 "/etc/nginx/html/b/index.html" is not found (2: No such file or directory), client: 10.0.2.2, server: , request: "GET /b/ HTTP/1.1", host: "localhost:8181"

nGINX read Header & Pass it to different Application Server

I have an nGINX server running. I want to read custom HTTP Header from the incoming Request and redirect it to different application server. I did search for similar questions but found for writing custom headers but not how to read..
if a header is set with this -> "version = Version 1.0" then it should redirect different application (say uwsgi_pass x.x.x.x:80)
if it is set as "version = Version 2.0" then it should redirect to (uwsgi_pass x.x.x.x:99)
I tried in my nginx.conf file
server{
listen 80;
server_name xyz.com;
if ($http_version ~ 'Version 1.0') {
proxy_pass http://192.168.0.116:99/calc;
}
if ($http_version ~ 'Version 2.0') {
proxy_pass http://192.168.0.116:99;
}
location /hello {
proxy_pass http://192.168.0.116:99/calc;
}
}
I'm getting error when I restart my nGINX
nginx: [emerg] "proxy_pass" directive is not allowed here in /etc/nginx/nginx.conf:19
nginx: configuration file /etc/nginx/nginx.conf test failed
Suppose you set a custom header in this form:
version: Version 1.0
Then you can configure nginx like in this way:
location / {
if ($http_version ~ 'Version 1.0') {
uwsgi_pass localhost:8888;
}
if ($http_version ~ 'Version 2.0') {
uwsgi_pass localhost:9999;
}
}
Reference: http://wiki.nginx.org/HttpCoreModule#.24http_HEADER

Resources