-
-
Save Zahorone/984e75c6a3e8c4a1706f81b6c5e55071 to your computer and use it in GitHub Desktop.
Rustdesk + Nginx proxy manager + permanent setting of NFTables to suppress Docker bypass of UFW
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| version: '3' | |
| networks: | |
| rustdesk-net: | |
| external: false | |
| services: | |
| nginx-proxy-manager: | |
| image: 'jc21/nginx-proxy-manager:latest' | |
| restart: unless-stopped | |
| ports: | |
| # These ports are in format <host-port>:<container-port> | |
| - '80:80' # Public HTTP Port | |
| - '443:443' # Public HTTPS Port | |
| - '127.0.0.1:8081:81' # Admin Web Port. NPM bypass UFW. 127.0.0.1 is easy setting to fix it from localhost only. | |
| # Add any other Stream port you want to expose | |
| # - '21:21' # FTP | |
| # Ports needed for Rustdesk: | |
| - '21115:21115' | |
| - '21116:21116' | |
| - '21116:21116/udp' | |
| - '21117:21117' | |
| - '21118:21118' | |
| - '21119:21119' | |
| # Uncomment the next line if you uncomment anything in the section | |
| # environment: | |
| # Uncomment this if you want to change the location of | |
| # the SQLite DB file within the container | |
| # DB_SQLITE_FILE: "/data/database.sqlite" | |
| # Uncomment this if IPv6 is not enabled on your host/ | |
| # DISABLE_IPV6: 'true' | |
| volumes: | |
| - ./data:/data | |
| - ./letsencrypt:/etc/letsencrypt | |
| networks: | |
| - rustdesk-net | |
| hbbs: | |
| container_name: hbbs | |
| image: rustdesk/rustdesk-server:latest | |
| command: hbbs -r rustdesk.yourDomain.com:21117 | |
| volumes: | |
| - ./data:/root | |
| networks: | |
| - rustdesk-net | |
| depends_on: | |
| - hbbr | |
| restart: unless-stopped | |
| hbbr: | |
| container_name: hbbr | |
| image: rustdesk/rustdesk-server:latest | |
| command: hbbr | |
| volumes: | |
| - ./data:/root | |
| networks: | |
| - rustdesk-net | |
| restart: unless-stopped |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you want to change NFT (IP) tables instead of changing line 16 - '127.0.0.1:8081:81' in docker-compose.yml
Here is how to do it.
Problem: DOCKER-USER Chain Rules Disappear After Reboot
After server restart, the DOCKER-USER chain is empty and custom firewall rules (e.g., blocking port 8081) disappear.
Root Cause
Docker completely resets its firewall on every startup. The daemon clears all custom rules and recreates the necessary chains (DOCKER, DOCKER-ISOLATION, DOCKER-USER). Since
/etc/nftables.confloads before the Docker service starts, Docker subsequently overwrites any custom modifications inDOCKER-USER.Solution: Systemd Service with Automatic Rule Injection
Step 1: Create Firewall Rules Script
sudo nano /usr/local/bin/docker-firewall-rules.shScript content:
This version includes all the status messages so it’s easy to see which rules were removed,
left unchanged, newly added, or already present in your firewall.
It's fully idempotent and always logs every action
Make it executable:
sudo chmod +x /usr/local/bin/docker-firewall-rules.shStep 2: Create Systemd Service Unit
sudo nano /etc/systemd/system/docker-firewall.serviceService file content:
This service runs automatically after the Docker daemon starts, ensuring rules are added only after Docker creates its chains.
Step 3: Enable the Service
Step 4: Verify Functionality
Check if the rule was added:
sudo nft list ruleset | grep -A 5 'chain DOCKER-USER'Expected output:
Testing Persistence After Reboot
Reboot the server:
sudo rebootAfter reboot, verify the rule persists:
sudo nft list ruleset | grep -A 5 'chain DOCKER-USER'Troubleshooting
If rules still disappear, check service status:
The service should show Active: active (exited) with status=0/SUCCESS.