My n8n instance on Render worked perfectly.
It was fast, simple, fully managed, and cost-effectiveness. And I barely had to think about infrastructure.
So why move it?
Because I wanted:
- More control over my environment
- Centralized cloud billing in Azure
- Hands-on experience with Infrastructure as Code (IaC), GitHub Actions, and cloud security
- A real-world project instead of another tutorial
This post shares what I built and what I learned along the way.
Repository
git clone https://github.com/TQKNG/lab-n8n-azure.git
Check out README file for full guide
What I Wanted to Build
I wanted a fully reproducible deployment where I could:
- Deploy everything from GitHub Actions
- Authenticate to Azure without long-lived secrets (OIDC)
- Run n8n securely behind HTTPS
- Add identity + edge protection layers
- Tear everything down when not needed
Think: personal SaaS-grade infrastructure, but lightweight
Architecture
This setup adds two important layers compared to a basic VM deployment:
Cloudflare as the edge layer
Azure AD (Entra ID) as the identity gate
What Gets Deployed
Compute
- Ubuntu 22.04 LTS VM (Azure)
- Trusted Launch enabled
- SSH key-based access
Networking
- Virtual Network (isolated subnet)
- Network Security Group (restricted ports)
- Public IP behind controlled ingress
Application
- n8n (Docker container)
- Caddy reverse proxy (HTTPS + routing)
Edge & Identity
- Cloudflare (DNS + protection layer)
- Azure AD (Entra ID authentication gate)
GitHub Actions Pipeline
To trace logs, I use below manually triggered workflows. These allows full lifecycle control from GitHub. Feel free to customize it based on your own workflow setup.
- Setup → initialize repo variables
- OIDC bootstrap → configure Azure trust
- Verify → test authentication
- Deploy → run Bicep infrastructure
- Start → validate VM + n8n endpoint
- Teardown → destroy resources safely
Key Security Layers
This architecture is intentionally layered:
- Cloudflare → edge protection + TLS
- Azure AD → identity verification before access
- NSG → network-level filtering
- Caddy → HTTPS termination + reverse proxy
- Docker → container isolation
This creates a simple zero-trust-inspired flow.
What I Learned
- Azure OIDC is a game changer. No more storing long-lived secrets in GitHub.
- Bicep is actually pleasant. Much easier than ARM templates and still powerful.
- Cloudflare simplifies edge security. It reduces direct exposure of Azure resources.
- Infrastructure as Code changes everything. Even a small project becomes reproducible and disposable.
Next Step
- Add Azure Key Vault for secrets
- Add automated backups for n8n workflows
- Move monitoring to Azure Monitor dashboards
- Restrict SSH via IP allowlist or JIT access
- Evaluate Azure Container Apps instead of VM
- Add cost automation (auto shutdown dev environment)
Resources
Project
- GitHub Repository: https://github.com/TQKNG/lab-n8n-azure
- n8n Documentation: https://docs.n8n.io
- Cloudfare Developer Docs: https://developers.cloudflare.com/
Azure
- Bicep Docs: https://learn.microsoft.com/azure/azure-resource-manager/bicep
- Azure OIDC with GitHub Actions: https://learn.microsoft.com/azure/developer/github/connect-from-azure-openid-connect
- Azure Well-Architected Framework: https://learn.microsoft.com/azure/architecture/framework
CI/CD & Infra
- GitHub Actions Docs: https://docs.github.com/actions
- Docker Docs: https://docs.docker.com
- Caddy Server Docs: https://caddyserver.com/docs


Top comments (0)