Skip to content

OpenAppSec attachment module fails with corrupted shared memory / missing nano service on NPMplus develop #67

Description

@fulviocri

Summary

I am trying to enable the OpenAppSec attachment module in NPMplus using the current develop image and a Docker Compose configuration derived from the current upstream example.

The OpenAppSec agent starts correctly and appears to be registered/healthy, but when NGINX_LOAD_OPENAPPSEC_ATTACHMENT_MODULE=true is enabled in the NPMplus container, the Nginx attachment module repeatedly fails during IPC/shared-memory initialization.

Depending on the test, the logs show either:

Detected corrupted shared memory queue. Shared memory name: 3
Shared memory is corrupted! restarting communication

or:

Could not connect to nano service.
Path: /dev/shm/check-point/cp-nano-http-transaction-handler-2
Error: No such file or directory

The issue persists after recreating the shared-memory volume and redeploying the stack.

Environment

  • NPMplus image: docker.io/zoeyvid/npmplus:develop
  • OpenAppSec agent image: ghcr.io/openappsec/agent:latest
  • OpenAppSec agent version observed: 1.1.33
  • Deployment method: Docker Compose stack managed through Portainer
  • Docker networking:
    • NPMplus attached to two external bridge networks:
      • APPSEC_NET
      • NPMPLUS_NET
    • OpenAppSec agent attached to APPSEC_NET
  • NPMplus is not using network_mode: host; it uses explicit published ports.

Relevant compose excerpt

Sensitive values replaced with placeholders. This is the effective compose currently in use after rollback; the issue is reproduced by changing NGINX_LOAD_OPENAPPSEC_ATTACHMENT_MODULE=false to true and redeploying.

name: npmplus

