NetLock RMMNetLock RMM Docs
III — How-To Guides

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_console

Create 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/internal

Create the appsettings.json file:

nano /home/netlock/web_console/appsettings.json

Fill 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/server

Create directories for Let's Encrypt and logs:

mkdir -p /home/netlock/server/letsencrypt
mkdir -p /home/netlock/server/logs

Create the persistent files directory used by the file server:

mkdir -p /home/netlock/server/files
mkdir -p /home/netlock/server/internal

Create the appsettings.json file:

nano /home/netlock/server/appsettings.json

Fill 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/16

Troubleshooting

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.

RolePurpose
CommHandles communication with the comm agent — device information, policy, and event synchronisation.
UpdateProvides update packages for the agents — comm agent, health agent, remote agent, installer, and uninstaller.
TrustProvides the hashes of all update packages. Agents contact the trust role to verify the hash of a downloaded package.
RemoteHandles real-time connections between agents and the Web Console, such as the remote shell and file browser.
NotificationSends third-party notifications — email, Microsoft Teams, Telegram, and ntfy.sh.
FileProvides the file storage service for downloading and uploading files.
LLMProvides the AI language-model integration for the intelligent features.
RelayHandles 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 MySQL block addresses the database server, and its NetLock_Remote_Server and NetLock_File_Server blocks address the backend.
  • The server's MySQL block 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.