From 1562cca09f775991853b36d0495d46b39870bff0 Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Tue, 8 Jan 2019 16:00:10 +0200 Subject: [PATCH 01/17] Housekeeping 1. Extract HTTPS handling in nginx.conf into its own `.lua` file 2. Configure log level according to `CERYX_DEBUG` 3. Introduce several debugging logs --- ceryx/Dockerfile | 5 ++ ceryx/bin/entrypoint.sh | 9 ++++ ceryx/nginx/conf/nginx.conf.tmpl | 78 ++------------------------------ ceryx/nginx/lualib/https.lua | 72 +++++++++++++++++++++++++++++ ceryx/nginx/lualib/router.lua | 42 ++++++++++------- 5 files changed, 115 insertions(+), 91 deletions(-) create mode 100644 ceryx/nginx/lualib/https.lua diff --git a/ceryx/Dockerfile b/ceryx/Dockerfile index b8e925f..a55338c 100644 --- a/ceryx/Dockerfile +++ b/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' \ @@ -15,6 +18,8 @@ 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 mkdir /etc/resty-auto-ssl/ +RUN chown -R $user:$group /etc/resty-auto-ssl/ # Add the entrypoint script COPY ./bin/entrypoint.sh /entrypoint.sh diff --git a/ceryx/bin/entrypoint.sh b/ceryx/bin/entrypoint.sh index 4d745a5..e2a955c 100755 --- a/ceryx/bin/entrypoint.sh +++ b/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} \ diff --git a/ceryx/nginx/conf/nginx.conf.tmpl b/ceryx/nginx/conf/nginx.conf.tmpl index 7de17fb..a5b184b 100644 --- a/ceryx/nginx/conf/nginx.conf.tmpl +++ b/ceryx/nginx/conf/nginx.conf.tmpl @@ -23,7 +23,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;;"; @@ -36,81 +36,9 @@ 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" - } + # see https://github.com/openresty/lua-resty-core + init_by_lua_file "lualib/https.lua"; init_worker_by_lua_block { auto_ssl:init_worker() diff --git a/ceryx/nginx/lualib/https.lua b/ceryx/nginx/lualib/https.lua new file mode 100644 index 0000000..953117e --- /dev/null +++ b/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" \ No newline at end of file diff --git a/ceryx/nginx/lualib/router.lua b/ceryx/nginx/lualib/router.lua index b0dd172..419d89c 100644 --- a/ceryx/nginx/lualib/router.lua +++ b/ceryx/nginx/lualib/router.lua @@ -2,6 +2,11 @@ local host = ngx.var.host local is_not_https = (ngx.var.scheme ~= "https") local cache = ngx.shared.ceryx +function route(source, target) + ngx.var.container_url = target + ngx.log(ngx.INFO, "Routing request for " .. source .. " to " .. target .. ".") +end + local prefix = os.getenv("CERYX_REDIS_PREFIX") if not prefix then prefix = "ceryx" end @@ -48,27 +53,32 @@ end -- Check if key exists in local cache res, flags = cache:get(host) if res then - ngx.var.container_url = res - return -end + ngx.log(ngx.DEBUG, "Cache hit for " .. host .. ".") + route(host, res) +else + ngx.log(ngx.DEBUG, "Cache miss for " .. host .. ".") --- Construct Redis key -local key = prefix .. ":routes:" .. host - --- Try to get target for host -res, err = red:get(key) -if not res or res == ngx.null then - -- Construct Redis key for $wildcard - key = prefix .. ":routes:$wildcard" + -- Construct Redis key + 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 ngx.exit(ngx.HTTP_BAD_GATEWAY) + ngx.log(ngx.INFO, "Could not find target for " .. host .. ".") + + -- Construct Redis key for $wildcard + key = prefix .. ":routes:$wildcard" + res, err = red:get(key) + if not res or res == ngx.null then + ngx.log(ngx.INFO, "No $wildcard target configured for fallback. Exiting with Bad Gateway.") + return ngx.exit(ngx.HTTP_BAD_GATEWAY) + else + ngx.log(ngx.DEBUG, "Falling back to " .. res .. ".") + end end - ngx.var.container_url = res - return end -- Save found key to local cache for 5 seconds +route(host, res) cache:set(host, res, 5) - -ngx.var.container_url = res +ngx.log(ngx.DEBUG, "Saving route from " .. host .. " to " .. res .. " in local cache for 5 seconds.") From 90f40e6fcc9193c69f24669582f237be8eba4ac7 Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Tue, 8 Jan 2019 16:23:12 +0200 Subject: [PATCH 02/17] Update README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 19388a5..41208e3 100644 --- a/README.md +++ b/README.md @@ -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. From f88a0089898680f0ce53802e2acfff8a1494601e Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Tue, 8 Jan 2019 17:14:13 +0200 Subject: [PATCH 03/17] Remove `/usr/local/openresty/nginx/conf` so it includes only Ceryx' config. --- ceryx/Dockerfile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ceryx/Dockerfile b/ceryx/Dockerfile index a55338c..ea5800d 100644 --- a/ceryx/Dockerfile +++ b/ceryx/Dockerfile @@ -21,11 +21,13 @@ RUN /usr/local/openresty/luajit/bin/luarocks install lua-resty-auto-ssl 0.12.0 RUN mkdir /etc/resty-auto-ssl/ RUN chown -R $user:$group /etc/resty-auto-ssl/ -# Add the entrypoint script -COPY ./bin/entrypoint.sh /entrypoint.sh -ENTRYPOINT [ "/entrypoint.sh" ] +RUN rm -f /usr/local/openresty/nginx/conf COPY ./nginx/conf /usr/local/openresty/nginx/conf COPY ./nginx/lualib /usr/local/openresty/nginx/lualib +# Add the entrypoint script +COPY ./bin/entrypoint.sh /entrypoint.sh +ENTRYPOINT [ "/entrypoint.sh" ] + CMD ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"] From 5bd4d024700bad2a3238996a8b25da718a2159df Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Tue, 8 Jan 2019 17:26:36 +0200 Subject: [PATCH 04/17] Remove directory contents. Not the directory itself. --- ceryx/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ceryx/Dockerfile b/ceryx/Dockerfile index ea5800d..30e9ca0 100644 --- a/ceryx/Dockerfile +++ b/ceryx/Dockerfile @@ -21,7 +21,7 @@ RUN /usr/local/openresty/luajit/bin/luarocks install lua-resty-auto-ssl 0.12.0 RUN mkdir /etc/resty-auto-ssl/ RUN chown -R $user:$group /etc/resty-auto-ssl/ -RUN rm -f /usr/local/openresty/nginx/conf +RUN rm -f /usr/local/openresty/nginx/conf/* COPY ./nginx/conf /usr/local/openresty/nginx/conf COPY ./nginx/lualib /usr/local/openresty/nginx/lualib From f56d528096cf792a059dd7553990a6c4b008fcce Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Tue, 8 Jan 2019 18:05:24 +0200 Subject: [PATCH 05/17] Do not run any "resty-auto-ssl" code if `CERYX_DISABLE_LETS_ENCRYPT` is `true`. --- ceryx/nginx/conf/ceryx.conf.tmpl | 10 ++++++++-- ceryx/nginx/conf/nginx.conf.tmpl | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ceryx/nginx/conf/ceryx.conf.tmpl b/ceryx/nginx/conf/ceryx.conf.tmpl index 94d19d2..aa9a87f 100644 --- a/ceryx/nginx/conf/ceryx.conf.tmpl +++ b/ceryx/nginx/conf/ceryx.conf.tmpl @@ -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() } @@ -73,7 +75,10 @@ server { } } -# 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; @@ -84,3 +89,4 @@ server { } } } +{{ end }} diff --git a/ceryx/nginx/conf/nginx.conf.tmpl b/ceryx/nginx/conf/nginx.conf.tmpl index a5b184b..b846980 100644 --- a/ceryx/nginx/conf/nginx.conf.tmpl +++ b/ceryx/nginx/conf/nginx.conf.tmpl @@ -37,12 +37,16 @@ http { lua_code_cache on; {{ end }} - # see https://github.com/openresty/lua-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; From a67b1ce0e624efaa611b1a77e35c561394c4b2d8 Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Tue, 8 Jan 2019 19:02:18 +0200 Subject: [PATCH 06/17] Make Ceryx 503 fallback a static HTML page to avoid messing with network. --- ceryx/Dockerfile | 1 + ceryx/README.md | 1 - ceryx/nginx/conf/ceryx.conf.tmpl | 20 +++------------- ceryx/nginx/conf/nginx.conf.tmpl | 1 - ceryx/nginx/lualib/router.lua | 4 ++-- ceryx/static/503.html | 41 ++++++++++++++++++++++++++++++++ docker-compose.override.yml | 1 + 7 files changed, 48 insertions(+), 21 deletions(-) create mode 100644 ceryx/static/503.html diff --git a/ceryx/Dockerfile b/ceryx/Dockerfile index 30e9ca0..5b5c9b9 100644 --- a/ceryx/Dockerfile +++ b/ceryx/Dockerfile @@ -25,6 +25,7 @@ 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 diff --git a/ceryx/README.md b/ceryx/README.md index 156305e..ab855d8 100644 --- a/ceryx/README.md +++ b/ceryx/README.md @@ -18,7 +18,6 @@ services: environment: - CERYX_REDIS_HOST=redis - CERYX_REDIS_PORT=6379 - - CERYX_FALLBACK=www.something.com restart: always ... diff --git a/ceryx/nginx/conf/ceryx.conf.tmpl b/ceryx/nginx/conf/ceryx.conf.tmpl index aa9a87f..7f2edc0 100644 --- a/ceryx/nginx/conf/ceryx.conf.tmpl +++ b/ceryx/nginx/conf/ceryx.conf.tmpl @@ -55,23 +55,9 @@ 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; - - proxy_pass http://$fallback_url$request_uri; + error_page 503 /503.html; + location = /503.html { + root /etc/ceryx/static; } } diff --git a/ceryx/nginx/conf/nginx.conf.tmpl b/ceryx/nginx/conf/nginx.conf.tmpl index b846980..a8b6346 100644 --- a/ceryx/nginx/conf/nginx.conf.tmpl +++ b/ceryx/nginx/conf/nginx.conf.tmpl @@ -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; diff --git a/ceryx/nginx/lualib/router.lua b/ceryx/nginx/lualib/router.lua index 419d89c..e949381 100644 --- a/ceryx/nginx/lualib/router.lua +++ b/ceryx/nginx/lualib/router.lua @@ -24,7 +24,7 @@ local res, err = red:connect(redis_host, redis_port) -- Return if could not connect to Redis if not res then - return ngx.exit(ngx.HTTP_BAD_GATEWAY) + return ngx.exit(ngx.HTTP_SERVER_ERROR) end if redis_password then @@ -71,7 +71,7 @@ else res, err = red:get(key) if not res or res == ngx.null then ngx.log(ngx.INFO, "No $wildcard target configured for fallback. Exiting with Bad Gateway.") - return ngx.exit(ngx.HTTP_BAD_GATEWAY) + return ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE) else ngx.log(ngx.DEBUG, "Falling back to " .. res .. ".") end diff --git a/ceryx/static/503.html b/ceryx/static/503.html new file mode 100644 index 0000000..4fa7b7c --- /dev/null +++ b/ceryx/static/503.html @@ -0,0 +1,41 @@ + + + + + There is nothing here. + + + + + +
+

