symfony-opcua · v4.3.x
Docs · Session manager

Starting the daemon

The php bin/console opcua:session command — every option, every wire to Symfony's logger / cache / event dispatcher.

The bundle ships a Symfony console command that launches the daemon with Symfony-side wiring (logger, cache, event dispatcher) flowing in:

bash terminal — basic
php bin/console opcua:session

That reads session_manager.* from config/packages/php_opcua_symfony_opcua.yaml and starts the daemon. Blocks until Ctrl+C or signalled.

Why the console command?

Three things php bin/console opcua:session does that vendor/bin/opcua-session-manager doesn't:

  1. Wires LoggerInterface from the configured Monolog channel (session_manager.log_channelmonolog.logger.<name>).
  2. Wires CacheInterface from the configured Symfony cache pool (session_manager.cache_poolcache.app by default, wrapped in Psr16Cache).
  3. Wires EventDispatcherInterface — Symfony's dispatcher, for auto-publish.

Run the console command unless you have a specific reason not to.

Options

Option Default Effect
--timeout=<sec> session_manager.timeout Idle session timeout
--cleanup-interval=<sec> session_manager.cleanup_interval Reaper loop period
--max-sessions=<n> session_manager.max_sessions Cap on concurrent sessions
--socket-mode=<oct> session_manager.socket_mode Unix socket permissions

CLI flags override YAML config for that one invocation. All flags accept --socket-mode=0660 octal form.

Examples

Development

bash dev
php bin/console opcua:session

Pure defaults. Socket at var/opcua-session-manager.sock.

Custom timeout

bash custom timeout
php bin/console opcua:session --timeout=1800 --max-sessions=50

Production-style

Production typically pulls all settings from YAML; the command runs with no flags:

bash prod
APP_ENV=prod php bin/console opcua:session

…with config/packages/prod/php_opcua_symfony_opcua.yaml:

text prod config
php_opcua_symfony_opcua:
    session_manager:
        socket_path:       /var/run/opcua/sessions.sock
        socket_mode:       0660
        timeout:           600
        cleanup_interval:  30
        max_sessions:      100
        auth_token:        '%env(secret:OPCUA_AUTH_TOKEN)%'
        log_channel:       opcua
        cache_pool:        cache.redis
        auto_publish:      true
        allowed_cert_dirs:
            - /etc/opcua/certs
            - /var/lib/opcua/trust

Run under systemd — see Production supervisor.

What happens at start

  1. Boot Symfony (kernel boot, container compile).
  2. Resolve the log channel and cache pool services.
  3. Resolve EventDispatcherInterface if auto_publish is on.
  4. Construct SessionManagerDaemon with the wired deps.
  5. Pre-connect configured connections if auto_connect is on on individual connections.
  6. Bind the socket, set permissions, start listening.
  7. Block in the event loop.

First log line:

text startup log
[2026-05-15 10:00:00] opcua.INFO: SessionManagerDaemon started
  socket=/var/run/opcua/sessions.sock mode=0660
  timeout=600 cleanup=30 max_sessions=100 auto_publish=true

Auto-connect on startup

Connections with auto_connect: true and a subscriptions: block are connected on the first event loop tick:

text auto-connect
php_opcua_symfony_opcua:
    session_manager:
        auto_publish: true
    connections:
        plc-line-a:
            endpoint:     '%env(OPCUA_LINE_A)%'
            auto_connect: true
            subscriptions:
                -
                    publishing_interval: 500.0
                    monitored_items:
                        - { node_id: 'ns=2;s=Speed',       client_handle: 1 }
                        - { node_id: 'ns=2;s=Temperature', client_handle: 2 }

The daemon opens the session, creates the subscription, and starts publishing events to Symfony's EventDispatcher. See Auto-publish.

Stopping the daemon

Send SIGTERM for graceful shutdown:

bash terminal
sudo systemctl stop opcua-session-manager
# or by PID
kill -TERM <pid>

SIGINT (Ctrl+C) does the same. On exit the daemon:

  1. Stops accepting new connections.
  2. Closes all OPC UA sessions cleanly.
  3. Unlinks the Unix socket file.
  4. Exits with status 0.

Restarting

After deploying new code, restart the daemon — it caches the autoload index at boot:

bash terminal
sudo systemctl restart opcua-session-manager

This briefly closes all daemon-held sessions. Symfony processes reconnect on the next IPC call.

Multiple daemons

The opcua:session command does not accept a --socket-path flag — its only options are --timeout, --cleanup-interval, --max-sessions, --socket-mode. To run multiple daemons on different socket paths, wire session_manager.socket_path through an env var and launch each daemon with a different env value:

bash env-per-daemon
OPCUA_SOCKET_PATH=/var/run/opcua/tenant-a.sock php bin/console opcua:session &
OPCUA_SOCKET_PATH=/var/run/opcua/tenant-b.sock php bin/console opcua:session &

With the bundle config pointing at %env(OPCUA_SOCKET_PATH)%:

php_opcua_symfony_opcua:
    session_manager:
        socket_path: '%env(OPCUA_SOCKET_PATH)%'

See Recipes · Multi-plant tenant.

Running outside Symfony

If you need the daemon without Symfony's runtime:

bash raw CLI
vendor/bin/opcua-session-manager \
    --socket /var/run/opcua/sessions.sock \
    --timeout 600 \
    --auth-token "${OPCUA_AUTH_TOKEN}"

You lose the Symfony wiring — no Monolog channel, no Symfony cache pool, no EventDispatcher. The daemon falls back to a null logger and in-memory cache. For most production needs the console command is the right choice.