How to Deploy Nginx Proxy Manager on MikroTik RouterOS Using Containers

mikrotik Aug 26, 2025

Use the MikroTik RouterOS device as a reverse proxy server using Nginx Proxy Manager container. This guide walks you through enabling container support on RouterOS v7.4+, setting up external storage to protect your device's flash memory, and deploying a fully functional reverse proxy with SSL certificate management.

Alert: for some reason, the container performance currently is terrible, without a proper solution. During my investigation, the CPU usage for containers is very limited no matter how powerful you router is:
- https://forum.mikrotik.com/t/horrible-container-performance-from-7-14-up-to-7-15rc2/175900/32

This guides was based on the following video:

Prerequisites

NOTE: RouterOS already provides a reverse proxy server but it doesn't have a so powerful feature set as Nginx Proxy Manager.

1. Enable Container Support on RouterOS

📖 Official Documentation: Container - MikroTik Documentation

Prerequisites:

  • RouterOS device with v7.4beta or later
  • Container package installed (available since RouterOS 7.18+ via System Packages, or manual installation)
  • Physical access to the device (required for container mode activation)
  • At least 512 MB of RAM

I'm using the "Chateau Pro ax / 7.19.4 (stable)".

Steps:

  1. First, install the container package if not already installed:
    • RouterOS 7.18+: Go to System > Packages > select Container package > Enable
    • Earlier versions: Download and install manually from MikroTik downloads
  2. Enable container support:
# Connect to your RouterOS via SSH or terminal
# Enable container support (requires physical confirmation)
/system/device-mode/update container=yes
  1. Important: After running the command, you'll see a message about "too many unsuccessful attempts". You must physically press the reset button or power cycle the device to confirm this change.
  2. Verify that container support is enabled:
/system/device-mode/print

📖 More Info: Device Mode Configuration

📖 Related Documentation: System Packages | Device Mode

Critical: Using external storage (HDD, SSD, or USB) is required for container operations. Internal flash memory can be damaged by constant read/write operations.

  1. Connect a USB storage device
  2. Format the drive with a RouterOS-supported filesystem:
# List available storage devices
/disk/print

# Format the USB drive (replace usb1 with your device name)
# Use ext4 filesystem with MBR partition table
/disk format usb1 file-system=ext4 label=containers mbr-partition-table=yes
  1. Configure container registry and storage:
# List available storage devices again to know which partition you will use
/disk/print

# Set registry URL and temporary directory on external storage
#   Note: this is optional, since I'm using the full path in the example.
/container/config/set registry-url=https://registry-1.docker.io tmpdir=usb1-part1/tmp

Deployment Steps

3. Network Configuration

📖 Network Documentation: Bridge Interface | Firewall NAT

First, set up the network infrastructure for containers:

# Create veth interface for the container
/interface/veth/add name=veth1 address=172.17.0.2/24 gateway=172.17.0.1 comment=Container

# Create bridge interface for container networking
/interface/bridge/add name=containers comment=Container
/ip/address/add address=172.17.0.1/24 interface=containers comment=Container

# Add veth to bridge
/interface/bridge/port/add bridge=containers interface=veth1 comment=Container

# Add NAT rule for outgoing traffic
/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.17.0.0/24 comment=Container

4. Deploy Nginx Proxy Manager Container

📖 Container Management: Container Commands | NPM Docker Hub

Now deploy the Nginx Proxy Manager container:

# List available storage devices again to know which partition you will use
/disk/print

# First, create mount points for persistent data storage
/container/mounts/add name=npm-data src=usb1-part1/npm-data dst=/data
/container/mounts/add name=npm-letsencrypt src=usb1-part1/npm-letsencrypt dst=/etc/letsencrypt

