<!-- MIT License. Copyright (c) 2026 Decentralized Science Labs LLC. -->
<!-- summary: What to prepare before the installer runs: the server, DNS for every name, the firewall, an existing nginx, the main host, the RPC and a funded wallet. -->
# Before you install: server, DNS and names

This page is the checklist to work through before you run `server/install.sh`: the server, the
DNS records of the four names, the firewall, an nginx that already serves other sites, which name
is the main one, the RPC endpoint of the prerender job, and what to have at hand. Most install
problems come from a step here done late, above all DNS.

## The server

- **System.** Debian or Ubuntu, with `apt`. The installer refuses other systems with "This
  installer supports Debian and Ubuntu (apt); this system is …". The admin service needs Python
  3.9 or later, so use Debian 11 or later, or Ubuntu 22.04 or later.
- **systemd.** It must be running: the services are systemd units. (`--no-systemd` exists only for
  testing.)
- **nginx.** The installer installs the distribution's package when nginx is missing, and works
  with an nginx configured from `/etc/nginx/nginx.conf`. Without that file it stops: "There is no
  /etc/nginx/nginx.conf: this installer works with the nginx package of Debian and Ubuntu."
- **Root.** You run the installer with `sudo`.
- **Packages.** The installer adds only what is missing: nginx, certbot, python3, python3-pil
  (Pillow), python3-pycryptodome (only when the system has no keccak-256 otherwise), openssl and
  curl.

What COLLAB itself needs is small. nginx serves static files, the admin service is one Python
process listening on 127.0.0.1, and the prerender job runs every 10 minutes at low priority (nice
10, idle I/O). On disk, a copy of release 2.2.0 takes about 20 MB, and the installer keeps three:
the current release and the two before it. The prerender job's pages and images grow with the
number of DAOs and tokens. The Status tab warns when less than a tenth of the disk is free.

## Ports

| Port | Who uses it | Open to |
|---|---|---|
| 80 (TCP) | Let's Encrypt's validation, then a `301` to HTTPS | the internet |
| 443 (TCP) | the site | the internet |
| 8411 (TCP) | the admin service, on 127.0.0.1 only | nobody: nginx reaches it locally |

No other program may hold ports 80 or 443. The installer checks with `ss` and stops before it
changes anything:

```text
Port 80 is used by another program:
  …
Stop it, then run this again. Nothing was changed.
```

Apache or Caddy on the same server are the usual cause. On a server without nginx, the same check
runs before nginx's package is installed. If port 8411 is taken on 127.0.0.1, pick another one
with `--admin-port N`.

## DNS: point every name first

Create the records before you install. The certificate covers only the names whose DNS points at
the server when the installer runs; a name that does not is left out, with a warning, and gets its
certificate on a later run.

| Name | Records | Role |
|---|---|---|
| `collab.genesisl1.com` | A, and AAAA when the server has IPv6 | the site (the default main host) |
| `dao.genesisl1.com` | A, and AAAA when the server has IPv6 | `301` to the site |
| `collab.descifi.org` | A, and AAAA when the server has IPv6 | `301` to the site |
| `dao.descifi.org` | A, and AAAA when the server has IPv6 | `301` to the site |

Add an AAAA record only when the server has a working public IPv6 address: browsers and Let's
Encrypt use it when it is there.

### Checking with dig

From your computer:

```bash
for n in collab.genesisl1.com dao.genesisl1.com collab.descifi.org dao.descifi.org; do
  echo "$n: $(dig +short A "$n" | tr '\n' ' ')$(dig +short AAAA "$n" | tr '\n' ' ')"
done
```

On the server, `ip -o addr show scope global` lists its own addresses, and
`getent ahosts collab.genesisl1.com` shows what the server itself resolves for a name, which is
what the installer looks at.

### How the installer decides

For each name, the installer looks up its addresses:
- the name passes when one of them is an address of this server;
- behind NAT or a proxy, where the address is not on the server itself, it passes when a request
  for a one-time token through the name, over HTTP, reaches this server. The server sends that
  request itself, so behind NAT the router must send it back in (NAT loopback, or hairpinning);
- otherwise it reports why: "no DNS record (or it does not resolve from here)" or "points at …,
  not at this server".

When the main name does not pass, there is no certificate at all, and port 80 answers with a short
"being set up" notice until there is one.

### Cloudflare

