All skills
microsoft avatar

/azure-prepare

@7995851 official

Prepare azd-based Azure projects for deployment: generates azure.yaml, infrastructure (Bicep/Terraform), and Dockerfiles for the Azure Developer CLI (azd) workflow. USE ONLY when the user explicitly wants to use azd as the deployment tool, or the project already has an azure.yaml file. DO NOT USE FOR: non-azd deployments, Python App Service code-only deploys (use python-appservice-deploy), or cross-cloud migration (use azure-cloud-migrate). WHEN: prepare app for azd, create azure.yaml, set up azd infrastructure, modernize app for Azure with azd, deploy with azd, function app, timer trigger, service bus trigger, event-driven function, managed identity, generate Bicep, generate Terraform, create and deploy to Azure.

Use this Skill: https://skilld.dev/gh/microsoft/github-copilot-for-azure/azure-prepare

This session only. Nothing lands on disk.

referencesruntimesnodejs.md

≈1.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Node.js/Express Production Configuration for Azure

Configure Express/Node.js applications for production deployment on Azure Container Apps and App Service.

Required Production Settings

1. Trust Proxy (CRITICAL)

Azure load balancers and reverse proxies sit in front of your app. Without trust proxy, you'll get wrong client IPs, HTTPS detection failures, and cookie issues.

const app = express();

// REQUIRED for Azure - trust the Azure load balancer
app.set('trust proxy', 1);  // Trust first proxy

// Or trust all proxies (less secure but simpler)
app.set('trust proxy', true);

2. Cookie Configuration

Azure's infrastructure requires specific cookie settings:

app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: process.env.NODE_ENV === 'production',  // HTTPS only in prod
    sameSite: 'lax',  // Required for Azure
    httpOnly: true,
    maxAge: 24 * 60 * 60 * 1000  // 24 hours
  }
}));

Key settings:

  • sameSite: 'lax' — Required for cookies through Azure's proxy
  • secure: true — Only in production (HTTPS)
  • httpOnly: true — Prevent XSS attacks

3. Health Check Endpoint

Azure Container Apps and App Service check your app's health:

app.get('/health', (req, res) => {
  res.status(200).json({ status: 'healthy', timestamp: new Date().toISOString() });
});

Configure in Container Apps:

az containerapp update \
  --name APP \
  --resource-group RG \
  --health-probe-path /health \
  --health-probe-interval 30

4. Port Configuration

Azure sets the port via environment variable:

const port = process.env.PORT || process.env.WEBSITES_PORT || 3000;
app.listen(port, '0.0.0.0', () => {
  console.log(`Server running on port ${port}`);
});

Important: Bind to 0.0.0.0, not localhost or 127.0.0.1.

5. Environment Detection

const isProduction = process.env.NODE_ENV === 'production';
const isAzure = process.env.WEBSITE_SITE_NAME || process.env.CONTAINER_APP_NAME;

if (isProduction || isAzure) {
  app.set('trust proxy', 1);
}

Complete Production Configuration

// app.js - Production-ready Express configuration for Azure
const express = require('express');
const session = require('express-session');

const app = express();
const isProduction = process.env.NODE_ENV === 'production';

// Trust Azure load balancer
if (isProduction) {
  app.set('trust proxy', 1);
}

// Security headers
app.use((req, res, next) => {
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('X-Frame-Options', 'DENY');
  next();
});

// JSON parsing
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Session (if using)
app.use(session({
  secret: process.env.SESSION_SECRET || 'dev-secret-change-in-prod',
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: isProduction,
    sameSite: 'lax',
    httpOnly: true,
    maxAge: 24 * 60 * 60 * 1000
  }
}));

// Health check
app.get('/health', (req, res) => {
  res.status(200).json({ status: 'ok' });
});

// Your routes here
app.get('/', (req, res) => {
  res.json({ message: 'Hello from Azure!' });
});

// Error handler
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: isProduction ? 'Internal error' : err.message });
});

// Start server
const port = process.env.PORT || 3000;
app.listen(port, '0.0.0.0', () => {
  console.log(`Server running on port ${port}`);
});

Dockerfile for Azure

FROM node:20-alpine

WORKDIR /app

# Install dependencies first (better caching)
COPY package*.json ./
RUN npm ci --only=production

