
August 17, 2026
12 min read
Table of Contents
By Kokil Thapa | Last reviewed: August 2026
Azure App Service: Deploy a Web App the Easy Way is a common search because teams want managed hosting without the operational overhead of virtual machines. For developers accustomed to Linux VPS environments or platform-as-a-service tools like Heroku, Azure offers a middle ground where infrastructure is abstracted but configuration remains granular. This guide covers the exact workflow I use to ship PHP and Laravel applications to Azure, focusing on CLI-driven reproducibility rather than portal clicks.
While many tutorials focus on .NET, the reality for Laravel developers and PHP practitioners is that Azure’s Linux App Service is now a first-class citizen. The "easy way" isn't clicking through wizards; it's establishing a repeatable command-line workflow that treats infrastructure as code. Whether you are migrating a legacy WordPress site or deploying a fresh SaaS API, the principles of immutable deployments and environment isolation remain constant.
How do you provision Azure App Service via CLI for PHP?
The Azure Portal is useful for exploration, but for production workloads, the CLI prevents configuration drift. When setting up Azure App Service: Deploy a Web App the Easy Way, you need three resources grouped together: a Resource Group, an App Service Plan, and the Web App itself. For PHP and Laravel, always choose Linux. Windows App Service plans run PHP via FastCGI in IIS, which introduces latency and filesystem permission quirks that don't exist on native Linux containers.
Create the resource group and plan
Start by creating a dedicated resource group. This keeps billing and access control isolated. Then provision the App Service Plan. In 2026, the B1 (Basic) tier is the practical minimum for any business application. The F1 (Free) and D1 (Shared) tiers lack custom domain support, SSL binding, and scale-out capabilities. They also share CPU cycles with other tenants, making them unsuitable for anything beyond hobby projects.
# Create resource group
az group create --name rg-legal-portal-prod --location eastus
# Create Linux App Service Plan (B1 Basic)
az appservice plan create \
--name asp-legal-portal \
--resource-group rg-legal-portal-prod \
--sku B1 \
--is-linux
# Create Web App with PHP 8.4 runtime
az webapp create \
--name legal-portal-app \
--resource-group rg-legal-portal-prod \
--plan asp-legal-portal \
--runtime "PHP|8.4" Note the explicit runtime specification. Azure defaults can lag behind current stable releases. As of mid-2026, PHP 8.4 is the latest stable version supported on Azure App Service Linux. If you omit the runtime flag, you may inherit an older default. Always verify available runtimes before provisioning:
az webapp list-runtimes --linux --query "[?starts_with(runtime, 'PHP')]" Configure application settings securely
Never commit secrets to source control. Azure App Settings are injected as environment variables at runtime and encrypted at rest. For Laravel, map your .env values directly:
az webapp config appsettings set \
--name legal-portal-app \
--resource-group rg-legal-portal-prod \
--settings \
APP_ENV=production \
APP_DEBUG=false \
DB_HOST=my-sql-server.mysql.database.azure.com \
DB_DATABASE=legal_portal_prod \
DB_USERNAME=app_user \
DB_PASSWORD=@KeyVaultReference(...) \
CACHE_DRIVER=redis \
QUEUE_CONNECTION=redis For database passwords and API keys, integrate Azure Key Vault references instead of storing plaintext values. This adds a layer of security auditability that matters for legal-tech and financial applications where compliance is non-negotiable.
What is the best deployment method for Azure App Service?
There are four primary ways to execute Azure App Service: Deploy a Web App the Easy Way, but only two are viable for production. FTP is insecure and lacks atomicity. Local Git is acceptable for solo prototypes. For real applications, choose between GitHub Actions (recommended for most teams) and Azure DevOps Pipelines (common in enterprise Microsoft shops).
| Method | Best For | Zero-Downtime | Build Location | Complexity |
|---|---|---|---|---|
| GitHub Actions | Open-source & SMB teams | Yes (with slots) | GitHub runners | Low |
| Azure DevOps | Enterprise / Microsoft ecosystem | Yes (with slots) | Microsoft-hosted agents | Medium |
| Local Git | Prototypes / solo devs | No | Kudu on App Service | Very Low |
| FTP/SFTP | Emergency hotfixes only | No | None (pre-built) | Low (but risky) |
GitHub Actions workflow for Laravel
The key insight for Azure App Service: Deploy a Web App the Easy Way with CI/CD is separating build from deploy. Build artifacts on GitHub's infrastructure, then push only the compiled output to Azure. This avoids running composer install or npm run build on the production server, which consumes CPU/memory during deployment windows.
# .github/workflows/azure-deploy.yml
name: Deploy to Azure App Service
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup PHP 8.4
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
extensions: mbstring, pdo_mysql, redis, zip
- name: Install Composer dependencies
run: composer install --no-dev --optimize-autoloader
- name: Build frontend assets
run: |
npm ci
npm run build
- name: Deploy to Azure Web App
uses: azure/webapps-deploy@v3
with:
app-name: legal-portal-app
slot-name: staging
package: .
publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE }} This workflow targets the staging slot, not production directly. That distinction is what separates professional deployments from amateur ones. The publish profile should be stored as a GitHub secret, never hardcoded.
Why Kudu builds fail for complex apps
If you use Local Git or ZIP deploy without pre-building, Azure's Kudu engine attempts to detect your framework and run build commands automatically. For simple static sites this works. For Laravel applications with private Composer repositories, custom Node toolchains, or specific PHP extensions, Kudu builds frequently fail due to missing SSH keys, memory limits, or incompatible system libraries. Pre-building in CI eliminates this entire category of failures.
How do deployment slots enable zero-downtime releases?
Deployment slots are the single most important feature for anyone treating Azure App Service: Deploy a Web App the Easy Way as a production platform. A slot is a fully independent App Service instance with its own URL, app settings, and connection strings. You deploy to the slot, validate it, then swap it into production. The swap operation exchanges virtual IP addresses, meaning existing connections drain gracefully and new requests route instantly.
Create and configure a staging slot
# Create staging slot
az webapp deployment slot create \
--name legal-portal-app \
--resource-group rg-legal-portal-prod \
--slot staging
# Configure slot-specific settings (not swapped)
az webapp config appsettings set \
--name legal-portal-app \
--resource-group rg-legal-portal-prod \
--slot staging \
--slot-settings \
APP_URL=https://legal-portal-app-staging.azurewebsites.net \
MAIL_MAILER=log The --slot-settings flag marks settings as sticky to the slot. These values stay with the slot during swaps, preventing staging URLs or debug mailers from leaking into production. Production-only settings like payment gateway credentials should similarly be marked sticky on the production slot.
Execute the swap safely
# Validate staging health before swap
curl -sf https://legal-portal-app-staging.azurewebsites.net/health || exit 1
# Perform swap
az webapp deployment slot swap \
--name legal-portal-app \
--resource-group rg-legal-portal-prod \
--slot staging \
--target-slot production
# Verify production health post-swap
curl -sf https://legal-portal-app.azurewebsites.net/health || \
az webapp deployment slot swap \
--name legal-portal-app \
--resource-group rg-legal-portal-prod \
--slot production \
--target-slot staging Always automate health checks before and after swaps. If the post-swap check fails, immediately swap back. This gives you sub-minute rollback capability compared to re-running a full deployment pipeline. For legal-tech portals handling sensitive document uploads or court date tracking, this reliability guarantee is non-negotiable.
What Laravel-specific configurations does Azure App Service require?
Azure App Service Linux runs PHP in a containerized environment with some constraints that differ from traditional VPS setups. Understanding these prevents the "works locally, breaks on Azure" problems I've encountered repeatedly on client projects.
Filesystem persistence and storage
Azure App Service provides persistent storage at /home. All other paths are ephemeral and reset on restarts. Laravel's storage directory must be symlinked or configured to use this persistent path:
# In your startup script or custom Dockerfile
ln -s /home/site/wwwroot/storage /var/www/html/storage
# Or set via App Setting
STORAGE_PATH=/home/site/wwwroot/storage Better yet, offload file storage to Azure Blob Storage entirely. Use the league/flysystem-azure-blob-storage adapter so your application doesn't depend on local disk persistence. This also enables CDN integration for media-heavy sites like florist eCommerce platforms or travel agency galleries.
OPcache and performance tuning
Azure enables OPcache by default, but the default settings are conservative for development safety. For production Laravel applications, override these via a custom .ini file placed in /home/site/config/php.ini:
[opcache]
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
[php]
upload_max_filesize=64M
post_max_size=64M
max_execution_time=300 Setting validate_timestamps=0 means OPcache never checks for file changes. This is safe because deployment slots provide atomic updates — new code arrives as a complete unit, not incremental file modifications. Remember to restart the App Service after changing INI settings, or include them in your deployment artifact.
Queue workers and scheduled tasks
Azure App Service doesn't natively support long-running processes like Laravel queue workers. You have two options. For low-volume queues, use Azure Functions triggered by Redis/Service Bus. For consistent workload, add an Azure Container App or VM running php artisan queue:work as a systemd service. Never rely on HTTP-triggered cron endpoints for critical background processing; they're subject to request timeouts and scaling limitations.
For scheduled tasks, use Azure Logic Apps or GitHub Actions scheduled workflows to hit your scheduler endpoint, or better yet, use the Azure Scheduler replacement (Logic Apps) to invoke php artisan schedule:run via SSH or a secure webhook every minute. Documenting this architecture clearly helps when handing off maintenance to clients who may later seek guidance on website development costs and ongoing operational expenses.
When should you choose Azure App Service over alternatives?
Azure App Service: Deploy a Web App the Easy Way isn't always the right answer. Understanding trade-offs prevents costly migrations later. Compare it against the alternatives I regularly evaluate for clients considering cloud hosting services.
- Choose Azure App Service when: You need managed PaaS with built-in scaling, staging slots, and Microsoft ecosystem integration. Ideal for B2B SaaS, legal-tech portals, and applications requiring enterprise compliance certifications.
- Choose a VPS (DigitalOcean/Linode/Hetzner) when: Budget is under Rs 3,000/month (~USD 22), you need root access for custom system packages, or your team has strong Linux sysadmin skills. Better for hobby projects and early-stage startups validating product-market fit.
- Choose AWS Lambda/Vapor when: Traffic is highly spiky with long idle periods, and you want true serverless billing. Trade-off: cold starts hurt user-facing latency for Laravel apps.
- Choose Kubernetes (AKS/EKS) when: You operate 10+ microservices with dedicated DevOps staff. Overkill for single monolithic Laravel applications unless you're already standardized on K8s.
For Nepal-based businesses serving international clients, Azure's global datacenter network provides lower latency than Kathmandu-hosted servers. However, if your primary users are domestic and budget is constrained, a well-configured VPS with proper caching often delivers better price-performance. The decision hinges on operational capacity, not just raw specs.
Next Steps for Production Azure Deployments
Azure App Service: Deploy a Web App the Easy Way becomes genuinely easy once you establish the CLI-first workflow, enforce staging slot discipline, and handle Laravel's filesystem requirements correctly. Start with the B1 Linux plan, automate provisioning via scripts, and integrate GitHub Actions from day one. Resist the temptation to click through the portal for production setups; the time saved upfront costs hours of debugging later.
If you're evaluating Azure for a Laravel application, legal-tech platform, or eCommerce system and want to discuss architecture decisions specific to your workload, reach out to discuss your deployment strategy. I help teams navigate cloud infrastructure choices that balance cost, reliability, and maintainability for real-world production systems.

