Centauri is a TLS-terminating reverse-HTTP proxy written in Go.
Centauri is currently in development. There may be breaking changes as it evolves. Individual builds should be usable for production purposes, but you might want to keep another more established proxy around as a backup just in case.
Centauri will obtain TLS certificates from an ACME provider such as Let's Encrypt. It will keep these up to date, and ensure each one has a valid OCSP staple that can be sent to clients.
Centauri runs with sensible defaults for establishing TLS connections, in line with Mozilla's Intermediate recommendations. This balances security with accessibility for older clients.
Centauri's route configuration looks like this:
route www.example.com example.com
upstream server1.internal.example.com:8080
route www.example.net
upstream server1.internal.example.com:8080
You don't need to configure separate front-ends or back-ends, or
deal with proxy_pass
instructions.
Centauri can listen directly on a Tailscale network instead of a public TCP port, removing the need for complex configuration or sidecar containers. Change the "frontend" setting to "tailscale", supply an API key, and Centauri will connect directly to your Tailscale network!
Centauri will also pass details of the Tailscale user making the request to the upstream service, via the following headers:
Tailscale-User-Login
Tailscale-User-Name
Tailscale-User-Profile-Pic
If running in Docker, you will need to persist the directory
at /home/nonroot/.config
or the Tailscale client will lose
its authorisation whenever the container restarts.
Centauri is packaged as a docker container, with the latest
stable version available at ghcr.io/csmith/centauri:latest
.
You can also use specific major, minor or patch versions
such as :0.2.0
or :0.2
. The :dev
tag follows the master
branch.
Some example setups can be found in the examples
directory.
Centauri's behaviour is configured by environment vars. The following options are available:
CONFIG
- path to the route configuration (see below). Default:centauri.conf
.FRONTEND
- the frontend to use to serve requests. Valid options aretcp
andtailscale
. Default:tcp
.CERTIFICATE_STORE
- path to the file to store certificates in. Default:certs.json
WILDCARD_DOMAINS
- space separated list of domains that should use a wildcard certificate instead of listing individual subdomains. See below.CERTIFICATE_PROVIDERS
- a space separated list of certificate providers to try to get a certificate from, in order, if a route does not have an explicitprovider
. Default:lego selfsigned
.OCSP_STAPLING
- whether to request certificates with the "must-staple" extension and then automatically staple OCSP responses to them. If changing this setting you should manually remove Centauri's certificate store to ensure all certificates are regenerated with the new setting. Default:true
.
For the TCP frontend, the following options are used:
HTTP_PORT
- port to listen on for non-TLS connections. These are automatically redirected to https. Default:8080
.HTTPS_PORT
- port to listen on for TLS connections. Default:8443
.
For the Tailscale frontend, the following options are used:
TAILSCALE_HOSTNAME
- the hostname to use on the Tailscale network. Default:centauri
.TAILSCALE_KEY
- the key to use to authenticate to Tailscale.TAILSCALE_MODE
- eitherhttp
to serve all proxy traffic over http, orhttps
to serve proxy traffic over https with a redirect from http to https. Default:http
.
For the lego certificate provider, the following options are used:
USER_DATA
- path to the file to store ACME user data in. Default:user.pem
.DNS_PROVIDER
- the name of the DNS provider to use for ACME DNS-01 challenges. See "ACME DNS Configuration" below.ACME_EMAIL
- the e-mail address to supply to the ACME server when registering.ACME_DIRECTORY
- the URL of the ACME directory to obtain certs from. Default:https://acme-v02.api.letsencrypt.org/directory
In order to support wildcard domains, Centauri uses the DNS-01 challenge
when proving ownership of domains. The DNS_PROVIDER
env var must be set
to one of the providers supported by Lego,
and any credentials required for that provider must be specified in the
relevant environment variables.
For example to configure Centauri to use the
httpreq
provider:
DNS_PROVIDER: httpreq
HTTPREQ_ENDPOINT: https://httpreq.example.com/
HTTPREQ_USERNAME: dade
HTTPREQ_PASSWORD: h4ck_7h3_p14n37
If you put a domain such as example.com
in the WILDCARD_DOMAINS
list,
whenever a route needs a certificate for anything.example.com
Centauri will
instead replace it with *.example.com
.
For example, a route with names example.com
test.example.com
and
admin.example.com
will result in a certificate issued for
example.com *.example.com
. This can be useful if you have a lot of
different subdomains, or you don't want a particular subdomain exposed
in certificate information.
Note that only one level of wildcard is supported: a wildcard certificate
for *.example.com
won't match foo.bar.example.com
, nor will it match
example.com
.
To tell Centauri how it should route requests, you need to supply it with a route configuration file. This has a simple line-by-line format with the following directives:
route
- defines a route with a list of domain names that will be accepted from clientsupstream
- provides the hostname/IP and port of the upstream server the request will be proxied toprovider
- specifies which certificate provider will be used for the routeheader add
- sets a header on all responses to the client, adding it to any issued by upstream.header replace
- sets a header on all responses to the client, replacing any with the same name issued by upstream.header default
- sets a header on all response to the client, only if upstream has not set the same header.header delete
- removes a header from all responses to the client.
Lines that are empty or start with a #
character are ignored, as is
any whitespace at the start or end of lines. It is recommended to indent
each route
for readability, but it is entirely option.
A full route config may look something like this:
route example.com www.example.com
upstream server1:8080
header delete server
header default Strict-Transport-Security max-age=15768000
header add X-Via Centauri
route example.net
upstream server1:8081
header replace Content-Security-Policy default-src 'self';
provider selfsigned
The following certificate providers are supported:
lego
- uses the Lego library to obtain certificates from Let's Encrypt using a DNS-01 challenge (default).selfsigned
- generates a self-signed certificate. This will not be trusted by browsers, but may be useful for certain advanced scenarios.
Routes can specify which provider to use with the provider
directive,
and you can configure the global defaults using the CERTIFICATE_PROVIDERS
environment var.
If you know in advance you will only use a single DNS provider, you can use build tags to include only support
for that provider in the binary. For example to support only the httpreq
provider you can build with
go build -tags lego_httpreq
. See the legotapas project for more
info.
You can also disable Centauri's frontends by specifying the notcp
and notailscale
build tags.
Centauri will automatically set the following headers:
X-Forwarded-For
- to include the IP address of the client making the requestX-Forwarded-proto
- to indicate the protocol of the downstream connection (http/https)Tailscale-User-Login
- username of the Tailscale user making the request, if applicableTailscale-User-Name
- display name of the Tailscale user making the request, if applicableTailscale-User-Profile-Pic
- profile picture of the Tailscale user making the request, if applicable
It will also actively remove any of the following headers sent by clients:
X-Real-IP
True-Client-IP
X-Forwarded-Host
Forwarded
No. Centauri currently performs all routing based on the requested hostname. Additional methods may be added in the future, but Centauri will likely stick to being simple and easy to understand vs becoming a swiss army knife.
Feedback, feature requests, bug reports and pull requests are all welcome!