Apache STeVe 配置参数详解

详解 Apache STeVe v3 的三类配置载体:服务端 config.yaml 的端口/TLS 证书/数据库路径参数、建选举用 election.yaml 的元数据/议题/STV 候选人映射/席位/选民名单字段与校验规则、以及热加载的 queries.yaml 查询游标,附生产配置模板、防篡改机制说明与常见故障排障,全部参数与回显均实测

Apache STeVeApache STeVe2026/10/12

Apache STeVe 配置参数详解

目标:详解 Apache STeVe v3 的三类配置载体——服务端 server/config.yaml(端口、TLS、数据库路径)、建选举用的 election.yaml(元数据、议题、STV 参数、选民名单)与高级查询定义 queries.yaml,并给出可直接套用的生产模板。参数与默认值均基于 Ubuntu 22.04.5 真实环境实测。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • Apache STeVe:v3(pyproject 版本 3.0.0,trunk 提交 3222df7)
  • Python:3.12.15(venv,SQLite 3.53.1);uv 0.13.0
  • 源码目录:/opt/steve;服务目录:/opt/steve/v3/server
  • 配置文件:/opt/steve/v3/server/config.yaml、/opt/steve/v3/server/election.yaml、/opt/steve/v3/queries.yaml
  • 数据库:/opt/steve/v3/server/steve.db(SQLite,五表:election/issue/person/mayvote/vote)
  • 服务端口:58383;systemd 服务:steve.service
  • 示例管理账号:admin(演示口令 q1w2e3r4,仅作团队演示记忆;STeVe v3 无本地口令登录,认证经 asfquart 对接 Apache OAuth)

二、前置条件

  • 已按《Apache STeVe 安装指南》完成安装并初始化 steve.db。
  • 配置修改后需重启服务生效:systemctl restart steve.service。
  • 查看服务状态与日志:systemctl is-active steve.service、journalctl -u steve.service。

三、参数查看与修改方式

STeVe v3 没有集中式配置命令,参数分布在三个文件:

文件位置作用
config.yaml/opt/steve/v3/server/服务端口、TLS 证书、数据库路径
election.yaml自定义(建议 /opt/steve/v3/server/)定义一次选举的全部内容,交给 bin/create-election.py 执行
queries.yaml/opt/steve/v3/SQL 游标定义(进阶),被 main.py 纳入热加载监视

config.yaml 由模板拷贝生成:

cd /opt/steve/v3/server
cp config.yaml.example config.yaml

election.yaml 样例在 bin/election.yaml.sample:

cd /opt/steve/v3/server
cp bin/election.yaml.sample my-election.yaml

💡 standalone 模式下服务通过 watchfiles 监视模板、源码与 queries.yaml,改动即自动重载;但 config.yaml 的端口/证书项在启动时读取一次,修改后需 systemctl restart steve.service。

四、参数总览

载体参数默认值说明
config.yamlserver.port58383HTTP/HTTPS 监听端口
config.yamlserver.certfile空(模板带 mkcert 示例文件名)TLS 证书,空则明文 HTTP
config.yamlserver.keyfile空TLS 私钥,空则明文 HTTP
config.yamldbsteve.dbSQLite 库路径,相对 server 目录或绝对路径
election.yamlelection.title必填选举标题
election.yamlelection.owner_pid必填选举 owner,须存在于 person 表
election.yamlelection.authz空授权组标记(如 pmc/members)
election.yamlelection.open_at/close_at空开/关时间(Unix 秒),仅提示性
election.yamlissues[].title必填议题标题
election.yamlissues[].description空议题描述
election.yamlissues[].vtype必填议题类型:yna 或 stv
election.yamlissues[].kvstv 必填STV 参数:version/labelmap/seats
election.yamlrecord必填有资格投票的 pid 名单
queries.yamlelection.*/issue.* 等游标内置全部 SQL 语句定义,键名以 c_/q_ 区分写/读

五、核心参数分类详解

5.1 config.yaml 服务参数

5.1.1 server.port

服务监听端口。config.yaml.example 的注释解释了 58383 的由来:电话键盘上 58383 拼出 "STEVE",但超出 65536 上限,故取 58383:

