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
6.4 KiB
Docker Deployment
quicprochat includes a multi-stage Dockerfile and a Docker Compose configuration for building and running the server in containers.
Quick start
docker compose up
This builds the server image (if not already built) and starts a single server service listening on port 7000. The server will generate a self-signed TLS certificate on first launch and begin accepting QUIC connections.
To rebuild after code changes:
docker compose up --build
To run in the background:
docker compose up -d
Docker Compose configuration
The docker-compose.yml at the repository root defines a single service:
services:
server:
build:
context: .
dockerfile: docker/Dockerfile
ports:
- "7000:7000/udp"
environment:
RUST_LOG: "info"
QPC_LISTEN: "0.0.0.0:7000"
QPC_DATA_DIR: "/var/lib/quicprochat"
QPC_PRODUCTION: "true"
volumes:
- server-data:/var/lib/quicprochat
restart: unless-stopped
volumes:
server-data:
Port mapping
The container exposes port 7000 (QUIC/UDP). Note that QUIC uses UDP, so ensure your firewall allows UDP traffic on this port.
Restart policy
restart: unless-stopped ensures the server restarts automatically after crashes but stays stopped if you explicitly docker compose stop or docker compose down.
Multi-stage Docker build
The Dockerfile at docker/Dockerfile uses a two-stage build to produce a minimal runtime image.
Stage 1: Builder (rust:bookworm)
FROM rust:bookworm AS builder
WORKDIR /build
# Copy manifests first so dependency layers are cached independently of source.
COPY Cargo.toml Cargo.lock ./
COPY crates/quicprochat-core/Cargo.toml crates/quicprochat-core/Cargo.toml
# ... (all 9 crate manifests)
# Create dummy source files for dependency caching.
RUN mkdir -p ... && echo 'fn main() {}' > ...
# Schemas must exist before the proto crate's build.rs runs.
COPY schemas/ schemas/
# Build dependencies only (cache layer).
RUN cargo build --release --bin qpc-server 2>/dev/null || true
# Copy real source and build for real.
COPY crates/ crates/
RUN cargo build --release --bin qpc-server
Key steps:
- Base image:
rust:bookworm(Debian Bookworm with the Rust toolchain pre-installed). - No system compiler required: Unlike v1, the builder stage does not install
capnproto. The v2 Protobuf compiler is vendored byprotobuf-srcand compiled automatically as part ofcargo build. - Copy manifests first:
Cargo.tomlandCargo.lockare copied before source code with dummy stubs so that dependency compilation is cached in a separate Docker layer. - Copy schemas: The
schemas/directory is copied before the dependency build becausequicprochat-proto/build.rsreferences it. - Copy real source and build: After the dependency cache layer, real source files are copied in and
cargo build --releaseproduces the final binary.
Stage 2: Runtime (debian:bookworm-slim)
FROM debian:bookworm-slim AS runtime
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /build/target/release/qpc-server /usr/local/bin/qpc-server
RUN groupadd --system qpc \
&& useradd --system --gid qpc --no-create-home --shell /usr/sbin/nologin qpc \
&& mkdir -p /var/lib/quicprochat \
&& chown qpc:qpc /var/lib/quicprochat
EXPOSE 7000
VOLUME ["/var/lib/quicprochat"]
ENV RUST_LOG=info \
QPC_LISTEN=0.0.0.0:7000 \
QPC_DATA_DIR=/var/lib/quicprochat \
QPC_TLS_CERT=/var/lib/quicprochat/server-cert.der \
QPC_TLS_KEY=/var/lib/quicprochat/server-key.der \
QPC_PRODUCTION=true
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD test -f /var/lib/quicprochat/server-cert.der || exit 1
USER qpc
CMD ["qpc-server"]
Key characteristics:
- Minimal image: No Rust toolchain, no build tools, no
protocbinary. ca-certificates: Included for future HTTPS calls (e.g., ACME certificate provisioning).- Dedicated user: The container runs as the
qpcsystem user (notroot) for defense in depth. - Named volume:
/var/lib/quicprochatis declared as aVOLUMEfor data persistence. QPC_PRODUCTION=true: The runtime image defaults to production mode, requiring pre-existing TLS certificates and a strong auth token.
Volume persistence
The server stores its state (TLS certificates, KeyPackages, delivery queues, OPAQUE setup, KT log) in the data directory. Mount a volume to persist this data across container restarts:
services:
server:
# ... existing config ...
volumes:
- server-data:/var/lib/quicprochat
volumes:
server-data:
Or use a bind mount for easier inspection:
mkdir -p ./server-data
docker run -d \
--name quicprochat \
-p 7000:7000/udp \
-v "$(pwd)/server-data:/var/lib/quicprochat" \
-e QPC_ALLOW_INSECURE_AUTH=true \
-e QPC_PRODUCTION=false \
-e RUST_LOG=info \
qpc-server
Without a volume, all server state (including TLS certificates and message queues) is lost when the container is removed. The server will generate a new self-signed certificate on each fresh start, which means clients will need the new certificate to connect.
Building just the image
To build the Docker image without starting a container:
docker build -t qpc-server -f docker/Dockerfile .
To run it in development mode (without production validation):
docker run -d \
--name quicprochat \
-p 7000:7000/udp \
-e QPC_ALLOW_INSECURE_AUTH=true \
-e QPC_PRODUCTION=false \
-e RUST_LOG=info \
qpc-server
Connecting the client to a containerised server
When the server runs in Docker with docker compose up, the client can connect from the host:
# Extract the server's TLS cert from the container volume
docker compose cp server:/var/lib/quicprochat/server-cert.der ./data/server-cert.der
# Connect
cargo run -p quicprochat-client -- ping \
--ca-cert ./data/server-cert.der \
--server-name localhost
If you mounted a bind volume (e.g., ./server-data:/var/lib/quicprochat), the certificate is directly accessible at ./server-data/server-cert.der.
Next steps
- Running the Server -- server configuration without Docker
- Running the Client -- CLI subcommands
- Demo Walkthrough -- step-by-step messaging scenario