Metadata-Version: 2.4
Name: edox-ops
Version: 0.1.0
Summary: CLI for preparing and managing documentation hosting on Ubuntu VPS hosts
Author-email: LibESys <ops@libesys.org>
License-Expression: Apache-2.0
Project-URL: Homepage, https://gitlab.com/libesys/esysdox-ops
Project-URL: Repository, https://gitlab.com/libesys/esysdox-ops.git
Project-URL: Documentation, https://esysdox-ops.org/docs/guides/package-release
Project-URL: Release notes, https://gitlab.com/libesys/esysdox-ops/-/releases
Keywords: documentation,hosting,nginx,cli,ubuntu
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typer>=0.12
Requires-Dist: rich>=13.7
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: ruff>=0.8; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=7.4; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
Provides-Extra: release
Requires-Dist: build>=1.2; extra == "release"
Requires-Dist: twine>=5.0; extra == "release"
Dynamic: license-file

# edox-ops

Production-oriented Python CLI for preparing and operating **Ubuntu 24.04 LTS**,
**Debian 12+**, and **Debian derivatives** (including **Raspberry Pi OS**) for
documentation hosting with nginx, rsync deploys, and optional GitLab Runner.

## Requirements

- Python 3.11+
- Target host: **Ubuntu 24.04**, **Debian 12+**, or a **Debian derivative** (e.g.
  Raspberry Pi OS) for `bootstrap`, `doctor`, and project operations

## Install

```bash
pip install edox-ops
```

