Complete guide to deploying NetLock RMM Server using Docker. Covers both automated and manual installation methods.
In this guide, we will cover the basic server installation. The server and web console can be installed either in the cloud or in offline environments, depending on your specific requirements.

The agents only perform outgoing connections, so port forwarding is not required on these machines. The web console renders the content server-sided and then sends it to the admin user's browser. Therefore, a permanent connection between the web console and admin user is necessary for operation.
The web console communicates either directly with the SQL server or contacts the NetLock remote server through SignalR in cases like using the remote shell and file browser for real-time processes. Ensure the connection between the web console and NetLock remote server is possible. The web console should only be accessible from trusted environments.
NetLock RMM can be deployed in any environment with Docker support. This also includes setups like Cloudflare tunnels or similar. Our script builder focuses on typical server installations.
If you need assistance in the deployment of NetLock RMM in non-standard environments, consider reaching out to our support team for guidance.
Navigate to our installation tool and follow the steps:
Open Installation ToolHappy monitoring! 🥳
Note: For high-performance, memory-optimized updates. If insufficient RAM is available, the setup may fail or NetLock RMM may run more slowly due to reliance on swap space. The backend is highly efficient, and 8 GB of RAM is sufficient for at least 2,000+ devices.
The following tags are available: latest
mkdir -p /home/netlock/web_consolemkdir -p /home/netlock/web_console/letsencrypt
mkdir -p /home/netlock/web_console/logs
mkdir -p /home/netlock/web_console/internalnano /home/netlock/web_console/appsettings.json{
"Logging": {
"LogLevel": {
"Default": "Warning",
"Microsoft": "Error",
"Microsoft.Hosting.Lifetime": "Warning"
},
"Custom": {
"Enabled": false
}
},
"AllowedHosts": "*",
"Kestrel": {
"Endpoint": {
"Http": {
"Enabled": true,
"Port": 80
},
"Https": {
"Enabled": false,
"Port": 443,
"Force": false,
"Hsts": {
"Enabled": true
},
"Certificate": {
"Path": "/certificates/certificate.pfx",
"Password": ""
}
}
},
"IpWhitelist": [],
"KnownProxies": ["172.18.0.2"]
},
"NetLock_Remote_Server": {
"Server": "netlock-rmm-server",
"Port": 7080,
"UseSSL": false
},
"NetLock_File_Server": {
"Server": "netlock-rmm-server",
"Port": 7080,
"UseSSL": false
},
"MySQL": {
"Server": "mysql-container",
"Port": 3306,
"Database": "vwffyq",
"User": "root",
"Password": "frfsL9FGmQWGbZDM",
"SslMode": "None",
"AdditionalConnectionParameters": "AllowPublicKeyRetrieval=True;"
},
"Webinterface": {
"Title": "NetLock RMM On Premises",
"Language": "en-US",
"Membership_Reminder": false,
"PublicOverrideUrl": "https://nl-webconsole.penguin-monitoring.de"
},
"Members_Portal_Api": {
"Enabled": true,
"ApiKeyOverride": "YOUR-MEMBERS-PORTAL-API-KEY"
}
}Adjust the values according to your environment's requirements.
mkdir -p /home/netlock/servermkdir -p /home/netlock/server/letsencrypt
mkdir -p /home/netlock/server/logsmkdir -p /home/netlock/server/files
mkdir -p /home/netlock/server/internalnano /home/netlock/server/appsettings.json{
"Logging": {
"LogLevel": {
"Default": "Warning",
"Microsoft": "Error",
"Microsoft.Hosting.Lifetime": "Warning",
"Microsoft.AspNetCore.SignalR": "Error",
"Microsoft.AspNetCore.Http.Connections": "Error"
},
"Custom": {
"Enabled": false
}
},
"AllowedHosts": "*",
"Kestrel": {
"Endpoint": {
"Http": {
"Enabled": true,
"Port": 7080
},
"Https": {
"Enabled": false,
"Port": 7443,
"Force": false,
"Hsts": {
"Enabled": true
},
"Certificate": {
"Path": "/certificates/certificate.pfx",
"Password": ""
}
}
},
"Roles": {
"Comm": true,
"Update": true,
"Trust": true,
"Remote": true,
"Notification": true,
"File": true,
"LLM": true,
"Relay": true
}
},
"Relay_Server": {
"Port": 7081
},
"MySQL": {
"Server": "mysql-container",
"Port": 3306,
"Database": "vwffyq",
"User": "root",
"Password": "frfsL9FGmQWGbZDM",
"SslMode": "None",
"AdditionalConnectionParameters": "AllowPublicKeyRetrieval=True;"
},
"Members_Portal_Api": {
"Enabled": true,
"ApiKeyOverride": "YOUR-MEMBERS-PORTAL-API-KEY"
},
"Environment": {
"Docker": true
}
}services:
traefik:
image: traefik:latest
container_name: traefik
command:
- '--providers.docker=true'
- '--providers.docker.exposedbydefault=false'
- '--entrypoints.web.address=:80'
- '--entrypoints.websecure.address=:443'
- '--entrypoints.web.http.redirections.entryPoint.to=websecure'
- '--entrypoints.web.http.redirections.entryPoint.scheme=https'
- '--entrypoints.web.http.redirections.entryPoint.permanent=true'
- '--certificatesresolvers.myresolver.acme.httpchallenge=true'
- '--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web'
- '--certificatesresolvers.myresolver.acme.email=support@netlockrmm.com'
- '--certificatesresolvers.myresolver.acme.storage=/certificates/acme.json'
ports:
- '80:80'
- '443:443'
volumes:
- '/var/run/docker.sock:/var/run/docker.sock:ro'
- '/home/netlock/certificates/traefik:/certificates'
networks:
netlock-network:
ipv4_address: 172.18.0.2
restart: always
mysql:
image: mysql:8.0
container_name: mysql-container
environment:
MYSQL_ROOT_PASSWORD: "frfsL9FGmQWGbZDM"
MYSQL_DATABASE: "vwffyq"
volumes:
- /home/netlock/mysql/data:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
networks:
netlock-network:
ipv4_address: 172.18.0.3
restart: always
command:
- --skip-log-bin
- --innodb_buffer_pool_size=1G
- --innodb_log_file_size=256M
- --innodb_flush_log_at_trx_commit=2
- --max_connections=200
netlock-rmm-web-console:
image: nicomak101/netlock-rmm-web-console:latest
container_name: netlock-rmm-web-console
environment:
- TZ=Europe/Berlin
volumes:
- '/home/netlock/web_console/appsettings.json:/app/appsettings.json'
- '/home/netlock/web_console/internal:/app/internal'
- '/home/netlock/web_console/logs:/var/0x101 Cyber Security/NetLock RMM/Web Console/'
- '/home/netlock/certificates:/app/certificates'
- /etc/localtime:/etc/localtime:ro
labels:
- 'traefik.enable=true'
- "traefik.http.routers.webconsole.rule=Host(\`nl-webconsole.penguin-monitoring.de\`)"
- 'traefik.http.routers.webconsole.entrypoints=websecure'
- 'traefik.http.routers.webconsole.tls.certresolver=myresolver'
- 'traefik.http.services.webconsole.loadbalancer.server.port=80'
- "traefik.http.routers.webconsole-http.rule=Host(\`nl-webconsole.penguin-monitoring.de\`)"
- 'traefik.http.routers.webconsole-http.entrypoints=web'
- 'traefik.http.routers.webconsole-http.middlewares=redirect-to-https'
- 'traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https'
networks:
netlock-network:
ipv4_address: 172.18.0.4
restart: always
depends_on:
- mysql
netlock-rmm-server:
image: nicomak101/netlock-rmm-server:latest
container_name: netlock-rmm-server
environment:
- TZ=Europe/Berlin
volumes:
- '/home/netlock/server/appsettings.json:/app/appsettings.json'
- '/home/netlock/server/internal:/app/internal'
- '/home/netlock/server/files:/app/www/private/files'
- '/home/netlock/server/logs:/var/0x101 Cyber Security/NetLock RMM/Server/'
- '/home/netlock/certificates:/app/certificates'
- /etc/localtime:/etc/localtime:ro
labels:
- 'traefik.enable=true'
- "traefik.http.routers.rmmserver.rule=Host(\`nl-backend.penguin-monitoring.de\`)"
- 'traefik.http.routers.rmmserver.entrypoints=websecure'
- 'traefik.http.routers.rmmserver.tls.certresolver=myresolver'
- 'traefik.http.services.rmmserver.loadbalancer.server.port=7080'
- "traefik.http.routers.rmmserver-http.rule=Host(\`nl-backend.penguin-monitoring.de\`)"
- 'traefik.http.routers.rmmserver-http.entrypoints=web'
- 'traefik.http.routers.rmmserver-http.middlewares=redirect-to-https'
- "traefik.tcp.routers.relay-tcp.rule=HostSNI(\`nl-relay.penguin-monitoring.de\`)"
- 'traefik.tcp.routers.relay-tcp.entrypoints=websecure'
- 'traefik.tcp.routers.relay-tcp.tls=true'
- 'traefik.tcp.routers.relay-tcp.tls.certresolver=myresolver'
- 'traefik.tcp.routers.relay-tcp.tls.passthrough=false'
- 'traefik.tcp.routers.relay-tcp.service=relay-tcp'
- 'traefik.tcp.services.relay-tcp.loadbalancer.server.port=7081'
networks:
netlock-network:
ipv4_address: 172.18.0.5
restart: always
depends_on:
- mysql
networks:
netlock-network:
driver: bridge
ipam:
config:
- subnet: 172.18.0.0/16To view container logs, use:
docker logs CONTAINERIDThe NetLock server comes in eight different roles:
Handles communication with the NetLock comm agent, including device information, policy, and events synchronization.
Provides update packages for the agents, including the comm agent, health agent, remote agent, agent installer, and agent uninstaller.
Provides the hashes of all update packages. Agents contact the trust server to verify the hashes of downloaded packages.
Handles real-time connections between agents and the web console, such as the remote shell and file browser.
Sends third-party notifications, such as email, Microsoft Teams, Telegram, and ntfy.sh.
Provides a file storage service for downloading and uploading files. This can be used to download tools or files on the customer side.
Provides AI-powered language model integration for intelligent automation and analysis features.
Handles persistent TCP connections for real-time agent communication and data relay functionality.

The agents only perform outgoing connections, so port forwarding is not required on these machines. The web console renders the content server-sided and then sends it to the user's browser. Therefore, a permanent connection between the web console and user is necessary for operation.

In addition to using load balancers in your network, splitting the NetLock server into different roles can improve response times.
By dividing the server into different roles, you can significantly enhance security, especially against supply chain attacks like those seen with SolarWinds or Kaseya.
A classic update server supply chain attack works by supplying malicious update packages through a compromised update server to installed agents.
The NetLock comm agent contacts the NetLock comm server to verify if it is up-to-date. If the server indicates that it is outdated, the agent contacts the NetLock update server and downloads the NetLock agent installer. Before executing it, the NetLock comm agent contacts the NetLock trust server to request the hash of the downloaded package.
If the local package hash differs from the hash provided by the NetLock trust server, the agent will not execute the downloaded installer. In summary, if an attacker compromises your NetLock update server, they would still need to compromise the NetLock trust server to deploy a malicious update.