chore: rename quicproquo → quicprochat in docs, Docker, CI, and packaging
Rename all project references from quicproquo/qpq to quicprochat/qpc across documentation, Docker configuration, CI workflows, packaging scripts, operational configs, and build tooling. - Docker: crate paths, binary names, user/group, data dirs, env vars - CI: workflow crate references, binary names, artifact names - Docs: all markdown files under docs/, SDK READMEs, book.toml - Packaging: OpenWrt Makefile, init script, UCI config (file renames) - Scripts: justfile, dev-shell, screenshot, cross-compile, ai_team - Operations: Prometheus config, alert rules, Grafana dashboard - Config: .env.example (QPQ_* → QPC_*), CODEOWNERS paths - Top-level: README, CONTRIBUTING, ROADMAP, CLAUDE.md
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
# Key Rotation Procedures
|
||||
|
||||
This document provides step-by-step procedures for rotating all cryptographic material in a quicproquo deployment.
|
||||
This document provides step-by-step procedures for rotating all cryptographic material in a quicprochat deployment.
|
||||
|
||||
## Auth Token Rotation
|
||||
|
||||
The auth token (`QPQ_AUTH_TOKEN`) is used for bearer-token authentication (auth version 1). OPAQUE-authenticated sessions are not affected by token rotation.
|
||||
The auth token (`QPC_AUTH_TOKEN`) is used for bearer-token authentication (auth version 1). OPAQUE-authenticated sessions are not affected by token rotation.
|
||||
|
||||
### Procedure
|
||||
|
||||
@@ -15,22 +15,22 @@ echo "New token: $NEW_TOKEN"
|
||||
|
||||
# 2. Update the config file or environment
|
||||
# Option A: TOML config file
|
||||
sed -i "s/^auth_token = .*/auth_token = \"$NEW_TOKEN\"/" qpq-server.toml
|
||||
sed -i "s/^auth_token = .*/auth_token = \"$NEW_TOKEN\"/" qpc-server.toml
|
||||
|
||||
# Option B: Environment variable (systemd)
|
||||
systemctl edit qpq-server --force
|
||||
# Add: Environment=QPQ_AUTH_TOKEN=<new-token>
|
||||
systemctl edit qpc-server --force
|
||||
# Add: Environment=QPC_AUTH_TOKEN=<new-token>
|
||||
|
||||
# Option C: Docker Compose
|
||||
# Update QPQ_AUTH_TOKEN in docker-compose.prod.yml or .env file
|
||||
# Update QPC_AUTH_TOKEN in docker-compose.prod.yml or .env file
|
||||
|
||||
# 3. Restart the server
|
||||
systemctl restart qpq-server
|
||||
systemctl restart qpc-server
|
||||
# or: docker compose restart server
|
||||
|
||||
# 4. Update all clients with the new token
|
||||
# Clients using OPAQUE auth are unaffected.
|
||||
# Clients using bearer-token auth must update their QPQ_ACCESS_TOKEN.
|
||||
# Clients using bearer-token auth must update their QPC_ACCESS_TOKEN.
|
||||
```
|
||||
|
||||
### Impact
|
||||
@@ -49,7 +49,7 @@ The server uses DER-encoded X.509 certificates for QUIC TLS 1.3. The server vali
|
||||
# 1. Obtain a new certificate (example with Let's Encrypt / certbot)
|
||||
certbot certonly --standalone -d chat.example.com
|
||||
|
||||
# 2. Convert PEM to DER format (qpq-server expects DER)
|
||||
# 2. Convert PEM to DER format (qpc-server expects DER)
|
||||
openssl x509 -in /etc/letsencrypt/live/chat.example.com/fullchain.pem \
|
||||
-outform DER -out /tmp/server-cert.der
|
||||
|
||||
@@ -71,10 +71,10 @@ cp /tmp/server-key.der data/server-key.der
|
||||
openssl x509 -inform DER -in data/server-cert.der -noout -text | head -20
|
||||
|
||||
# 7. Restart the server (QUIC requires restart for new TLS config)
|
||||
systemctl restart qpq-server
|
||||
systemctl restart qpc-server
|
||||
|
||||
# 8. Verify the server started with the new certificate
|
||||
journalctl -u qpq-server --since "1 min ago" | grep -i tls
|
||||
journalctl -u qpc-server --since "1 min ago" | grep -i tls
|
||||
```
|
||||
|
||||
### Self-Signed Certificate (Development)
|
||||
@@ -83,7 +83,7 @@ In non-production mode, the server auto-generates a self-signed certificate if n
|
||||
|
||||
```bash
|
||||
rm data/server-cert.der data/server-key.der
|
||||
systemctl restart qpq-server
|
||||
systemctl restart qpc-server
|
||||
# Server will generate a new self-signed cert for localhost/127.0.0.1/::1
|
||||
```
|
||||
|
||||
@@ -91,26 +91,26 @@ systemctl restart qpq-server
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# /opt/qpq/scripts/renew-cert.sh
|
||||
# /opt/qpc/scripts/renew-cert.sh
|
||||
set -euo pipefail
|
||||
|
||||
DOMAIN="chat.example.com"
|
||||
CERT_DIR="/etc/letsencrypt/live/$DOMAIN"
|
||||
QPQ_DATA="/var/lib/quicproquo"
|
||||
QPC_DATA="/var/lib/quicprochat"
|
||||
|
||||
certbot renew --quiet
|
||||
|
||||
openssl x509 -in "$CERT_DIR/fullchain.pem" -outform DER -out "$QPQ_DATA/server-cert.der"
|
||||
openssl pkey -in "$CERT_DIR/privkey.pem" -outform DER -out "$QPQ_DATA/server-key.der"
|
||||
chmod 600 "$QPQ_DATA/server-key.der"
|
||||
chown qpq:qpq "$QPQ_DATA/server-cert.der" "$QPQ_DATA/server-key.der"
|
||||
openssl x509 -in "$CERT_DIR/fullchain.pem" -outform DER -out "$QPC_DATA/server-cert.der"
|
||||
openssl pkey -in "$CERT_DIR/privkey.pem" -outform DER -out "$QPC_DATA/server-key.der"
|
||||
chmod 600 "$QPC_DATA/server-key.der"
|
||||
chown qpc:qpc "$QPC_DATA/server-cert.der" "$QPC_DATA/server-key.der"
|
||||
|
||||
systemctl restart qpq-server
|
||||
systemctl restart qpc-server
|
||||
```
|
||||
|
||||
```cron
|
||||
# Run cert renewal check twice daily
|
||||
0 3,15 * * * /opt/qpq/scripts/renew-cert.sh >> /var/log/qpq-cert-renew.log 2>&1
|
||||
0 3,15 * * * /opt/qpc/scripts/renew-cert.sh >> /var/log/qpc-cert-renew.log 2>&1
|
||||
```
|
||||
|
||||
## Federation Certificate Rotation
|
||||
@@ -134,43 +134,43 @@ openssl pkey -in /tmp/federation-key.pem -outform DER -out data/federation-key.d
|
||||
chmod 600 data/federation-key.der
|
||||
|
||||
# 3. Restart the server
|
||||
systemctl restart qpq-server
|
||||
systemctl restart qpc-server
|
||||
|
||||
# 4. Coordinate with federation peers: they must trust the same CA
|
||||
```
|
||||
|
||||
## Database Encryption Key Rotation
|
||||
|
||||
The SQLCipher database key (`QPQ_DB_KEY`) encrypts all data at rest.
|
||||
The SQLCipher database key (`QPC_DB_KEY`) encrypts all data at rest.
|
||||
|
||||
### Procedure (SQLCipher PRAGMA rekey)
|
||||
|
||||
```bash
|
||||
# 1. Stop the server
|
||||
systemctl stop qpq-server
|
||||
systemctl stop qpc-server
|
||||
|
||||
# 2. Back up the database
|
||||
cp data/qpq.db /backups/qpq-pre-rekey-$(date +%Y%m%d).db
|
||||
cp data/qpc.db /backups/qpc-pre-rekey-$(date +%Y%m%d).db
|
||||
|
||||
# 3. Rekey the database
|
||||
sqlite3 data/qpq.db <<EOF
|
||||
sqlite3 data/qpc.db <<EOF
|
||||
PRAGMA key = 'old-encryption-key';
|
||||
PRAGMA rekey = 'new-encryption-key';
|
||||
EOF
|
||||
|
||||
# 4. Verify the database opens with the new key
|
||||
sqlite3 data/qpq.db "PRAGMA key = 'new-encryption-key'; PRAGMA integrity_check;"
|
||||
sqlite3 data/qpc.db "PRAGMA key = 'new-encryption-key'; PRAGMA integrity_check;"
|
||||
|
||||
# 5. Update the environment/config with the new key
|
||||
# Option A: systemd
|
||||
systemctl edit qpq-server --force
|
||||
# Environment=QPQ_DB_KEY=new-encryption-key
|
||||
systemctl edit qpc-server --force
|
||||
# Environment=QPC_DB_KEY=new-encryption-key
|
||||
|
||||
# Option B: Docker Compose .env
|
||||
echo "QPQ_DB_KEY=new-encryption-key" >> .env
|
||||
echo "QPC_DB_KEY=new-encryption-key" >> .env
|
||||
|
||||
# 6. Start the server
|
||||
systemctl start qpq-server
|
||||
systemctl start qpc-server
|
||||
```
|
||||
|
||||
### Full Re-encryption (Alternative)
|
||||
@@ -179,18 +179,18 @@ If `PRAGMA rekey` is unavailable or you want a fresh database file:
|
||||
|
||||
```bash
|
||||
# 1. Stop the server and back up
|
||||
systemctl stop qpq-server
|
||||
cp data/qpq.db /backups/qpq-pre-rekey.db
|
||||
systemctl stop qpc-server
|
||||
cp data/qpc.db /backups/qpc-pre-rekey.db
|
||||
|
||||
# 2. Export with old key, import with new key
|
||||
sqlite3 data/qpq.db "PRAGMA key='old-key'; .dump" | \
|
||||
sqlite3 data/qpq-new.db "PRAGMA key='new-key'; .read /dev/stdin"
|
||||
sqlite3 data/qpc.db "PRAGMA key='old-key'; .dump" | \
|
||||
sqlite3 data/qpc-new.db "PRAGMA key='new-key'; .read /dev/stdin"
|
||||
|
||||
# 3. Replace the database
|
||||
mv data/qpq-new.db data/qpq.db
|
||||
mv data/qpc-new.db data/qpc.db
|
||||
|
||||
# 4. Update config and restart
|
||||
systemctl start qpq-server
|
||||
systemctl start qpc-server
|
||||
```
|
||||
|
||||
## OPAQUE ServerSetup Rotation
|
||||
@@ -201,20 +201,20 @@ The OPAQUE ServerSetup is generated once and persisted. Rotating it invalidates
|
||||
|
||||
```bash
|
||||
# 1. Stop the server
|
||||
systemctl stop qpq-server
|
||||
systemctl stop qpc-server
|
||||
|
||||
# 2. Back up the database
|
||||
cp data/qpq.db /backups/qpq-pre-opaque-rotate.db
|
||||
cp data/qpc.db /backups/qpc-pre-opaque-rotate.db
|
||||
|
||||
# 3. Delete the persisted OPAQUE setup
|
||||
# For SQL backend:
|
||||
sqlite3 data/qpq.db "PRAGMA key='${QPQ_DB_KEY}'; DELETE FROM server_state WHERE key = 'opaque_setup';"
|
||||
sqlite3 data/qpc.db "PRAGMA key='${QPC_DB_KEY}'; DELETE FROM server_state WHERE key = 'opaque_setup';"
|
||||
|
||||
# For file backend:
|
||||
rm data/opaque_setup.bin 2>/dev/null || true
|
||||
|
||||
# 4. Start the server (it will generate a new OPAQUE ServerSetup)
|
||||
systemctl start qpq-server
|
||||
systemctl start qpc-server
|
||||
|
||||
# 5. All users must re-register (existing OPAQUE credentials are invalid)
|
||||
```
|
||||
@@ -225,17 +225,17 @@ The Ed25519 signing key is used for delivery proofs. Rotating it means old deliv
|
||||
|
||||
```bash
|
||||
# 1. Stop the server
|
||||
systemctl stop qpq-server
|
||||
systemctl stop qpc-server
|
||||
|
||||
# 2. Back up
|
||||
cp data/qpq.db /backups/qpq-pre-sigkey-rotate.db
|
||||
cp data/qpc.db /backups/qpc-pre-sigkey-rotate.db
|
||||
|
||||
# 3. Delete the persisted signing key seed
|
||||
# For SQL backend:
|
||||
sqlite3 data/qpq.db "PRAGMA key='${QPQ_DB_KEY}'; DELETE FROM server_state WHERE key = 'signing_key_seed';"
|
||||
sqlite3 data/qpc.db "PRAGMA key='${QPC_DB_KEY}'; DELETE FROM server_state WHERE key = 'signing_key_seed';"
|
||||
|
||||
# 4. Start the server (generates a new Ed25519 signing key)
|
||||
systemctl start qpq-server
|
||||
systemctl start qpc-server
|
||||
```
|
||||
|
||||
## Rotation Schedule
|
||||
|
||||
Reference in New Issue
Block a user