# Built-in web server

> API Maker v4 serves HTTPS itself, with nothing in front of it - certificates from Let's Encrypt renewed by API Maker, kernel TLS, a gateway that shares connections over several servers, static sites, reverse proxies and SSR websites - set up from the admin panel, the installer or API Maker Launchpad.

Source: https://docs.apimaker.dev/v4/docs/features/built-in-web-server.html

- API Maker can serve **HTTPS itself**. No Caddy, Nginx or other program stands in front of it.
- A request goes from the socket straight to the code of API Maker. Nothing reads it on the way, nothing copies it.
- It is optional. Caddy or any other reverse proxy in front of API Maker keeps working as before.

## Why it is faster

A reverse proxy in front of API Maker reads every request, opens or reuses a connection to API Maker, and copies the
request and the answer from one connection to the other. The built-in web server does none of that :

- **The connection is decided once.** When a client connects, API Maker looks at the port, the name it asks for (SNI)
  and the protocol (ALPN). A connection for API Maker then goes to the same code as port 38246. Its requests are never
  looked at again.
- **Kernel TLS.** After the TLS handshake, the keys of the connection go to the Linux kernel. The kernel encrypts and
  decrypts with the instructions of the processor (AES-GCM). API Maker reads and writes a plain socket, so HTTPS costs
  almost what plain HTTP costs.
- **Restarts refuse no client.** A restart from the admin panel, or a new version deployed, keeps the listening
  sockets. The clients that connect meanwhile wait a moment and are served.

Measured on one Linode Nanode (1 shared vCPU, 1 GB), with clients on another Nanode :

| In front of API Maker | Requests per second | CPU per request (whole server) | p50 / p99 latency |
|---|---|---|---|
| Built-in web server, HTTPS | 12,047 | 58 µs | 7 / 19 ms |
| Caddy, HTTPS | 3,295 | 292 µs | 28 / 68 ms |
| Nothing, plain HTTP on port 38246 | 18,724 | 44 µs | 5 / 11 ms |

## Turn it on

Pick one way :

- **The installer** : `bash install.sh --proxy=builtin` (with `--ssl=yes` and your domains, or `--ssl=ip`). Learn more
  [Install on a server](https://docs.apimaker.dev/v4/docs/getting-started/install-on-server.html).
- **API Maker Launchpad** : choose **API Maker (built in)** as the reverse proxy of a server that runs API Maker, then
  deploy.
- **The admin panel** : **Settings → Web Server**. Choose how API Maker is reached, check, then click **Save and apply**.
- **By hand** : write `edge.json` in the folder of its settings (below). API Maker applies it within two seconds.

## How API Maker is reached

| Mode | Addresses | Certificates |
|---|---|---|
| **Address of the server** (`ip`) | `http://<address>` admin panel, `:8080` API, `:8081` web sockets | none (plain HTTP) |
| **HTTPS on the address** (`ip` with `httpsOnIp`) | `https://<address>` for everything | for the address itself, 6 days each (the only ones Let's Encrypt issues for an address), renewed by API Maker |
| **Domains** (`domains`) | a domain for the admin panel, one for the API (the web sockets may share it) | one per domain, 90 days each |
| **One domain** (`oneDomain`) | `https://example.com` for everything : the routes of API Maker first, the admin panel for the rest | one, 90 days |

HTTP on port 80 goes to HTTPS (308), except the challenges of the certificate authorities.

## Certificates

- API Maker gets them from **Let's Encrypt**, and from **ZeroSSL** when Let's Encrypt fails twice and an email is set.
- **90 days for a domain**, as with Caddy : API Maker asks Let's Encrypt for its default certificate (profile
  `classic`). **6 days for an IP address** : the longest certificate Let's Encrypt issues for an address (profile
  `shortlived`); ZeroSSL issues none. For a longer one, use a domain or a certificate of your own. Let's Encrypt
  shortens its default to 64 days from 10 February 2027 and 45 days from 16 February 2028 : API Maker follows, nothing
  to change.
- Before it orders a certificate, API Maker checks that the domain points to this server. A domain that does not yet
  waits, and no failed order counts against the limits of the authority.
- They renew by themselves, when the authority says (ARI), else at two thirds of their lifetime : a certificate of 90
  days renews when 30 days are left.
- They are kept in the MongoDB of API Maker, their keys encrypted. **Every server of the installation shares them** :
  one server orders, the others load the certificate.
- **Your own certificates** : paste a PEM chain and its key on the Web Server page, or list the files in `tls.own`.
  Wildcard certificates are fine. API Maker warns 30 days and 7 days before they expire.
- **Coming from Caddy** : the valid certificates of Caddy are taken over (`tls.importCertificates`). No new order, no
  wait. The installer and Launchpad do it for you.
- A certificate that fails to renew, or has less than 7 days left, shows on the Web Server page and in the log. The
  root users get an email when the mail of the installation is set up.

## Kernel TLS

API Maker turns it on where the kernel has the `tls` module (Linux 4.17 and later; Ubuntu 22.04 and 24.04 have it).
The installer and Launchpad load it, now and at every boot. To do it by hand :

```bash
modprobe tls
echo tls > /etc/modules-load.d/api-maker-tls.conf
```

API Maker takes it at the next change of its settings, without a restart. Without it HTTPS still works, with more
processor time : the Web Server page says why it is off.

## Several API Maker servers

The built-in web server of one server can share the **connections** with the other API Maker servers : a gateway.

- Each new connection goes to one server, chosen once : fewest connections, each in turn, same visitor same server,
  active / standby, or at random. Its bytes then go from socket to socket inside the kernel.
- The other servers learn the address of each client from the PROXY protocol (v2) of the gateway. They take it only from
  the addresses listed in `acceptProxyProtocolFrom`.
- Every server is checked every 10 seconds (`/ping`). A server that does not answer gets no new connection.

> **Note**
>
> A gateway that shares connections keeps a connection on its server while it lasts. Clients that keep a connection
> open for long (web sockets, HTTP keep-alive) stay where they are when a server is added.

## Sites

Next to API Maker, the built-in web server serves sites : one file each in `sites/`.

| Type | What it serves |
|---|---|
| `static` | the files of a folder, single page apps too, ranges, ETag, compressed files |
| `proxy` | other programs (`http://127.0.0.1:3000`), with health checks and web sockets; asked over HTTP/1.1 whatever the browser speaks |
| `ssr` | an SSR website of API Maker at the root of a domain or a port |
| `redirect` | every request to another address |
| `routes` | routes of your own : paths to folders, programs, redirects, fixed answers, headers, passwords |

A site has domains (HTTPS) or a port of its own (plain HTTP). It never takes the ports or domains of API Maker.

## The folder of its settings

The setting `edge.folder` names it. Empty, it is `edge` next to the `.env` file (`/root/config/edge` of the installer
and of Launchpad).

```
edge/
  edge.json          how API Maker is reached, TLS, the gateway, the access log
  sites/<slug>.json  one site per file
  edge.status.json   written by API Maker : what runs, its ports, kernel TLS, certificates, errors
  backups/           earlier versions of the files
```

API Maker reads JSON5 (comments are fine). A key it does not know is refused, so a typo never stays silent. A file it
can not apply is not applied : the settings that ran go on, and the status file says why.

New settings apply to new connections. An open connection keeps the settings it started with. A port the new
settings close answers its request in flight, then closes its connections. So does every port when the built-in web
server is turned off.

```json5
{
  "enabled": true,
  "managedBy": "",                 // launchpad, installer, panel, or "" (by hand)
  "apiMaker": {
    "mode": "domains",             // off, ip, domains, oneDomain
    "adminDomain": "admin.example.com",
    "apiDomain": "api.example.com",
    "wsDomain": "api.example.com",
    "gateway": { "servers": ["10.0.0.2:38246"], "thisServer": true, "policy": "least_conn" }
  },
  "tls": { "email": "ops@example.com" }
}
```

Check a folder without changing anything, and read what runs (in words; `--json` prints `edge.status.json` itself) :

```bash
api_maker_be edge check --envPath=/root/config/.env
api_maker_be edge status --envPath=/root/config/.env
```

## Who keeps the settings

`managedBy` says it. The admin panel changes settings that are not Launchpad's. Settings Launchpad keeps show read
only, with a **Take over** button : the panel can then change them, and the next deployment from Launchpad writes its
own again (the panel's are kept in `backups/`).

## Security

- Private keys are encrypted in MongoDB. They never appear in logs, the status file or answers.
- With kernel TLS, the keys of each connection are in the kernel, not in API Maker.
- The admin panel can answer only some addresses (`apiMaker.adminPanel.allowFrom`), checked once per connection.
- A connection of the admin panel or of a site serves its own names. A request for a name another site serves gets
  421, and the browser asks again on a connection of its own (browsers reuse a connection of HTTP/2 when one
  certificate covers both names, a wildcard). API Maker's own connections answer the API on each of its names.
- Static sites never serve a file outside their folder, and hide dotfiles.

## Limits

- HTTP/3 (QUIC) is not served.
- A wildcard domain needs a certificate of your own (no DNS challenge).
- Kernel TLS needs Linux. macOS and Windows serve TLS inside API Maker.