Ceryx

+

Service Not Available

+

The website you are trying to access, does not exist.

+
+ + \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 4d58b47..ab15a66 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -6,6 +6,7 @@ services: volumes: - ./ceryx/nginx/conf:/usr/local/openresty/nginx/conf - ./ceryx/nginx/lualib:/usr/local/openresty/nginx/lualib + - ./ceryx/static:/etc/ceryx/static environment: CERYX_DEBUG: ${CERYX_DEBUG:-true} CERYX_DOCKERIZE_EXTRA_ARGS: "" From 86abc100f3e1478ef1e3e68d6c06fe176d7ee8f0 Mon Sep 17 00:00:00 2001 From: Paris Kasidiaris Date: Tue, 8 Jan 2019 20:08:39 +0200 Subject: [PATCH 07/17] Add Server Error page and more debug logs --- ceryx/nginx/conf/ceryx.conf.tmpl | 5 ++++ ceryx/nginx/lualib/router.lua | 10 ++++++-- ceryx/static/500.html | 41 ++++++++++++++++++++++++++++++++ ceryx/static/503.html | 2 +- 4 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 ceryx/static/500.html diff --git a/ceryx/nginx/conf/ceryx.conf.tmpl b/ceryx/nginx/conf/ceryx.conf.tmpl index 7f2edc0..5a84d53 100644 --- a/ceryx/nginx/conf/ceryx.conf.tmpl +++ b/ceryx/nginx/conf/ceryx.conf.tmpl @@ -59,6 +59,11 @@ server { location = /503.html { root /etc/ceryx/static; } + + error_page 500 /500.html; + location = /500.html { + root /etc/ceryx/static; + } } {{ if ne (lower (default .Env.CERYX_DISABLE_LETS_ENCRYPT "")) "true" }} diff --git a/ceryx/nginx/lualib/router.lua b/ceryx/nginx/lualib/router.lua index e949381..8a18634 100644 --- a/ceryx/nginx/lualib/router.lua +++ b/ceryx/nginx/lualib/router.lua @@ -11,6 +11,7 @@ local prefix = os.getenv("CERYX_REDIS_PREFIX") if not prefix then prefix = "ceryx" end -- Prepare the Redis client +ngx.log(ngx.DEBUG, "Preparing Redis client.") local redis = require "resty.redis" local red = redis:new() red:set_timeout(100) -- 100 ms @@ -24,16 +25,21 @@ local res, err = red:connect(redis_host, redis_port) -- Return if could not connect to Redis if not res then + ngx.log(ngx.DEBUG, "Could not prepare Redis client: " .. err) return ngx.exit(ngx.HTTP_SERVER_ERROR) end +ngx.log(ngx.DEBUG, "Redis client prepared.") + if redis_password then + ngx.log(ngx.DEBUG, "Authenticating with Redis.") local res, err = red:auth(redis_password) if not res then - ngx.ERR("Failed to authenticate Redis: ", err) - return + ngx.ERR("Could not authenticate with Redis: ", err) + return ngx.exit(ngx.HTTP_SERVER_ERROR) end end +ngx.log(ngx.DEBUG, "Authenticated with Redis.") if is_not_https then local settings_key = prefix .. ":settings:" .. host diff --git a/ceryx/static/500.html b/ceryx/static/500.html new file mode 100644 index 0000000..6fa3240 --- /dev/null +++ b/ceryx/static/500.html @@ -0,0 +1,41 @@ + + + + + Ceryx - Server Error + + + + + +
+

Ceryx

+

Server Error

+

We are sorry, an unexpected error occured while servicing your request.

+
+ + \ No newline at end of file diff --git a/ceryx/static/503.html b/ceryx/static/503.html index 4fa7b7c..feb4356 100644 --- a/ceryx/static/503.html +++ b/ceryx/static/503.html @@ -2,7 +2,7 @@ - There is nothing here. + Ceryx - Service Not Available