Vicarian
Vicarian is a TLS-only (sort-of; see features below) reverse proxy server with built-in ACME support. It is currently targeted at self-hosting and SOHO installations; in particular it supports provisioning TLS certificates behind-the-firewall via ACME DNS-01 and the zone-update library.
Vicarian aims to have sensible defaults without additional configuration.
Project Status
This software should be consider pre-alpha; the feature-set is MVP and is still in active development. It should not be considered production-ready and no warranty is expressed or implied. It is very-much a work-in-progress and virtually every part of it subject to change without notice.
Only Linux is currently supported (x86_64 and Arm64). Testing for other platforms is welcome.
Features
Current features
- TLS-only: More accurately 'TLS-first'. Port-80/HTTP can be enabled, but will always redirect to the configured TLS server. The exception to this is when the HTTP-01 ACME is enabled; Vicarian will serve the challenge responses in this case.
- Native ACME Support: Vicarian has first-class support for
ACME/LetsEncrypt, including DNS-01. LetEncrypt certificate
profiles are supported;
tlsserveris the default. - Multiple DNS-01 Providers: Multiple DNS providers are supported for DNS-01 via the zone-update sibling-project. See that project for a list of supported providers. (Contributions of provider support are very welcome.)
- Dynamic Certificate Loading: Where TLS certificates are maintained externally Vicarian will dynamically reload certificates when they are updated.
- Simple backend routing: Traffic can be routed to multiple backend services based on URL paths.
- Basic path rewriting: This may work with some simple apps that don't support contexts natively, but is likely to fail with more complex apps that have hardcoded paths.
- Virtual hosts: Hosting of multiple domains and domain aliases is supported, along with certificate generation for host aliases.
- Separated secrets: ACME DNS requires DNS-provider secrets to be configured. These can be placed in a separate secure file using systemd EnvironmentFile and corn environment injection (see vicarian-dns01.corn for an example).
To-dos
-
Access & error logs
-
Happy Eyeballs support
-
Static file support. Pingora itself doesn't support static-files. There are 3rd-party crates that support this but they appear unmaintained at the moment and will need to be evaluated. If you wish to serve a static website one workaround is to use
static-web-serverto create a static backend:static-web-server \ --host 127.0.0.1 --port 8080 \ --security-headers true \ --log-level info \ --root .This is how vicarian.org and haltcondition.net are served currently.
-
Docker images.
Possible Future Features
The following may be implemented at some point depending on interest and resources.
- TLS-ALPN-01 ACME support.
- Other ACME providers (e.g. ZeroSSL)
- Prometheus stats.
- Basic 12-factor configuration-style configuration. This should be relatively easy due to corn's support for environment injection; however there is a known issue limiting this currently.
Probably-not features
Vicarian is very opinionated and tries to do the sensible thing by
default. Ideally if a particular header or setting was usually required by, say,
nginx then it should be the default. e.g. X-Forwarded-For and
HSTS
are always set. Consequently there are no plans to add a large number of
features and settings.
Other notable non-features:
- Wildcard ACME certs; these are better generated externally and distributed to multiple servers.
- Load-balancing, round-robin, complex rewrite rules, etc.
- Advanced connection tuning
Installation
Release Binaries
Tarballs are available on the Github release page. These contain binaries, documentation, example configuration files, and an example systemd configuration:
├── bin
│ └── vicarian
├── CONFIGURATION.md
├── etc
│ ├── systemd
│ │ └── system
│ │ └── vicarian.service
│ └── vicarian
│ ├── examples
│ │ ├── vicarian-dns01.corn
│ │ ├── vicarian-http01.corn
│ │ └── vicarian-tls-files.corn
│ ├── secrets
│ └── vicarian.corn
├── LICENSE
└── README.md
Install from crates.io
The binary will be available at
~/.crates/bin/vicarian. cargo-binstall
is also supported.
Running
Systemd Service
An example systemd service in provided in systemd/vicarian.service. The
systemd service sets the CAP_NET_BIND_SERVICE flag which allows binding to
ports 80/443 without root.
Configuration
Vicarian currently uses the corn configuration
language. The default configuration file is located at
/etc/vicarian/vicarian.corn, but can be changed with the --config flag.
Basic Configuration Structure
The full configuration structure is documented in
CONFIGURATION.md, and additional examples are available in
the examples directory, but a basic working configuration with HTTP-based
Let's Encrypt TLS would look like:
{
listen = {
addr = "[::]" // Default; this covers IPv4 & IPv6
insecure_port = 80 // Disabled by default, this will redirect to HTTPS
tls_port = 443 // Default
}
vhosts = [
{
hostname = "example.com"
tls = {
acme = {
contact = "admin@example.com"
challenge.type = "http-01"
}
}
backends = [
{
context = "/"
url = "http://localhost:8080"
}
{
context = "/app2"
url = "https://localhost:8443"
trust = true
}
]
}
]
}
Contributing
Contributions, bug reports, fixes, etc. are welcome.
Additionally, a useful contributions would be to add additional DNS provider APIs to the zone-update project.
Code of Conduct
The project follows the Rust Code of Conduct; this can be found online.
Tech stack
As well as the usual dependencies Vicarian also uses:
- Pingora for HTTP/TLS proxying.
- instant-acme for ACME/LetEncrypt support.
- path-tree for routing.
- corn for configuration.
AI Contribution Policy
LLM and related 'AI' technologies can be useful for software development, but best-practices on their usage are still evolving. For this reason this project will not accept runtime code generated by AI. Generation of draft documentation and test code is acceptable, but should be reviewed by the submitter before raising a PR.
Security Notes
- Vicarian binds to ports 80 and 443 by default, requiring appropriate permissions
- The systemd service uses
CAP_NET_BIND_SERVICEto bind to privileged ports without full root privileges - Private keys are stored in PEM format and should be properly secured
- When using ACME with DNS-01 challenges, ensure DNS provider API credentials are stored securely
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.