# Add and configure the Nginx Proxy Manager container
#   Note: to get the latest image, go to Docker Hub and
#         grab the offical digest for linux/arm64:
#         https://hub.docker.com/r/jc21/nginx-proxy-manager/tags
/container/add remote-image=docker.io/jc21/nginx-proxy-manager:latest@sha256:6ab097814f54b1362d5fd3c5884a01ddd5878aaae9992ffd218439180f0f92f3 interface=veth1 root-dir=usb1-part1/npm-container logging=yes start-on-boot=yes mounts=npm-data,npm-letsencrypt name=nginx-proxy-manager
# (this may take a long time 10min+, you can check the WinBox GUI for status or print it as shown below)

# Start the container (replace [number] with actual container number from print command)
/container/print
/container/start [number]

5. Configure External Network Access

📖 Firewall Documentation: Firewall Filter Rules | NAT Rules

Port Conflict Solution:

Since Nginx Proxy Manager exposes ports 80 and 443 which are already used by RouterOS, we need to create a separate IP address for the container interface to avoid port collisions.

First, add a secondary IP address to your main interface:

# Add a secondary IP address to your main interface (adjust interface name as needed)
# Example: if your router's main IP is 192.168.88.1, add 192.168.88.4
/ip/address/add address=192.168.88.4/24 interface=bridge comment="Container services"

# Verify the new IP address was added
/ip/address/print

Then configure NAT rules to forward traffic to the container, using the new IP address as destination:

# Add firewall rules to allow access to the web interface
# Forward traffic to the new IP address (192.168.88.4) to the container
/ip/firewall/nat/add chain=dstnat protocol=tcp dst-address=192.168.88.4 dst-port=81 action=dst-nat to-addresses=172.17.0.2 to-ports=81 comment="NPM Admin Interface"
/ip/firewall/nat/add chain=dstnat protocol=tcp dst-address=192.168.88.4 dst-port=80 action=dst-nat to-addresses=172.17.0.2 to-ports=80 comment="NPM HTTP"
/ip/firewall/nat/add chain=dstnat protocol=tcp dst-address=192.168.88.4 dst-port=443 action=dst-nat to-addresses=172.17.0.2 to-ports=443 comment="NPM HTTPS"

Access Methods:

  • NPM Admin Interface: http://192.168.88.4:81 (instead of main router IP)
  • HTTP Traffic: http://192.168.88.4:80
  • HTTPS Traffic: https://192.168.88.4:443

This approach completely eliminates port conflicts while maintaining full functionality.

6. First Time Setup

📖 NPM Setup Guide: Nginx Proxy Manager Quick Setup

After deployment, access the Nginx Proxy Manager web interface:

  1. Open your web browser and navigate to http://192.168.88.4:81
  2. Default login credentials:
    • Email: admin@example.com
    • Password: changeme
  3. Change the default credentials immediately after first login

Performance Optimization

📖 Container Documentation: Container Performance

Memory Optimization

Configure memory limits to prevent the container from consuming excessive RAM:

# Set soft RAM limit for containers (recommended: 200M-500M for NPM)
/container/config/set ram-high=300M

# Verify the configuration
/container/config/print

Important Notes:

  • Memory limits in RouterOS 7.14+ may cause slow container startup
  • If experiencing performance issues, try removing the limit: /container/config/set ram-high=0
  • Monitor memory usage: /system/resource/print

Storage Performance

For optimal performance, ensure you're using fast external storage:

# Check current disk performance
/system/resource/print

# Monitor disk usage
/disk/print

# Use faster storage options when possible:
# - USB 3.0 drives over USB 2.0
# - SSD over HDD via USB-to-SATA adapters
# - NVMe drives if supported by your device

Container Resource Monitoring

Monitor your container performance with these commands:

# Check overall system resources
/system/resource/print

# View container status and resource usage
/container/print detail

# Check container logs for performance issues
/container/log/print name=nginx-proxy-manager

# Monitor network performance
/interface/monitor-traffic interface=veth1 duration=10

Performance Troubleshooting

If experiencing slow container performance:

  1. Use faster external storage (SSD recommended over USB drives)

Monitor for memory pressure:

/log/print where topics~"system" and message~"memory"

