{"id":50513726,"url":"https://github.com/cloudnativeworks/certautopilot-archive","last_synced_at":"2026-06-02T22:01:15.963Z","repository":{"id":351345003,"uuid":"1210390339","full_name":"CloudNativeWorks/certautopilot-archive","owner":"CloudNativeWorks","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-22T09:31:53.000Z","size":29,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-22T11:32:40.259Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CloudNativeWorks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-14T11:19:45.000Z","updated_at":"2026-04-22T09:31:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/CloudNativeWorks/certautopilot-archive","commit_stats":null,"previous_names":["cloudnativeworks/certautopilot-archive"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/CloudNativeWorks/certautopilot-archive","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CloudNativeWorks%2Fcertautopilot-archive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CloudNativeWorks%2Fcertautopilot-archive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CloudNativeWorks%2Fcertautopilot-archive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CloudNativeWorks%2Fcertautopilot-archive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CloudNativeWorks","download_url":"https://codeload.github.com/CloudNativeWorks/certautopilot-archive/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CloudNativeWorks%2Fcertautopilot-archive/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33838221,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-02T22:01:14.108Z","updated_at":"2026-06-02T22:01:15.932Z","avatar_url":"https://github.com/CloudNativeWorks.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# certautopilot-archive\n\nPublic bootstrap shims for the\n[CertAutoPilot](https://github.com/CloudNativeWorks/certautopilot)\nstandalone installer. The main project repo stays private; this tiny\nrepo and the companion public OCI package at\n`ghcr.io/cloudnativeworks/standalone/certautopilot` are the only\nexternal entry points for bare-metal deployment.\n\n## What's here\n\nThree self-contained scripts, each exactly one command to run:\n\n| Script | Purpose |\n|---|---|\n| [`get.sh`](./get.sh) | First-time install. Pulls the pinned tarball from GHCR, verifies sha256, extracts, runs the bundled `install.sh`. |\n| [`update.sh`](./update.sh) | In-place upgrade to a newer pinned version. Atomic binary + frontend swap; config, secrets, KEK, TLS, Mongo data all preserved. |\n| [`uninstall.sh`](./uninstall.sh) | Remove the service (three levels from gentle to full purge). Self-contained — does NOT pull anything from GHCR. |\n\nNo runtime dependencies. No `oras`, no `jq`, no `docker`. Just `curl`,\n`tar`, `awk`, `sha256sum`, and `bash` — all present out of the box on\nevery supported distro (RHEL 9+, Oracle Linux 9+, Rocky 9+,\nAlmaLinux 9+, Debian 12+, Ubuntu 22.04+).\n\n---\n\n## Install — `get.sh`\n\n`--version=\u003cpinned\u003e` is required for every install. There is no\n`latest` auto-resolve — every release pins an explicit version by\ndesign.\n\n\u003e **Security:** `get.sh` needs root (writes `/etc`, creates the service\n\u003e user, installs systemd units). The CertAutoPilot backend then runs\n\u003e as a dedicated non-root system user (`certautopilot`, nologin shell,\n\u003e no home directory) under a hardened systemd unit\n\u003e (`NoNewPrivileges`, `ProtectSystem=strict`, `LimitCORE=0`). Root is\n\u003e never used at runtime.\n\u003e\n\u003e `install.sh` — the script inside the tarball — refuses to run unless\n\u003e invoked via `get.sh` (the sentinel `CAP_INVOKED_FROM_BOOTSTRAP=1` is\n\u003e exported by `get.sh` just before exec). This keeps the pinned-version\n\u003e contract and the SHA256 integrity check as the only supported path.\n\n### Choose a KEK backend before installing\n\nCertAutoPilot envelope-encrypts every field-level secret in MongoDB\n(ACME keys, DNS credentials, module secrets, license blob, …) under a\n**Key Encryption Key**. Pick how the KEK is stored before you run the\nbootstrap — **this choice is immutable** after first install (locked\nin MongoDB via the `kek_install` singleton), so changing it later\nrequires a planned migration.\n\n| | `env` (default) | `pkcs11` |\n|---|---|---|\n| Where is the KEK? | Raw hex bytes in `/etc/certautopilot/secrets.env` (mode 0600). | Inside an HSM token; never leaves the device. |\n| Install prereqs | None beyond the OS. | Vendor PKCS#11 SDK installed and HSM reachable from the host. |\n| Threat model | Root-on-host = full compromise. | Root-on-host alone cannot exfiltrate the KEK. |\n| Backup story | Back up `secrets.env` alongside MongoDB dumps. | HSM-native (vendor clustering / key export to a wrapped blob). |\n| Typical fit | Homelabs, single-VM prod, CI, small multi-VM fleets. | Regulated environments, FIPS 140-2/3 requirements, HSM already in use. |\n\nBelow: one quickstart block per provider. Everything else on this page\n(external MongoDB, multi-VM, TLS, custom ports, upgrade) applies to\neither backend — pick your provider flow here, then layer on flags\nfrom the later sections as needed.\n\n### Quickstart — env provider (default)\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/get.sh \\\n  | sudo bash -s -- --version=1.4.0 --mongo=local\n```\n\nThe bootstrap provisions a local MongoDB with SCRAM auth, generates a\nrandom 32-byte AES-256 KEK plus JWT secret and API-key pepper, writes\n`/etc/certautopilot/secrets.env` (mode 0600), installs nginx with a\n10-year self-signed TLS cert, and starts the service. `--kek-provider`\ndefaults to `env`, so no extra flags are needed for the default path.\n\nUse this backend when you don't have an HSM. Its full threat model\nassumes that root on the host = full compromise — back up\n`secrets.env` to a separate trust boundary so a lost host doesn't lose\nyour data.\n\n### Quickstart — PKCS#11 provider (HSM-backed KEK)\n\nThe HSM's vendor SDK (SoftHSM2 for dev, Thales Luna client, AWS\nCloudHSM client, Fortanix DSM agent, …) must be installed on the host\nseparately — every vendor has its own install procedure. See\n\u003chttps://certautopilot.com/docs/encryption/pkcs11-vendors.html\u003e for\nper-vendor notes. Once the vendor bits are in place, one command\ninstalls CertAutoPilot on top:\n\n```bash\n# Inline PIN (one-liner — PIN visible in /proc/\u003cpid\u003e/cmdline during install\n# only; persists afterward only in /etc/certautopilot/secrets.env mode 0600):\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/get.sh \\\n  | sudo bash -s -- \\\n      --version=1.4.0 --mongo=local \\\n      --kek-provider=pkcs11 \\\n      --pkcs11-module=/usr/lib/softhsm/libsofthsm2.so \\\n      --pkcs11-token-label=certautopilot-prod \\\n      --pkcs11-pin='\u003cHSM_USER_PIN\u003e'\n```\n\n```bash\n# PIN from a mode-0600 file (production-grade — the PIN never appears in\n# argv or shell history):\numask 077\nprintf '%s' \"$HSM_PIN\" \u003e /tmp/cap-pin\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/get.sh \\\n  | sudo bash -s -- \\\n      --version=1.4.0 --mongo=local \\\n      --kek-provider=pkcs11 \\\n      --pkcs11-module=/opt/thales/lib/libCryptoki2_64.so \\\n      --pkcs11-token-label=certautopilot \\\n      --pkcs11-pin-file=/tmp/cap-pin\nshred -u /tmp/cap-pin\n```\n\nBetween MongoDB bootstrap and service start, the installer runs\n`certautopilot kek pkcs11-init --version=1`: it probes HSM\ncapabilities (`CKM_AES_GCM`, key-generation privileges), generates the\ninitial AES-256 v1 key inside the HSM, and writes the immutable\n`kek_install` lock. A probe failure aborts the install before any\npersistent state is committed.\n\nThe PIN is copied once to `/etc/certautopilot/secrets.env` (mode 0600,\nowned by the `certautopilot` service user). Systemd loads it via\n`EnvironmentFile=` on every service start, so reboots and\n`systemctl restart` work without re-supplying the PIN. Treat\n`secrets.env` as a root-level credential and back it up alongside the\nHSM slot metadata.\n\n\u003e **`--pkcs11-module` and `--pkcs11-token-label` are NOT locked** —\n\u003e they can be edited in `/etc/certautopilot/config.yaml` post-install\n\u003e if the new module + token still contain the SAME keys (e.g. a\n\u003e library path change, or mirroring HA to a different token). Run\n\u003e `sudo certautopilot kek verify` after every edit.\n\n### External MongoDB\n\nEither provider can point at an existing MongoDB instead of letting\nthe installer provision one locally:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/get.sh \\\n  | sudo bash -s -- \\\n      --version=1.4.0 \\\n      --mongo=external \\\n      --mongo-uri=\"mongodb://user:pass@db.internal:27017\"\n```\n\nThe full URI is persisted verbatim to `secrets.env` as\n`CERTAUTOPILOT_DATABASE_URI` so multi-host replica sets, `authSource`,\n`tls=true`, and any other query-string options survive the install.\nCredentials MUST be URL-encoded per RFC 3986 — any raw `@`, `:`, `/`,\n`?`, `#`, or `%` in the username or password will break parsing. Add\n`--kek-provider=pkcs11` + the `--pkcs11-*` flags above to combine\nexternal MongoDB with HSM-backed KEKs.\n\n### Multi-VM deployment (2+ hosts, shared external MongoDB)\n\nRunning two or more CertAutoPilot hosts against a single external\nMongoDB is supported, but each host generates its own random KEK /\nJWT / API-key pepper on first install. Every host after the first\nMUST adopt the first host's `/etc/certautopilot/secrets.env` via the\n`--secrets-from=\u003cpath\u003e` flag — otherwise the new host cannot decrypt\nany envelope-encrypted field (ACME private keys, DNS credentials,\nmodule secrets, license API key, …) the other hosts already wrote.\n\n```bash\n# On cap-a (first host):\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/get.sh \\\n  | sudo bash -s -- \\\n      --version=1.4.0 \\\n      --mongo=external \\\n      --mongo-uri=\"mongodb://user:pass@db.internal:27017\"\n\n# Copy secrets.env from cap-a to cap-b (use SSH; treat this file as a\n# root-level credential — whoever holds it can decrypt everything).\nscp cap-a:/etc/certautopilot/secrets.env /tmp/cap-shared.env\nscp /tmp/cap-shared.env cap-b:/tmp/\nshred -u /tmp/cap-shared.env\n\n# On cap-b (and every additional host):\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/get.sh \\\n  | sudo bash -s -- \\\n      --version=1.4.0 \\\n      --mongo=external \\\n      --mongo-uri=\"mongodb://user:pass@db.internal:27017\" \\\n      --secrets-from=/tmp/cap-shared.env\n\nsudo shred -u /tmp/cap-shared.env\n```\n\n\u003e **secrets.env holds the KEK.** Transfer only over SSH, install with\n\u003e mode `0600`, and shred temporary copies immediately. For production\n\u003e consider an ephemeral shared-secret channel (Vault, 1Password shared\n\u003e vault, SealedSecrets export) instead of `scp`.\n\n**Run the initial admin wizard on exactly ONE host.** The backend\nguards setup with a cluster-wide `$setOnInsert` flag, so concurrent\nwizard submissions from two hosts still produce exactly one admin +\none default project — the loser receives\n`400 setup already completed`. Every host beyond the first sees the\nflag already set and redirects `/setup` to the login page.\n\nFull procedure (TLS options, setup wizard, backups, upgrade order,\ntroubleshooting) is documented at\n\u003chttps://certautopilot.com/docs/deployment/multi-vm.html\u003e.\n\n### User-provided TLS\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/get.sh \\\n  | sudo bash -s -- \\\n      --version=1.4.0 \\\n      --mongo=local \\\n      --tls=provided \\\n      --cert=/etc/ssl/certs/cert.example.com.pem \\\n      --key=/etc/ssl/private/cert.example.com.key\n```\n\n### Custom ports\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/get.sh \\\n  | sudo bash -s -- \\\n      --version=1.4.0 \\\n      --mongo=local \\\n      --port=8443 \\\n      --backend-port=18181\n```\n\nEvery flag after `--version=` is forwarded verbatim to the bundled\n`install.sh`. Run `get.sh --help` for the full flag list.\n\n---\n\n## Operator helpers — what `get.sh` / `update.sh` install alongside the backend\n\nEvery install/update drops the backend binary and — when the operator\nopts in — a small backup helper alongside it.\n\n| Path | Purpose |\n|---|---|\n| `/usr/local/bin/certautopilot` | The backend binary (what `certautopilot.service` runs). All KEK lifecycle commands live under `certautopilot kek \u003csubcommand\u003e`. |\n| `/usr/local/bin/certautopilot-backup` | mongodump wrapper the `certautopilot-backup.timer` fires daily. Installed only when the operator passes `--enable-backup` **and** `--mongo=local`. External-mongo deployments own their own backup stack; local-mongo installs without `--enable-backup` stay backup-free so operators with their own cron/restic/Ansible orchestration aren't doubled up. |\n\n`update.sh` refreshes both on every version bump and preserves the\noperator's prior `--enable-backup` choice — if the timer was enabled\nbefore, it stays enabled after upgrade; if it was absent, upgrade\ndoesn't silently install one.\n\n### KEK rotation on a single host\n\n```bash\n# 1. Add the new key material to secrets.env (env provider only) and\n#    restart so the service loads V2 alongside V1.\nprintf '\\nCERTAUTOPILOT_ENCRYPTION_ENV_KEK_V2=%s\\n' \"$(openssl rand -hex 32)\" \\\n  | sudo tee -a /etc/certautopilot/secrets.env \u003e/dev/null\nsudo systemctl restart certautopilot\n\n# 2. Verify every live process has V2 LOADED (not \"already current\" —\n#    the keystore's active row only flips at rotation finalize).\nsudo certautopilot kek verify --target=2\n\n# 3. Rotate. The keystore in MongoDB is authoritative for the active\n#    version; the rewrap explicitly targets V2 so envelopes stay\n#    consistent with their outer kek_version tag regardless of what\n#    any process happens to have as current mid-rotation.\nsudo certautopilot kek rotate --from-version=1 --to-version=2\nsudo certautopilot kek status    # poll until completed\n\n# 4. Wait ~30s — each node's heartbeat tick detects the keystore flip\n#    and hot-reloads V2 as current WITHOUT a restart. `kek status` and\n#    the Settings → KEK versions page show the fleet converging.\n#    (Optional forced-sync: `sudo systemctl restart certautopilot` if\n#    you can't tolerate the heartbeat cadence lag.)\n\n# 5. (After your backup window) retire V1. The command refuses with a\n#    clear error if any live node still reports V1 as its current —\n#    combined with step 4's auto-reload, this is observably safe.\nsudo certautopilot kek remove --version=1\nsudo sed -i '/^CERTAUTOPILOT_ENCRYPTION_ENV_KEK_V1=/d' /etc/certautopilot/secrets.env\nsudo systemctl restart certautopilot   # drops V1 from process memory\n```\n\nFor a multi-VM deployment, loop step 1 over every host before step 2.\nStep 4 is automatic fleet-wide (heartbeat tick polls the shared\nkeystore); no per-host post-rotation restart is required. Full\nprocedure (including PKCS#11 and K8s paths) at\n\u003chttps://certautopilot.com/docs/encryption/kek-rotation.html\u003e.\n\n---\n\n## Upgrade — `update.sh`\n\nIn-place upgrade to a newer pinned version:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/update.sh \\\n  | sudo bash -s -- --version=1.4.0\n```\n\nWhat it does:\n- pulls the new tarball from GHCR\n- verifies the sha256\n- extracts the bundle\n- stops `certautopilot.service`\n- atomically replaces `/usr/local/bin/certautopilot`\n- refreshes `/usr/share/certautopilot/web` (frontend assets)\n- starts `certautopilot.service`\n- probes backend loopback + nginx `/readyz`\n\nEverything else is preserved byte-for-byte:\n- `/etc/certautopilot/secrets.env` (KEK / JWT / pepper / Mongo creds)\n- `/etc/certautopilot/config.yaml`\n- `/etc/certautopilot/tls/`\n- `/etc/certautopilot/mongo-root.env`\n- `/etc/nginx/conf.d/certautopilot.conf`\n- MongoDB data and users\n\n\u003e **`update.sh` is for binary + frontend refresh only.** Topology and\n\u003e config flags — `--mongo`, `--mongo-uri`, `--tls`, `--cert`, `--key`,\n\u003e `--port`, `--bind-host`, `--extra-hostnames`, `--kek-provider`,\n\u003e `--enable-backup`, etc. — are NOT honored here. Rerun `get.sh` with\n\u003e the new flags to change any of them; the bundled `install.sh` is\n\u003e idempotent and re-renders just the parts the new flags affect while\n\u003e preserving every secret on disk.\n\n---\n\n## Uninstall — `uninstall.sh`\n\nThree levels, pick the gentlest one that meets your need.\n\n### Level 1 — Gentle (data preserved, reinstallable)\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/uninstall.sh \\\n  | sudo bash\n```\n\nStops the service and removes the binary, systemd unit, nginx\ndrop-in, logrotate config, and frontend assets. Everything under\n`/etc/certautopilot` (including the KEK) and `/var/lib/certautopilot`\nstays on disk, so a later `get.sh` re-install on the same host picks\nup exactly where this host left off — same KEK, same Mongo users,\nsame TLS cert.\n\n### Level 2 — Purge (data wiped, KEK gone)\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/uninstall.sh \\\n  | sudo bash -s -- --purge --yes-i-mean-it\n```\n\nAdds: wipe `/etc/certautopilot`, `/var/lib/certautopilot`,\n`/var/log/certautopilot`, `/usr/share/certautopilot`, and the\n`certautopilot` service user. **MongoDB data is NOT touched** — the\ndatabase and its users stay in place.\n\n\u003e ⚠️ **This deletes the KEK.** If this host holds ANY envelope-\n\u003e encrypted data in MongoDB (ACME account keys, DNS provider\n\u003e credentials, module secrets, any encrypted field), the `--purge`\n\u003e run makes ALL of it permanently unrecoverable, even if you keep\n\u003e MongoDB. Only use `--purge` when you're sure either (a) there is\n\u003e no encrypted data on this host, or (b) you have restored the KEK\n\u003e from a backup elsewhere.\n\n\u003e **Multi-VM note:** Every host in a multi-VM deployment holds the\n\u003e same KEK in its local `secrets.env`. `--purge` on one host deletes\n\u003e the file only there — the surviving hosts still hold a working\n\u003e copy, so the cluster's encrypted data remains decryptable and new\n\u003e hosts can be bootstrapped with `--secrets-from` pointing at any\n\u003e surviving host's file. But `--purge`'ing EVERY host without first\n\u003e exporting a copy of `secrets.env` elsewhere is equivalent to losing\n\u003e the KEK entirely — there is no recovery path.\n\n### Level 3 — Purge + drop local MongoDB\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/CloudNativeWorks/certautopilot-archive/main/uninstall.sh \\\n  | sudo bash -s -- --purge --purge-db --yes-i-mean-it\n```\n\nAdds: remove the `mongodb-org*` packages, `/var/lib/mongodb`,\n`/etc/mongod.conf`, apt/yum repo files. This is the cleanest possible\nstate for a fresh reinstall on a host that was only used for\nCertAutoPilot. **Removes every database on this host**, not just the\n`certautopilot` one — don't use it on shared MongoDB hosts.\n\n### Non-interactive context\n\nWhen running via `curl | bash`, there is no controlling tty and the\nscript refuses to perform destructive operations without\n`--yes-i-mean-it`. This is intentional — a fat-finger `--purge` on a\nhot-key copy-paste without the confirmation flag is a safe no-op.\n\n---\n\n## Installation topology\n\n```\nInternet\n   │\n   │ :443 HTTPS  (TLS terminated at nginx with a 10-year self-signed cert,\n   ▼                or user-provided cert via --tls=provided)\nnginx (systemd unit, distro package)\n   │\n   │ /api/*, /healthz, /readyz, /metrics     static SPA assets\n   ▼                                         (/usr/share/.../web)\n127.0.0.1:18181  certautopilot (systemd unit, loopback plaintext, hardened)\n   │\n   ▼\nMongoDB 7.0/8.0 (local SCRAM auth, or external URI parsed into fields)\n```\n\n- **HTTPS-only**: the backend has no public port. nginx terminates\n  TLS. The firewall rule only opens the HTTPS port.\n- **MongoDB**: local mode always provisions SCRAM authorization with\n  a random `capRoot` (admin) + a scoped `capApp` user. Root password\n  is saved to `/etc/certautopilot/mongo-root.env` (mode 0600) for\n  disaster recovery. External mode trusts whatever URI you provide.\n- **Hardened systemd unit**: `ProtectSystem=strict`,\n  `NoNewPrivileges`, `MemoryDenyWriteExecute`, narrow\n  `ReadWritePaths`, loopback-only listener.\n\n## Rerun / upgrade safety\n\nThe installer is idempotent. On a rerun with `get.sh`:\n\n- **KEK / JWT secret / API key pepper** — preserved byte-for-byte.\n- **MongoDB `capApp` password** — fast-path skip when auth is already\n  on and `secrets.env` holds working credentials.\n- **`config.yaml`** — preserved. Fresh defaults dropped next to it\n  as `config.yaml.example` for diff + merge.\n- **`/etc/nginx/conf.d/certautopilot.conf`** — preserved unless\n  `nginx -t` says it's broken, in which case it's backed up to\n  `.broken.\u003cts\u003e` and re-rendered from template (self-healing).\n- **TLS cert + key** — preserved if both files already exist.\n\nForce a clean re-render by deleting the relevant file before\nrerunning `get.sh`.\n\n## Troubleshooting\n\n```bash\nsystemctl status certautopilot nginx\njournalctl -u certautopilot -f\njournalctl -u nginx -f\ncurl -k https://127.0.0.1/readyz             # via nginx\ncurl    http://127.0.0.1:18181/readyz        # direct to backend\n```\n\n## License\n\nPublished under the same terms as the main CertAutoPilot repo.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudnativeworks%2Fcertautopilot-archive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudnativeworks%2Fcertautopilot-archive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudnativeworks%2Fcertautopilot-archive/lists"}