Starting the daemon
The `php artisan opcua:session` command — every option, what it does, how it wires Laravel logging and caching into the daemon.
The Laravel package ships an artisan command that launches the daemon with Laravel-wired logging, caching, and config:
php artisan opcua:session
That reads config/opcua.php's session_manager block and
starts the daemon. Block until Ctrl+C or until the process is
signalled.
Why the artisan command?
Three things php artisan opcua:session does that
vendor/bin/opcua-session-manager doesn't:
- Wires
LoggerInterfacefromconfig('logging.channels.{name}')— daemon logs land in your Laravel log channels. - Wires
CacheInterfacefromconfig('cache.stores.{name}')— daemon caches use Redis/database/file via Laravel's cache abstraction. - Resolves PSR-14
EventDispatcher— necessary for auto-publish.
Run the artisan command unless you have a specific reason not to (e.g. you don't want Laravel as a runtime dependency for the daemon).
Options
The command exposes six options. Everything else
(socket_path, auth_token, allowed_cert_dirs, auto_publish,
the auto-connect connection list) comes from config/opcua.php —
there is no --socket-path, --auth-token,
--allowed-cert-dirs, --auto-publish, or --no-auto-connect
option.
| Option | Default | Effect |
|---|---|---|
--timeout=<sec> |
config('opcua.session_manager.timeout') |
Idle session timeout |
--cleanup-interval=<sec> |
config('opcua.session_manager.cleanup_interval') |
Reaper loop period |
--max-sessions=<n> |
config('opcua.session_manager.max_sessions') |
Cap on concurrent sessions |
--socket-mode=<oct> |
config('opcua.session_manager.socket_mode') (0600) |
Permissions on the Unix socket file |
--log-channel=<name> |
config('opcua.session_manager.log_channel') |
Laravel log channel for the daemon |
--cache-store=<name> |
config('opcua.session_manager.cache_store') |
Laravel cache store for the daemon's client |
Examples
Development
php artisan opcua:session
Pure defaults. Socket at storage/framework/opcua-session-manager.sock
on POSIX or tcp://127.0.0.1:9990 on Windows.
Custom socket location
Set the socket path in config/opcua.php (or via
OPCUA_SOCKET_PATH in .env):
'session_manager' => [
'socket_path' => env('OPCUA_SOCKET_PATH', '/var/run/opcua/sessions.sock'),
],
There is no CLI override for the socket path — the value the daemon listens on comes from config.
Production-style
# config/opcua.php has socket_path, socket_mode, auth_token,
# allowed_cert_dirs, and auto_publish set. The CLI only tunes
# the per-run knobs:
php artisan opcua:session \
--log-channel=opcua \
--cache-store=redis
You'd put this in a Supervisor / systemd unit — see Production supervisor.
What happens at start
The command, in order:
- Boot Laravel (config, bindings).
- Resolve the log channel and cache store.
- Construct
SessionManagerDaemonwith the wired dependencies. - Pre-connect configured connections if
auto_connectis on — see Auto-connect below. - Bind the socket, set permissions, start listening.
- Block in the event loop.
The first log line looks like:
[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
If you see this, the daemon is ready.
Auto-connect
By default, the daemon does not pre-connect to anything. The first IPC request that names a connection triggers the actual OPC UA handshake.
To pre-warm specific connections at daemon boot, mark them
auto_connect in config/opcua.php:
'connections' => [
'plc-line-a' => [
'endpoint' => 'opc.tcp://plc-a.factory.local:4840',
'auto_connect' => true,
],
],
There is no --no-auto-connect CLI flag. To skip auto-connect
temporarily, either set auto_publish to false in
config/opcua.php (auto-connect only runs when auto-publish is
enabled) or remove the auto_connect => true flag from the
specific connections you want to skip.
Stopping the daemon
Send SIGTERM for graceful shutdown:
# By PID (if known)
kill -TERM <pid>
# Or use Supervisor / systemctl
sudo systemctl stop opcua-session-manager
On SIGTERM the daemon:
- Stops accepting new connections.
- Closes all OPC UA sessions cleanly.
- Unlinks the socket file.
- Exits with status 0.
SIGINT (Ctrl+C) does the same thing.
Restarting
The daemon is stateless across restarts as far as OPC UA is concerned — sessions are torn down on stop and re-established on the next request. Subscriptions are also lost on restart.
For production, run the daemon under a supervisor that restarts on crash. See Production supervisor.
Multiple daemons
Running multiple daemons requires multiple Laravel installations
(or multiple distinct config/opcua.php files served from
separate processes) — the daemon's socket path is per-config,
not per-connection. The per-connection socket_path override is
not consumed by the manager.
For multi-tenant patterns see Recipes · Multi-plant tenant.
Running outside Laravel
If you need to run the daemon without Laravel as a runtime dependency (e.g. in a separate, minimal container):
vendor/bin/opcua-session-manager \
--socket-path=/var/run/opcua/sessions.sock \
--timeout=600 \
--auth-token="${OPCUA_AUTH_TOKEN}"
You lose the Laravel-side wiring — no Laravel log channels, no Laravel cache. The daemon falls back to a PSR-3-null logger and an in-memory cache. For most production needs the artisan command is the right choice.
Where to read next
- Auto-publish — the subscription bridge.
- Production supervisor — putting the daemon under a process supervisor.
- Monitoring the daemon — liveness, metrics, logging.