Files
reverse-proxy/tasks/deploy/systemd-and-container.md

95 lines
3.1 KiB
Markdown

---
id: deploy/systemd-and-container
name: Create systemd unit file, Dockerfile, and docker-compose.yml for production deployment
status: complete
depends_on: [ops/signals-and-shutdown]
scope: moderate
risk: low
impact: component
level: implementation
---
## Description
Create the deployment artifacts: systemd unit file, Dockerfile, and docker-compose.yml template.
### Systemd Unit File
```ini
[Unit]
Description=Reverse Proxy
After=network.target
Wants=network-online.target
[Service]
Type=notify
NotifyAccess=all
ExecStart=/usr/local/bin/reverse-proxy --config /etc/reverse-proxy/config.toml
Restart=on-failure
RestartSec=5
# Security hardening
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadWritePaths=/var/lib/reverse-proxy /var/log/reverse-proxy
# ACME challenge cache directory
StateDirectory=reverse-proxy
[Install]
WantedBy=multi-user.target
```
The proxy signals readiness to systemd via `sd_notify("READY=1")` after binding listeners and completing initial configuration load.
### Dockerfile
Multi-stage build:
- Build stage: `rust:alpine` with `x86_64-unknown-linux-musl` target for static linking
- Run stage: `alpine` (or `scratch` for absolute minimum)
- The `aws_lc_rs` crypto provider is statically linked — no OpenSSL dependency
- Binary is self-contained, no runtime dependencies beyond libc for DNS resolution
### Docker Compose Template
Example template showing:
- Reverse proxy with volume mounts for config, ACME cache, logs, and admin socket
- `allow_wildcard_bind = true` for container deployments
- Health check using `wget` against local health endpoint
- Network configuration for upstream services
### Fail2ban Configuration
- Filter definition matching the `RATE_LIMIT` log prefix
- Jail configuration for rate-limiting offenders
## Acceptance Criteria
- [ ] Systemd unit file at `deploy/reverse-proxy.service`
- [ ] `Type=notify` with `sd_notify("READY=1")` integration in binary
- [ ] Security hardening directives in unit file
- [ ] `ReadWritePaths` for ACME cache and log directory
- [ ] Dockerfile with multi-stage build (`rust:alpine``alpine`/`scratch`)
- [ ] Static linking with `x86_64-unknown-linux-musl` target
- [ ] Docker Compose template at `deploy/docker-compose.yml`
- [ ] Volume mounts for config (ro), ACME cache (rw), logs (rw), admin socket (rw)
- [ ] Health check in Docker Compose using `wget` against `http://127.0.0.1:9900/health`
- [ ] Fail2ban filter definition at `deploy/fail2ban/filter.d/reverse-proxy.conf`
- [ ] Fail2ban jail configuration at `deploy/fail2ban/jail.d/reverse-proxy.conf`
- [ ] `docker build` succeeds
- [ ] Container starts and responds to health check
## References
- docs/architecture/operations.md — systemd, container deployment, fail2ban, health check
- docs/architecture/decisions/020-container-deployment.md — container model rationale
## Notes
> The Dockerfile should use `musl` for static linking. The `aws_lc_rs` crypto provider is statically linked. The resulting binary has no runtime dependencies beyond libc for DNS resolution (which `musl` provides).
## Summary
> To be filled on completion