server:
    port: 58383

修改端口后 systemctl restart steve.service,用 ss -tlnp | grep <port> 核对监听。

5.1.2 server.certfile / server.keyfile

TLS 证书与私钥,留空即 HTTP 明文模式(本专栏实测采用):

    certfile:
    keyfile:

填文件名即启用 HTTPS,相对 server/certs/ 目录解析(也可写绝对路径)。openssl 自签证书生成与 HTTPS 验证:

cd /opt/steve/v3/server/certs
openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes \
    -keyout server.key -out server.crt -subj "/CN=localhost"

config.yaml 改为 certfile: server.crt、keyfile: server.key 并重启后:

curl -sk -o /dev/null -w "HTTPS %{http_code}\n" https://127.0.0.1:58383/

回显:

HTTPS 200

💡 官方 server/certs/README.md 推荐 mkcert;openssl 等任何标准工具链均可。

5.1.3 db

SQLite 数据库路径,相对路径以 /opt/steve/v3/server/ 为基准:

db: steve.db

指向挂载/独立数据盘时写绝对路径(如 db: /var/lib/steve/steve.db),目录须存在且服务运行用户可写。首次建库:

sqlite3 /var/lib/steve/steve.db < /opt/steve/v3/schema.sql

5.2 election.yaml 选举定义参数

5.2.1 election 段(元数据)

election:
  title: "Demo Election 2026"
  owner_pid: "admin"
  authz: "pmc"
  open_at: 1760000000
  close_at: 1880000000
参数约束实测行为
title必填缺失报 Election must have title and owner_pid
owner_pid必填,须存在于 person 表实测写入 admin 后创建成功,回显 by owner "admin"
authz可选留空表示仅 owner 可编辑
open_at/close_at可选,Unix 秒纯提示性展示字段;到点不会自动开/关选举,开闭须显式操作

⚠️ open_at/close_at 不控制实际投票窗口:选举开闭由 Web 端 /do-open/<eid>、/do-close/<eid>(或等价的 Election API)执行;关闭后这两个字段的值被数据库触发器锁定,不可再改。

5.2.2 issues 段(议题)

issues:
  - title: "Approve Budget"
    description: "Vote yes/no/abstain on the proposed budget."
    vtype: "yna"

  - title: "Elect Board Members"
    description: "Rank candidates for board seats using STV."
    vtype: "stv"
    kv:
      version: 2
      labelmap:
        a: [alice, "Alice"]
        b: [bob, "Bob"]
        c: [carlos, "Carlos"]
        d: [david, "David"]
      seats: 2
  • vtype 只接受 yna 与 stv,其他值报 Invalid vtype: <值>。
  • yna(yes/no/abstain 计数制):选票取值 yes/no/abstain(及其等价写法 y/n/1/0/true/false,其余任何非空值按弃权计)。
  • stv(单一可转移投票):kv 必填,缺字段报 STV issue missing required kv fields: version, labelmap, seats。

5.2.3 stv 的 kv 参数

参数约束说明
version1 或 22:labelmap 值为 [asfid, name] 二元组;1:labelmap 值直接是姓名字符串
labelmap必填选票标签到候选人的映射,键(a/b/c/…)即投票时填写的偏好序元素
seats正整数当选席位数,<=0 报 STV seats must be a positive integer

实测计票回显(2 席位、5 张选票 a,b,c / b,a,d / a,c,b / d,c,b / b,c,a):

Issue c156373ef0: Elect Board Members (stv)
Result: Alice                                    elected
        Bob                                      elected
        Carlos                                   not elected
        David                                    not elected
Details: {'candidates': {'a': True, 'b': True, 'c': False, 'd': False}, 'version': 2, 'labelmap': {'a': ['alice', 'Alice'], 'b': ['bob', 'Bob'], 'c': ['carlos', 'Carlos'], 'd': ['david', 'David']}, 'seats': 2, 'votestrings': ['b,c,a', 'b,a,d', 'd,c,b', 'a,c,b', 'a,b,c']}

5.2.4 record 段(选民名单)

