Skip to content

Commit

Permalink
Merge pull request #58 from sourcelair/housekeeping
Browse files Browse the repository at this point in the history
Overhaul
  • Loading branch information
parisk committed Jan 26, 2019
2 parents 396b686 + 2c4bc04 commit 8db3ec9
Show file tree
Hide file tree
Showing 16 changed files with 317 additions and 125 deletions.
16 changes: 15 additions & 1 deletion .travis.yml
Expand Up @@ -3,14 +3,28 @@ language: python
python:
- 3.6

env:
- DOCKER_COMPOSE_VERSION=1.23.2 COMPOSE_FILE=docker-compose.yml:docker-compose.override.yml:docker-compose.test.yml

install:
- pip install --upgrade --ignore-installed docker-compose==${DOCKER_COMPOSE_VERSION}
- docker-compose build

- pip install pipenv==11.9
- bash -c "cd api && pipenv install --dev --deploy --system"

services:
- redis-server
- docker

script:
- docker-compose run api ./bin/test
- docker-compose run test

script: bash -c "cd api && ./bin/test"
addons:
apt:
packages:
- docker-ce

notifications:
email: false
1 change: 0 additions & 1 deletion CHANGES.txt

This file was deleted.

18 changes: 18 additions & 0 deletions Dockerfile.test
@@ -0,0 +1,18 @@
FROM ubuntu:18.04

RUN apt-get update && \
apt-get install -y curl httpie

ARG bats_version=1.1.0
RUN curl -sSL https://github.com/bats-core/bats-core/archive/v${bats_version}.tar.gz | tar -xz && \
./bats-core-${bats_version}/install.sh /usr/local && \
rm -rf ./bats-core-${bats_version}

ENV CERYX_DEBUG true
ENV CERYX_DISABLE_LETS_ENCRYPT true

WORKDIR /usr/src/app

COPY . .

CMD ["bats", "ceryx/tests"]
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -32,6 +32,10 @@ Ceryx is configured with the following environment variables:
- `CERYX_SSL_CERT_KEY`: The path to the fallback SSL certificate key (default: randomly generated)
- `CERYX_SSL_CERT`: The path to the fallback SSL certificate (default: randomly generated)

## Adjusting log level

Ceryx will output logs of level to equal or higher of `info` by default. Setting `CERYX_DEBUG` to `true` will also output logs of `debug` level.

### Not running Ceryx as container?

👋 **Heads up!** Ceryx is designed to be run inside a container using Docker or similar tools.
Expand Down
17 changes: 13 additions & 4 deletions ceryx/Dockerfile
@@ -1,5 +1,8 @@
FROM openresty/openresty:1.13.6.1-xenial

ARG user=www-data
ARG group=www-data

RUN mkdir -p /etc/letsencrypt &&\
openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
-subj '/CN=sni-support-required-for-valid-ssl' \
Expand All @@ -14,13 +17,19 @@ RUN curl -fSslL https://github.com/jwilder/dockerize/releases/download/${DOCKERI

# Install lua-resty-auto-ssl for dynamically generating certificates from LE
# https://github.com/GUI/lua-resty-auto-ssl
RUN /usr/local/openresty/luajit/bin/luarocks install lua-resty-auto-ssl 0.12.0
RUN /usr/local/openresty/luajit/bin/luarocks install lua-resty-auto-ssl 0.12.0 &&\
mkdir /etc/resty-auto-ssl/ &&\
chown -R $user:$group /etc/resty-auto-ssl/

