I'm an intern migrating an internal tool from a physical lab server to Azure and would appreciate a sanity check on the architecture. The current setup consists of four Docker Compose containers: Open WebUI as the chat interface, Caddy for TLS and path-based routing, and two FastAPI services that perform separate tasks. One connects to internal systems over SSH and creates ZIP files, while the other generates certificate packages. The entire application must remain private and accessible only through our internal network or VPN.
I'm considering placing all four containers in a private Azure Container Apps environment connected to a VNET. Container Apps seems attractive because it can scale down when unused, which fits an internal tool with roughly 100 users who are active mainly during business hours. It also provides a shared private network similar to the current Compose setup.
The surrounding design includes private endpoints, private DNS so our internal domain resolves only within the network, Azure Key Vault for secrets currently stored in the Compose file, managed identity for passwordless access to Azure resources, Azure Files for persistent application data and generated files, and Azure Container Registry for private image storage and pulls. I measured the existing CPU and memory usage rather than estimating, and the projected cost is around $90–$100 per month, with the private endpoint accounting for much of that.
I'm unsure whether Caddy is still necessary if Azure can handle TLS and routing, whether Container Apps is a better choice than App Service for this workload, and whether there are any deployment or security issues I may be overlooking. I'd also like feedback on using Azure Files for the database and on the overall identity and networking design.
2 Answers
The identity model is worth documenting explicitly. Use Azure RBAC to control which members of the team can administer the resource group and its services. For service-to-service access, assign a managed identity to the Container Apps workloads and grant only the permissions each one needs—for example, reading specific secrets from Key Vault or pulling images from ACR. That avoids putting passwords or registry keys in configuration and keeps access scoped to the required resources.
I’d be careful with putting the database on Azure Files. It’s a reasonable place for generated files, but if the database is SQLite or another file-based database, network-share locking, latency, and failure behavior can become problems. Test concurrent access, restarts, disconnects, and backup recovery before committing to it. If the database workload grows, a managed database service may be safer.
Caddy may be unnecessary if Azure’s ingress features cover your TLS termination and path routing, but keep it if it provides behavior you would otherwise have to recreate. Removing it is beneficial only if Azure can replace its responsibilities cleanly; otherwise it may still be a useful single internal entry point.

That matches the approach we're taking. Team access is handled through Azure RBAC, while the containers use managed identities for Key Vault and ACR access, with permissions granted only to the relevant resources.