Run Wowza Streaming Engine as a named user

By default, Wowza Streaming Engine™ media server software and Wowza Streaming Engine Manager run with full system privileges:

  • Linux: Both systemd services run as root (User=root, Group=root).
  • Windows: Both services are installed with NSSM and no account is set, so they run as LocalSystem.

This article explains how to run each service under its own dedicated account: wowzasvc for Wowza Streaming Engine (the engine) and wowzamanagersvc for Wowza Streaming Engine Manager (the Manager). Each account can write only to the folders that its own service changes at runtime. Everything else (lib/, bin/, java/, and manager/lib/) stays owned by root or Administrators, so neither account can replace JAR files or scripts.

The two services use separate accounts so that the engine can't write to the Manager's folders. The Manager serves files from manager/temp/ over HTTP. If the engine could write there, a script running in the engine could copy files into manager/temp/ and then download them through the Manager.


Notes:
  • These instructions apply to Wowza Streaming Engine installed on Linux (systemd services) or Windows (NSSM services). They don't cover Docker images.
  • The examples use the paths and service names for WSE 4.12.1. You may need to adjust them for your version.

Before you start


  • Ports below 1024. The default configuration uses only ports 1024 and higher: 1935 (streaming), 8083, 8086, 8087, and 8088 (Manager). If you added port 80, 443, or 554 to a host port, the Linux steps include the capability the engine needs to bind to them. Windows doesn't restrict these ports.
  • Storage outside the install folder. These steps only cover folders inside the install folder. If an application's StorageDir, a DVR store, a MediaCache store, or a log path points somewhere else (including through a symlink), also give the engine account read-write access to that location.

    Windows

    The default install folder is C:\Program Files\Wowza Media Systems\Wowza Streaming Engine <version>. Run all commands in PowerShell as Administrator.

    1. Stop the services and find their names

    The service names include the version number, for example WowzaStreamingEngine4121 and WowzaStreamingEngineManager4121.

    Get-Service *Wowza* | Format-Table Name, DisplayName, Status
    Get-Service *Wowza* | Stop-Service

    2. Create the accounts

    Skip this step for any account that already exists.

    $password = Read-Host -AsSecureString "Password for wowzasvc"
    New-LocalUser -Name wowzasvc -Password $password -PasswordNeverExpires -UserMayNotChangePassword -Description "Wowza Streaming Engine service"
    $password = Read-Host -AsSecureString "Password for wowzamanagersvc"
    New-LocalUser -Name wowzamanagersvc -Password $password -PasswordNeverExpires -UserMayNotChangePassword -Description "Wowza Streaming Engine Manager service"

    Don't add either account to the Administrators group. Use a different password for each account and keep a record of both. Windows asks for them again when you set the service accounts, and after any password change.

    3. Set folder permissions

    Give both accounts read access to the install folder. Then give each account modify access to the folders its service writes to: the engine folders to wowzasvc and the Manager folders to wowzamanagersvc. The commands also create any of these folders that don't exist yet.

    $wse = "C:\Program Files\Wowza Media Systems\Wowza Streaming Engine 4.12.1"
    icacls "$wse" /grant "wowzasvc:(OI)(CI)RX" "wowzamanagersvc:(OI)(CI)RX"
    foreach ($d in "conf","logs","content","applications","keys","transcoder","dvr","mediacache","stats") {
        New-Item -ItemType Directory -Force -Path "$wse\$d" | Out-Null
        icacls "$wse\$d" /grant "wowzasvc:(OI)(CI)M"
    }
    foreach ($d in "manager\logs","manager\temp","manager\wse-plugins") {
        New-Item -ItemType Directory -Force -Path "$wse\$d" | Out-Null
        icacls "$wse\$d" /grant "wowzamanagersvc:(OI)(CI)M"
    }

    (OI)(CI) applies the permission to everything inside the folder, including files created later. RX is read and execute, and M is modify. The folders and owners are the ones listed in Folders each service writes to.

    4. Set the services to run as the accounts

    Use either the Services console or NSSM.

    Option A: Services console

    1. Open services.msc and open the engine service.
    2. On the Log On tab, select This account, enter .\wowzasvc and its password, and then click OK.
    3. Repeat for the Manager service, using .\wowzamanagersvc and its password.

    Windows grants each account the Log on as a service right and confirms it.

    Option B: NSSM

    Run NSSM from the engine's and the Manager's bin folders. On 32-bit Windows, use nssm_x32.exe instead.

    & "$wse\bin\nssm_x64.exe" set WowzaStreamingEngine4121 ObjectName .\wowzasvc "<wowzasvc password>"
    & "$wse\manager\bin\nssm_x64.exe" set WowzaStreamingEngineManager4121 ObjectName .\wowzamanagersvc "<wowzamanagersvc password>"

    If you use option B, check afterwards that both accounts have the Log on as a service right. In secpol.msc, go to Local Policies > User Rights Assignment > Log on as a service.

    5. Start and verify

    Get-Service *Wowza* | Start-Service
    Get-CimInstance Win32_Service -Filter "Name like 'Wowza%'" | Format-Table Name, StartName, State

    Check that:

    1. Both services are running, and StartName is .\wowzasvc for the engine service and .\wowzamanagersvc for the Manager service.
    2. icacls "$wse\manager\temp" lists wowzamanagersvc with (M) and doesn't list wowzasvc.
    3. You can change and save a setting in the Manager (for example, add an application).
    4. The logs in logs\ and manager\logs\ show no AccessDeniedException errors.

    Run manually (optional)

    No script edits are needed on Windows. To run the engine or Manager manually as its account, start the script with runas, which opens a new console window.

    Engine:

    runas /user:wowzasvc "<install folder>\bin\startup.bat"

    Manager:

    runas /user:wowzamanagersvc "<install folder>\manager\bin\startmgr.bat"

    After an update

    • Update tool X.Y.Z or later: Existing permissions aren't changed, and files the update adds inherit the folder's permissions. No extra step is needed.
    • Update tools earlier than X.Y.Z: The update tool sets permissions for SYSTEM, Administrators, and Users on the install folder, and only edits those entries. The accounts' entries should remain, and files the update adds inherit the folder's permissions. Until this is confirmed, re-run step 3, Set folder permissions after an update.

    Switch back to LocalSystem

    In services.msc, set the Log On option for each service to Local System account, or run:

    & "$wse\bin\nssm_x64.exe" set WowzaStreamingEngine4121 ObjectName LocalSystem
    & "$wse\manager\bin\nssm_x64.exe" set WowzaStreamingEngineManager4121 ObjectName LocalSystem

    Then restart the services.

    Linux

    The examples use the symlink /usr/local/WowzaStreamingEngine, which the installer points to the versioned install folder (for example, /usr/local/WowzaStreamingEngine-4.12.1).


    Notes:
    • Standalone mode. As shipped, bin/startup.sh refuses to run unless it's started as root, and then runs the engine as root. To run the engine manually as its account, edit the start scripts as described in 6. Run manually (optional). Without that edit, only start the engine through its service. If you do run the unedited sudo bin/startup.sh, re-run step 3 afterwards, because files it creates (logs, for example) are owned by root.
    • Xilinx (AMD) U30 servers. On servers with the xrmd service, the engine's start script restarts xrmd with systemctl, which a non-root account can't do. Keep these servers running as root.
    • Updates. Update tools earlier than version X.Y.Z reset file ownership. After an update with one of them, re-run the ownership step (see After an update).

    1. Stop the services

    sudo systemctl stop WowzaStreamingEngineManager WowzaStreamingEngine

    2. Create the users and groups

    Skip this step for any account that already exists. To check, run id wowzasvc or id wowzamanagersvc; the command prints the account if it exists.

    sudo useradd --system --user-group --create-home --home-dir /var/lib/wowzasvc --shell /usr/sbin/nologin wowzasvc
    sudo useradd --system --user-group --create-home --home-dir /var/lib/wowzamanagersvc --shell /usr/sbin/nologin wowzamanagersvc

    Each command creates a system account with:

    • A group with the same name.
    • No password and no login shell.
    • A home folder for the Java runtime's per-user files.

    Don't add either account to the sudo or wheel group, and don't add either account to the other account's group.

    3. Set file ownership and permissions

    1. Make root the owner of the entire install folder, and then give each account the folders its service writes to: the engine folders to wowzasvc and the Manager folders to wowzamanagersvc (see Folders each service writes to).
       

      Making root the owner first resets anything that was previously given to another user, for example by the cloud images or by an earlier run of these steps. The commands also create any of these folders that don't exist yet. The server creates some of them on first use, which it can't do inside a root-owned folder.

      WSE=/usr/local/WowzaStreamingEngine
      sudo chown -R root:root "$WSE/"
      for d in conf logs content applications keys transcoder dvr mediacache stats; do
          sudo mkdir -p "$WSE/$d"
          sudo chown -R wowzasvc:wowzasvc "$WSE/$d"
      done
      for d in manager/logs manager/temp manager/wse-plugins; do
          sudo mkdir -p "$WSE/$d"
          sudo chown -R wowzamanagersvc:wowzamanagersvc "$WSE/$d"
      done
    2. Remove the write access that the installer gives to other users.
       

      The installer makes most folders, and many of the files in them, writable by everyone (drwxr-xrwx), and leaves bin, lib, lib-native, and jre at drwxr-xr-x. The following commands set every folder to drwxr-xr-x and remove group and other write access from every file. The owner's access and the execute bits on scripts don't change.

      sudo chmod -R go-w "$WSE/"
      sudo find "$WSE/" -type d -exec chmod u+rwx,go+rx {} +

      This step is what keeps each account out of the other's folders. As long as the installer's world-writable permissions remain, the engine account can still write to manager/temp/.

      The trailing / on "$WSE/" makes the chown, chmod, and find commands follow the /usr/local/WowzaStreamingEngine symlink to the install folder. None of these commands follow symlinks inside it. The find command also repairs transcoder/templates, which the installer may leave without execute permission (drw-r--r--), so that the engine account can't open it.

    3. Check that no file or folder is writable by group or others. This command should print nothing:
      sudo find "$WSE/" -perm /022
    4. Everything else is owned by root and readable by all users. Check that each account can read its service's files:
      sudo -u wowzasvc test -r "$WSE/lib/wms-server.jar" && echo readable
      sudo -u wowzamanagersvc test -r "$WSE/manager/lib/WMSManager.war" && echo readable

    Note: chown -R doesn't follow symlinks inside these folders. Storage reached through a symlink needs its own permissions (see Before you start).

    4. Configure the systemd units

    Add a drop-in file to each unit instead of editing the unit files. Drop-ins in /etc/systemd/system are kept when Wowza Streaming Engine is updated or reinstalled.

    1. Create the drop-in for the engine:
      sudo mkdir -p /etc/systemd/system/WowzaStreamingEngine.service.d
      sudo tee /etc/systemd/system/WowzaStreamingEngine.service.d/named-user.conf > /dev/null <<'EOF'
      [Service]
      User=wowzasvc
      Group=wowzasvc
      RuntimeDirectory=WowzaStreamingEngine
      ExecStart=
      ExecStart=/usr/local/WowzaStreamingEngine/bin/systemd.sh start /run/WowzaStreamingEngine/WowzaStreamingEngine.pid
      LimitNOFILE=64000
      AmbientCapabilities=CAP_NET_BIND_SERVICE
      CapabilityBoundingSet=CAP_NET_BIND_SERVICE
      EOF

      What each setting does:

      • User= and Group= run the engine as wowzasvc.
      • RuntimeDirectory= and the replacement ExecStart= write the PID file to /run/WowzaStreamingEngine/, which systemd creates for the engine account. The shipped unit writes it to /var/run/, which only root can write to. The empty ExecStart= line clears the shipped command before the new one is set.
      • LimitNOFILE=64000 sets the open-file limit. The start script raises the limit to 64000 itself, but only root can raise it beyond the default hard limit.
      • AmbientCapabilities= lets the engine bind to ports below 1024 (80, 443, and 554) without root. CapabilityBoundingSet= limits it to that one capability. Both settings require systemd 229 or later. Don't use setcap on the Java binary instead: a file capability makes the runtime ignore LD_LIBRARY_PATH and LD_PRELOAD, which the engine's start scripts rely on.
    2. Amazon Linux and Ubuntu 22.04 only: On every start, bin/setenv.sh copies native libraries into lib-native/linux64, which the engine account can't write to. Add the following line to the [Service] section of the engine drop-in so that the copy runs as root before the engine starts. The + prefix requires systemd 231 or later.
      ExecStartPre=+/bin/bash -c '. /usr/local/WowzaStreamingEngine/bin/setenv.sh'
    3. Create the drop-in for the Manager:
      sudo mkdir -p /etc/systemd/system/WowzaStreamingEngineManager.service.d
      sudo tee /etc/systemd/system/WowzaStreamingEngineManager.service.d/named-user.conf > /dev/null <<'EOF'
      [Service]
      User=wowzamanagersvc
      Group=wowzamanagersvc
      LimitNOFILE=20000
      EOF
    4. Reload systemd:
      sudo systemctl daemon-reload

    5. Start and verify

    sudo systemctl start WowzaStreamingEngine WowzaStreamingEngineManager

    Check that the following are true. Some commands use the WSE variable set in step 3.

    1. The engine's Java process runs as wowzasvc and the Manager's Java process runs as wowzamanagersvc:
      ps -o user=,pid=,args= -C java
    2. The ports are listening (1935, 8086, 8087, and 8088, plus 80, 443, or 554 if configured):
      sudo ss -ltnp | grep java
    3. Nothing in the writable folders is owned by another user. Both commands should print nothing:
      sudo find "$WSE"/{conf,logs,content,applications,keys,transcoder,dvr,mediacache,stats} ! -user wowzasvc
      sudo find "$WSE"/manager/{logs,temp,wse-plugins} ! -user wowzamanagersvc
    4. Neither account can change the installation's own files or the other service's folders. Each command should return Permission denied:
      sudo -u wowzasvc touch "$WSE/lib/test"                  # expect "Permission denied"
      sudo -u wowzasvc touch "$WSE/manager/temp/test"         # expect "Permission denied"
      sudo -u wowzamanagersvc touch "$WSE/manager/lib/test"   # expect "Permission denied"
      sudo -u wowzamanagersvc touch "$WSE/conf/test"          # expect "Permission denied"
    5. You can change and save a setting in the Manager (for example, add an application).
    6. The logs show no permission errors:
      grep -il 'permission denied\|AccessDenied' "$WSE"/logs/*.log "$WSE"/manager/logs/*.log

    6. Run manually (optional)

    Use this step if you start the engine or Manager from the command line (standalone mode) instead of through the services. Stop the services first.

    With these edits, you keep using the same commands as today: sudo bin/startup.sh and sudo manager/bin/startmgr.sh. The scripts still start as root, so the setup steps that need root still work:

    • The open-file limit.
    • The native library copy on Amazon Linux and Ubuntu 22.04.
    • The Xilinx xrmd restart.

    Just before starting Java, each script switches to its service's account with setpriv. The engine keeps the one capability it needs to bind to ports below 1024.

    1. Engine: In /usr/local/WowzaStreamingEngine/bin/startup.sh, add one line after the line that loads setenv.sh.
       

      Before:

      . /usr/local/WowzaStreamingEngine/bin/setenv.sh
      mode=standalone

      After:

      . /usr/local/WowzaStreamingEngine/bin/setenv.sh
      _EXECJAVA="setpriv --reuid=wowzasvc --regid=wowzasvc --init-groups --inh-caps=+net_bind_service --ambient-caps=+net_bind_service $_EXECJAVA"
      mode=standalone
    2. Manager: In /usr/local/WowzaStreamingEngine/manager/bin/startmgr.sh, add one line after ulimit -n 20000. The Manager uses port 8088, so it doesn't need a capability.
       

      Before:

      	# Linux
      	. /usr/local/WowzaStreamingEngine/manager/bin/setmgrenv.sh
      	
      	ulimit -n 20000

      After:

      	# Linux
      	. /usr/local/WowzaStreamingEngine/manager/bin/setmgrenv.sh
      	
      	ulimit -n 20000
      	[ "$(id -u)" -eq 0 ] && _EXECJAVA="setpriv --reuid=wowzamanagersvc --regid=wowzamanagersvc --init-groups $_EXECJAVA"

      The Manager script has no root check, so the added line only switches accounts when the script is started as root. Without this edit, you can start the Manager as its account with sudo -u wowzamanagersvc /usr/local/WowzaStreamingEngine/manager/bin/startmgr.sh, but the open-file limit may then stay below 20000.

    3. If your account names are different, replace wowzasvc and wowzamanagersvc with your account names. Then start each one as usual:
      sudo /usr/local/WowzaStreamingEngine/bin/startup.sh
      sudo /usr/local/WowzaStreamingEngine/manager/bin/startmgr.sh
    4. Check which user each process runs as with ps -o user=,args= -C java.

    bin/shutdown.sh and manager/bin/shutdownmgr.sh don't need any changes. Run them with sudo as before.

    These edits don't affect the services. The engine service runs bin/systemd.sh, not startup.sh. The Manager service already runs startmgr.sh as its account, so the added line does nothing there.


    Important: Updates replace these scripts. Every update installs new copies of bin/startup.sh and manager/bin/startmgr.sh, which removes your edits. The scripts then run Java as root again, and files they create are owned by root. After every update:
    1. Check whether the edit is still there. A count of 0 means the edit is gone.
      grep -c setpriv /usr/local/WowzaStreamingEngine/bin/startup.sh /usr/local/WowzaStreamingEngine/manager/bin/startmgr.sh
    2. Make the edit again in the new scripts. Don't copy your old scripts over the new ones. Updates sometimes change these scripts, and an old copy can stop the server from starting. For example, 4.12.0 changed the library versions that startmgr.sh loads.
    3. If you started either script after the update and before re-applying the edit, re-run step 3, Set file ownership and permissions.

    After an update

    • Update tool X.Y.Z or later: Existing files and folders keep their owner and permissions. Files and folders that the update adds get the owner and group of the folder they're in. No extra step is needed.
    • Update tools earlier than X.Y.Z: The update tool sets the owner of every file in the install folder, including existing files, to the owner of lib/wms-server.jar (root), and follows symlinks while doing so. Folders keep their owner, but the accounts can no longer change existing files such as conf/*.xml. After every update with one of these versions:
      1. Wait until the update tool's permission script has finished. The update tool starts the script in the background and doesn't wait for it, so it can still be running after the update tool exits:
        while pgrep -f updatepermissions.sh > /dev/null; do sleep 2; done
      2. Re-run step 3, Set file ownership and permissions.
      3. Start the services.

    Updates don't affect the drop-in files. The update tool only refreshes the copies of the unit files in bin/ and manager/bin/, not the installed units or the drop-ins.

    Switch back to root

    sudo rm /etc/systemd/system/WowzaStreamingEngine.service.d/named-user.conf \
            /etc/systemd/system/WowzaStreamingEngineManager.service.d/named-user.conf
    sudo systemctl daemon-reload
    sudo systemctl restart WowzaStreamingEngine WowzaStreamingEngineManager

    You don't need to change file ownership back, because root can use files owned by the accounts.