nginx Reverse Proxy
nginx Reverse Proxy
Section titled “nginx Reverse Proxy”Running nginx as a container on RouterOS centralizes HTTP/HTTPS ingress for services on your LAN. Instead of maintaining per-service port-forwarding rules, a single nginx instance receives inbound requests and proxies them to the appropriate backend by hostname or path.
Use Cases
Section titled “Use Cases”- Reverse-proxy multiple LAN web services (NAS, home automation, cameras) through a single public IP and port
- Terminate TLS at the nginx container, forwarding plain HTTP to internal backends
- Add basic authentication or rate limiting without touching individual backend services
- Host custom internal HTTP services alongside standard router functions
Prerequisites
Section titled “Prerequisites”- RouterOS v7.4 or later with
containerpackage installed - External storage (USB, SATA, or NVMe)
- Device mode with container support enabled
- A prepared nginx configuration file
Networking Configuration
Section titled “Networking Configuration”Create a dedicated bridge and veth interface for the nginx container:
/interface/bridge/add name=br-proxy/ip/address/add address=172.19.0.1/24 interface=br-proxy/interface/veth/add name=veth-nginx address=172.19.0.2/24 gateway=172.19.0.1/interface/bridge/port/add bridge=br-proxy interface=veth-nginx/ip/firewall/nat/add chain=srcnat src-address=172.19.0.0/24 action=masqueradeForwarding WAN Traffic to the Container
Section titled “Forwarding WAN Traffic to the Container”Redirect inbound HTTP and HTTPS from the WAN interface to the nginx container:
/ip/firewall/nat/add chain=dstnat in-interface-list=WAN protocol=tcp dst-port=80 action=dst-nat to-addresses=172.19.0.2 to-ports=80/ip/firewall/nat/add chain=dstnat in-interface-list=WAN protocol=tcp dst-port=443 action=dst-nat to-addresses=172.19.0.2 to-ports=443If your firewall forward chain default policy is drop, add explicit accept rules:
/ip/firewall/filter/add chain=forward dst-address=172.19.0.2 protocol=tcp dst-port=80,443 action=accept place-before=0Accessing LAN Backends from the Container
Section titled “Accessing LAN Backends from the Container”nginx proxies requests to LAN backends (for example, 192.168.88.10). The container reaches LAN addresses through the RouterOS bridge if the br-proxy bridge is in the same L3 domain, or through the default gateway (172.19.0.1). Ensure firewall forward rules allow traffic from 172.19.0.0/24 to the target backend addresses.
nginx Configuration
Section titled “nginx Configuration”nginx requires a configuration file before the container starts. Create a configuration directory on external storage and upload your config:
/file/add name=disk1/nginx/conf type=directory/file/add name=disk1/nginx/logs type=directoryExample Configuration
Section titled “Example Configuration”Create disk1/nginx/conf/nginx.conf via FTP, SCP, or the RouterOS file editor:
worker_processes auto;
events { worker_connections 512;}
http { # Service A — route by hostname server { listen 80; server_name serviceA.example.com;
location / { proxy_pass http://192.168.88.10:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
# Service B — route by hostname server { listen 80; server_name serviceB.example.com;
location / { proxy_pass http://192.168.88.20:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }}Adjust server_name, proxy_pass targets, and ports to match your environment. For TLS termination, add a listen 443 ssl block and provide certificate paths mounted from router storage.
Storage Mounts
Section titled “Storage Mounts”/container/mounts/add name=nginx-conf src=disk1/nginx/conf dst=/etc/nginx/container/mounts/add name=nginx-logs src=disk1/nginx/logs dst=/var/log/nginxDeploying the Container
Section titled “Deploying the Container”/container/config/set registry-url=https://registry-1.docker.io tmpdir=disk1/tmp/container/add \ remote-image=nginx:alpine \ interface=veth-nginx \ root-dir=disk1/images/nginx \ mounts=nginx-conf,nginx-logs \ start-on-boot=yes \ logging=yes \ name=nginx-proxyWait for image extraction to complete:
/container/printStatus changes to stopped when extraction finishes.
Starting the Container
Section titled “Starting the Container”/container/start nginx-proxyVerify it is running:
/container/printResource Usage
Section titled “Resource Usage”The nginx Alpine image is lightweight and well-suited for RouterOS hardware:
| Resource | Typical Usage |
|---|---|
| RAM | 20–50 MB |
| CPU | Low (< 5% at typical LAN load) |
| Storage | ~10 MB image |
Apply resource limits to protect the router:
/container/set nginx-proxy memory-high=64MiB cpu-list=0See Container Resource Limits for details.
Troubleshooting
Section titled “Troubleshooting”Container exits immediately
Section titled “Container exits immediately”The most common cause is a malformed nginx.conf. Test your config before deploying using nginx’s check mode. If already deployed, check container logs:
/log print where topics~"container"Port 80/443 not reachable from WAN
Section titled “Port 80/443 not reachable from WAN”Confirm the container is running and the veth has its address:
/container/print/interface/veth/printVerify the dst-nat rules are present and in-interface-list is correct for your WAN interface:
/ip/firewall/nat/printContainer cannot reach LAN backends
Section titled “Container cannot reach LAN backends”Check that the router forwards traffic from 172.19.0.0/24 to backend addresses. Add a firewall forward accept rule if needed:
/ip/firewall/filter/add chain=forward src-address=172.19.0.0/24 dst-address=192.168.88.0/24 action=accept place-before=0Related Information
Section titled “Related Information”- Container — core container feature documentation
- VETH — virtual ethernet interface details
- Container Resource Limits — CPU and memory controls
- AdGuard Home — DNS filtering container example