Restart the container:

/container/stop nginx-proxy-manager
/container/start nginx-proxy-manager

Disable memory limits temporarily:

/container/config/set ram-high=0

Check RouterOS version: Versions 7.14+ have known performance issues

/system/package/update/print

Known Limitations:

  • CPU limits are not available in RouterOS (feature requested)
  • Memory limits may cause startup delays in newer RouterOS versions
  • Container performance varies significantly based on external storage speed

Maintenance

📖 Container Management: Container Operations

Upgrading Nginx Proxy Manager

To update to the latest version of Nginx Proxy Manager:

# First, check current containers and note the container number
/container/print

# Stop the current container (replace [number] with actual container number)
/container/stop [number]

# Remove the old container (data is preserved in mounted volumes)
/container/remove [number]

# Add the updated container with latest image (mounts should already exist)
#   Note: to get the latest image, go to Docker Hub and
#         grab the offical digest for linux/arm64:
#         https://hub.docker.com/r/jc21/nginx-proxy-manager/tags
/container/add remote-image=docker.io/jc21/nginx-proxy-manager:latest@sha256:6ab097814f54b1362d5fd3c5884a01ddd5878aaae9992ffd218439180f0f92f3 interface=veth1 root-dir=usb1-part1/npm-container logging=yes start-on-boot=yes mounts=npm-data,npm-letsencrypt name=nginx-proxy-manager
# (this may take a long time 10min+, you can check the WinBox GUI for status or print it as shown below)

# Check the new container number and start it
/container/print
/container/start [new-number]

Container Management Commands

Essential commands for managing your containers:

# List all containers with their status and numbers
/container/print

# Start a container
/container/start [number]

# Stop a container
/container/stop [number]

# Access container shell (for troubleshooting)
/container/shell [number]

# View container configuration
/container/print detail where .id=[number]

# View system logs for container activity
/log/print where topics~"container"

# Monitor container resource usage
/system/resource/print

Backup Recommendations

📖 File System: Files and Folders | NPM Backup Guide

Regularly backup your container data from external storage:

# Important directories to backup from your external drive:
# - usb1-part1/npm-data (contains database and configuration)
# - usb1-part1/npm-letsencrypt (contains SSL certificates)

# You can access these via SFTP/SCP or by mounting the drive on another system
# Example: backup via RouterOS file system
/file/print where name~"usb1-part1"

Security Considerations

📖 Security Documentation: Container Security

⚠️ Important Security Warning: If your RouterOS device is compromised, containers can be used to easily install malicious software. Ensure proper security measures:

  • Keep RouterOS updated to the latest stable version
  • Use strong authentication credentials
  • Limit access to the RouterOS device
  • Regularly monitor container activities and logs
  • Only run trusted container images from reputable sources

Troubleshooting

Common Issues

  1. Container fails to start: Check if container mode is properly enabled and device was rebooted
    • Verify: /system/device-mode/print shows container=yes
    • Check logs: /log/print where topics~"container"
  2. Web interface not accessible: Verify firewall rules and network configuration
    • Test container networking: /ping 172.17.0.2
    • Check NAT rules: /ip/firewall/nat/print
  3. SSL certificate issues: Ensure proper port forwarding (80/443) from your internet router to the RouterOS device
    • Verify Let's Encrypt can reach your domain on ports 80/443
    • Check NPM logs for certificate errors
  4. Storage issues: Monitor USB drive health and free space regularly
    • Check disk usage: /system/resource/print
    • Verify mount status: /disk/print
  5. Container won't pull image: Check internet connectivity and registry access
    • Test DNS resolution: /ping registry-1.docker.io
    • Verify registry URL: /container/config/print

Additional Resources

MikroTik RouterOS Documentation

Nginx Proxy Manager Documentation

Community Resources

Tags

Luiz Costa

I am a senior software engineer at Red Hat / Ansible. I love automation tools, games, and coffee. I am also an active contributor to open-source projects.