Install the NetLock RMM server with Docker
Deploy the NetLock RMM server and Web Console on your own infrastructure with Docker, using the guided installer or a manual Docker Compose setup.
Install the NetLock RMM server with Docker
Self-hosted only: This guide applies to self-hosted deployments. Cloud customers do not install the server — the hosted platform is run for them.
This guide covers installing the NetLock RMM server and Web Console with Docker. Both can run in the cloud or in an offline environment, depending on your requirements. Two methods are described: a guided installer that generates the setup for a standard server, and a manual Docker Compose setup for full control.
Network structure
Agents only make outgoing connections, so no port forwarding is required on the managed machines. The Web Console renders content server-side and sends it to the administrator's browser, so a persistent connection between the Web Console and the administrator is required during operation.
The Web Console communicates either directly with the SQL server or, for real-time features such as the remote shell and file browser, with the NetLock Remote Server over SignalR. Make sure the Web Console can reach the NetLock Remote Server.
Warning: The Web Console should only be reachable from trusted networks.
Guided installation
NetLock RMM can be deployed in any environment with Docker support, including setups behind Cloudflare tunnels and similar. The guided script builder targets typical server installations.
For help deploying NetLock RMM in non-standard environments, contact the support team.
Open the installation tool and follow its steps: https://netlockrmm.com/install
Manual installation
For full control, install the stack manually with Docker Compose.
Requirements
- The latest version of Docker.
- MySQL Server, version 8.0 or newer.
- 2 CPU cores — more may be needed depending on how many agents you monitor.
- 8 GB RAM.
Note: The 8 GB RAM requirement supports the high-performance, memory-optimised update delivery. With insufficient RAM the setup may fail, or NetLock RMM may run slowly because it falls back to swap space. The backend is efficient — 8 GB is sufficient for 2,000 or more devices.
The Docker images are published under the latest tag.
Warning: The database name, password, domains, time zone, and Members Portal API key in the templates below are examples. Replace every one of them with values for your own environment before deploying.
Web Console
Create a directory for the appsettings.json file:
mkdir -p /home/netlock/web_consoleCreate directories for Let's Encrypt, internal data, and logs:
mkdir -p /home/netlock/web_console/letsencrypt
mkdir -p /home/netlock/web_console/logs
mkdir -p /home/netlock/web_console/internalCreate the appsettings.json file:
nano /home/netlock/web_console/appsettings.jsonFill it in with your configuration:
{
"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 to match your environment.
Server
Create a directory for the appsettings.json file:
mkdir -p /home/netlock/serverCreate directories for Let's Encrypt and logs:
mkdir -p /home/netlock/server/letsencrypt
mkdir -p /home/netlock/server/logsCreate the persistent files directory used by the file server:
mkdir -p /home/netlock/server/files
mkdir -p /home/netlock/server/internalCreate the appsettings.json file:
nano /home/netlock/server/appsettings.jsonFill it in with your configuration:
{
"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
}
}The Roles block decides which server roles this instance runs — see Server roles below.
Docker Compose
The following docker-compose.yml brings up Traefik (as a reverse proxy handling Let's Encrypt certificates), MySQL, the Web Console, and the server:
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/16Troubleshooting
To view a container's logs, use:
docker logs <container-id>Server roles
The NetLock RMM server runs in eight roles. Each is toggled in the server's appsettings.json under the Roles block; a single instance can run all of them, or they can be split across multiple instances.
| Role | Purpose |
|---|---|
Comm | Handles communication with the comm agent — device information, policy, and event synchronisation. |
Update | Provides update packages for the agents — comm agent, health agent, remote agent, installer, and uninstaller. |
Trust | Provides the hashes of all update packages. Agents contact the trust role to verify the hash of a downloaded package. |
Remote | Handles real-time connections between agents and the Web Console, such as the remote shell and file browser. |
Notification | Sends third-party notifications — email, Microsoft Teams, Telegram, and ntfy.sh. |
File | Provides the file storage service for downloading and uploading files. |
LLM | Provides the AI language-model integration for the intelligent features. |
Relay | Handles persistent TCP connections for real-time agent communication and data relay. |
Advanced server concept
The Docker Compose setup above runs every component — the reverse proxy, MySQL, the Web Console, and the NetLock RMM server — on a single host. This is the recommended starting point and is sufficient for most deployments.
For larger fleets or specific infrastructure requirements, the three main components can instead run on separate servers: the MySQL database, the NetLock RMM server (the backend), and the Web Console.
The components communicate over the network, so nothing forces them onto the same machine. Each one is pointed at the others through its appsettings.json:
- The Web Console's
MySQLblock addresses the database server, and itsNetLock_Remote_ServerandNetLock_File_Serverblocks address the backend. - The server's
MySQLblock addresses the database server.
In the single-host Compose setup these settings use Docker container names (mysql-container, netlock-rmm-server) because every component shares one Docker network. In a distributed setup, you replace those with the hostnames or IP addresses of the separate servers.
Splitting the deployment this way lets you size and scale each component independently — for example, running MySQL on dedicated database infrastructure, or keeping the Web Console and the backend on separate hosts.
Related
- A.1 — System overview & licensing — the read-only system health and licence pages on a running deployment.
- Upgrade NetLock RMM — pulling new container images once the stack is running.
- Deploy your first agent — the next step once the server is up.