Skip to content

Commit

Permalink
Feature/rework config (#3)
Browse files Browse the repository at this point in the history
* Added test badge

* Default to yaml

* Document error handling

* Remove unused error sections

* Make error template accessible
  • Loading branch information
byrnedo committed Apr 17, 2023
1 parent db816a3 commit c78c9cd
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 155 deletions.
8 changes: 5 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@ COPY docker_entrypoint.sh /docker_entrypoint.sh

RUN mkdir $RESTY_ROOT/nginx/conf.d/

COPY data /etc/gomplate/data
COPY nginx.conf.tmpl /etc/gomplate/nginx.conf.tmpl
COPY test /etc/lurch/test
COPY example-apps.yaml /etc/lurch/
COPY nginx.conf.tmpl /etc/lurch/
COPY error.html /etc/lurch/
COPY test/ /etc/lurch/test


COPY lua $RESTY_ROOT/nginx/lua

Expand Down
164 changes: 73 additions & 91 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## Lurch

![main](https://github.com/byrnedo/lurch/actions/workflows/docker-image.yml/badge.svg?branch=main)

<p align="center">
Expand All @@ -17,48 +18,44 @@ Docker image available on [docker hub](https://hub.docker.com/r/byrnedo/lurch).

### Config

The nginx config is generated from the json structure using [Gomplate.](https://docs.gomplate.ca)
The nginx config is generated from the yaml structure using [Gomplate.](https://docs.gomplate.ca)

Gomplate supports many kinds of [datasources](https://docs.gomplate.ca/datasources/) ( local file, remote file over
http, git, you name it!).

By default the proxy expects the json file at `/etc/gomplate/data/apps.json`.
By default the proxy expects the config file at `/etc/lurch/apps.yaml`.

This can be modified with env:

- APPS_CONFIG_PATH

Alternatively the config can be passed directly as env with:

- APPS_CONFIG_JSON
- APPS_CONFIG_YAML

The config looks like this:

```json
{
"services": [
{
"name": "my-service",
"subdomains": [
{
"name": "www",
"enabled": "true",
"enableClientCerts": false,
"enableSsl": true,
"baseUrl": "local.foo.bar"
}
],
"origin": {
"type": "remote",
"port": 9111,
"host": "app.upstream.com"
}
}
]
}
```yaml
---
services:
- name: my-service
subdomains:
- name: www
enabled: 'true'
enableClientCerts: false
enableSsl: true
baseUrl: local.foo.bar
origin:
type: remote
port: 9111
host: app.upstream.com
```

### Reloading

Sending a SIGHUP to the container will rebuild the template and reload openresty.

### JSON Spec
### YAML Spec

**An app can have multiple subdomains**

Expand All @@ -82,7 +79,7 @@ Top level options
|----------------------------------------------------------------------------------------|
|`name` |true | |The service name |
|`subdomains` |true | |The subdomains for the service |
|`origin` |true | |The origin settings for the service |
|`origin` |true | |The origin settings for the service |

`subdomain` options explained

Expand Down Expand Up @@ -124,32 +121,26 @@ If `origin.type = "local"`
|`stripPath` |false | |Strip the `path` value when proxying requests |
|`origin` |true | |Origin object |

Example json:

```json
{
"type": "prefix",
"path": "/api/",
"stripPath": true,
"origin": {
"type": "remote",
"host": "nginx-api.web",
"port": 80
}
}
Example yaml:

```yaml
type: prefix
path: "/api/"
stripPath: true
origin:
type: remote
host: nginx-api.web
port: 80
```

`errorPages` options explained

This is an object where keys are the http status code.
Each status code key value is an object with one property `file`.

```json
{
"404": {
"file": "404.html"
}
}
```yaml
'404':
file: 404.html
```

NOTE: A subdomain of 'www' also will be available at 'foo.bar' or whatever the base-url is set to.
Expand All @@ -158,55 +149,46 @@ NOTE: A subdomain of 'www' also will be available at 'foo.bar' or whatever the b

### Static Site Which Proxies /api to Upstream

```json
{
"services": [
{
"name": "static",
"subdomains": [
{
"name": "static",
"enabled": "true",
"baseUrl": "test.com",
"enableSsl": false,
"port": 80
}
],
"origin": {
"type": "local",
"root": "/data/static/html",
"fallbacks": [
"/index.html;"
],
"errorPages": {
"404": {
"file": "/404.html"
}
},
"pathRules": [
{
"type": "prefix",
"path": "/api/",
"stripPath": true,
"origin": {
"type": "remote",
"host": "backend.web",
"port": 80
}
}
]
}
}
]
}
```yaml
---
services:
- name: static
subdomains:
- name: static
enabled: 'true'
baseUrl: test.com
enableSsl: false
port: 80
origin:
type: local
root: "/data/static/html"
fallbacks:
- "/index.html;"
errorPages:
'404':
file: "/404.html"
pathRules:
- type: prefix
path: "/api/"
stripPath: true
origin:
type: remote
host: backend.web
port: 80
```

# SSL Defaults
## Error pages

The default error page can be overridden by changing the template file:
`/etc/lurch/error.html`.
Note that the syntax in error.html is for [resty.template](https://github.com/bungle/lua-resty-template#template-syntax), not golang templating
Check [lua/error_page.lua](./lua/error_page.lua).

A default certificate needs to be supplied, even when using letsencrypt.
# SSL Defaults

These must be named `server.crt` and placed in `/usr/local/openresty/nginx/ssl/<baseUrl>/`.
A default certificate needs to be supplied, even when using letsencrypt (in case issuance fails).

So generate a self-signed one for worst case and mount it in :)
Lurch generates a self-signed one for you automatically, but should you need to add your own, lurch expects
a `server.crt` and `server.key` and placed in `/usr/local/openresty/nginx/ssl/<baseUrl>/`.

FYI: A `subdomain` with no `port` will default to 443
36 changes: 0 additions & 36 deletions data/apps.json

This file was deleted.

18 changes: 8 additions & 10 deletions docker_entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
#!/bin/bash
set -eu

GOMP_DIR=${GOMP_DIR:-/etc/gomplate}
LURCH_DIR=${LURCH_DIR:-/etc/lurch}

# the nginx configuration template
TEMPLATE_PATH="$GOMP_DIR/nginx.conf.tmpl"
TEMPLATE_PATH="$LURCH_DIR/nginx.conf.tmpl"

# the apps json config path if local
DEFAULT_APPS_CONFIG_PATH="$GOMP_DIR/data/apps.json"
# the apps yaml config path if local
DEFAULT_APPS_CONFIG_PATH="$LURCH_DIR/apps.yaml"

# the user supplied apps json config path, defaults to local
# the user supplied apps yaml config path, defaults to local
APPS_CONFIG_PATH=${APPS_CONFIG_PATH:-${DEFAULT_APPS_CONFIG_PATH}}

# the path openresty will look for the nginx config
CONF_PATH="/usr/local/openresty/nginx/conf/nginx.conf"

APPS_CONFIG_JSON=${APPS_CONFIG_JSON:-}
APPS_CONFIG_YAML=${APPS_CONFIG_YAML:-}

# If config supplied as env then write the file locally
if [ -n "$APPS_CONFIG_JSON" ]; then
echo "$APPS_CONFIG_JSON" >"$DEFAULT_APPS_CONFIG_PATH"
if [ -n "$APPS_CONFIG_YAML" ]; then
echo "$APPS_CONFIG_YAML" >"$DEFAULT_APPS_CONFIG_PATH"
fi


pidfile=/usr/local/openresty/nginx/logs/nginx.pid

ensure_self_signed() {
Expand Down Expand Up @@ -51,7 +50,6 @@ kill_child() {

trap 'echo kill signal received; kill_child' INT TERM QUIT


## Chown storage of ssl certs
mkdir -p /etc/resty-auto-ssl/storage
chown -R nobody /etc/resty-auto-ssl/storage
Expand Down
File renamed without changes.
21 changes: 21 additions & 0 deletions example-apps.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
authRequestUpstream: https://auth.com
authRequestRedirect: https://login.com
authRequestCookie: mycookie
services:
- name: an-upstream
subdomains:
- name: sub1
enabled: 'true'
baseUrl: foo.bar
enableSso: true
port: 80
- name: sub2
enabled: 'true'
baseUrl: foo.bar2
enableSso: false
port: 80
origin:
type: remote
port: 9000
host: an.upstream.com
35 changes: 20 additions & 15 deletions lua/error_page.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,40 @@ local errors_map = {
title = "Something went wrong",
message = "We're very sorry for any inconvenience, our service team has been notified."
},
[502] = {
title = "Something went wrong",
message = "We're very sorry for any inconvenience, our service team has been notified."
},
[503] = {
title = "Something went wrong",
message = "We're very sorry for any inconvenience, our service team has been notified."
},
[504] = {
title = "Something went wrong",
message = "We're very sorry for any inconvenience, our service team has been notified."
},
--[502] = {
-- title = "Something went wrong",
-- message = "We're very sorry for any inconvenience, our service team has been notified."
--},
--[503] = {
-- title = "Something went wrong",
-- message = "We're very sorry for any inconvenience, our service team has been notified."
--},
--[504] = {
-- title = "Something went wrong",
-- message = "We're very sorry for any inconvenience, our service team has been notified."
--},
[404] = {
title = "That site doesn't seem to exist",
message = "Sorry, but there's nothing to see."
}
}

local function getResponse(code)
local function getVars(code)
if errors_map[code] then
return errors_map[code]
else
return errors_map["default"]
end
end

local template = require "resty.template".new({
root = "/etc/lurch",
location = "/etc/lurch"
})

function _M.go(err_code)
local template = require "resty.template"
template.render("error_page/error.html", { title = errors_map[err_code]["title"], message = errors_map[err_code]["message"] })
local vars = getVars(err_code)
template.render("error.html", { title = vars["title"], message = vars["message"] })
end

return _M
Expand Down

0 comments on commit c78c9cd

Please sign in to comment.