Running Windows inside Docker using dockurr/windows is incredibly convenient, especially with its built-in noVNC web interface on port 8006.
Howeverβ¦
π¨ By default, that web interface has no authentication.
Anyone who reaches http://your-server:8006 can see your Windows desktop.
In this article, Iβll show you how to:
β
Hide port 8006 from the internet
β
Add a password prompt in front of noVNC
β
Use Nginx as a reverse proxy
β
Keep everything simple and Docker-based
π§± Architecture
Browser
|
v
Nginx (port 8080, password protected)
|
v
dockurr/windows (noVNC on 8006, localhost/internal only)
β Prerequisites
- Docker & Docker Compose installed
- Linux host (Ubuntu/Debian/VPS)
- Basic terminal knowledge
π Final docker-compose.yml
services:
windows:
image: dockurr/windows
container_name: windows
environment:
VERSION: "10l"
DISK_SIZE: "32G"
RAM_SIZE: "4G"
CPU_CORES: "2"
USERNAME: "test"
PASSWORD: "123123"
devices:
- /dev/kvm
- /dev/net/tun
cap_add:
- NET_ADMIN
ports:
- "127.0.0.1:8006:8006" # noVNC only on localhost
- 3389:3389/tcp
- 3389:3389/udp
volumes:
- ./storage:/storage
- ./shared:/shared
restart: always
stop_grace_period: 2m
networks:
- win_net
novnc_proxy:
image: nginx:alpine
container_name: novnc_proxy
depends_on:
- windows
ports:
- "8080:80" # public protected port
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./htpasswd:/etc/nginx/.htpasswd:ro
restart: always
networks:
- win_net
networks:
win_net:
driver: bridge
π Nginx Configuration (nginx.conf)
Create file: nginx.conf
server {
listen 80;
auth_basic "Protected noVNC";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
proxy_pass http://windows:8006;
# WebSocket support for noVNC
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
proxy_buffering off;
}
}
π Create Username & Password
Generate htpasswd file:
docker run --rm httpd:2.4-alpine \
htpasswd -nb admin STRONG_PASSWORD > htpasswd
Replace:
admin -> your username
STRONG_PASSWORD -> your password
βΆ Start Everything
docker compose up -d
π§ͺ Test
From another machine:
http://SERVER_IP:8006 β should NOT open
http://SERVER_IP:8080 β
shows login prompt
After login β Windows desktop appears.
π Extra Security Tips
- Use a long, strong password
- If you donβt need public RDP:
- "127.0.0.1:3389:3389/tcp"
- "127.0.0.1:3389:3389/udp"
- Consider VPN (Tailscale/WireGuard) for even stronger protection
- Add HTTPS later with Nginx + Letβs Encrypt
π― Result
You now have:
β
Hidden noVNC
β
Password-protected access
β
No changes inside Windows
β
Fully containerized solution
If this helped you, feel free to like or comment.
Happy self-hosting! π
Top comments (0)