# Running the Server The quicproquo server is a single binary (`qpq-server`) that exposes a unified **NodeService** endpoint combining Authentication Service (KeyPackage management) and Delivery Service (message relay) operations over a single QUIC + TLS 1.3 connection. --- ## Quick start ```bash cargo run -p quicproquo-server ``` On first launch the server will: 1. Create the `data/` directory if it does not exist. 2. Generate a self-signed TLS certificate and private key (`data/server-cert.der`, `data/server-key.der`) with SANs `localhost`, `127.0.0.1`, and `::1`. 3. Open a QUIC endpoint on `0.0.0.0:7000`. 4. Begin accepting connections. You should see output similar to: ``` 2025-01-01T00:00:00.000000Z INFO quicproquo_server: generated self-signed TLS certificate cert="data/server-cert.der" key="data/server-key.der" 2025-01-01T00:00:00.000000Z INFO quicproquo_server: accepting QUIC connections addr="0.0.0.0:7000" ``` --- ## Configuration All configuration is available via CLI flags and environment variables. Environment variables take precedence when both are specified. | Purpose | CLI flag | Env var | Default | |---|---|---|---| | QUIC listen address | `--listen` | `QPQ_LISTEN` | `0.0.0.0:7000` | | TLS certificate (DER) | `--tls-cert` | `QPQ_TLS_CERT` | `data/server-cert.der` | | TLS private key (DER) | `--tls-key` | `QPQ_TLS_KEY` | `data/server-key.der` | | Data directory | `--data-dir` | `QPQ_DATA_DIR` | `data` | | Log level | -- | `RUST_LOG` | `info` | ### Examples ```bash # Listen on a custom port cargo run -p quicproquo-server -- --listen 0.0.0.0:9000 # Use pre-existing TLS credentials cargo run -p quicproquo-server -- \ --tls-cert /etc/quicproquo/cert.der \ --tls-key /etc/quicproquo/key.der # Via environment variables QPQ_LISTEN=0.0.0.0:9000 \ RUST_LOG=debug \ cargo run -p quicproquo-server ``` ### Production deployment Set `QPQ_PRODUCTION=1` (or `true` / `yes`) so the server enforces production checks: - **Auth:** A non-empty `QPQ_AUTH_TOKEN` is required; the value `devtoken` is rejected. - **TLS:** Existing cert and key files are required (auto-generation is disabled). - **SQL store:** When `--store-backend=sql`, a non-empty `QPQ_DB_KEY` is required. An empty key leaves the database unencrypted on disk and is not acceptable for production. --- ## TLS certificate handling ### Self-signed certificate auto-generation If the files at `--tls-cert` and `--tls-key` do not exist when the server starts, it generates a self-signed certificate using the `rcgen` crate. The generated certificate includes three Subject Alternative Names: - `localhost` - `127.0.0.1` - `::1` The certificate and key are written in DER format. Parent directories are created automatically. ### Using your own certificate To use a certificate issued by a CA or a custom self-signed certificate: 1. Convert your certificate and key to DER format if they are in PEM: ```bash openssl x509 -in cert.pem -outform DER -out cert.der openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -out key.der -nocrypt ``` 2. Point the server at them: ```bash cargo run -p quicproquo-server -- \ --tls-cert cert.der \ --tls-key key.der ``` 3. Distribute the certificate (or its CA root) to clients so they can verify the server. The client's `--ca-cert` flag accepts a DER file. ### TLS configuration details The server's TLS stack is configured as follows: - **Protocol versions**: TLS 1.3 only (`rustls::version::TLS13`). TLS 1.2 and below are rejected. - **Client authentication**: Disabled (`with_no_client_auth()`). The server does not request a client certificate. Client identity is established at the MLS layer via Ed25519 credentials, not at the TLS layer. - **ALPN**: The server advertises `b"capnp"` as the application-layer protocol. --- ## ALPN negotiation Both the server and client must agree on the ALPN token `b"capnp"` during the TLS handshake. This token is hardcoded in the server's TLS configuration: ```rust tls.alpn_protocols = vec![b"capnp".to_vec()]; ``` If a client connects with a different (or no) ALPN token, the QUIC handshake will fail with an ALPN mismatch error. --- ## Storage The server persists its state to the data directory (`--data-dir`, default `data/`): | File | Contents | |---|---| | `data/server-cert.der` | TLS certificate (DER) | | `data/server-key.der` | TLS private key (DER) | | `data/keypackages.bin` | `bincode`-serialised map of identity keys to KeyPackage queues | | `data/deliveries.bin` | `bincode`-serialised map of `(channelId, recipientKey)` to message queues | | `data/hybridkeys.bin` | `bincode`-serialised map of identity keys to hybrid (X25519 + ML-KEM-768) public keys | Storage is implemented by the `FileBackedStore` in `crates/quicproquo-server/src/storage.rs`. Every mutation (upload, enqueue, fetch) flushes the entire map to disk synchronously. This is suitable for proof-of-concept workloads but not production traffic. See [Storage Backend](../internals/storage-backend.md) for details. --- ## Connection handling Each incoming QUIC connection is handled in a `tokio::task::spawn_local` task on a shared `LocalSet`. The `capnp-rpc` library uses `Rc>` internally, making it `!Send`, which is why all RPC tasks must run on a `LocalSet` rather than being spawned with `tokio::spawn`. The connection lifecycle: 1. Accept incoming QUIC connection. 2. Complete TLS 1.3 handshake. 3. Accept a bidirectional QUIC stream. 4. Wrap the stream in a `capnp_rpc::twoparty::VatNetwork`. 5. Bootstrap a `NodeService` RPC endpoint. 6. Serve requests until the client disconnects or an error occurs. --- ## Logging The server uses `tracing` with `tracing-subscriber` and respects the `RUST_LOG` environment variable: ```bash # Default: info level RUST_LOG=info cargo run -p quicproquo-server # Debug level for detailed RPC tracing RUST_LOG=debug cargo run -p quicproquo-server # Trace level for maximum verbosity RUST_LOG=trace cargo run -p quicproquo-server # Filter to specific crates RUST_LOG=quicproquo_server=debug,quinn=warn cargo run -p quicproquo-server ``` --- ## Next steps - [Running the Client](running-the-client.md) -- connect to the server and exercise the CLI - [Demo Walkthrough](demo-walkthrough.md) -- step-by-step Alice-and-Bob group messaging scenario - [Service Architecture](../architecture/service-architecture.md) -- how the NodeService combines AS and DS