# https://github.com/mherrmann/djevops 项目说明书

生成时间：2026-06-21 21:49:36 UTC

## 目录

- [项目概述与快速入门](#page-1)
- [配置文件 djevops.yml 与密钥管理](#page-2)
- [部署架构与组件系统](#page-3)
- [核心功能与运维指南](#page-4)

<a id='page-1'></a>

## 项目概述与快速入门

### 相关页面

相关主题：[配置文件 djevops.yml 与密钥管理](#page-2)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/mherrmann/djevops/blob/main/README.md)
- [djevops/__main__.py](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)
- [djevops/__init__.py](https://github.com/mherrmann/djevops/blob/main/djevops/__init__.py)
- [djevops/check_django_settings.py](https://github.com/mherrmann/djevops/blob/main/djevops/check_django_settings.py)
- [djevops/remote/scaffold.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/scaffold.py)
- [djevops/remote/deploy.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/deploy.py)
- [djevops/remote/component_registry.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/component_registry.py)
- [djevops/remote/actions.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/actions.py)
- [djevops/util.py](https://github.com/mherrmann/djevops/blob/main/djevops/util.py)
</details>

# 项目概述与快速入门

## 一、项目定位与核心价值

djevops 是一款面向 Django 应用的命令行部署工具，旨在帮助开发者将 Django Web 应用一键部署到运行 Ubuntu 或 Debian 的 Linux VPS（虚拟专用服务器）上。它不依赖 Docker，而是直接在服务器上以原生进程的方式管理数据库、Redis、Nginx、Postfix 等组件，从而显著缩短"推送上线"的时间。

根据 README.md 的描述，djevops 的核心价值体现在以下几点：

- **非容器化部署**：避免 Docker 引入的额外抽象层与性能开销，实现秒级上线 [README.md:1-10](https://github.com/mherrmann/djevops/blob/main/README.md)。
- **Ansible 的精简替代品**：djevops 专注于 Django 场景，相比通用配置管理工具，所需的配置代码量显著更少 [README.md:9-11](https://github.com/mherrmann/djevops/blob/main/README.md)。
- **安全默认值**：每个服务以独立用户运行，进程间环境变量不会泄漏；默认不开放非预期端口，例如 Postfix 场景下会自动屏蔽 25 端口的外部访问 [README.md](https://github.com/mherrmann/djevops/blob/main/README.md)。
- **自动运维**：内置操作系统自动更新、日志轮转压缩、数据库持续备份（基于 Litestream）等能力 [README.md](https://github.com/mherrmann/djevops/blob/main/README.md)。

## 二、整体架构概览

djevops 在客户端与服务器端协同工作：客户端负责生成配置与传输文件，服务器端通过"组件注册表"按需安装与卸载底层依赖。

```mermaid
flowchart LR
    A[本地开发机<br/>执行 djevops CLI] -->|rsync djevops.yml<br/>+ secrets.json| B[远程服务器<br/>root@VPS]
    A -->|SSH| B
    B --> C[ComponentRegistry<br/>组件注册表]
    C --> D[AptPackage<br/>系统包]
    C --> E[ServiceUser<br/>服务用户]
    C --> F[NginxSite<br/>反向代理]
    C --> G[VirtualEnvironment<br/>Python venv]
    C --> H[Litestream / Postfix<br/>数据库与邮件]
    C --> I[TemplatedFile / Crontab<br/>配置与定时任务]
    G --> J[/srv/app<br/>Django 应用]
    J --> K[Gunicorn<br/>WSGI 服务]
```

如架构图所示，djevops 客户端通过 SSH 将 `djevops.yml`（部署配置）和 `secrets.json`（密钥字典）上传到服务器的 `/root/.djevops/` 状态目录，再调用服务器端的 `python -m djevops.remote.deploy` 触发安装流程 [djevops/__main__.py:142-162](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)。服务器端的 `ComponentRegistry` 会记录每个组件的安装参数，确保重复部署时跳过已安装项，必要时卸载不再被声明的组件 [djevops/remote/component_registry.py:6-19](https://github.com/mherrmann/djevops/blob/main/djevops/remote/component_registry.py)。

## 三、快速入门步骤

### 3.1 环境准备

- 在本地开发机通过 `pip install djevops` 安装 CLI。
- 准备一台拥有 SSH root 权限的 Linux VPS，操作系统要求为 Ubuntu 或 Debian [README.md:12-18](https://github.com/mherrmann/djevops/blob/main/README.md)。
- 在 Django 项目根目录初始化 Git 仓库并添加远程仓库，否则 `djevops init` 会报错 [djevops/__main__.py:67-72](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)。

### 3.2 初始化项目（init）

在 Django 仓库根目录执行 `djevops init`，CLI 会自动：

1. 校验 `.git` 目录与 `manage.py` 是否存在 [djevops/__main__.py:67-79](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)。
2. 通过 `_get_declared_dependencies()` 函数读取依赖列表。**最新版本同时支持 `pyproject.toml` 的 `[project.dependencies]` 与 `requirements.txt` 两种声明方式**，这是社区近期关注的重要改进 [djevops/__main__.py:108-126](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)。
3. 校验依赖中必须包含 `django` 与 `gunicorn` [djevops/__main__.py:79-83](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)。
4. 自动从 Git 远程地址解析服务器地址与分支，写入 `deploy/djevops.yml` [djevops/__main__.py:84-104](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)。
5. 生成 `deploy/secrets.py` 模板，便于集中管理敏感信息 [djevops/__main__.py:106-110](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)。

### 3.3 配置与密钥

生成的 `deploy/djevops.yml` 是声明式配置文件，支持 `server`、`git`、`services`、`db`、`mail`、`redis` 等顶层节点；密钥则统一写入 `deploy/secrets.py`，通过本地求值后上传为 JSON 常量，从而避免直接提交到 Git [djevops/__main__.py:24-43](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)。常见做法是在 `secrets.py` 中通过 `os.environ['MY_SECRET']` 读取本地环境变量。

### 3.4 部署（deploy）与远程命令

执行 `djevops deploy` 时，CLI 会调用 [`deploy()` 函数](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)：先用 `check_config()` 进行本地校验，再通过 SSH 在服务器上安装 djevops 自身，然后 rsync 推送配置文件并最终调用 `python -u -m djevops.remote.deploy` [djevops/__main__.py:142-162](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)。

此外，CLI 还提供以下常用子命令：

| 命令 | 功能说明 | 源码引用 |
| --- | --- | --- |
| `djevops init` | 在仓库根目录生成部署配置与密钥模板 | [djevops/__main__.py:67-110](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py) |
| `djevops deploy` | 上传配置并触发远程安装流程 | [djevops/__main__.py:142-162](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py) |
| `djevops getbackup` | 从远程服务器下载数据库备份 | [djevops/__main__.py:163](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py) |
| `djevops shell` | 进入服务器端的 Django 管理 shell | [djevops/__main__.py:164](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py) |

## 四、常见前置检查与故障提示

djevops 会在多个阶段进行"失败即终止"的校验，错误信息会附带 `GIT_HINT` 提示，提醒开发者提交并推送变更 [djevops/__init__.py:1](https://github.com/mherrmann/djevops/blob/main/djevops/__init__.py)。常见的检查包括：

- `settings.ALLOWED_HOSTS` 必须包含域名或 IP，且格式受支持，否则会被 `check_django_settings.py` 拒绝 [djevops/check_django_settings.py:6-16](https://github.com/mherrmann/djevops/blob/main/djevops/check_django_settings.py)。
- SQLite 模式下，`settings.DATABASES['default']['NAME']` 必须等于环境变量 `SQLITE_DB_FILE` 的值 [djevops/check_django_settings.py:36-43](https://github.com/mherrmann/djevops/blob/main/djevops/check_django_settings.py)。
- PostgreSQL 模式下，数据库引擎必须是 `django.db.backends.postgresql` [djevops/check_django_settings.py:23-30](https://github.com/mherrmann/djevops/blob/main/djevops/check_django_settings.py)。
- 远程部署时，本地与服务器端通过 `SshKey` 组件注册 SSH 密钥，并通过 `KnownHostsEntry` 预置 Git 主机的指纹，避免首次拉取时的交互确认 [djevops/remote/deploy.py:36-44](https://github.com/mherrmann/djevops/blob/main/djevops/remote/deploy.py)。

服务器侧的运行时支持也较为完善，例如 `actions.py` 暴露了 `migrate_db`、`collect_static_files`、`get_django_setting` 等便捷操作，可在远程 deploy 流程中调用 `manage.py` 子命令 [djevops/remote/actions.py:1-20](https://github.com/mherrmann/djevops/blob/main/djevops/remote/actions.py)；`util.py` 则提供 SSH、apt-get、域名校验等通用工具 [djevops/util.py](https://github.com/mherrmann/djevops/blob/main/djevops/util.py)。

## 五、See Also

- [数据库与备份配置（基于 Litestream 与 PostgreSQL）](https://github.com/mherrmann/djevops/wiki)
- [服务与组件管理：Celery、Redis、Nginx](https://github.com/mherrmann/djevops/wiki)
- [密钥管理与 `secrets.py` 最佳实践](https://github.com/mherrmann/djevops/wiki)

---

<a id='page-2'></a>

## 配置文件 djevops.yml 与密钥管理

### 相关页面

相关主题：[部署架构与组件系统](#page-3), [核心功能与运维指南](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [djevops/__main__.py](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)
- [djevops/__init__.py](https://github.com/mherrmann/djevops/blob/main/djevops/__init__.py)
- [djevops/remote/scaffold.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/scaffold.py)
- [djevops/remote/component_registry.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/component_registry.py)
- [djevops/litestream.py](https://github.com/mherrmann/djevops/blob/main/djevops/litestream.py)
- [djevops/util.py](https://github.com/mherrmann/djevops/blob/main/djevops/util.py)
- [djevops/check_django_settings.py](https://github.com/mherrmann/djevops/blob/main/djevops/check_django_settings.py)
- [README.md](https://github.com/mherrmann/djevops/blob/main/README.md)
</details>

# 配置文件 djevops.yml 与密钥管理

## 概述

djevops 是一个面向 Django 应用的部署命令行工具，它通过一份声明式 YAML 配置文件 `deploy/djevops.yml` 来描述目标服务器、Git 仓库、服务、数据库、邮件与 Redis 等组件，并配合一份 Python 形式的密钥文件 `deploy/secrets.py` 提供敏感数据。配置信息会在本地被解析后上传到服务器的 `/root/.djevops/` 目录下，分别保存为 `deploy.yml`、`secrets.json` 和 `components.json`，供部署与运行时使用（[README.md](https://github.com/mherrmann/djevops/blob/main/README.md)、[djevops/remote/scaffold.py:5-19](https://github.com/mherrmann/djevops/blob/main/djevops/remote/scaffold.py#L5-L19)）。

社区中最常被讨论的需求是「依赖从哪里声明」与「密钥如何安全传入」。最新版本已支持 `requirements.txt`，用户既可以使用现代的 `pyproject.toml`，也可以沿用传统的 `requirements.txt`（[djevops/__main__.py:_get_declared_dependencies](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)）。

## djevops.yml 的结构

`djevops init` 命令会基于当前 Git 仓库与远端地址生成一份最小可用的配置样例。生成的 `deploy/djevops.yml` 形如：

```yaml
server: 0.0.0.0
git:
  repo: githubuser/mydjangoapp
  branch: main
services:
  web:
    type: django
```

该样例由 `init()` 中的 `deploy_yml` 字典组装得到，其中 `server` 默认使用 `SAMPLE_SERVER_IP = '0.0.0.0'`（[djevops/__main__.py:SAMPLE_SERVER_IP](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)）。下面是顶层配置项的速查：

| 顶层键 | 是否必填 | 说明 |
| --- | --- | --- |
| `server` | 必填 | 目标 VPS 的 IP 或主机名，由 init 写入默认值 |
| `git` | 必填 | `repo`、`branch` 以及非 GitHub 时的 `server` 字段 |
| `services` | 必填 | 至少需要一个 `type: django` 服务，可选 `celery` |
| `db` | 可选 | `type` 仅接受 `sqlite` 或 `postgres`，可附带 `backup` 子段 |
| `mail` | 可选 | SMTP 发信配置，决定 Postfix 与错误邮件功能 |
| `redis` | 可选 | 出现即安装 Redis，常配合 Celery 使用 |

若缺少 `services.web`，CLI 会以 `CommandError` 提示用户添加至少一个 `django` 类型服务（[djevops/__main__.py:init/deploy](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)）。`db.type` 必须在 `sqlite` 与 `postgres` 之间二选一，否则同样抛出错误（[djevops/__main__.py](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)）。

## 初始化流程

下图展示了 `djevops init` 在本地生成配置和密钥文件的关键流程：

```mermaid
flowchart TD
    A[执行 djevops init] --> B{存在 .git?}
    B -- 否 --> X1[报错: 非 Git 仓库]
    B -- 是 --> C{存在 Git remote?}
    C -- 否 --> X2[报错: 缺少 remote]
    C -- 是 --> D{存在 manage.py?}
    D -- 否 --> X3[报错: 缺少 manage.py]
    D -- 是 --> E[读取 pyproject.toml 或 requirements.txt]
    E --> F[写入 deploy/djevops.yml]
    F --> G[写入 deploy/secrets.py 样例]
    G --> H[提示运行 djevops deploy]
```

关键约束包括：必须在 Git 仓库中、必须配置过至少一个 remote、必须存在 `manage.py`，并要求本地已声明依赖（[djevops/__main__.py:init](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)）。依赖项既可以写在 `pyproject.toml` 的 `[project.dependencies]`，也可以写在 `requirements.txt` 中（[djevops/__main__.py:_get_declared_dependencies](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)）。

## 密钥管理：deploy/secrets.py

`deploy/secrets.py` 是一个普通的 Python 文件，它会在本地被 `runpy.run_path` 执行，并把执行结果作为环境常量上传到服务器。这种方式使密钥可以来自任意 Python 表达式，包括硬编码、读取 `os.environ`、调用密码管理器等。`SAMPLE_SECRETS_PY` 中给出的推荐写法是：

```python
import os
MY_SECRET = os.environ['MY_SECRET']
DJANGO_SECRET_KEY = '...'
```

变量名需匹配正则 `SECRETS_NAME_RE = r'^[A-Z][A-Z0-9_]+$'`，以便在 YAML 中清晰引用。部署时 `get_services_users_envs` 会把密钥合并进每个服务的环境变量中，从而避免明文密钥进入 Git 历史（[djevops/__main__.py:SAMPLE_SECRETS_PY](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)、[README.md](https://github.com/mherrmann/djevops/blob/main/README.md)）。

服务器端的密钥文件最终落地为 JSON：部署完成后，`/root/.djevops/secrets.json` 由 `get_secrets()` 读取；部署配置由 `get_deploy_config()` 从 `/root/.djevops/deploy.yml` 解析；组件状态则保存在 `components.json`，由 `ComponentRegistry` 用来判断哪些组件需要安装、卸载或复用（[djevops/remote/scaffold.py:5-37](https://github.com/mherrmann/djevops/blob/main/djevops/remote/scaffold.py#L5-L37)、[djevops/remote/component_registry.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/component_registry.py)）。

## 数据库与备份配置

`db.backup` 子段是声明式备份的核心入口。`sqlite` 类型会通过 `get_litestream_config` 生成 Litestream 的 `replica` 配置：

```yaml
db:
  type: sqlite
  backup:
    type: s3
    bucket: mybackup
    access-key-id: S3_BACKUP_ACCESS_KEY
    secret-access-key: S3_BACKUP_SECRET_KEY
    path: db
    region: us-east-1
```

若使用 `postgres`，则由 `djevops/remote/postgres.py` 通过 `pg_dump` 与 cron 周期执行备份；周期字符串需同时能被 `parse_sync_interval` 解析并能用 `as_cron` 转换为 cron 表达式，否则抛出 `CommandError`（[djevops/__main__.py](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)、[djevops/litestream.py](https://github.com/mherrmann/djevops/blob/main/djevops/litestream.py)、[djevops/remote/postgres.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/postgres.py)）。

## 常见校验与失败模式

在执行 `deploy` 之前，本地 CLI 会调用 `check_django_settings.py` 校验 Django `settings.py`。例如 `ALLOWED_HOSTS` 中如果出现既非域名又非 IP 的条目，会打印错误并通过 `GIT_HINT` 提示用户提交推送；`DATABASES['default']['NAME']` 必须等于环境变量 `SQLITE_DB_FILE` 的值（[djevops/check_django_settings.py](https://github.com/mherrmann/djevops/blob/main/djevops/check_django_settings.py)、[djevops/__init__.py:GIT_HINT](https://github.com/mherrmann/djevops/blob/main/djevops/__init__.py)）。`util.is_domain` 与 `is_ip` 用于辅助判断 `ALLOWED_HOSTS` 合法性（[djevops/util.py](https://github.com/mherrmann/djevops/blob/main/djevops/util.py)）。

## See Also

- [README.md — 部署示例与功能总览](https://github.com/mherrmann/djevops/blob/main/README.md)
- [djevops/remote/deploy.py — 部署主流程](https://github.com/mherrmann/djevops/blob/main/djevops/remote/deploy.py)
- [djevops/remote/components.py — 可复用组件基类](https://github.com/mherrmann/djevops/blob/main/djevops/remote/components.py)
- [djevops/remote/actions.py — Django 管理命令封装](https://github.com/mherrmann/djevops/blob/main/djevops/remote/actions.py)

---

<a id='page-3'></a>

## 部署架构与组件系统

### 相关页面

相关主题：[配置文件 djevops.yml 与密钥管理](#page-2), [核心功能与运维指南](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [djevops/remote/deploy.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/deploy.py)
- [djevops/remote/component_registry.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/component_registry.py)
- [djevops/remote/components.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/components.py)
- [djevops/remote/scaffold.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/scaffold.py)
- [djevops/remote/actions.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/actions.py)
- [djevops/__main__.py](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)
- [djevops/__init__.py](https://github.com/mherrmann/djevops/blob/main/djevops/__init__.py)
- [djevops/util.py](https://github.com/mherrmann/djevops/blob/main/djevops/util.py)
</details>

# 部署架构与组件系统

djevops 是一套面向 Django 应用的部署命令行工具，采用"本地编排 + 远端执行"的双端架构：本地负责解析 `deploy/djevops.yml` 与 `deploy/secrets.py`、组装配置并通过 SSH/RSync 将其上传；远端则由一组声明式"组件"在服务器上落实具体变更。其核心思想是 *不可变声明 + 幂等应用*——每次运行都把服务器当作目标态去收敛，而不是编写过程式脚本。资料来源：[djevops/__main__.py:42-87]()、[README.md]()

## 总体架构与执行流

部署流程由 `djevops` CLI 启动入口 `main()` 分发命令。`init` 用于生成 `deploy/djevops.yml` 与 `deploy/secrets.py` 模板；`deploy` 负责把本地配置推送到服务器并触发远端脚本 `python -u -m djevops.remote.deploy` 实施变更。资料来源：[djevops/__main__.py:53-58]()

```mermaid
sequenceDiagram
    participant Dev as 开发者本地
    participant CLI as djevops CLI
    participant Server as 远程服务器
    participant Reg as ComponentRegistry
    Dev->>CLI: djevops deploy
    CLI->>CLI: load_config() 校验 yml + secrets.py
    CLI->>Server: rsync djevops.yml → /root/.djevops/deploy.yml
    CLI->>Server: rsync secrets.json → /root/.djevops/secrets.json
    CLI->>Server: ssh python -m djevops.remote.deploy
    Server->>Reg: require(AptPackage/ServiceUser/...)
    Reg->>Server: install() / save_components()
    Server-->>Dev: 部署完成日志
```

## 状态文件与脚手架

服务器侧的"事实来源"由三个文件构成，集中存放在 `STATE_DIR = /root/.djevops`：

| 路径 | 作用 | 读取函数 |
| --- | --- | --- |
| `deploy.yml` | 来自本地的 `deploy/djevops.yml`，定义服务、数据库、git、域名等 | `get_deploy_config()` |
| `secrets.json` | 本地 `secrets.py` 执行后序列化得到的键值对 | `get_secrets()` |
| `components.json` | 组件注册表持久化文件，记录已安装组件及其参数 | `load_components()` / `save_components()` |

资料来源：[djevops/remote/scaffold.py:5-37]()

`secrets.py` 在本地通过 `runpy.run_path` 执行后再上传，因此可以安全地使用 `os.environ`、密码管理器等动态来源，服务器侧只看到 JSON 常量。资料来源：[djevops/__main__.py:128-150]()

## 组件系统与注册表

djevops 远端的所有"做事的单元"都派生自抽象基类 `Component`，例如 `AptPackage`、`ServiceUser`、`NginxSite`、`LetsEncryptCertificate`、`Litestream`、`Postfix`、`TemplatedFile` 等。`ComponentRegistry` 负责协调它们的安装/卸载：

- `require(component)`：以 `ClassName[:key]` 为唯一键检查持久化记录 `components.json`。若参数完全一致则跳过；否则调用 `component.install()` 并写回文件。资料来源：[djevops/remote/component_registry.py:7-30]()
- `uninstall_unused()`：在部署结束时反向遍历 `components.json`，对已不再被 `require` 的组件执行 `uninstall()`，并按"删一条存一次"的方式写回，以避免中断运行后留下脏数据。资料来源：[djevops/remote/component_registry.py:32-46]()

这种设计天然支持*增量部署*与*自动清理*：用户在 `djevops.yml` 中删除某项服务，下次部署即可回收相应资源。

## 远端部署主流程

`djevops/remote/deploy.py` 的 `main()` 是远端编排核心，其典型步骤包括：

1. 读取 `deploy.yml` 与 `secrets.json`，并解析 `git` 段（`server`、`repo`、`branch`、`key`）。资料来源：[djevops/remote/deploy.py:32-45]()
2. 依据是否存在 `git_repo_key` 选择 HTTPS 或 SSH 拉取方式；如有 SSH 私钥则通过 `require(SshKey(...))` 安装并配置 `KnownHostsEntry`。资料来源：[djevops/remote/deploy.py:47-58]()
3. 通过 `git fetch` + `reset --hard origin/<branch>` 更新 `/srv/app`；失败时回退到 `git clone`。资料来源：[djevops/remote/deploy.py:60-72]()
4. 注册 `ServiceUser`、`VirtualEnvironment`、`TemplatedFile`（Nginx、systemd 单元等）、`IptablesRules`、`Hostname`、`Postfix`、`Litestream` 等组件并调用 `install()`。
5. 最后调用 `registry.uninstall_unused()` 回收残留组件。

Django 特有的副作用——如 `migrate_db`、`collect_static_files`、`install_python_deps`——被封装在 `djevops/remote/actions.py` 中，并通过 `run_in_django_shell` 在 `/srv/venv/bin/python` 下执行 `manage.py`，环境变量来自 `get_services_users_envs()`。资料来源：[djevops/remote/actions.py:1-25]()

## 失败模式与安全默认

- **缺少依赖声明**：`init` 与 `deploy` 会同时检查 `pyproject.toml` 与 `requirements.txt`；两者都不存在或 `django` / `gunicorn` 未声明时，CLI 会直接 `CommandError` 退出，提示用户提交并推送修改（`GIT_HINT`）。资料来源：[djevops/__main__.py:60-78]()、[djevops/__init__.py:1]()
- **配置错误**：`check_django_settings.py` 会核对 `ALLOWED_HOSTS` 中域名/IP 合法性，并强制 `DATABASES['default']['NAME']` 与 `SQLITE_DB_FILE` 环境变量一致。
- **组件一致性**：所有远端写入都被 `ComponentRegistry` 持久化；任何中断后下次 `deploy` 会以 JSON 为准重新收敛。
- **安全默认**：每个服务以独立系统用户运行（`ServiceUser`），环境变量按服务隔离，端口通过 `IptablesRules` 收敛至仅暴露 80/443，避免 Postfix 误开 25 端口。资料来源：[README.md:secure-defaults]()

## See Also

- [项目概览与命令](README.md)
- [配置文件 `deploy/djevops.yml` 详解](djevops/__main__.py)
- [Litestream 备份与 PostgreSQL 接入](djevops/remote/postgres.py)

---

<a id='page-4'></a>

## 核心功能与运维指南

### 相关页面

相关主题：[配置文件 djevops.yml 与密钥管理](#page-2), [部署架构与组件系统](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [djevops/__init__.py](https://github.com/mherrmann/djevops/blob/main/djevops/__init__.py)
- [djevops/__main__.py](https://github.com/mherrmann/djevops/blob/main/djevops/__main__.py)
- [djevops/check_django_settings.py](https://github.com/mherrmann/djevops/blob/main/djevops/check_django_settings.py)
- [djevops/remote/scaffold.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/scaffold.py)
- [djevops/remote/deploy.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/deploy.py)
- [djevops/remote/component_registry.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/component_registry.py)
- [djevops/remote/postgres.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/postgres.py)
- [djevops/util.py](https://github.com/mherrmann/djevops/blob/main/djevops/util.py)
- [README.md](https://github.com/mherrmann/djevops/blob/main/README.md)
</details>

# 核心功能与运维指南

## 概述

djevops 是一款面向 Django 开发者的命令行部署工具，用于将 Django Web 应用部署到 Linux VPS（Ubuntu 或 Debian）上。它不依赖 Docker，因此可以在数秒内完成"推送至生产环境"的操作。相比 Ansible，djevops 专注于 Django 场景，用户需要编写的配置代码显著更少。资料来源：[README.md:1-15]()

安装方式为 `pip install djevops`，随后在 Django 项目的 Git 仓库中执行 `djevops init` 即可生成初始配置文件。资料来源：[README.md:18-22]()

## 核心命令

djevops 提供四个子命令，由 `__main__.py` 统一调度：

| 命令 | 作用 | 关键源码 |
|------|------|----------|
| `djevops init` | 在当前仓库生成 `deploy/djevops.yml` 与 `deploy/secrets.py` | `djevops/__main__.py` |
| `djevops deploy` | 推送代码并重启远端服务 | `djevops/remote/deploy.py` |
| `djevops getbackup` | 下载数据库备份 | `djevops/backup.py` |
| `djevops shell` | 进入远端 Django Shell | `djevops/__main__.py` |

`init` 命令会校验当前目录是否为 Git 仓库、是否存在远程、是否存在 `manage.py`，并要求声明依赖。资料来源：[djevops/__main__.py:50-60]()。依赖文件支持 `pyproject.toml` 与 `requirements.txt` 两种格式（最新版本扩展支持）。资料来源：[djevops/__main__.py:80-100]()

`deploy` 流程会通过 `ComponentRegistry` 注册所需组件，仅在组件描述发生变化时执行安装或更新。资料来源：[djevops/remote/component_registry.py:6-25]()

```mermaid
flowchart LR
    A[本地 djevops deploy] --> B[解析 djevops.yml + secrets.py]
    B --> C[SSH 推送 secrets.json]
    C --> D[远端 ComponentRegistry]
    D --> E[安装/更新组件]
    E --> F[git fetch + reset]
    F --> G[migrate + collectstatic]
    G --> H[重启服务]
```

## 配置与密钥管理

`deploy/djevops.yml` 是核心配置文件，包含 `server`、`git`、`services`、`db`、`mail` 等顶层键。最简配置示例如下：

```yaml
server: 1.2.3.4
git:
  repo: githubuser/mydjangoapp
  branch: main
services:
  web:
    type: django
    env:
      clear:
        ALLOWED_HOSTS: your.website.com
      secret:
        - DJANGO_SECRET_KEY
db:
  type: sqlite
```

密钥通过 `deploy/secrets.py` 在本地求值，结果以 `secrets.json` 形式上传到 `/root/.djevops/`。资料来源：[djevops/remote/scaffold.py:5-15]()、`README.md:60-75]()`。这种设计让用户可以硬编码密钥（不入库）、读取环境变量或调用密码管理器，每个服务以独立用户运行，避免环境变量泄露。资料来源：[README.md:115-125]()

部署前 `check_django_settings.py` 会校验 `ALLOWED_HOSTS`、`DATABASES` 等设置是否与配置一致。资料来源：[djevops/check_django_settings.py:30-50]()

## 数据库与备份

djevops 支持 SQLite 与 PostgreSQL 两种数据库。SQLite 场景下，`SQLITE_DB_FILE` 环境变量必须指向实际的数据库文件路径。资料来源：[djevops/check_django_settings.py:60-70]()

PostgreSQL 由 `djevops/remote/postgres.py` 负责：自动创建角色与数据库，并可通过 `dump` 子命令导出。资料来源：[djevops/remote/postgres.py:25-50]()

备份功能通过 `db.backup` 段启用：

- **SQLite**：使用 Litestream 持续复制到 S3/Azure 等对象存储。资料来源：[README.md:130-150]()
- **PostgreSQL**：通过 cron 周期性执行 `pg_dump`，`sync-interval` 需同时为合法的秒数与 cron 表达式。资料来源：[djevops/__main__.py:130-145]()

服务端路径常量定义于 `djevops/remote/scaffold.py`：`STATE_DIR='/root/.djevops'`、`DEPLOY_CONFIG_PATH`、`SECRETS_PATH`、`COMPONENTS_PATH` 共同构成状态管理基础。资料来源：[djevops/remote/scaffold.py:5-10]()

## 运维与监控

### 服务与日志

每个服务以独立 Linux 用户运行，日志写入 `/var/log/<service>.log`，由 logrotate 轮转压缩。资料来源：[README.md:155-160]()

### 远程 Shell

`djevops shell` 通过 SSH 跳板调用 `manage.py shell`，免去手动进入容器或虚拟环境的步骤。资料来源：[djevops/__main__.py:115-120]()

### SSL 与邮件

`ALLOWED_HOSTS` 中的域名若指向服务器 IP，djevops 会自动签发并续期 Let's Encrypt 证书。资料来源：[README.md:90-100]()` 当 `mail` 段已配置且 `DEBUG=False` 时，Django 会在出错时通过 `ADMINS` 发送邮件。资料来源：[README.md:100-110]()

### 安全与更新

djevops 默认开启自动 OS 更新（不包含主版本升级），并通过 iptables 规则阻止未预期端口外联（如 Postfix 场景下的 25 端口）。资料来源：[README.md:120-130]()` 远程命令执行通过 `util.get_apt_install_cmd` 封装，仅在包未安装时执行 `apt-get install`。资料来源：[djevops/util.py:15-25]()

## 常见失败模式

| 现象 | 根因 | 资料来源 |
|------|------|----------|
| `init` 报错 "not a Git repository" | 当前目录无 `.git` | `__main__.py:50-55` |
| `init` 报错 "no `django` in dependencies" | 依赖文件中未声明 `django` 与 `gunicorn` | `__main__.py:90-100` |
| 部署后 502 | `ALLOWED_HOSTS` 未覆盖域名/IP | `check_django_settings.py:30-50` |
| PostgreSQL 备份失败 | `sync-interval` 无法转为 cron 表达式 | `__main__.py:135-145` |

## See Also

- [README.md](https://github.com/mherrmann/djevops/blob/main/README.md) — 项目概览与功能清单
- [djevops/remote/component_registry.py](https://github.com/mherrmann/djevops/blob/main/djevops/remote/component_registry.py) — 组件注册与幂等安装机制
- [djevops/check_django_settings.py](https://github.com/mherrmann/djevops/blob/main/djevops/check_django_settings.py) — 部署前设置校验逻辑

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：mherrmann/djevops

摘要：发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。

## 1. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://news.ycombinator.com/item?id=48582629 | README/documentation is current enough for a first validation pass.

## 2. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://news.ycombinator.com/item?id=48582629 | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://news.ycombinator.com/item?id=48582629 | no_demo; severity=medium

## 4. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://news.ycombinator.com/item?id=48582629 | no_demo; severity=medium

## 5. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://news.ycombinator.com/item?id=48582629 | issue_or_pr_quality=unknown

## 6. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://news.ycombinator.com/item?id=48582629 | release_recency=unknown

<!-- canonical_name: mherrmann/djevops; human_manual_source: deepwiki_human_wiki -->
