# HoTCo:RE

HoTCo:RE is an HTTP(S) reverse proxy that routes requests based on the domain
name.

- Painless install
- Zero configuration
- Out of the box HTTPS

# Problem

You have multiple web apps running on the same machine.

You want to route requests based on the domain name. e.g.:

* `https://a-app.com` → `localhost:8080`
* `https://b-app.com` → `localhost:9000`

DNS entries already set up & point to your server.

Now what? You need a reverse proxy that handles http(s) and routes requests to
the ports your webapps are listening on.

# Getting started

On a Linux server, run the install script:

    curl -fsSL https://judi.systems/hotcore/install.sh | bash

Or install a downloaded release binary with root permissions:

    sudo ./hotcore-linux-amd64-v<version> install

Start mapping domains to ports

    hotcore add <domain> <port>

For the example above:

    hotcore add a-app.com 8080
    hotcore add b-app.com 9000

That's all you need to do!

# Installation process

Here's what the install command does:

- Create a user `hotcore` if it does not exist
- Copy the SSH authorized keys of the user who runs the install to the `hotcore`
  user's home, when that user has an `authorized_keys` file
- Create directory `/opt/hotcore`, if it does not exist, and assign it to user
  `hotcore`
- Install the program binary to `/opt/hotcore/bin`
- Provision capability to listen on port 80 and 443 without root permissions
  using `setcap CAP_NET_BIND_SERVICE=+eip`.
- Unblock ports 80 and 443 from the system firewall. Supported firewalls:
  - `ufw`
  - `firewall-cmd`
- Install a symlink to `/usr/local/bin/`
- Create a system wide SystemD service:
  - Service runs under non-root user `hotcore`
  - Service is started immediately
  - Configured to start on system boot
  - Configured to restart if crashed

The install command is idempotent, and it upgrades an existing installation.

HoTCo:RE is a self-contained binary. It's not a wrapper around some other tool.

# Building from source

HoTCo:RE is implemented in Go.

The release source tarball is vendored, so it builds as-is without downloading
any packages from the internet. A git checkout fetches its module dependencies
normally.

Make sure to pass the `-tags=release` argument.

    go build -tags=release .

For reference, this is the actual full build command we use:

    GOWORK=off GOOS=linux GOARCH=amd64 go build -ldflags "-w -s" -tags=release -o $binpath .

## Local mode

If you build this program without any build tags, it will run in "local dev
mode".

- You still need to run `sudo ./hotcore install` for the local build.
- HTTPS support requires `mkcert`. If it's not detected, it will fall back to
  HTTP.
- No special `hotcore` user is created.

We recommend using domains of the form `app.localhost`, since they work out of
the box, without having to edit the system's `hosts` file.

# Threat Model

HoTCo:RE is assumed to run on a system controlled entirely by one person or
entity.

* Any program on the system can tell HoTCo:RE to map any domain to any port.
  This would be undesirable in a system with multiple users with different or
  competing interests. Linux is designed with that in mind; that's why it has a
  system of users, groups, and permissions.

* You should only run programs that you trust. Even under regular Linux rules,
  any program you run can read off your private ssh keys and upload them to a
  malicious server, for example. Linux security is based on users, not programs.
  Any program you run will run under your username, with all of your
  permissions.

HoTCo:RE's threat model assumes attackers cannot gain access to your server
machine, your VPS account or your DNS account.

If someone gains access to your server, they can "take over" your domain without
needing root permissions. They can run their own reverse proxy that listens on
the mapped port, forwarding requests to their own malicious server.

This is already the case whether you use HoTCo:RE or not.

For example, if nginx is configured to forward requests for `a-app.com` to port
`8080`, an attacker who gains access to your server can simply run a process on
port `8080`. No root privileges are needed to hijack the domain.
