Skip to content

Commit

Permalink
Merge pull request #57 from sourcelair/improve-docs
Browse files Browse the repository at this point in the history
Improve docs and remove obsolete settings
  • Loading branch information
parisk authored Jan 3, 2019
2 parents 0bf6b19 + af2fb9c commit 396b686
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 73 deletions.
178 changes: 107 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,100 +1,136 @@
# Ceryx - Simple, but powerful Reverse Proxy
# Ceryx - Rock-solid, programmable HTTP(S) reverse proxy

[![Build Status](https://travis-ci.org/sourcelair/ceryx.svg)](https://travis-ci.org/sourcelair/ceryx)

Ceryx is a dynamic reverse proxy based on NGINX OpenResty with an API.
Ceryx is the rock-solid, programmable reverse proxy used to provide tens of thousands of [SourceLair](https://www.sourcelair.com/) projects with their unique HTTPS-enabled public URLs.

Ceryx is used to provide public URLs to tens of thousands of projects at https://www.sourcelair.com.
## High-level architecture

## Proxy
Ceryx is using NGINX OpenResty under the hood, in order to route requests
based on the request host. The routing is made using the NGINX Lua module,
which is querying a Redis backend for results.
One of the main traits of Ceryx that makes it rock-solid is the simplicity in its design. Ceryx is comprised of two components and a Redis backend: the HTTP(S) reverse proxy and an API.

## API
Ceryx comes with a simple Flask web service, which supports REST operations on
routes. You can dynamically create, update, and delete routes on the go using
a REST client.
### Proxy
Ceryx uses NGINX OpenResty under the hood to route requests, based on the HTTP request's `Host` header or the [Server Name Indication](https://en.wikipedia.org/wiki/Server_Name_Indication) in HTTPS requests. Ceryx queries the Redis backend to decide to which target it should route each request.

### API
The Ceryx API lets users dynamically create, update and delete Ceryx routes via any HTTP client. The API essentially validates, sanitizes and eventually stores input in the Ceryx backend, to be queried by the proxy.

## Configuration
Ceryx supports configuration using environment variables. The supported
configuration options are the following:

* ``CERYX_API_HOST``: sets the host that the API will bind to - defaults to 127.0.0.1
* ``CERYX_API_HOSTNAME``: identical to `CERYX_SERVER_NAME`, but without imposing `Host` header limits - default to None
* ``CERYX_API_PORT``: sets the port that the API will listen - defaults to 5555
* ``CERYX_DEBUG``: enables debugging on the API service - defaults to true
* ``CERYX_DISABLE_LETS_ENCRYPT``: if true, the automatic generation through Let's Encrypt does not kick in, defaults to false
* ``CERYX_DNS_RESOLVER``: the IP of the DNS resolver to use, defaults to 127.0.0.11 — the Docker DNS resolver
* ``CERYX_DOCKERIZE_EXTRA_ARGS``: extra arguments, to pass to `dockerize`
* ``CERYX_NAME``: sets the API service name - defaults to ceryx
* ``CERYX_REDIS_HOST``: the redis host to connect to - defaults to 127.0.0.1
* ``CERYX_REDIS_PASSWORD``: the redis password to use - defaults to none
* ``CERYX_REDIS_PORT``: the redis port to connect to - defaults to 6379
* ``CERYX_REDIS_PREFIX``: the redis prefix to use in keys - defaults to ceryx
* ``CERYX_SECRET_KEY``: the path of the secret key to use - defaults to None
* ``CERYX_SERVER_NAME``: the URL of the API service - default to None
* ``CERYX_SSL_CERT_KEY``: the path to the SSL certificate key to use as fallback, defaults to a randomly generated key
* ``CERYX_SSL_CERT``: the path to the SSL certificate to use as fallback, defaults to a randomly generated certificate

If you're not using the [`sourcelair/ceryx`](https://hub.docker.com/r/sourcelair/ceryx/) image, you'll need to use a command similar to the one below, to generate the configuration files needed from the environment, using [`dockerize`](https://github.com/jwilder/dockerize), through the [`entrypoint.sh`](ceryx/bin/entrypoint.sh) script.

```bash
bash ceryx/nginx/entrypoint.sh /usr/local/openresty/bin/openresty -g "daemon off;"
```

## Quick Bootstrap
Ceryx loves Docker, so you can easily bootstrap Ceryx using the following
command, given that you have already installed Docker and Docker Compose.
Ceryx is configured with the following environment variables:

- `CERYX_API_HOST`: The host to bind the Ceryx API (default: `127.0.0.1`)
- `CERYX_API_HOSTNAME`: Optional publicly accessible hostname for the Ceryx API (default: None)
- `CERYX_API_PORT`: The port to bind the Ceryx API (default: `5555`)
- `CERYX_DEBUG`: Enable debug logs for Ceryx API (default: `true`)
- `CERYX_DISABLE_LETS_ENCRYPT`: Disable automatic Let's Encrypt HTTPS certificate generation (default: `false`)
- `CERYX_DNS_RESOLVER`: The IP of the DNS resolver to use (default: `127.0.0.11` — the Docker DNS resolver)
- `CERYX_DOCKERIZE_EXTRA_ARGS`: extra arguments, to pass to `dockerize` (default: None)
- `CERYX_REDIS_HOST`: The Redis host to use as backend (default: `127.0.0.1`)
- `CERYX_REDIS_PASSWORD`: Optional password to use for authenticating with Redis (default: None)
- `CERYX_REDIS_PORT`: The where Redis should be reached (default: `6379`)
- `CERYX_REDIS_PREFIX`: The prefix to use in Ceryx-related Redis keys (default: `ceryx`)
- `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)

### Not running Ceryx as container?

👋 **Heads up!** Ceryx is designed to be run inside a container using Docker or similar tools.

If you're not running Ceryx using the official [`sourcelair/ceryx`](https://hub.docker.com/r/sourcelair/ceryx/) image, you'll need to take care of configuration file generation yourself. Take a look at [`entrypoint.sh`](ceryx/bin/entrypoint.sh) to get ideas.

### Dynamic SSL certificates

By default, Ceryx will try to generate a certificate when a domain is hit via HTTPS through Let's Encrypt, if and only if a route exists for it. To disable this behavior, set `CERYX_DISABLE_LETS_ENCRYPT` to `true`.

## Quick start

You can start using Ceryx in a few seconds!

### Requirements

Before getting started, make sure you have the following:

1. A computer accessible from the internet with Docker ([docs](https://docs.docker.com/install/linux/docker-ce/ubuntu/)) and Docker Compose ([docs](https://docs.docker.com/compose/install/))
2. At least one domain (or subdomain) resolving to the computer's public IP addtess

### Running Ceryx

Just run the following command to run Ceryx in the background:

```
docker-compose up
docker-compose up -d
```

To access (and therefore 🐶 dogfood 🐶) the Ceryx API via Ceryx' proxy, set the
`CERYX_API_HOSTNAME` environment variable and run the following command in your terminal:
### Exposing the API to the public

**👋 Heads up!** Don't ever do this in production! Anyone from the internet will be able to access the Ceryx API and mess with it. It's useful for development/testing though.

To access (and therefore 🐶 dogfood) the Ceryx API via Ceryx' proxy, set the `CERYX_API_HOSTNAME` setting and run the following command in your terminal:

```
docker-compose exec api bin/populate-api
```

## Development
## The Ceryx API

Ceryx was developed as a private project for SourceLair PC. Initial development
had different stages, having tproxy, Twisted and plain NGINX as a proxy server
and backends ranging from MongoDB to etcd.
### Add a new route to Ceryx

After a lot of experimentation, we have ended up in this solution and we'll
keep developing this as an Open Source project. Feel free to make suggestions
in the [issues section](https://github.com/sourcelair/ceryx/issues) in Github
or open o pull request.
```
curl -H "Content-Type: application/json" \
-X POST \
-d '{"source":"publicly.accessible.domain","target":"http://service.internal:8000"}' \
http://ceryx-api-host/api/routes
```

## Dynamic SSL certificates
### Update a route in Ceryx

By default, Ceryx will try to generate a certificate when a domain is hit via HTTPS through Let's Encrypt, if and only if a route exists for it. If you don't want this to be enabled, you can use the `CERYX_DISABLE_LETS_ENCRYPT` setting.
```
curl -H "Content-Type: application/json" \
-X PUT \
-d '{"source":"publicly.accessible.domain","target":"http://another-service.internal:8000"}' \
http://ceryx-api-host/api/routes/publicly.accessible.domain
```

## License
### Delete a route from Ceryx

```
curl -H "Content-Type: application/json" \
-X DELETE \
http://ceryx-api-host/api/routes/publicly.accessible.domain
```

### HTTPS redirects

You can enforce redirection from HTTP to HTTPS for any host you would like.

```
curl -H "Content-Type: application/json" \
-X POST \
-d '{"source":"publicly.accessible.domain","target":"http://service.internal:8000", "settings": {"enforce_https": true}}' \
http://ceryx-api-host/api/routes
```

The above functionality works in `PUT` update requests as well.

## Ceryx web UI

The [Ceryx Web community project](https://github.com/parisk/ceryx-web) provides a sweet web UI

Ceryx is licensed under the "The MIT License (MIT)".
## Real-world uses

The MIT License (MIT)
Ceryx has proven to be extremely reliable in production systems, handling tens of thousands of routes in its backend. Some of them are:

Copyright (c) 2015 SourceLair PC
- [**SourceLair**](https://www.sourcelair.com/): In-browser IDE for web applications, made publicly accessible via development web servers powered by Ceryx.
- [**Stolos**](http://stolos.io/): Managed Docker development environments for enterprises.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Do you use Ceryx in production as well? Please [open a Pull Request](https://github.com/sourcelair/ceryx/pulls) to include it here. We would love to have it in our list.

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
## Origin

Ceryx started in [SourceLair](https://www.sourcelair.com) to help provide tens of thousands of users with a unique public URL (subdomain) for each one of their projects. Initial development had different stages; from using [tproxy](https://github.com/benoitc/tproxy), [Twisted](https://www.twistedmatrix.com/trac/) and bare [NGINX](https://nginx.org/en/) as a proxy and backends ranging from [MongoDB](https://www.mongodb.com/) to [etcd](https://github.com/etcd-io/etcd).

After a lot of experimentation, we have ended up in using [OpenResty](https://openresty.org/en/) as the proxy and [Redis](https://redis.io/) as the backend. This solution has served us and we are now developing it in the open as an open source project.

## License

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Ceryx is [MIT licensed](LICENSE).
3 changes: 1 addition & 2 deletions api/ceryx/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
"""
import os

NAME = os.getenv('CERYX_NAME', 'ceryx')

DEBUG = True
if os.getenv('CERYX_DEBUG', '').lower() in ['0', 'no', 'false']:
DEBUG = False

API_BIND_HOST = os.getenv('CERYX_API_HOST', '127.0.0.1')
API_BIND_PORT = int(os.getenv('CERYX_API_PORT', 5555))
SERVER_NAME = os.getenv('CERYX_SERVER_NAME')
SECRET_KEY = os.getenv('CERYX_SECRET_KEY')
if SECRET_KEY:
with open(SECRET_KEY, 'r') as f:
Expand Down

0 comments on commit 396b686

Please sign in to comment.