# Add the entrypoint script
COPY ./bin/entrypoint.sh /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh" ]
# Clean up all existing NGINX configuration
RUN rm -f /usr/local/openresty/nginx/conf/*

COPY ./nginx/conf /usr/local/openresty/nginx/conf
COPY ./nginx/lualib /usr/local/openresty/nginx/lualib
COPY ./static /etc/ceryx/static

# Add the entrypoint script
COPY ./bin/entrypoint.sh /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh" ]

CMD ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"]
1 change: 0 additions & 1 deletion ceryx/README.md
Expand Up @@ -18,7 +18,6 @@ services:
environment:
- CERYX_REDIS_HOST=redis
- CERYX_REDIS_PORT=6379
- CERYX_FALLBACK=www.something.com
restart: always

...
Expand Down
9 changes: 9 additions & 0 deletions ceryx/bin/entrypoint.sh
@@ -1,5 +1,14 @@
#! /bin/bash

set -ex

if [ $CERYX_DEBUG == "true" ]
then
export CERYX_LOG_LEVEL=debug
else
export CERYX_LOG_LEVEL=info
fi

# Use Dockerize for templates and to wait for Redis
/usr/local/bin/dockerize \
${CERYX_DOCKERIZE_EXTRA_ARGS} \
Expand Down
33 changes: 15 additions & 18 deletions ceryx/nginx/conf/ceryx.conf.tmpl
Expand Up @@ -17,8 +17,10 @@ server {
ssl_certificate {{ default .Env.CERYX_SSL_CERT "/etc/ssl/resty-auto-ssl-fallback.crt" }};
ssl_certificate_key {{ default .Env.CERYX_SSL_CERT_KEY "/etc/ssl/resty-auto-ssl-fallback.key" }};

# Disable the LE certificate generation
{{ if ne (lower (default .Env.CERYX_DISABLE_LETS_ENCRYPT "")) "true" }}
# Generate Let's Encrypt certificates automatically, if
# `CERYX_DISABLE_LETS_ENCRYPT` is *not* set to `true`.

ssl_certificate_by_lua_block {
auto_ssl:ssl_certificate()
}
Expand Down Expand Up @@ -53,27 +55,21 @@ server {
proxy_pass http://$container_url$request_uri;
}

error_page 502 @bad_gateway;
location @bad_gateway {
set $fallback_url "";

# Get fallback URL from environment
access_by_lua_block {
ngx.var.fallback_url = os.getenv("CERYX_FALLBACK")
if not ngx.var.fallback_url then ngx.var.fallback_url = "www.something.com" end
}

# Proxy configuration
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $proxy_set_x_forwarded_proto;
error_page 503 /503.html;
location = /503.html {
root /etc/ceryx/static;
}

proxy_pass http://$fallback_url$request_uri;
error_page 500 /500.html;
location = /500.html {
root /etc/ceryx/static;
}
}

# Internal server running on port 8999 for handling certificate tasks.
{{ if ne (lower (default .Env.CERYX_DISABLE_LETS_ENCRYPT "")) "true" }}
# Launch the Let's Encrypt certificate internal server running on port 8999, if
# `CERYX_DISABLE_LETS_ENCRYPT` is *not* set to `true`.

server {
listen 127.0.0.1:8999;
client_body_buffer_size 1m;
Expand All @@ -84,3 +80,4 @@ server {
}
}
}
{{ end }}
83 changes: 7 additions & 76 deletions ceryx/nginx/conf/nginx.conf.tmpl
Expand Up @@ -6,7 +6,6 @@ env CERYX_REDIS_PREFIX;
env CERYX_REDIS_HOST;
env CERYX_REDIS_PASSWORD;
env CERYX_REDIS_PORT;
env CERYX_FALLBACK;

events {
worker_connections 1024;
Expand All @@ -23,7 +22,7 @@ http {

# Logging
access_log /dev/stdout;
error_log /dev/stderr warn;
error_log /dev/stderr {{ default .Env.CERYX_LOG_LEVEL "info" }};

# Lua settings
lua_package_path "$prefix/lualib/?.lua;;";
Expand All @@ -36,85 +35,17 @@ http {
{{ else }}
lua_code_cache on;
{{ end }}
# see https://github.com/openresty/lua-resty-core
init_by_lua_block {
auto_ssl = (require "resty.auto-ssl").new()

-- Define a function to determine which SNI domains to automatically handle
-- and register new certificates for. Defaults to not allowing any domains,
-- so this must be configured.
auto_ssl:set("allow_domain", function(domain)
local host = domain

-- Check if key exists in local cache
local cache = ngx.shared.ceryx
local res, flags = cache:get(host)
if res then
return true
end

local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(100) -- 100 ms
local redis_host = os.getenv("CERYX_REDIS_HOST")
if not redis_host then redis_host = "127.0.0.1" end
local redis_port = os.getenv("CERYX_REDIS_PORT")
if not redis_port then redis_port = 6379 end
local redis_password = os.getenv("CERYX_REDIS_PASSWORD")
if not redis_password then redis_password = nil end

local res, err = red:connect(redis_host, redis_port)

-- Return if could not connect to Redis
if not res then
ngx.log(ngx.ERR, "Error connecting to redis: " .. (err or ""))
return false
end

-- Authenticate with Redis if necessary
if redis_password then
local res, err = red:auth(redis_password)
if not res then
ngx.log(ngx.ERR, "Failed to authenticate with redis: ", err)
return false
end
end

-- Construct Redis key
local prefix = os.getenv("CERYX_REDIS_PREFIX")
if not prefix then prefix = "ceryx" end
local key = prefix .. ":routes:" .. host

-- Try to get target for host
res, err = red:get(key)
if not res or res == ngx.null then
return false
end

-- Save found key to local cache for 5 seconds
cache:set(host, res, 5)

return true
end)

-- Set the resty-auto-ssl storage to Redis, using the CERYX_* env variables
local redis_host = os.getenv("CERYX_REDIS_HOST")
if not redis_host then redis_host = "127.0.0.1" end
local redis_port = os.getenv("CERYX_REDIS_PORT")
if not redis_port then redis_port = 6379 end
auto_ssl:set("storage_adapter", "resty.auto-ssl.storage_adapters.redis")
auto_ssl:set("redis", {
host = redis_host,
port = redis_port
})

auto_ssl:init()
require "resty.core"
}
{{ if ne (lower (default .Env.CERYX_DISABLE_LETS_ENCRYPT "")) "true" }}
# Enable automatic Let's Encryps certificate generation, if
# `CERYX_DISABLE_LETS_ENCRYPT` is *not* set to `true`.
# Check out https://github.com/openresty/lua-resty-core
init_by_lua_file "lualib/https.lua";

init_worker_by_lua_block {
auto_ssl:init_worker()
}
{{ end }}

# Includes
include mime.types;
Expand Down
72 changes: 72 additions & 0 deletions ceryx/nginx/lualib/https.lua
@@ -0,0 +1,72 @@
auto_ssl = (require "resty.auto-ssl").new()

-- Define a function to determine which SNI domains to automatically handle
-- and register new certificates for. Defaults to not allowing any domains,
-- so this must be configured.
auto_ssl:set("allow_domain", function(domain)
local host = domain

-- Check if key exists in local cache
local cache = ngx.shared.ceryx
local res, flags = cache:get(host)
if res then
return true
end

local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(100) -- 100 ms
local redis_host = os.getenv("CERYX_REDIS_HOST")
if not redis_host then redis_host = "127.0.0.1" end
local redis_port = os.getenv("CERYX_REDIS_PORT")
if not redis_port then redis_port = 6379 end
local redis_password = os.getenv("CERYX_REDIS_PASSWORD")
if not redis_password then redis_password = nil end

local res, err = red:connect(redis_host, redis_port)

-- Return if could not connect to Redis
if not res then
ngx.log(ngx.ERR, "Error connecting to redis: " .. (err or ""))
return false
end

-- Authenticate with Redis if necessary
if redis_password then
local res, err = red:auth(redis_password)
if not res then
ngx.log(ngx.ERR, "Failed to authenticate with redis: ", err)
return false
end
end

-- Construct Redis key
local prefix = os.getenv("CERYX_REDIS_PREFIX")
if not prefix then prefix = "ceryx" end
local key = prefix .. ":routes:" .. host

-- Try to get target for host
res, err = red:get(key)
if not res or res == ngx.null then
return false
end

-- Save found key to local cache for 5 seconds
cache:set(host, res, 5)

return true
end)

-- Set the resty-auto-ssl storage to Redis, using the CERYX_* env variables
local redis_host = os.getenv("CERYX_REDIS_HOST")
if not redis_host then redis_host = "127.0.0.1" end
local redis_port = os.getenv("CERYX_REDIS_PORT")
if not redis_port then redis_port = 6379 end
auto_ssl:set("storage_adapter", "resty.auto-ssl.storage_adapters.redis")
auto_ssl:set("redis", {
host = redis_host,
port = redis_port
})

auto_ssl:init()
require "resty.core"

0 comments on commit 8db3ec9

Please sign in to comment.