services:
    npmplus:
        container_name: npmplus
        image: docker.io/zoeyvid/npmplus:develop
        restart: unless-stopped
        networks:
            - APPSEC_NET
            - NPMPLUS_NET
        ipc: host
        cap_drop:
            - ALL
        cap_add:
            - NET_BIND_SERVICE
            - SETGID
        security_opt:
            - no-new-privileges:true
        ports:
            - "<host-ip>:80:80/tcp"
            - "<host-ip>:81:81/tcp"
            - "<host-ip>:443:443/tcp"
            - "<host-ip>:443:443/udp"
            - "<host-ip>:10050:10050/tcp"
            - "<host-ip>:10050:10050/udp"
            - "<host-ip>:10051:10051/tcp"
            - "<host-ip>:10051:10051/udp"
        volumes:
            - "npm_data:/data"
            - "shm_data:/dev/shm/check-point"
        environment:
            - "TZ=Europe/Rome"
            - "ACME_EMAIL=<redacted-email>"
            - "ACME_SERVER=https://acme-v02.api.letsencrypt.org/directory"
            - "ACME_PROFILE=shortlived"
            - "ACME_KEY_TYPE=ecdsa"
            - "ACME_SERVER_TLS_VERIFY=true"
            - "NPM_PORT=81"
            - "IPV4_BINDING=0.0.0.0"
            - "NPM_IPV4_BINDING=0.0.0.0"
            - "DISABLE_IPV6=true"
            - "NPM_LISTEN_LOCALHOST=false"
            - "GOA_LISTEN_LOCALHOST=false"
            - "DEFAULT_CERT_ID=0"
            - "HTTP_PORT=80"
            - "HTTPS_PORT=443"
            - "DISABLE_HTTP=false"
            - "LISTEN_PROXY_PROTOCOL=false"
            - "LISTEN_PROXY_PROTOCOL_HTTP=false"
            - "LISTEN_PROXY_PROTOCOL_HTTPS=false"
            - "DISABLE_H3_QUIC=false"
            - "NGINX_QUIC_BPF=false"
            - "NGINX_LOG_NOT_FOUND=true"
            - "NGINX_WORKER_PROCESSES=1"
            - "NGINX_WORKER_CONNECTIONS=512"
            - "NGINX_FORCE_X25519MLKEM768=false"
            - "NGINX_DISABLE_TLS12=false"
            - "NGINX_TRUST_SECPR1=true"
            - "DISABLE_NGINX_BEAUTIFIER=false"
            - "LOGROTATE=true"
            - "LOGROTATIONS=7"
            - "TRUST_CLOUDFLARE=false"
            - "CERTBOT_RUN_INTERVAL=3"
            - "ECH_ROTATION_INTERVAL=1"
            - "GOA=false"
            - "PHP83=false"
            - "PHP84=false"
            - "PHP85=false"
            - "INITIAL_ADMIN_EMAIL=<redacted-email>"
            - "INITIAL_ADMIN_PASSWORD=<redacted-password>"
            - "INITIAL_DEFAULT_PAGE=congratulations"
            - "DISABLE_GRAVATAR=false"
            - "COOKIE_SECRET=<redacted-static-random-secret>"
            - "ENABLE_PRERUN=false"
            - "NGINX_LOAD_OPENAPPSEC_ATTACHMENT_MODULE=false"
            - "NGINX_LOAD_NJS_MODULE=false"
            - "NGINX_LOAD_GEOIP2_MODULE=false"
            - "NGINX_LOAD_LDAP_MODULE=false"
            - "NGINX_LOAD_NTLM_MODULE=false"
            - "NGINX_LOAD_VHOST_TRAFFIC_STATUS_MODULE=false"

    crowdsec:
        container_name: crowdsec
        image: docker.io/crowdsecurity/crowdsec:latest
        restart: unless-stopped
        networks:
            - APPSEC_NET
        ports:
            - "127.0.0.1:7422:7422"
            - "127.0.0.1:8080:8080"
        environment:
            - "TZ=Europe/Rome"
            - "USE_WAL=true"
            - "COLLECTIONS=ZoeyVid/npmplus"
            - "TRUSTED_IPS=127.0.0.1,<npmplus-appsec-ip>,<other-trusted-container-ip>,<docker-gateway-ip>"
        volumes:
            - "crowdsec_conf:/etc/crowdsec"
            - "crowdsec_data:/var/lib/crowdsec/data"
            - "npm_data:/opt/npmplus:ro"
            - "openappsec_logs:/opt/openappsec/logs:ro"

    openappsec-agent:
        container_name: openappsec-agent
        image: ghcr.io/openappsec/agent:latest
        restart: unless-stopped
        networks:
            - APPSEC_NET
        ipc: host
        volumes:
            - "shm_data:/dev/shm/check-point"
            - "openappsec_conf:/etc/cp/conf"
            - "openappsec_data:/etc/cp/data"
            - "openappsec_logs:/var/log/nano_agent"
            - "openappsec_localconf:/ext/appsec"
            - "/opt/openappsec/open-appsec-advanced-model.tgz:/advanced-model/open-appsec-advanced-model.tgz:ro"
        environment:
            - "TZ=Europe/Rome"
            - "autoPolicyLoad=true"
            - "registered_server=NPMplus"
            - "user_email=<redacted-email>"
            - "AGENT_TOKEN=<redacted-token>"
        command: /cp-nano-agent

    crowdsec-web-ui:
        image: ghcr.io/theduffman85/crowdsec-web-ui:latest
        container_name: crowdsec-web-ui
        networks:
            - APPSEC_NET
            - NPMPLUS_NET
        environment:
            - "CROWDSEC_URL=http://crowdsec:8080"
            - "CROWDSEC_USER=crowdsec-web-ui"
            - "CROWDSEC_PASSWORD=<redacted-password>"
            - "CROWDSEC_LOOKBACK_PERIOD=5d"
            - "CROWDSEC_REFRESH_INTERVAL=30s"
            - "CROWDSEC_IDLE_REFRESH_INTERVAL=5m"
            - "CROWDSEC_IDLE_THRESHOLD=2m"
            - "CROWDSEC_FULL_REFRESH_INTERVAL=5m"
            - "CROWDSEC_BOOTSTRAP_RETRY_DELAY=30s"
            - "CROWDSEC_BOOTSTRAP_RETRY_ENABLED=true"
            - "CROWDSEC_SIMULATIONS_ENABLED=true"
        volumes:
            - "crowdsec_web_ui_data:/app/data"
        restart: unless-stopped

volumes:
    shm_data:
        driver: local
        driver_opts:
            type: tmpfs
            device: tmpfs
    npm_data:
    crowdsec_conf:
    crowdsec_data:
    openappsec_logs:
    openappsec_storage:
    openappsec_conf:
    openappsec_data:
    openappsec_localconf:
    openappsec_pgdb:
    crowdsec_web_ui_data:

