← All migration guides

Competitor migration guide

Migrate from NGINX to Webship without a blind cutover.

Map server blocks, locations, upstreams, health checks, timeouts, and TLS files into strict Webship TOML with an edge-first cutover.

Applies to Webship 1.1.0nginx.conf

Define the migration boundary before changing traffic.

Start by moving only the behavior Webship can reproduce and validate. Leave application authentication, service discovery, scripts, and specialized cache rules on the existing origin until their replacements pass production-like tests.

Translate the smallest production path first.

The source fragment identifies the migration concept; the Webship fragment shows the target shape. Replace example domains, addresses, certificates, limits, and health paths with values validated for your environment.

Representative NGINX configuration
upstream app {
  server 127.0.0.1:8080;
  server 127.0.0.1:8081;
}
server {
  listen 443 ssl http2;
  server_name app.example.com;
  location / { proxy_pass http://app; }
}
Equivalent Webship TOML
listen = "0.0.0.0:443"
workers = 4

[reverse_proxy]
enabled = true
connect_timeout_ms = 2000
max_retries = 0

[reverse_proxy.protocols]
h1 = true
h2 = true
h3 = true

[reverse_proxy.tls]
cert = "/etc/letsencrypt/live/app.example.com/fullchain.pem"
key = "/etc/letsencrypt/live/app.example.com/privkey.pem"

[[reverse_proxy.routes]]
domain = "app.example.com"
path_prefix = "/"
upstreams = ["127.0.0.1:8080", "127.0.0.1:8081"]
load_balancing = "weighted-peak-ewma"

[[reverse_proxy.upstreams]]
address = "127.0.0.1:8080"
protocol = "http1"
health_check_path = "/health"
health_check_interval_ms = 5000
health_check_timeout_ms = 1000

[[reverse_proxy.upstreams]]
address = "127.0.0.1:8081"
protocol = "http1"
health_check_path = "/health"
health_check_interval_ms = 5000
health_check_timeout_ms = 1000

[[reverse_proxy.policies]]
name = "default"
hosts = []
path_prefixes = ["/"]
methods = []
max_body_bytes = 1048576
total_timeout_ms = 30000

Map concepts, not syntax.

Technical directives do not always match one-to-one. Use this table to locate the equivalent Webship configuration area, then validate the effective configuration and runtime behavior.

Current concept or directiveWebship configuration target
listenlisten + [reverse_proxy.protocols]
server_name + location[[reverse_proxy.routes]]
proxy_pass / upstream[[reverse_proxy.upstreams]]
proxy_*_timeout[[reverse_proxy.policies]]
ssl_certificate + ssl_certificate_key[reverse_proxy.tls] / [[sites]] cert + key

Use a reversible five-step cutover.

Keep the old listener ready until Webship has passed correctness, capacity, security, observability, and rollback gates on representative traffic.

  1. 1

    Inventory observable behavior

    Record listeners, domains, routes, upstreams, certificates, rewrites, authentication, cache rules, health probes, limits, and operational integrations.

  2. 2

    Translate one boundary

    Move one host or route into strict TOML. Retain vendor-specific modules and application logic behind Webship until separate replacements are proven.

  3. 3

    Validate offline and locally

    Run --check-config and --print-effective-config, inspect the redacted result, probe health locally, and exercise TLS over both TCP and UDP when HTTP/3 is enabled.

  4. 4

    Canary real traffic

    Send a small, observable traffic slice to Webship. Compare status codes, headers, bodies, latency, upstream health, cache behavior, logs, and security decisions.

  5. 5

    Promote with rollback ready

    Increase traffic in measured stages. Keep the previous target healthy and immediately routable until the agreed observation window and load gates pass.

Validate first. Roll back by routing, not by editing live.

Validate the candidate file, inspect the redacted effective configuration, and probe the private listener before changing traffic. Preserve the old binary, configuration, listener, and DNS or load-balancer target until the observation window closes.

/usr/local/bin/webship --check-config --config /etc/webship/production.toml
/usr/local/bin/webship --print-effective-config --config /etc/webship/production.toml
curl --http3-only --insecure https://127.0.0.1:443/health