Pin a version (`pip install edox-ops==0.1.0`), use a venv, and host prerequisites:
[`website/docs/installation.md`](website/docs/installation.md) (published at
[esysdox-ops.org/docs/installation](https://esysdox-ops.org/docs/installation)).

## Development setup

**Automated (contributor venv + hooks + smoke checks):**

```bash
# Linux / macOS
./scripts/setup-dev.sh

# Windows (PowerShell)
.\scripts\setup-dev.ps1
```

Options: `--with-docs` / `-WithDocs`, `--skip-verify` / `-SkipVerify`,
`--recreate-venv` / `-RecreateVenv`, `--install-glab` / `-InstallGlab`, `--no-glab` / `-NoGlab`.
Checks Python 3.11+ up front; can install **glab** after confirmation. See
[Contributing](website/docs/contributing.md).

**Manual:**

```bash
python -m venv .venv
source .venv/bin/activate  # or .venv\Scripts\activate on Windows
pip install -e ".[dev]"
pip install pre-commit
pre-commit install
pre-commit install --hook-type commit-msg
```

To build and publish the `edox-ops` package (sdist/wheel, TestPyPI, PyPI, GitLab PyPI),
install the release extra and follow [`docs/guides/package-release.md`](docs/guides/package-release.md):

```bash
pip install -e ".[dev,release]"
make build
make dist-check
```

## Usage

```bash
edox-ops bootstrap --yes
edox-ops doctor
edox-ops gitlab-runner install --yes   # optional CI executor on the host
export EDOX_RUNNER_TOKEN=TOKEN         # preferred: avoids token in shell history
edox-ops gitlab-runner register --url https://gitlab.example.com
edox-ops project add my-docs --domain docs.example.com
edox-ops project init my-docs
edox-ops project deploy my-docs
edox-ops project enable my-docs
edox-ops project validate my-docs
```

### Deploy backups and restore

Each deploy with existing content creates a timestamped snapshot under
`/var/www/docs/.edox-ops-backups/<slug>/`. List them and roll back the live tree:

```bash
edox-ops project backups list my-docs
edox-ops project restore my-docs --yes
edox-ops project restore my-docs --backup /var/www/docs/.edox-ops-backups/my-docs/20260102T120000Z --yes
```

`restore` overwrites the served directory; `--yes` is required (same contract as
`bootstrap --yes`).

### HTTPS (optional)

Typical flow: enable the site over HTTP, issue a certificate, then switch to TLS.

```bash
edox-ops certs install --yes
edox-ops project add my-docs --domain docs.example.com
edox-ops project init my-docs
edox-ops project deploy my-docs
edox-ops project enable my-docs
edox-ops project certs issue my-docs --email you@example.com --yes
edox-ops project update my-docs --tls
edox-ops project enable my-docs
edox-ops certs setup-auto-renew --yes
```

`setup-auto-renew` installs Certbot, the nginx reload deploy hook, and enables
`certbot.timer` so certificates renew on a schedule without manual steps.

Optional host hardening:

```bash
edox-ops host harden --yes                  # security-updates + firewall + fail2ban
edox-ops host security-updates --yes
edox-ops host firewall --yes              # use --ssh-port if sshd is not on 22
edox-ops host fail2ban --yes              # sshd jail; match --ssh-port to sshd
edox-ops host ssh-harden --yes            # key-based SSH only; test access first
edox-ops host logrotate --yes             # rotate /var/log/edox-ops/*.log
```

To host this repo's documentation build on a VPS (bootstrap, harden, deploy
`website/build/`, TLS), see [`docs/guides/vps-docs-hosting.md`](docs/guides/vps-docs-hosting.md).

`doctor` and `project validate` check that `fullchain.pem` and `privkey.pem` exist
under `/etc/letsencrypt/live/<domain>/` before you enable a TLS site. `certs renew`
reloads nginx after a successful renewal.

## Project documentation

Public documentation uses **Docusaurus** (`website/`) for guides and blog posts, and
**Sphinx** (`docs-api/`) for Python API reference. Built API HTML is embedded under
`/api/` in the Docusaurus output.

```bash
pip install -e ".[docs]"
make docs-api                  # API reference only
make docs-dev-api-sync         # preview /api/ with npm start
make docs                      # full static site → website/build/
cd website && npm install && npm start   # local dev server (Windows nvm4w: C:\nvm4w\nodejs\npm.cmd)
```

See `docs/documentation-architecture.md` and `docs/documentation-build.md`.

**Published docs (GitLab Pages):** [esysdox-ops.org](https://esysdox-ops.org) on pushes to
`master` (when the custom domain is live); [esysdox-ops-d340b4.gitlab.io](https://esysdox-ops-d340b4.gitlab.io)
on every push to `develop` and as the default hostname until then.

See `docs/guides/commit-messages.md` for commit message rules and
`docs/guides/commit-checklist.md` for the pre-commit checklist.

**Contributing:** onboarding (GitLab access, environment, Cursor AI) —
[`website/docs/contributing.md`](website/docs/contributing.md) (published as `/docs/contributing`);
index in [`docs/guides/how-to-contribute.md`](docs/guides/how-to-contribute.md).

**Cursor AI:** project context in [`instructions.md`](instructions.md); rules in
[`.cursor/rules/`](.cursor/rules/).

## Continuous integration

**GitLab (primary):** `.gitlab-ci.yml` runs Ruff, pytest with coverage, and Docker
integration tests. On version tags (`vX.Y.Z`), it also builds Python packages and can
publish to GitLab PyPI, TestPyPI, and PyPI.

- First push and first pipeline: [`docs/guides/gitlab-getting-started.md`](docs/guides/gitlab-getting-started.md)
- SSH keys and canonical remote `git@gitlab-ai:libesys/esysdox-ops.git`: [`docs/guides/gitlab-ssh-keys.md`](docs/guides/gitlab-ssh-keys.md)
- Pipeline, DinD, and runners: [`docs/guides/gitlab-ci.md`](docs/guides/gitlab-ci.md)
- Package build and release: [`docs/guides/package-release.md`](docs/guides/package-release.md)
- Release pipeline (automated tag tests + publish): [`docs/guides/release-pipeline.md`](docs/guides/release-pipeline.md)
- Release hygiene (Dependabot, audits, first tag): [`docs/guides/release-hygiene.md`](docs/guides/release-hygiene.md)
- Agent access to CI results (`glab`, API): [`docs/guides/gitlab-ci-agent-access.md`](docs/guides/gitlab-ci-agent-access.md)

**GitHub (optional):** `.github/workflows/ci.yml` runs the same checks if you mirror
the repository.

Run the same checks locally:

```bash
pip install -e ".[dev]"
ruff check src tests scripts/pre_commit scripts/gitlint_rules.py
ruff format --check src tests scripts/pre_commit scripts/gitlint_rules.py
python -m pytest -q --cov=edox_ops
```

## Integration tests

Docker-based integration tests live under `tests/integration/`. GitLab CI runs a full
harness on **Ubuntu 24.04** and **Debian 12**, plus an **ARM64** smoke job (Debian 12 /
Raspberry Pi proxy on native ARM runners).

```bash
# Ubuntu 24.04 (default)
bash tests/integration/run_docker.sh

# Debian 12
BASE_IMAGE=debian:12 bash tests/integration/run_docker.sh
```

## License

Licensed under the [Apache License, Version 2.0](LICENSE). Copyright 2026 Michel Gillet and contributors.