networks:
    APPSEC_NET:
        external: true
    NPMPLUS_NET:
        external: true

Logs

When using the OpenAppSec attachment module, NPMplus logs show:

2026-05-19T20:30:52.639: init_signaling_socket@ngx_cp_initializer.c:349 [uid 3 | pid 635] <session id 549> | Successfully connected on client socket 3
2026-05-19T20:30:52.639: ngx_cp_attachment_init_process@ngx_cp_initializer.c:717 [uid 3 | pid 635] <session id 549> | Initializing IPC channel
2026-05-19T20:30:52.639: isCorruptedShmem@shmem_ipc.c:324 [uid 3 | pid 635] <session id 549> | Detected corrupted shared memory queue. Shared memory name: 3
2026-05-19T20:30:52.639: handle_shmem_corruption@ngx_cp_initializer.c:832 [uid 3 | pid 635] <session id 549> | Shared memory is corrupted! restarting communication
2026-05-19T20:30:52.781: init_signaling_socket@ngx_cp_initializer.c:320 [uid 3 | pid 635] <session id 551> | Paired affinity disabled, sending target_core=-1 to service

After changing/redeploying and recreating the shared-memory volume, I also observed:

2026-05-19T20:37:54.708: init_signaling_socket@ngx_cp_initializer.c:250 [uid 2 | pid 627] <session id 51> | Could not connect to nano service. Path: /dev/shm/check-point/cp-nano-http-transaction-handler-2, Error: No such file or directory
2026-05-19T20:37:57.898: init_signaling_socket@ngx_cp_initializer.c:250 [uid 2 | pid 627] <session id 57> | Could not connect to nano service. Path: /dev/shm/check-point/cp-nano-http-transaction-handler-2, Error: No such file or directory
2026-05-19T20:37:58.200: init_signaling_socket@ngx_cp_initializer.c:250 [uid 2 | pid 627] <session id 59> | Could not connect to nano service. Path: /dev/shm/check-point/cp-nano-http-transaction-handler-2, Error: No such file or directory

What I already tested

I tested the following:

  1. Verified that NPMplus is running the develop image.
  2. Verified that the OpenAppSec agent container starts and registers successfully.
  3. Verified that the OpenAppSec orchestration status reports successful updates/policy load.
  4. Enabled the attachment module with:
- "NGINX_LOAD_OPENAPPSEC_ATTACHMENT_MODULE=true"
  1. Added the shared-memory volume to both containers:
- "shm_data:/dev/shm/check-point"
  1. Tested ipc: host for both npmplus and openappsec-agent.
  2. Also tested ipc: service:openappsec-agent for npmplus, but the upstream example appears to require ipc: host for NPMplus, so I reverted to ipc: host.
  3. Removed/recreated the shm_data volume.
  4. Redeployed the stack after changing the IPC setting.
  5. Set:
- "NGINX_WORKER_PROCESSES=1"

to rule out a multi-worker race/IPC mismatch.

  1. Temporarily considered removing the hardening block (cap_drop, cap_add, security_opt) to rule out capability/permission issues.
  2. Confirmed that CrowdSec is unrelated to this specific issue; it is running separately and its logs only show bouncer decisions.

Expected behavior

When NGINX_LOAD_OPENAPPSEC_ATTACHMENT_MODULE=true is enabled and both containers share the configured shm_data volume with the required IPC setting, the NPMplus OpenAppSec attachment module should initialize successfully and communicate with the OpenAppSec agent.

Actual behavior

The NPMplus OpenAppSec attachment module starts and connects to the signaling socket, but then repeatedly fails while initializing IPC/shared memory:

  • either detecting a corrupted shared-memory queue;
  • or failing to find the expected nano service socket/file under /dev/shm/check-point.

Question

Is this configuration missing any additional requirement for the current develop image, or could there be an incompatibility between the OpenAppSec attachment module currently shipped in docker.io/zoeyvid/npmplus:develop and ghcr.io/openappsec/agent:latest?

Also, should the OpenAppSec agent image be pinned to a specific version instead of using latest?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions