Appearance
Services & Ports
Complete reference for all services and ports used in the Club Wilo development environment.
Application Services
| Service | Port | Description | Command |
|---|---|---|---|
| Wilo.Api | 5000 | .NET 10 Backend API | bun run api:run |
| Wilo.App | 5173 | Vue 3 SPA (Vite dev server) | bun run app:dev |
| Wilo.Email | 3050 | Email renderer (Hono/Bun) | bun run email:dev |
| Wilo.Pdf | 3060 | PDF renderer (Hono/Bun) | bun run pdf:dev |
| Wilo.Docs | 5173 | VitePress documentation | bun run docs:dev |
INFO
Wilo.App and Wilo.Docs both default to port 5173 — run them separately or Vite will auto-increment to the next available port.
Docker Compose Services
All infrastructure services are defined in docker-compose.yml and started with bun run docker:up.
Persistence
| Service | Container | Port(s) | Image |
|---|---|---|---|
| PostgreSQL | postgresdb | 5432 | postgres:18.1-alpine |
| ClickHouse | clickhouse | 8123 (HTTP) | clickhouse/clickhouse-server:24.12-alpine |
- PostgreSQL — Main relational database. Used with EF Core, NodaTime types, and snake_case naming convention.
- ClickHouse — Analytical database for immutable audit logs (MergeTree engine). HTTP interface on port 8123.
Cache
| Service | Container | Port(s) | Image |
|---|---|---|---|
| Redis | redis | 6379 | redis:8.4-alpine |
| Redis Insight | redis-insight | 5540 | redis/redisinsight |
- Redis — Distributed cache backend for FusionCache (L1 memory + L2 Redis + backplane).
- Redis Insight — Web-based GUI for inspecting Redis keys and monitoring.
Object Storage
| Service | Container | Port(s) | Image |
|---|---|---|---|
| MinIO | minio | 9000 (API), 9001 (console) | minio/minio:RELEASE.2025-04-22T22-12-26Z |
- MinIO — S3-compatible object storage (AGPL-3.0, pinned to RELEASE.2025-04-22T22-12-26Z, never internet-exposed). Three buckets:
wilo-documents,wilo-images,wilo-temp. Console at http://localhost:9001.
Email
| Service | Container | Port(s) | Image |
|---|---|---|---|
| Email Renderer | wilo-email | 3050 | Built from services/Wilo.Email/Dockerfile |
| Mailpit | mailpit | 1025 (SMTP), 8025 (web UI) | axllent/mailpit |
- Email Renderer — React Email template rendering service (Hono HTTP server on Bun runtime). The API sends template data to this service, which returns rendered HTML.
- Mailpit — Development email capture. All SMTP traffic on port 1025 is captured and viewable at http://localhost:8025.
Dockerfile Locations
Each deployable service owns its Dockerfile inside its project directory. Dockerfiles are never placed at the monorepo root.
| Service | Dockerfile | Build context |
|---|---|---|
| wilo-api | src/Wilo.Api/Dockerfile | . (repo root) |
| wilo-frontend | sites/Wilo.App/Dockerfile | ./sites/Wilo.App |
| wilo-mobile | sites/Wilo.Mobile/Dockerfile | ./sites/Wilo.Mobile |
| wilo-email | services/Wilo.Email/Dockerfile | ./services/Wilo.Email |
The API build context is the repo root because the Dockerfile copies from multiple src/ subdirectories. Its dockerignore is named src/Wilo.Api/Dockerfile.dockerignore (Docker's per-Dockerfile naming convention). The frontend and mobile apps use a standard .dockerignore in their respective directories since the build context is scoped to each project folder.
Observability
| Service | Container | Port(s) | Image |
|---|---|---|---|
| Aspire Dashboard | aspire-dashboard | 18888 (UI), 18889 (OTLP) | mcr.microsoft.com/dotnet/aspire-dashboard |
- Aspire Dashboard — OpenTelemetry visualization dashboard for traces, metrics, and structured logs. The API exports telemetry via OTLP gRPC to port 18889. Dashboard UI at http://localhost:18888.
Health Check Endpoints
The API exposes three health check endpoints:
| Endpoint | Purpose | Checks |
|---|---|---|
GET /health | Aggregated status (cached 10s) | All dependencies |
GET /health/live | Liveness probe | None (process responsive) |
GET /health/ready | Readiness probe (3s timeout) | PostgreSQL, Redis, MinIO, ClickHouse, Email Renderer |
Response format:
json
{
"status": "Healthy",
"totalDuration": "00:00:01.234",
"entries": {
"postgres": { "status": "Healthy" },
"redis": { "status": "Healthy" },
"storage": { "status": "Healthy" },
"clickhouse": { "status": "Healthy" },
"email-renderer": { "status": "Healthy" }
}
}Service Dependencies
Wilo.Api ──┬── PostgreSQL (persistence)
├── Redis (cache)
├── MinIO (file storage)
├── ClickHouse (audit logs)
├── Email Renderer ── Mailpit (SMTP)
└── Aspire Dashboard (telemetry)Production Network Security
In production, no database, cache, analytics, or internal service port is exposed to the Internet. The only entry points accessible from outside are the reverse proxy (HTTPS 443) for the frontend and API, and optionally MinIO (9000) if external S3 access is required.
Port exposure policy
| Service | Dev | Production | Notes |
|---|---|---|---|
| Frontend (Nginx) | 3000 | 443 (via reverse proxy) | TLS terminated by reverse proxy |
| API | 5000 | 443 (via reverse proxy) | Internal port 5000 not exposed directly |
| MinIO API | 9000 | Optional (9000) | Only if external S3 access is needed |
| MinIO Console | 9001 | ❌ Never | Admin UI always internal only |
| PostgreSQL | 5432 ⚠️ | ❌ Never | Flagged ## REMOVE ON PRODUCTION in compose file |
| Redis | 6379 | ❌ Never | Internal Docker network only |
| ClickHouse | 8123 | ❌ Never | Internal Docker network only |
| Redis Insight | 5540 | ❌ Never | Dev tool, not deployed to production |
| Mailpit | 1025 / 8025 | ❌ Never | Dev tool, not deployed to production |
| Email Renderer | 3050 | ❌ Never | Internal Docker network only |
| Aspire Dashboard | 18888 / 18889 | Optional (internal) | OTLP receiver may be needed; UI is internal |
WARNING
docker-compose.yml exposes PostgreSQL on 5432:5432 for local development convenience. This line is explicitly marked ## REMOVE ON PRODUCTION and must be removed or commented out before deploying to any public server.
SSH tunnel for direct database access in production
Direct access to databases and internal services in production is performed exclusively through an SSH tunnel. Never expose these ports to the Internet.
bash
# PostgreSQL
ssh -L 15432:postgresdb:5432 deploy@your-server
# Connect with: psql -h localhost -p 15432 -U wilo
# Redis
ssh -L 16379:redis:6379 deploy@your-server
# Connect with: redis-cli -p 16379
# ClickHouse
ssh -L 18123:clickhouse:8123 deploy@your-server
# Connect with: curl http://localhost:18123/ping
# MinIO Console (if not exposed externally)
ssh -L 19001:minio:9001 deploy@your-server
# Open: http://localhost:19001
# Redis Insight (if deployed)
ssh -L 15540:redis-insight:5540 deploy@your-server
# Open: http://localhost:15540
# Aspire Dashboard (if deployed)
ssh -L 18888:aspire-dashboard:18888 deploy@your-server
# Open: http://localhost:18888The container names used above (postgresdb, redis, clickhouse, etc.) are the Docker Compose service names — they resolve correctly within the Docker network on the server.
Docker Commands
| Command | Description |
|---|---|
bun run docker:up | Start all infrastructure services |
bun run docker:down | Stop all infrastructure services |
bun run docker:logs | Follow logs from all services |
docker compose ps | Check service status |
docker compose logs -f <service> | Follow logs for a specific service |
docker compose restart <service> | Restart a specific service |
Environment Variables
All service credentials are configured via .env (copied from .env.example). Key variables:
| Variable | Service | Purpose |
|---|---|---|
POSTGRES_USER / POSTGRES_PASSWORD | PostgreSQL | Database credentials |
REDIS_PASSWORD | Redis | Cache authentication |
STORAGE_ACCESS_KEY / STORAGE_SECRET_KEY | MinIO | Object storage credentials |