# Copy app
COPY . .

# Set production environment
ENV NODE_ENV=production

# Expose port (Azure uses PORT env var)
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

# Start app
CMD ["node", "app.js"]

Common Issues

Cookies Not Setting

Symptom: Session lost between requests

Fix:

  1. Add app.set('trust proxy', 1)
  2. Set sameSite: 'lax' in cookie config
  3. Set secure: true only if using HTTPS

Wrong Client IP

Symptom: req.ip returns Azure internal IP

Fix: app.set('trust proxy', 1);

HTTPS Redirect Loop

Symptom: Infinite redirects when forcing HTTPS

Fix:

const TRUSTED_HOST = process.env.APP_PUBLIC_HOSTNAME;

app.use((req, res, next) => {
  if (req.get('x-forwarded-proto') !== 'https' && process.env.NODE_ENV === 'production') {
    if (!TRUSTED_HOST) return next();
    return res.redirect(`https://${TRUSTED_HOST}${req.originalUrl}`);
  }
  next();
});

Health Check Failing

Symptom: Container restarts repeatedly

Fix:

  1. Ensure /health endpoint returns 200
  2. Check app starts within startup probe timeout
  3. Verify port matches container configuration

Environment Variables

⚠️ Important distinction: azd env set vs Application Environment Variables

azd env set sets variables for the azd provisioning process, NOT application runtime. These are used by azd and Bicep during deployment.

Application environment variables must be configured via:

  1. Bicep templates — Define in the resource's env property
  2. Azure CLI — Use az containerapp update --set-env-vars
  3. azure.yaml — Use the env section in service configuration

Azure CLI:

az containerapp update \
  --name APP \
  --resource-group RG \
  --set-env-vars \
    NODE_ENV=production \
    SESSION_SECRET=your-secret-here \
    PORT=3000

azure.yaml:

services:
  api:
    host: containerapp
    env:
      NODE_ENV: production
      PORT: "3000"

Bicep:

env: [
  { name: 'NODE_ENV', value: 'production' }
  { name: 'SESSION_SECRET', secretRef: 'session-secret' }
]

Source: SKILL.md on GitHub

1 alert8d4 checks · Risk SAFE
  • Gen Agent Trust Hub8d

    The azure-prepare skill provides a comprehensive environment for preparing Azure applications for deployment. It focuses on generating infrastructure-as-code and deployment configuration while strictly enforcing security best practices like managed identity usage and secret management via Key Vault. No malicious patterns or security risks were identified.

  • Socket8d

    5 alerts: gptAnomaly, gptSecurity

  • Snyk8d

    Risk: LOW · No issues

  • Runlayer6mo

    68/196 files flagged

Signed by skilld at 7995851. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 3 weeks ago
metadata
{
  "author": "Microsoft",
  "version": "0.0.0-placeholder"
}
  • Infrastructure
  • azure
  • bicep
  • terraform
  • deployment
  • docker
  • functions
  • app-service

README badge

README badge for microsoft/github-copilot-for-azure/azure-prepare

Prepares Azure applications for deployment by generating infrastructure templates (Bicep or Terraform), azure.yaml configuration, and Dockerfiles. Covers new app creation, modernization, and hosting on App Service, Container Apps, or Functions—but excludes Python App Service deployments, copilot SDK apps, and cross-cloud migrations which have dedicated skills.

Generated from the current SKILL.md.

Does this skill handle Python App Service deployments?
No. Use the python-appservice-deploy skill instead for Python code-only App Service deploys.
Can I use this skill for cross-cloud migration?
No. This skill is for Azure-native preparation. Use azure-cloud-migrate for migrations from AWS, GCP, or other clouds.
Does this skill support Copilot SDK apps?
No. Use azure-hosted-copilot-sdk for apps with @github/copilot-sdk or CopilotClient.
What infrastructure templates does this skill support?
Azure Developer CLI (azd), Bicep, Terraform, and Azure CLI. The skill creates infrastructure code, Dockerfiles, and configuration files—actual deployment execution is handled by the azure-deploy skill.
Does this skill delete existing project files?
No. When adding features to existing projects, it modifies files rather than deletes them. It never removes the project or workspace directory itself.

Generated from the current SKILL.md. These answers refresh after source changes.