If the names are on Cloudflare, set them to **DNS only** (the grey cloud), at least until the
certificate is issued. [Domains, redirects and certificates](domains.md#behind-cloudflare) says
what to set if you turn the proxy on afterwards.

## The firewall

- **ufw.** When ufw is active, the installer allows `80/tcp` and `443/tcp` itself and says so:
  "ufw: ports 80 and 443 are open".
- **Other firewalls.** nftables or iptables rules, and a cloud provider's firewall or security
  group, are yours to open for TCP 80 and 443. Let's Encrypt must reach port 80 from the internet,
  for the first certificate and for every renewal.
- **Keep closed.** Port 8411 serves only 127.0.0.1; never forward it.
- **Outbound.** The server needs outbound HTTPS to the RPC endpoints and to `api.coingecko.com`
  for the prerender job, and to Let's Encrypt for certbot. `apt` needs the package mirrors, often
  over plain HTTP.

## An nginx that already serves other sites

COLLAB can share an nginx with other sites. The installer adds one file of its own and changes
nothing else:
- `/etc/nginx/sites-available/collab.conf`, linked as `sites-enabled/zz-collab.conf`, so it loads
  after the other sites (or `conf.d/zz-collab.conf` when `nginx.conf` includes no `sites-enabled`);
- it never edits the default site or another site's file, and it marks no server as
  `default_server`.

It checks nginx before it changes anything, and stops without changing anything when:
- nginx's configuration does not pass its own test (`nginx -T`) now;
- another site answers for one of COLLAB's names exactly:

  ```text
  Another site on this nginx answers for a name COLLAB would take:
    dao.genesisl1.com  (/etc/nginx/sites-enabled/example.conf)
  Remove the name there, or leave it out here (--main, --alias, --no-aliases). Nothing was changed.
  ```
- a file at COLLAB's path exists that the installer did not write ("… exists and was not written by
  this installer: move it away (or remove it), then run this again.").

A wildcard or regular-expression name of another site that also covers a COLLAB name (such as
`*.genesisl1.com`) is reported but not refused: nginx prefers an exact name, so that name comes to
COLLAB.

Two settings of the listening sockets are shared by every site on a port, so the installer adapts
to the other sites rather than change them:
- **HTTP/2.** From nginx 1.25.1 it is set per site (`http2 on;`). Before that, COLLAB uses HTTP/2 on
  port 443 only when the other sites there already do; otherwise it says "HTTP/2 stays off".
- **IPv6.** COLLAB listens on `[::]` only when the server has IPv6 and the other sites on that port,
  if there are any, listen on it too.
- **Addresses.** When another site listens on one of the server's own addresses on a port, rather
  than on all of them, COLLAB listens on that address too: nginx gives a request to the sites of the
  most specific address first.

Which site answers a request for a name nobody configured, or for the server's bare IP address,
is described in [Domains, redirects and certificates](domains.md#unknown-names-on-ports-80-and-443).

## Choosing the main host

One name is the site; the others answer `301` to the same path and query on it. Visitors' settings
and wallet connections belong to one origin, so a single main host keeps them in one place.

| Option | Effect |
|---|---|
| (none) | `collab.genesisl1.com` is the site; `dao.genesisl1.com`, `collab.descifi.org` and `dao.descifi.org` redirect to it |
| `--main HOST` | another main host, for example `--main dao.genesisl1.com` |
| `--alias HOST` | a name that redirects to the main host; repeat it for each name, the list replaces the default one |
| `--no-aliases` | no other names |

On a first install, `--main dao.genesisl1.com` alone makes the other three of the four names its
aliases. The installer remembers the main host and the aliases; later runs keep them unless you
name them again. Changing the main host after the install is explained in
[Domains, redirects and certificates](domains.md#changing-the-main-host).

## The RPC endpoint of the prerender job

`--rpc URL` names the GenesisL1 JSON-RPC endpoint the prerender job reads, for example a node of
your own. Without it, the job tries the site's own endpoints in order and uses the first that
answers for chain 29: those of the site settings, else the GenesisL1 RPC
(`https://rpc.genesisl1.org`) and the GL1X JSON-RPC (`https://gl1x.com/api/eth-rpc`).
`--rpc ""` goes back to them.

The URL must be https, or http only for `localhost` and `127.0.0.1`, with a plain host name. The
installer refuses anything else: "--rpc takes the https URL of a GenesisL1 JSON-RPC endpoint".
This option changes only the prerender job; visitors read the chain through the endpoints in
[Site settings](site-settings.md#rpc-endpoints).

## What to have ready

- **SSH access** with sudo, and the release archive with its `.sha256` file.
- **An email address** for the Let's Encrypt account (`--email`). It is optional.
- **A browser wallet with L1 on GenesisL1** for the deployment: MetaMask, Rabby, or Keplr in EVM
  mode. The 20 creations used 42,953,788 gas in the release rehearsal, about 2.15 L1 at a 50 gwei
  gas price; the Deploy tab shows the exact estimate at the current price before you start. See
  [Deploy the protocol from /admin](deploy-from-admin.md#how-much-l1-you-need).
- **Optional.** A Google Analytics 4 measurement ID, and the links of your website and accounts,
  for the [site settings](site-settings.md).

## Related

- [Installing COLLAB on a server](INSTALL.md)
- [Domains, redirects and certificates](domains.md)
- [Running a COLLAB site](operators.md)
- [Troubleshooting](troubleshooting.md)
