app armour on ragflow

you can use AppArmor to add an extra layer of confinement when running RAGFlow (especially useful if you’re suspicious about potential vulnerabilities, code execution risks in agents, parser bugs, or supply-chain issues).

RAGFlow is normally run via docker-compose with multiple containers (ragflow-server, Elasticsearch/Infinity, MinIO, Redis, MySQL, etc.). AppArmor confinement applies per container.

Quick options ranked by effort vs. security gain

1. Easiest — just use the built-in docker-default profile (almost zero effort)

On Ubuntu / Debian / derivatives where AppArmor is enabled by default, Docker already applies the docker-default profile to every container unless you override it.

Check whether it’s active:

# On the host
aa-status | grep docker
docker inspect ragflow-server --format '{{.AppArmorProfile}}'

→ If you see docker-default → you’re already getting baseline AppArmor protection (blocks many dangerous operations like mounting filesystems, loading kernel modules, ptrace, etc.).

This is usually “good enough” for most suspicious-but-not-paranoid cases.

2. Medium effort — create a stricter custom profile for ragflow-server

The most interesting container to confine more tightly is usually ragflow-server (the Python part that does parsing, agent logic, potential code execution in some features).

Steps:

  1. Create a file /etc/apparmor.d/ragflow-server
#include <tunables/global>

/usr/bin/ragflow-server flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>
  #include <abstractions/python>

  # Allow what Docker normally needs
  capability dac_override,
  capability setgid,
  capability setuid,
  capability sys_chroot,   # sometimes needed

  # Network (RAGFlow needs to talk to other containers + possibly internet)
  network tcp,
  network udp,

  # Very important paths — adjust according to your .env / volumes
  /etc/localtime r,
  /ragflow/ r,
  /ragflow/** rwlk,
  /app/** r,
  /ragflow/docker-entrypoint.sh ix,
  /usr/local/bin/python* ix,
  /usr/bin/python* ix,

  # Allow gunicorn / uvicorn / whatever RAGFlow uses
  /usr/local/lib/python*/site-packages/** r,
  @{PROC}/sys/kernel/random/uuid r,

  # Logging
  /var/log/** rw,

  # Deny dangerous stuff
  deny capability sys_admin,
  deny capability sys_module,
  deny capability sys_ptrace,
  deny /sys/** w,
  deny /proc/** w,
  deny /etc/** w,               # except /etc/localtime if needed
}
  1. Load & enforce it
sudo apparmor_parser -r /etc/apparmor.d/ragflow-server
sudo aa-enforce /etc/apparmor.d/ragflow-server
  1. Tell docker-compose to use it (edit docker-compose.yml)
services:
  ragflow-server:
    ...
    security_opt:
      - apparmor:ragflow-server
  1. Restart
docker compose up -d

Start in complain mode first (aa-complain ...) → look at /var/log/syslog or dmesg | grep audit for denials → gradually tighten.

3. Hardest but strongest — very locked-down profile + read-only rootfs + drop caps

Combine:

services:
  ragflow-server:
    ...
    security_opt:
      - apparmor:ragflow-locked
    read_only: true
    tmpfs:
      - /tmp:size=256m
      - /var/tmp:size=128m
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
      # almost nothing else

This requires a quite permissive profile for /tmp, log sockets, redis/mysql/minio/tcp connections, etc. — but it dramatically reduces blast radius if something goes wrong inside the container.

Quick reality check (2026 perspective)

If you’re extremely suspicious → strongest combo is:

Check: GitHub security advisories tab.