diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 000000000..2ee4a6887 --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,95 @@ +# Deploying Specref + +Specref is made of two independently deployed parts, both served under the +`specref.org` domain: + +| Hostname | What it serves | Hosted on | +| ------------------------------------------ | ------------------------------------------- | ----------------------------------------------- | +| `https://www.specref.org` (+ `specref.org`) | The static website (search UI) in [`docs/`](./docs/) | [GitHub Pages](https://pages.github.com/) | +| `https://api.specref.org` | The JSON API ([`index.js`](./index.js)) | [Clever Cloud](https://www.clever-cloud.com/) | + +Both deploy automatically from the `main` branch of +[specinfra/specref](https://github.com/specinfra/specref), which is also what +the [hourly auto-update](./CONTRIBUTING.md#hourly-auto-updating) pushes to. +There is no manual deployment step. + +## Table of Contents + +* [API (Clever Cloud)](#api-clever-cloud) + * [Health check](#health-check) +* [Website (GitHub Pages)](#website-github-pages) +* [DNS for specref.org](#dns-for-specreforg) + +## API (Clever Cloud) + +The API is a Node.js application (see the `engines` field in +[`package.json`](./package.json) for the required versions) hosted on +[Clever Cloud](https://www.clever-cloud.com/). It is started with `npm start` +(i.e. `node index.js`) and listens on the port given by the `PORT` +environment variable, which Clever Cloud sets automatically. + +The application is linked to the GitHub repository, so every push to `main` +triggers a new build and deployment. Once the new instance answers the +[health check](#health-check), traffic is switched over to it. + +[CORS is enabled for all origins](./README.md#cors) so that anyone can use +the API directly as JSON from a browser, whatever the origin of their page. +The API is not restricted to the Specref website in any way. + +### Health check + +The server exposes a lightweight health check endpoint at `/health` which +always responds with `200 OK` and `{ "status": "ok" }`, without touching the +reference database. + +Clever Cloud must be configured to poll this endpoint (rather than `/`, which +returns a 404) so that it can tell whether the instance is up during +deployment and while it is running, and only restarts it when it actually +stops responding. Set the following environment variable on the Clever Cloud +application: + + CC_HEALTH_CHECK_PATH=/health + +## Website (GitHub Pages) + +The website at [www.specref.org](https://www.specref.org/) is a static site +whose source lives in the [`docs/`](./docs/) directory. It is published by +[GitHub Pages](https://docs.github.com/en/pages) from the `main` branch. + +Repository settings (_Settings → Pages_): + +* **Source:** _Deploy from a branch_ +* **Branch:** `main`, folder `/docs` +* **Custom domain:** `www.specref.org` (this must match the content of + [`docs/CNAME`](./docs/CNAME), which GitHub Pages reads at build time; do not + delete or edit that file unless you are changing the domain) +* **Enforce HTTPS:** enabled + +The site is rendered by Jekyll. [`docs/_config.yml`](./docs/_config.yml) only +exists to make Jekyll include the `.well-known/` directory, which it would +otherwise skip because of the leading dot. + +The website is a plain client of the API: it fetches JSON from +`https://api.specref.org` from the browser like any other consumer would. + +## DNS for specref.org + +The `specref.org` domain is registered and its DNS zone hosted at +[Namecheap](https://www.namecheap.com/), on an account owned by Tobie Langel. + +The zone points at both hosting providers: + +* the apex `specref.org` and `www.specref.org` point at **GitHub Pages**. + `www.specref.org` is the canonical hostname (it is the custom domain + configured in the repository settings and in `docs/CNAME`); because the + apex also resolves to GitHub Pages, GitHub automatically redirects + `https://specref.org/…` to `https://www.specref.org/…`. +* `api.specref.org` points at **Clever Cloud**. The hostname must also be + added to the application's _Domain names_ in the Clever Cloud console, + otherwise Clever Cloud's load balancers will not route requests for it to + the application. Clever Cloud provisions and renews the TLS certificate + automatically once the record resolves. + +Each provider only ever sees the hostname it is responsible for, so moving +one part (e.g. the API to a different host) only requires changing that +hostname's record at Namecheap. diff --git a/README.md b/README.md index d96a6f9c4..a9005c430 100644 --- a/README.md +++ b/README.md @@ -224,11 +224,7 @@ If you need to find a reference ID (for either bibliographic or cross-references ## Deployment -The API is hosted on [Clever Cloud](https://www.clever-cloud.com/). The server exposes a lightweight health check endpoint at `/health` which always responds with `200 OK` and `{ "status": "ok" }`, without touching the reference database. - -Clever Cloud must be configured to poll this endpoint (rather than `/`, which returns a 404) so that it can tell whether the instance is up during deployment and while it is running, and only restarts it when it actually stops responding. Set the following environment variable on the Clever Cloud application: - - CC_HEALTH_CHECK_PATH=/health +The website (www.specref.org) is hosted on GitHub Pages and the API (api.specref.org) on Clever Cloud. See [DEPLOYMENT.md](./DEPLOYMENT.md) for how both are deployed and how the `specref.org` DNS is set up. ## Contributing diff --git a/docs/README.md b/docs/README.md index f8e251dbc..67303f740 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ www.specref.org =============== -Source code for the static website hosted on www.specref.org. +Source code for the static website hosted on www.specref.org (published with GitHub Pages, see [DEPLOYMENT.md](../DEPLOYMENT.md)). diff --git a/index.js b/index.js index f62fc3410..df354d410 100644 --- a/index.js +++ b/index.js @@ -15,7 +15,7 @@ app.enable("etag"); // Health check. Registered before the IP filter, compression and body // parsing middleware so that it stays cheap and can never be blocked or // slowed down by them. Clever Cloud polls this path (see -// CC_HEALTH_CHECK_PATH in the README) both during deployment and while +// CC_HEALTH_CHECK_PATH in DEPLOYMENT.md) both during deployment and while // the app is running, and restarts the instance if it fails to respond // with a 2xx status code. app.get('/health', function (req, res) {