{
    "product": "Cenvero Stratum",
    "generated_at": "2026-08-03T07:16:34+00:00",
    "format": "cenvero-docs-v1",
    "document_count": 1,
    "documents": [
        {
            "slug": "installation",
            "title": "Installation and First Configuration",
            "category": null,
            "url": "https://stratum.cenvero.com/docs/installation",
            "headings": [
                {
                    "level": 1,
                    "text": "Installation and First Configuration"
                },
                {
                    "level": 2,
                    "text": "Before you begin"
                },
                {
                    "level": 2,
                    "text": "1. Get a licence key"
                },
                {
                    "level": 2,
                    "text": "2. Check the kernel first"
                },
                {
                    "level": 2,
                    "text": "3. Run the installer"
                },
                {
                    "level": 3,
                    "text": "Unattended install"
                },
                {
                    "level": 2,
                    "text": "4. Know what you just installed"
                },
                {
                    "level": 2,
                    "text": "5. Activate the node"
                },
                {
                    "level": 2,
                    "text": "6. See what is actually running"
                },
                {
                    "level": 2,
                    "text": "7. Understand what is exposed"
                },
                {
                    "level": 2,
                    "text": "8. Turn on the management API — only if you need it"
                },
                {
                    "level": 3,
                    "text": "Generate one on the node"
                },
                {
                    "level": 3,
                    "text": "Supply your own instead"
                },
                {
                    "level": 3,
                    "text": "Check or remove it"
                },
                {
                    "level": 3,
                    "text": "At install time, if you prefer"
                },
                {
                    "level": 3,
                    "text": "Then enable the APIs you want"
                },
                {
                    "level": 2,
                    "text": "9. Get the node its certificate"
                },
                {
                    "level": 2,
                    "text": "10. Configure the node's job"
                },
                {
                    "level": 2,
                    "text": "Verify the install"
                },
                {
                    "level": 2,
                    "text": "Troubleshooting"
                },
                {
                    "level": 2,
                    "text": "Where to go next"
                },
                {
                    "level": 2,
                    "text": "Take this guide with you"
                }
            ],
            "word_count": 2701,
            "markdown": "# Installation and First Configuration\n\nThis is the complete guide: a bare server at the start, a licensed node carrying\nreal traffic at the end. Work through it in order. Nothing here assumes you have\nused Stratum before.\n\nThere are two halves. **Install** (steps 1–5) gets the agent running and\nlicensed. **Configure** (steps 6–10) is the part people skip and then wonder why\nnothing responds — a freshly installed node deliberately starts with almost\neverything switched off.\n\n## Before you begin\n\n| Requirement | Detail |\n|-------------|--------|\n| Operating system | Debian 11+, Ubuntu 22.04+, RHEL 8+, Rocky Linux 8+, or AlmaLinux 8+ |\n| Kernel | 5.8 or newer with kernel type information enabled (`CONFIG_DEBUG_INFO_BTF=y`) |\n| Architecture | x86-64 (amd64) or arm64 |\n| Privileges | `root` — the agent manages interfaces and loads the in-kernel data plane |\n| Network | Outbound HTTPS to your panel |\n| Interfaces | One is enough to start. Two (management + workload) is the recommended layout |\n| Licence | A valid key. The download itself is gated on it |\n\nA stock Debian 12 kernel is **older than this** and will not run the data plane.\nThe installer checks before it changes anything — see step 2.\n\n## 1. Get a licence key\n\nYou cannot download anything without one. The key gates the installer, the\nbinaries, and every later update.\n\nRegister on the site, place an **order** for the plan and node count you want,\nfollow the payment instructions, and submit your transaction reference and\nproof. Payment is verified by a person, and the licence is issued once it is —\nlicences are never handed out automatically. It then appears in your account\nwith its key.\n\nSee [Licensing](/docs/licensing) for the full model, and\n[Your Account](/docs/your-account) for where the key lives.\n\n## 2. Check the kernel first\n\nThe data plane runs inside the kernel, so the kernel has to be new enough. The\ninstaller does not guess: it loads the real data plane as a dry run before\ntouching your system, and stops if that fails.\n\nIf your kernel is too old, it tells you and offers three ways forward:\n\n- **Auto-upgrade** — installs a newer kernel, reboots, and resumes the install by itself.\n- **Show commands and stop** — prints exactly what to run, and changes nothing.\n- **Abort** — nothing is touched.\n\nA piped, non-interactive install never reboots you silently. It stops with the\nmanual instructions unless you explicitly ask otherwise with\n`CENVERO_KERNEL_UPGRADE=auto`.\n\n## 3. Run the installer\n\n```bash\ncurl -sSL -H \"X-License-Key: YOUR_LICENSE_KEY\" \\\n  https://stratum.cenvero.com/install | bash\n```\n\nSubstitute your own key, and your own panel host if you self-host. The key can\nalso travel as `?key=YOUR_LICENSE_KEY` in the URL or as an\n`Authorization: Bearer YOUR_LICENSE_KEY` header — prefer the header, since URLs\nend up in logs.\n\nEvery artifact is verified before it is written to disk: it must match the\nchecksum the panel advertises over TLS, **and** carry a valid publisher\nsignature. An artifact that fails either check is refused. The same verification\nruns on later self-updates.\n\nThe installer prompts for host IP, subnet, gateway, the interfaces to use, and\nthe address pool. It reads those prompts from the terminal directly, so it still\nworks under `curl … | bash`.\n\n### Unattended install\n\nSupply every setting through the environment and it runs with no prompts:\n\n```bash\nCENVERO_LICENSE_KEY=... \\\nCENVERO_HOST_IP=203.0.113.10 \\\nCENVERO_SUBNET=203.0.113.0/24 \\\nCENVERO_GATEWAY=203.0.113.1 \\\nCENVERO_MGMT_NIC=eth0 \\\nCENVERO_VM_NIC=eth1 \\\nCENVERO_POOL_START=203.0.113.100 \\\nCENVERO_POOL_END=203.0.113.200 \\\n  bash install.sh\n```\n\n| Variable | Purpose |\n|----------|---------|\n| `CENVERO_LICENSE_KEY` | Your licence key |\n| `CENVERO_HOST_IP` | This node's management address |\n| `CENVERO_SUBNET` | The management subnet, in CIDR form |\n| `CENVERO_GATEWAY` | Default gateway |\n| `CENVERO_MGMT_NIC` | Interface for management traffic |\n| `CENVERO_VM_NIC` | Interface for workload traffic |\n| `CENVERO_POOL_START` / `CENVERO_POOL_END` | Address range handed out to workloads |\n| `CENVERO_API_TOKEN` | Off unless set. `auto` generates one, or supply your own. Can also be done later — see step 8 |\n| `CENVERO_KERNEL_UPGRADE` | `auto`, `manual`, or `skip` for the kernel check in step 2 |\n| `CENVERO_REINSTALL` | Set to `1` to re-run over an existing install, keeping config and data |\n| `CENVERO_PANEL_URL` | Your panel, if you self-host |\n| `CENVERO_CHANNEL` | Pins this node to one release channel |\n| `CENVERO_API_DOMAIN` | Extra hostname to include on the node's certificate |\n\nThe installer is **idempotent**. It detects a previous install and stops rather\nthan overwriting your configuration and state. Use `CENVERO_REINSTALL=1` when\nyou genuinely mean to re-run.\n\n## 4. Know what you just installed\n\nTwo names look alike and are not the same thing. This trips up nearly everyone\nonce:\n\n| Name | What it is |\n|------|-----------|\n| `cenvero-stratum` | The **service**. This is what `systemctl` acts on |\n| `cenvero-str-ctl` | The **command-line tool**. It talks to the running service |\n\nSo restarting the node is:\n\n```bash\nsystemctl restart cenvero-stratum\n```\n\n`systemctl restart cenvero-str-ctl` fails with \"unit not found\" — that is the\nCLI, not a service. And `cenvero-str-ctl restart` is not a command either: the\nCLI talks *to* the agent, it does not start or stop it.\n\nWhere things live:\n\n| Path | Contents |\n|------|----------|\n| `/etc/cenvero-str/` | Node configuration |\n| `/var/lib/cenvero-str/` | State and local data |\n| `/var/log/cenvero-str/` | Logs |\n| `/run/cenvero-str/` | The local control socket |\n\n## 5. Activate the node\n\nActivation binds the licence to this specific machine and pulls down its signed\nlicence.\n\n```bash\nsudo cenvero-str-ctl license activate CNVR-XXXX-XXXX-XXXX-XXXX\n```\n\nThe key is **positional** — there is no `--key` flag. This raises an activation\nrequest for this machine, which you then **confirm in your account**. Once you\nconfirm, the agent installs the signed licence on its own and begins enforcing\nit.\n\nTo check where it has got to:\n\n```bash\ncenvero-str-ctl license status\ncenvero-str-ctl hardware\n```\n\n`hardware` prints this machine's hardware id, which is what you match against\nthe pending request in the panel when you have several machines activating at\nonce.\n\nIf activation is refused with a **node quota** message, this licence's node\nslots are all in use. Each machine you approve takes one slot; a machine you\nreject or revoke gives its slot back.\n\n---\n\nAt this point the node is installed and licensed. Everything below is\nconfiguration — and a fresh node starts with most services deliberately off, so\nthis half is not optional.\n\n---\n\n## 6. See what is actually running\n\n```bash\ncenvero-str-ctl status\ncenvero-str-ctl service\n```\n\n`service` is the one to read carefully. It looks like this:\n\n```text\nSERVICE        ENABLED  ADDRESS              STATE      NOTE\nREST API       off      203.0.113.10:7070    down       no api_token configured\ngRPC API       off      203.0.113.10:7071    down       no api_token configured\nWebSocket API  off      203.0.113.10:7072    down       no api_token configured\nMetrics        on       127.0.0.1:9090       listening  -\nDNS            on       127.0.0.1:53         listening  -\nDHCP           on       :67                  listening  -\n```\n\nRead it as three independent columns:\n\n- **ENABLED** is your switch — what you asked for. It takes effect at the next restart.\n- **STATE** is a live check of whether something is actually listening right now.\n- **NOTE** explains any gap between the two.\n\nA service can be enabled and still down. That is not a contradiction: it means\nyour switch was recorded but something else is stopping the service from\nstarting, and NOTE tells you what. For the three management APIs, that something\nis almost always a missing API token — see step 8.\n\nThe local control socket is always up and is not a service you can toggle. That\nis why `cenvero-str-ctl` keeps working even with every network API off.\n\nApply an enable/disable change with:\n\n```bash\nsystemctl restart cenvero-stratum\n```\n\n## 7. Understand what is exposed\n\nDefault ports, and who can reach them:\n\n| Port | Service | Bound to | Reachable from |\n|------|---------|----------|----------------|\n| 7070 | REST API | node address | the network — **off until you configure a token** |\n| 7071 | gRPC API | node address | the network — **off until you configure a token** |\n| 7072 | WebSocket API | node address | the network — **off until you configure a token** |\n| 9090 | Metrics | `127.0.0.1` | this machine only |\n| 53 | DNS | `127.0.0.1` | this machine only |\n| 67 | DHCP | all interfaces | the local network |\n\nTwo things worth taking in.\n\nThe three management APIs are **off by design**, not broken. With no API token\nconfigured the agent refuses to open a management API at all, rather than\nopening one with no credential on it. If you never turn them on, you manage the\nnode from the panel and from `cenvero-str-ctl` locally, and nothing is listening\non those ports.\n\nDHCP is the one service bound to every interface, because it has to answer\nbroadcasts from clients that do not have an address yet. On a node with a public\naddress, that means UDP/67 is reachable from outside unless your firewall drops\nit. Worth a rule if the node faces the internet.\n\n## 8. Turn on the management API — only if you need it\n\nYou need this if something other than you at a terminal has to drive the node:\nyour own automation, a script, an orchestrator. If the panel and the CLI are\nenough, skip this step and leave the surface closed.\n\nThe token is **not created for you**, and that is deliberate — a node that minted\nits own API credential would be granting access nobody asked for. You ask for one\nexplicitly, at any time, on a node that is already running. You do not need to\nreinstall anything.\n\n### Generate one on the node\n\nThe usual way. The node mints a strong random token, stores it, and shows it to\nyou:\n\n```bash\nsudo cenvero-str-ctl api-token generate\n```\n\nIt prints the token **once**. Copy it then — it is not displayed again, and\nthere is no command that will show it back to you. If you lose it, generate a\nnew one; that replaces the old, and anything still using the old token starts\ngetting 401 after the next restart.\n\n### Supply your own instead\n\nIf you need a specific value — one your automation already holds, or one from\nyour secret manager — pipe it in. Piping keeps it out of your shell history,\nwhich is why there is no flag to pass it as an argument:\n\n```bash\nprintf '%s' \"$MY_TOKEN\" | sudo cenvero-str-ctl api-token set\n```\n\nAnything under 16 characters is refused. A token short enough to guess is worse\nthan no token at all, because you would believe the API was protected.\n\n### Check or remove it\n\n```bash\ncenvero-str-ctl api-token status   # is one set? (never prints the value)\ncenvero-str-ctl api-token clear    # remove it — the APIs stop at the next restart\n```\n\n`status` deliberately reports only whether a token exists, never what it is.\n\n### At install time, if you prefer\n\n`CENVERO_API_TOKEN=auto` mints one during the install, and\n`CENVERO_API_TOKEN=<value>` sets yours — the same result, before the node first\nstarts. It is entirely optional: generating one later is fully supported and\nchanges nothing else about the node.\n\nWhichever way you set it, the token is kept in your local overrides, so a later\nsync from the panel will not discard it.\n\n### Then enable the APIs you want\n\n```bash\ncenvero-str-ctl service on rest\nsystemctl restart cenvero-stratum\n```\n\nThe API speaks **HTTPS**, never plaintext, so reach it as\n`https://<node>:7070/…`. An `http://` URL will fail even with everything\nconfigured correctly. Your node's certificate is signed by your own account\nauthority, so a browser warns until you trust that root.\n\nThe name comes after `on` — `service on rest`, not `service rest on`. Valid\nnames are `rest`, `grpc`, `websocket`, `metrics`, `dns` and `dhcp`, and `off`\ntakes the same form.\n\nThe API binds only when **all three** hold: a token is configured, the service is\non, and the node has a TLS certificate (step 9 — the agent refuses to serve\nplaintext). If any one is missing, the port stays closed and a browser gets\n\"connection refused\". `cenvero-str-ctl service status` tells you which.\n\nEvery protected endpoint then requires that token as a bearer credential.\n[API Reference](/docs/api) has the details.\n\n## 9. Get the node its certificate\n\nThe node serves its APIs over TLS. Ask the panel to sign a certificate for it:\n\n```bash\nsudo cenvero-str-ctl tls request\n```\n\nYou then **approve the request in your account**, under TLS. Once approved:\n\n```bash\nsudo cenvero-str-ctl tls pull\ncenvero-str-ctl tls info\n```\n\n`tls info` should report `mode: ca-signed` with an expiry. Note the commands\nhere are `tls info` and `tls pending-status` — there is no `tls status`.\n\nRenewal is automatic. See [TLS and Licence](/docs/tls-and-license).\n\n## 10. Configure the node's job\n\nNow give the node something to do. There is no node type to pick — every node\nhosts workloads *and* routes. What it can do is limited only by how many\ninterfaces it has free, which [Nodes and Interfaces](/docs/nodes) explains.\n\n**Define networks and addressing.** Create the networks your workloads sit on\nand the pools they draw addresses from:\n\n```bash\ncenvero-str-ctl network list\ncenvero-str-ctl ipam pools\ncenvero-str-ctl ipam allocations\n```\n\nSee [Networking Overview](/docs/networking/overview).\n\n**Set up DNS and DHCP.** Both are already listening. What they lack is your\nzones, scopes and reservations. See [DHCP and DNS](/docs/networking/dhcp-dns).\n\n**Write firewall rules.** A new node has no rules of its own. See\n[Firewall](/docs/networking/firewall).\n\n**Add a path to the internet.** Source-NAT lets a private tenant subnet reach\nthe internet through one public address. See\n[Gateway and NAT](/docs/networking/gateway-nat).\n\n**Set bandwidth and quotas.** Your plan already caps the node's total speed.\nThese divide it up between tenants. See [Tenants](/docs/tenants).\n\n## Verify the install\n\nRun through this list. Everything should be true before you put real traffic on\nthe node.\n\n| Check | Command | Expected |\n|-------|---------|----------|\n| Service is up | `systemctl status cenvero-stratum` | active (running) |\n| Agent responds | `cenvero-str-ctl status` | reports its state |\n| Licence is live | `cenvero-str-ctl license status` | active, with an expiry |\n| Certificate is signed | `cenvero-str-ctl tls info` | `mode: ca-signed` |\n| Services match intent | `cenvero-str-ctl service` | what you enabled is listening |\n| Node is healthy | `cenvero-str-ctl heal` | all checks pass |\n| Metrics answer | `curl 127.0.0.1:9090/metrics` | a metrics response |\n\n## Troubleshooting\n\n**`systemctl restart cenvero-str-ctl` says unit not found.** The service is\n`cenvero-stratum`. `cenvero-str-ctl` is the CLI.\n\n**`cenvero-str-ctl restart` says unknown command.** The CLI talks to the agent;\nit does not control the service. Use `systemctl restart cenvero-stratum`.\n\n**The REST, gRPC and WebSocket APIs are all `down`.** Expected on a fresh node\nwith no API token. This is fail-closed behaviour, not a fault. Fix it with\n`cenvero-str-ctl api-token generate`, then `service on rest`, then restart.\n\n**The API port refuses the connection** (`ERR_CONNECTION_REFUSED`, or `curl`\nreporting connection refused). Nothing is listening there. Enabling the service\nis only half of it — without a token the server does not start, so the port stays\nclosed. Check `cenvero-str-ctl api-token status` first, then\n`cenvero-str-ctl service status`: the row should read enabled and `listening`.\n\n**`service on rest` said it was enabled, but ENABLED still shows `off`.** Your\nswitch *was* saved — confirm with `cenvero-str-ctl config show`. On builds\nbefore this behaviour was corrected, the ENABLED column also folded in whether\nan API token exists, so a service you had genuinely enabled still displayed as\noff when no token was configured. Set a token (step 8) and the row resolves.\nENABLED now reports only your switch.\n\n**`curl 127.0.0.1:9090` returns 404.** That port serves `/metrics` and nothing\nelse. The bare root is not a page. Use `curl 127.0.0.1:9090/metrics`.\n\n**Activation fails with a node quota message.** Every slot on the licence is\ntaken. Reject or revoke a machine you no longer run and its slot comes back, or\nraise the node count on the licence.\n\n**`tls pull` succeeds but the panel shows nothing to approve.** The node needs\nto be registered before it can raise a request. Check `cenvero-str-ctl license\nstatus` first — if the node never registered, that is the thing to fix, and a\nnode quota message is the usual reason.\n\n**The install stopped over the kernel.** Your kernel is older than the data\nplane needs. Step 2 covers your options.\n\n**Something else.** `cenvero-str-ctl heal` runs the health checks, and the logs\nare in `/var/log/cenvero-str/`.\n\n## Where to go next\n\n- [Quick Start](/docs/quickstart) — define a network and attach a workload\n- [Configuration](/docs/configuration) — the node configuration in full\n- [Nodes and Interfaces](/docs/nodes) — what a node does, and the interfaces it needs\n- [Networking Overview](/docs/networking/overview) — how traffic moves\n- [Clustering Overview](/docs/clustering/overview) — join this node to others\n- [Operations](/docs/operations) — day-to-day running\n- [Upgrades](/docs/upgrades) — keeping the node current\n\n## Take this guide with you\n\nEvery page here is downloadable, so you can keep it alongside your runbooks or\nfeed it to your own tooling:\n\n- **This page** — [installation.json](/docs/installation.json)\n- **The whole documentation set** — [docs.json](/docs.json)\n\nBoth return the Markdown source, so they stay readable offline and are not tied\nto this site. Add `?include=html` to either for the rendered HTML as well.\n"
        }
    ]
}