Own servers
nginx
nginx is the HTTP server and reverse proxy in front of our self-hosted services: TLS termination, hostname based routing and upstream groups.
nginx is an HTTP server that also works as a reverse proxy. It serves static files, terminates TLS and forwards requests to backend services by hostname and path. In this stack it fronts every self-hosted service, in containers on Windows and Linux hosts.
The runtime is event-driven: a master process reads and evaluates configuration and maintains the workers, which process the requests. worker_processes sets how many run: a fixed number or adjusted to the available CPU cores.
The configuration model
Configuration lives in a single file, and directives sit in nested contexts: main, events, http, server, location. Directives inherit downward, and the narrower context overrides the wider one.
- A server block is a virtual server bound to a hostname; the request is resolved first by IP address and port through listen, then by the Host header against the server_name entries.
- server_name matching has a fixed order: exact name, longest wildcard starting with an asterisk, longest one ending with an asterisk, then the first regular expression in file order.
- No match means the default server of that port; default_server belongs to the listen port, not to the server name.
- location blocks split the path further: the exact match wins, then the longest prefix is kept and used only if no regular expression matches.
Forwarding requests and upstreams
proxy_pass inside a location names the destination: a hostname, an IP address with a port, a Unix socket or an upstream group. Without a URI in the target the full request URI is passed on, with one the matching location prefix is replaced, which makes the trailing slash a common source of routing bugs.
An upstream block groups several backends under one name. Round-robin is the default, least_conn picks the server with the fewest active connections and ip_hash pins a client address to a server; weight biases the distribution and max_fails with fail_timeout handles failures passively.
TLS, reloads and logs
TLS needs the ssl parameter on listen plus the certificate and private key paths, with the certificate chain in one file and the server certificate first, otherwise some clients cannot complete the handshake.
For proxied requests nginx sets Host to $proxy_host and Connection to close by default, so the original values must be passed explicitly with proxy_set_header. Responses are buffered until fully received; proxy_buffering off is what streaming endpoints want.
A configuration change takes effect only after a reload or restart. nginx -s reload makes the master validate the new file, start new workers and ask the old ones to finish the requests in flight; an invalid file is rolled back. quit stops gracefully, stop is immediate, reopen reopens the logs after rotation.
Under TLS the handshake is the CPU-heavy part, so the documentation recommends several workers and a shared session cache via ssl_session_cache. error_log defaults to the error level and access_log to the combined format; $request_time and $upstream_response_time separate proxy time from backend time.
What to watch
- proxy_buffering on lets the backend finish quickly while the client downloads slowly, which interactive endpoints do not want.
- A syntactically valid rule that is logically wrong routes traffic quietly, so rule changes deserve their own test step.
Cloudflare sits in front of us and Docker containers run behind us on Linux hosts, so the per-hostname rules live in one place: the nginx configuration. At CyberElectro every service we host is reachable through this layer, with TLS terminated here and traffic split by hostname.
Further reading
- Beginner’s Guide - start, stop, reload and config file structure.
- NGINX Reverse Proxy - proxy_pass behaviour, header passing and response buffering.
- Server names - matching order, wildcards and regular expressions.