record:
  - admin
  - alice
  - bob
  - carlos
  - david
  - eve
  • 每项是 person 表中的 pid;名单中的 pid 先于定义存在,否则报 PID <pid> from record not found in person database。
  • 名单写入 mayvote 关联表,决定哪些人可对哪些议题投票;开选举时对该表逐行生成盐值(salt),与 opened_key 一起构成选票匿名化/加密的输入。

5.3 queries.yaml 查询定义(进阶)

/opt/steve/v3/queries.yaml 集中定义全部 SQL 游标,键名前缀 c_ 为写操作、q_ 为查询,例如:

election:
    c_salt_mayvote: UPDATE mayvote SET salt = ? WHERE _ROWID_ = ?
    c_create: |
        INSERT INTO election
          (eid, title, owner_pid, authz, open_at, close_at)

该文件被 main.py 加入 watchfiles 监视集合(源码中 extra_files 含 steve.election.QUERIES),修改保存即热加载,无需重启。仅建议在需要扩展查询能力时调整,改动前备份原文件。

六、生产配置模板

适用场景:8GB 内存、SSD 磁盘、单机承载几十场委员会/社团选举、与 Apache OAuth 联动的正式投票。

/opt/steve/v3/server/config.yaml:

server:
    port: 58383
    certfile: server.crt
    keyfile: server.key

db: /var/lib/steve/steve.db

配套准备:

mkdir -p /var/lib/steve
sqlite3 /var/lib/steve/steve.db < /opt/steve/v3/schema.sql
cd /opt/steve/v3/server/certs
openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes \
    -keyout server.key -out server.crt -subj "/CN=steve.example.com"

/var/lib/steve/election-pmc.yaml(一次 PMC 选举):

election:
  title: "PMC Election 2026"
  owner_pid: "admin"
  authz: "members"
  open_at: 1760000000
  close_at: 1880000000

issues:
  - title: "Elect PMC Members"
    description: "Rank candidates for 3 PMC seats using STV."
    vtype: "stv"
    kv:
      version: 2
      labelmap:
        a: [alice, "Alice"]
        b: [bob, "Bob"]
        c: [carlos, "Carlos"]
        d: [david, "David"]
      seats: 3

record:
  - alice
  - bob
  - carlos
  - david
  - eve

💡 资源说明:STeVe 为单进程 Python/ASGI 应用,实测常驻内存约 54MB(systemctl status 输出 Memory: 53.7M),无 JVM,不需要堆参数;SQLite 单文件库,磁盘占用与投票规模线性相关(每张选票加密落库)。选票落库即经 vote_token 匿名化并加密,开启选举生成的 opened_key 绑定全部元数据/人员/议题,任何事后篡改都会使既有选票失配(is_tampered 返回 True、计票中止)。

七、常见问题

7.1 改了 server.port 不生效

解决:config.yaml 的端口在启动时读取,systemctl restart steve.service 后用 ss -tlnp | grep <port> 核对。

7.2 create-election.py 报 Election must have title and owner_pid

解决:election.yaml 的 election: 段补齐 title 与 owner_pid(owner_pid 须先写入 person 表)。

7.3 create-election.py 报 PID frank from record not found in person database

解决:先向 person 表插入该 pid(含非空 email)再重跑;示例:

sqlite3 /opt/steve/v3/server/steve.db "INSERT INTO person (pid, name, email) VALUES ('frank', 'Frank', 'frank@steve.apache.org');"

7.4 create-election.py 报 STV issue missing required kv fields: version, labelmap, seats

解决:vtype 为 stv 的议题必须带完整 kv:(version/labelmap/seats 三项齐全),并保证 seats 为正整数。

7.5 open_at 时间到了选举没有自动开放

说明:open_at/close_at 仅是给人类看的时间提示,不影响实际状态。开放选举用 Web 端 /do-open/<eid>,或等价的 Python API:steve.election.Election(db, eid).open(pdb);关闭用 /do-close/<eid> 或 close()。

7.6 改动选举后旧选票失配

说明:opened_key 绑定选举元数据、议题与选民名单;开选举后新增/修改议题或选民会使 opened_key 变化,既有选票无法匹配(防篡改机制的设计行为)。开选举前完成全部定义修改,开选举后只收票。

八、参考链接