Synopsis #
nginx is a high-performance HTTP server and reverse proxy known for its efficiency, low memory footprint, and rich feature set. It supports static content, TLS, FastCGI and SCGI backends, reverse proxying, load balancing, and basic authentication.
nginx is not included in the OpenBSD base system, but is available via packages.
Web Server History on OpenBSD #
OpenBSD removed the old Apache server from base in 5.6, introduced the native httpd in 5.6, and removed nginx from base in 5.7. Apache and nginx remain available as packages. See the 5.6 release notes and 5.7 release notes .
Web Server Comparison #
The Web overview compares httpd, nginx, and Apache and explains the separate role of relayd.
Installation #
Package versions, dependencies, and OpenBSD README instructions are available in the release package and current package entries. The package branch must match the installed OpenBSD system.
Install nginx from packages:
doas pkg_add nginx
This installs:
/etc/nginx/nginx.conf– main configuration file/usr/local/sbin/nginx– daemon binaryrc.dservice script forrcctl(8)
Basic Configuration #
The default configuration file is installed at /etc/nginx/nginx.conf.
Minimal example for static file hosting:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
root /htdocs;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
}
nginx workers run in a chroot at /var/www by default. Their /htdocs is /var/www/htdocs on the host. Create that directory and a test file:
doas sh <<'ROOT'
mkdir -p /var/www/htdocs
echo "OK" > /var/www/htdocs/index.html
chown -R www:www /var/www/htdocs
ROOT
Starting nginx #
Enable and start the service:
doas rcctl enable nginx
doas rcctl start nginx
To test or reload configuration:
doas nginx -t
doas nginx -s reload
The process runs as the www user.
TLS Configuration #
To enable HTTPS, obtain a certificate (e.g., via acme-client) and adjust the configuration:
server {
listen 443 ssl;
server_name example.org;
ssl_certificate /etc/ssl/example.org.fullchain.pem;
ssl_certificate_key /etc/ssl/private/example.org.key;
root /htdocs;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Do not forget to open port 443 in pf.conf:
pass in on $int_if proto tcp from any to (self) port 443
FastCGI Support (PHP, etc.) #
To serve dynamic content (e.g., via php-fpm):
- Install PHP 8.3, the release default; the main package includes PHP-FPM:
doas pkg_add php%8.3
doas php-fpm-8.3 -t
doas rcctl enable php83_fpm
doas rcctl start php83_fpm
- With PHP-FPM chrooted to
/var/www, put the site files in/var/www/htdocson the host. Its socket must be/var/www/run/php-fpm.sockand accessible towww. Inside the nginx chroot, the socket is/run/php-fpm.sock. Add this location to the nginx server:
location ~ \.php$ {
root /htdocs;
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /htdocs$fastcgi_script_name;
}
Ensure PHP files exist in the document root:
doas sh <<'ROOT'
mkdir -p /var/www/htdocs
echo "<?php echo 'PHP works'; ?>" > /var/www/htdocs/index.php
ROOT
Reverse Proxy Example #
nginx can proxy requests to a backend service, such as a Python or Node.js application:
server {
listen 80;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
This setup is commonly used for application frontends, TLS termination, or caching.
Logging and Diagnostics #
Access and error logs are defined in the http block:
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
Create /var/log/nginx before applying that custom log configuration. Validate with nginx -t and confirm both files are created.
To follow logs:
doas tail -f /var/log/nginx/access.log
Use nginx -t to verify syntax, and rcctl restart nginx after changes.
Security Practices #
- Run nginx as
www(default). - Ensure host-side files in
/var/www/htdocsare readable bywwwand not world-writable. - Use
try_filesto select existing files; it is not a general path-traversal defense. Review roots, aliases, and application path handling. - Do not expose nginx to the Internet without enabling TLS.
- Validate all reverse proxy headers if used.
Example pf.conf rules:
block in proto tcp from any to (self) port { 80 443 }
pass in on $int_if proto tcp from 192.0.2.0/24 to (self) port { 80 443 }