Security hardening, cost control and migrations

WAF, DDoS protection and security headers, patch policy, least-privilege access, rightsizing and egress savings, and moving a live site between hosts.

Edge protection and headers

# security headers that are safe for most sites
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" always;

# rate limit the endpoints that get abused
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
location = /login {
    limit_req zone=login burst=5 nodelay;
    proxy_pass http://app;
}
ControlProtects againstDo not rely on it for
WAF (managed rules)Known exploit patternsBusiness logic abuse
WAF (custom rules)Specific abusive patterns you observeAnything you have not tested
DDoS absorptionVolumetric floodsApplication-layer attacks that look like users
Rate limitingCredential stuffing and scrapingDistributed attacks from many addresses
Security headersClickjacking, MIME sniffing, referrer leakageServer-side vulnerabilities
Bot scoringAutomated abuseBlocking real users - test before enforcing
  • Roll out a CSP in report-only mode first. A strict policy applied blind breaks inline scripts and third-party widgets, and the users find out before you do.
  • Rate limit by the cheapest key that is correct - IP plus route, not IP alone, or one office behind a NAT gets blocked.
  • Block only what you can explain. Aggressive rules that block legitimate clients are a self-inflicted outage by a different name.

Access and patch policy

  1. No shared accounts. Every human has their own identity, and production access is granted per person and revoked on departure.
  2. Hardware-key two-factor for the provider console, the repository and the DNS provider. These three control everything else.
  3. Least privilege for service accounts: one role per service, scoped to the resources it needs, with no wildcard policies.
  4. No long-lived keys where an instance identity or a short-lived token is available.
  5. Patch on a schedule: OS security updates monthly, application dependencies weekly, with an emergency path for a critical advisory.
  6. Log every administrative action and keep the log where the administrator cannot edit it.
# automated dependency and OS patching signals
npm audit --omit=dev --audit-level=high
docker scout cves registry.example/app:latest

# unattended security upgrades on a Debian-based host
# /etc/apt/apt.conf.d/20auto-upgrades
# APT::Periodic::Update-Package-Lists "1";
# APT::Periodic::Unattended-Upgrade "1";

The security control that fails most often is not a missing WAF rule, it is an unpatched dependency or a former employee's still-active key. Put a calendar entry on the patch cycle and an audit of active keys next to it.

Cost control and migrations

Cost leverTypical savingRisk
Right-size instances20-40 percent on over-provisioned computeUnder-provisioning at peak
Move static assets to a CDNLarge on egressCache invalidation mistakes
Compress and convert imagesLarge on egressQuality regressions
Shorten log retentionModest but easyLess history when debugging
Delete unattached volumes and old snapshotsSurprisingly largeDeleting something still needed
Reserved capacity or commitments20-40 percent on steady baselineA lock-in if usage changes
Turn off non-production overnightLarge for stagingNobody can test when they want to
Reduce third-party API callsVariesFeature or quality loss
Migrating a live site between hosts

  1. inventory     every record, every cron job, every certificate, every integration
  2. lower TTLs    48 hours before any DNS change
  3. provision     the new environment and deploy the same artefact
  4. copy data     with a documented cutover point or continuous replication
  5. test          against the new environment by host header, not by the public name
  6. cut over      DNS, or the load balancer, in one change
  7. verify        resolution, TLS, email, payments, login, and the slowest page
  8. keep the old  running and unmodified for a week
  9. clean up      after the window, and only after a written sign-off
  • Test the new host with the Host header pointing at it before any public change. You want to discover certificate and absolute-URL problems while nobody is affected.
  • Move the data with a defined freeze or a replication lag target. "Copy it and then copy the delta" without a checkpoint loses writes.
  • After the switch, keep the previous environment serving for a week. It is the fastest rollback you will ever have.
⚠️
Never delete the old environment or its data on the day of a migration. The most expensive mistake in this whole area is cleaning up early - the old host and its backups cost a rounding error for a week, and deleting them removes every rollback path you have.

FAQ

Do I need a WAF?
If you run a login form, a payment flow or anything an attacker can automate, yes - a managed ruleset is cheap insurance. It does not replace fixing application vulnerabilities.
How long should a migration take?
The cutover is minutes. The safe window around it is days: lower TTLs before, test the new host directly, keep the old one afterwards, and only then clean up.

Choosing a host: cost, lock-in and support Custom domains and TLS

Last refreshed 2026-09-18.