DEV Community

Cover image for QNAP Container Station: Free Up Ports 80 & 443 for Docker Reverse Proxy
Alessandro Mainardi
Alessandro Mainardi

Posted on Originally published at alexmaina.dev

QNAP Container Station: Free Up Ports 80 & 443 for Docker Reverse Proxy

📖 Original Reference: Originally published with complete step-by-step storage configurations at alexmaina.dev/qnap-docker-reverse-proxy.

When trying to deploy a Reverse Proxy (like Nginx Proxy Manager, Traefik, or Caddy) inside QNAP's Container Station, Docker will fail with:

Error response from daemon: driver failed programming external connectivity on endpoint: bind: address already in use
Enter fullscreen mode Exit fullscreen mode

This happens because QNAP's operating system (QTS or QuTS hero) occupies port 80 and port 443 by default for its administrative interface and built-in web server.

Here is how to liberate both ports cleanly and set up a centralized reverse proxy without breaking access to your NAS.


Step 1: Move QTS Admin System Ports

  1. Log into your QTS web dashboard.
  2. Go to Control Panel → System → General Settings.
  3. Under the System Administration section:
    • System port (HTTP): Change from 8080 (or 80) to 8088.
    • Enable secure connection (HTTPS): Change from 443 (or 4433) to 8443.
    • Uncheck: "Redirect HTTP connection to HTTPS" if bound to port 80.
  4. Click Apply. Your browser will reload at https://NAS-IP:8443.

Step 2: Disable the Built-in Apache Web Server

Even with admin ports moved, QTS runs a background Apache server that listens on port 80.

  1. In Control Panel, navigate to Applications → Web Server.
  2. Uncheck Enable Web Server (or change its listening ports to 8085 and 8445).
  3. Click Apply.

Ports 80 and 443 are now completely free on the physical network interface!


Step 3: Deploy Nginx Proxy Manager with Docker Compose

Open Container Station → Applications → Create, and paste this clean docker-compose.yml:

version: '3.8'

services:
  npm-app:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: nginx-proxy-manager
    restart: unless-stopped
    ports:
      - '80:80'    # Public HTTP port now available
      - '443:443'  # Public HTTPS port now available
      - '81:81'    # NPM Web Admin Dashboard
    environment:
      DB_MYSQL_HOST: "npm-db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm"
      DB_MYSQL_PASSWORD: "SuperSecureDBPassword2026!"
      DB_MYSQL_NAME: "npm"
    volumes:
      - /share/Container/npm/data:/data
      - /share/Container/npm/letsencrypt:/etc/letsencrypt
    depends_on:
      - npm-db
    networks:
      - homelab-net

  npm-db:
    image: 'mariadb:10.11'
    container_name: npm-database
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: "RootSecretPassword2026!"
      MYSQL_DATABASE: "npm"
      MYSQL_USER: "npm"
      MYSQL_PASSWORD: "SuperSecureDBPassword2026!"
    volumes:
      - /share/Container/npm/mysql:/var/lib/mysql
    networks:
      - homelab-net

networks:
  homelab-net:
    name: homelab-net
    driver: bridge
Enter fullscreen mode Exit fullscreen mode

Step 4: Route Container Traffic Internally

With all your containers attached to homelab-net:

  • You no longer need to expose ports to the host for individual services (WordPress, Nextcloud, etc.).
  • Access NPM dashboard at http://NAS-IP:81 (Default credentials: admin@example.com / changeme).
  • Add a Proxy Host with your domain name and set Forward Hostname to the internal container name (e.g. wordpress-app) on port 80.
  • Request a free Let's Encrypt SSL certificate directly through NPM.

Author: Alessandro Mainardi — Software Developer & Computer Engineering Student @ UniBo. Explore homelab architectures at alexmaina.dev.

Top comments (0)