Multiplayer Mode with Unix Isolation
This guide covers running Agor with full RBAC (Role-Based Access Control) and Unix-level isolation, enabling secure multi-user collaboration on shared development infrastructure.
Overview
Agor’s multiplayer mode brings back the power of shared development servers with modern security:
- Shared development environments - Multiple users collaborate on the same codebase with proper isolation
- OS-level security - Worktree permissions enforced at the Unix filesystem level
- Process impersonation - Agent sessions run as the actual user who created them
- Real-time collaboration - See what teammates are working on, share terminals, pair program
Think of it as “once upon a time, teams shared servers” — but with proper RBAC, credential isolation, and modern workflows.
Security Model
Agor implements defense in depth with multiple security layers:
Multi-Layer Protection
- App Layer - Agor API validates permissions before any operation
- Sudoers Layer - Commands restricted to specific Agor-managed paths
- OS Layer - Unix permissions prevent unauthorized filesystem access
- Audit Layer - All privileged operations logged to
/var/log/auth.log
What the Daemon Can Do (With Proper Sudoers Configuration)
- Create and manage Unix users in the
agor_usersgroup - Create Unix groups for worktree isolation (
agor_wt_*) - Impersonate managed users to run agent sessions
- Modify filesystem permissions on Agor-managed directories only
- Execute scoped privileged commands via sudo
Scoped Privileges
All filesystem operations are strictly scoped to Agor-managed paths:
/home/*/agor/*- User worktree symlinks and config/home/*/.agor/*- Agor data directories/var/agor/*- Optional shared storage directory
System paths are NOT accessible - the daemon cannot modify /etc, /usr, /root, or other system directories.
Security Properties
- ✅ Scoped impersonation - Only
agor_usersgroup members can be impersonated (prevents root escalation) - ✅ Credential isolation - Each user’s API keys, SSH keys, and dotfiles are isolated
- ✅ Filesystem enforcement - Unix permissions prevent cross-user access
- ✅ Audit trail - All sudo operations logged with timestamp and command
- ✅ Defense in depth - Multiple layers: app validation → sudoers → OS permissions
Threat Model
| Threat | Impact | Mitigation |
|---|---|---|
| Malicious user prompts | ⚠️ Can damage own files | ✓ Permission system, audit logs |
| Daemon compromise | ⚠️ Can access daemon user files | ✓ Daemon unprivileged, limited blast radius |
| User escalation | ❌ Cannot access other users | ✓ Unix permissions, scoped sudoers |
| Credential theft | ❌ Cannot read other user keys | ✓ File permissions (600 on private keys) |
| Sudoers misconfiguration | ⚠️ Risk if overly permissive | ✓ Scoped rules, agor_users group restriction |
Recommendations
- Private Network - Run on VPN or trusted network, not public internet
- Trusted Users - Only grant access to users you trust with shared infrastructure
- API Key Rotation - Regularly rotate API keys, especially when users leave
- Monitor Audit Logs - Check
/var/log/auth.logfor suspicious sudo activity - Resource Limits - Use ulimits, cgroups, or quotas to prevent resource exhaustion
- Regular Audits - Review worktree ownership quarterly with
agor worktree owners audit
Setup Guide
Prerequisites
- Linux server with systemd
- PostgreSQL (recommended for production)
- sudo access for initial setup
- tmux (for multiplayer terminal sessions)
1. PostgreSQL Configuration
For production multiplayer deployments, use PostgreSQL instead of SQLite:
# ~/.agor/config.yaml
database:
driver: postgres
url: postgresql://agor:password@localhost:5432/agor2. Volume Configuration
Configure persistent storage for worktrees and repositories:
# ~/.agor/config.yaml
storage:
repos_dir: /var/lib/agor/repos
worktrees_dir: /var/lib/agor/worktrees3. Sudoers Configuration
The daemon requires sudo access for Unix user/group management. Agor provides a comprehensive, production-ready sudoers file with extensive documentation and security scoping.
Installation:
# Download the sudoers file
curl -O https://raw.githubusercontent.com/preset-io/agor/main/docker/sudoers/agor-daemon.sudoers
# CRITICAL: Always validate syntax before installing
sudo visudo -c -f ./agor-daemon.sudoers
# Install with correct permissions
sudo install -m 0440 ./agor-daemon.sudoers /etc/sudoers.d/agor
# Verify configuration
sudo -l -U agorView the complete file: docker/sudoers/agor-daemon.sudoers
What the sudoers file enables
User Impersonation (Core Feature):
# Run agent sessions as the user who created them
# SECURITY: Only agor_users group members can be impersonated
agor ALL=(%agor_users) NOPASSWD: ALLUser Management:
# Create/manage Unix users for Agor users
agor ALL=(ALL) NOPASSWD: /usr/sbin/useradd *
agor ALL=(ALL) NOPASSWD: /usr/sbin/userdel *
agor ALL=(ALL) NOPASSWD: /usr/sbin/usermod *
agor ALL=(ALL) NOPASSWD: /usr/sbin/chpasswdGroup Management (Worktree Isolation):
# Create Unix groups per worktree (agor_wt_<id>)
agor ALL=(ALL) NOPASSWD: /usr/sbin/groupadd *
agor ALL=(ALL) NOPASSWD: /usr/sbin/groupdel *
agor ALL=(ALL) NOPASSWD: /usr/sbin/gpasswd *Filesystem Operations (SCOPED TO AGOR PATHS ONLY):
# User home directories - worktree symlinks and config
agor ALL=(ALL) NOPASSWD: /usr/bin/chown * /home/*/agor/*
agor ALL=(ALL) NOPASSWD: /usr/bin/chown * /home/*/.agor/*
agor ALL=(ALL) NOPASSWD: /usr/bin/chmod * /home/*/agor/*
agor ALL=(ALL) NOPASSWD: /usr/bin/mkdir -p /home/*/agor/*
agor ALL=(ALL) NOPASSWD: /usr/bin/ln -sfn * /home/*/agor/worktrees/*
# Optional shared storage
agor ALL=(ALL) NOPASSWD: /usr/bin/chown * /var/agor/*
agor ALL=(ALL) NOPASSWD: /usr/bin/chmod * /var/agor/*Query Commands (Read-Only, Safe):
agor ALL=(ALL) NOPASSWD: /usr/bin/id *
agor ALL=(ALL) NOPASSWD: /usr/bin/getent *
agor ALL=(ALL) NOPASSWD: /usr/bin/readlink *Key Security Properties:
-
Scoped Impersonation - Only
agor_usersgroup members can be impersonated- Prevents escalation to system users (root, postgres, www-data, etc.)
- All Agor-managed users automatically added to
agor_users
-
Path Scoping - Filesystem operations restricted to Agor-managed paths:
/home/*/agor/*- User worktree symlinks/home/*/.agor/*- User Agor data/var/agor/*- Shared storage (optional)- Cannot access:
/etc,/usr,/root, system directories
-
No TTY Required -
Defaults:agor !requirettyenables daemon operation- Code MUST use
sudo -nto fail fast if TTY somehow required - Without
-nflag, missing TTY causes process freeze
- Code MUST use
-
Audit Trail - All sudo operations logged to
/var/log/auth.log- Monitor with:
sudo grep agor /var/log/auth.log | tail -20 - Consider forwarding to SIEM for compliance environments
- Monitor with:
Customization:
- Replace
agorwith your daemon username throughout (e.g.,agorpg) - The file includes extensive comments and troubleshooting tips
- Read the full file before deploying to production
4. Enable RBAC and Unix Isolation
Configure Agor’s execution mode via config:
# ~/.agor/config.yaml
execution:
# Enable RBAC system (default: false)
worktree_rbac: true
# Unix user mode (default: simple)
# Options:
# - simple: No isolation, all runs as daemon user
# - insulated: Worktree groups + single executor user
# - strict: Full per-user isolation, enforced impersonation
unix_user_mode: insulated # or strict
# Optional: Specific Unix user for executor (insulated mode)
executor_unix_user: agor_executorMode Comparison:
| Mode | Unix Groups | FS Permissions | Process Impersonation | Use Case |
|---|---|---|---|---|
simple | ❌ | ❌ | ❌ | Single user, dev/testing |
insulated | ✅ | ✅ | Optional | Shared dev, FS isolation |
strict | ✅ | ✅ | ✅ Required | Production, compliance |
When to use each mode:
simple- Default, single user or fully trusted team, no setup requiredinsulated- Recommended for shared development, isolates daemon from executorsstrict- Production environments, compliance requirements, full audit trail
5. Observability Setup
For production deployments, configure logging and monitoring:
# ~/.agor/config.yaml
logging:
level: info
format: json
file: /var/log/agor/daemon.log
metrics:
enabled: true
port: 9090 # Prometheus metrics endpointHow It Works
Three-Layer Architecture
Agor combines app-level RBAC with OS-level enforcement:
- App Layer - API validates permissions before operations
- Unix Groups - Worktree isolation via filesystem permissions
- Process Impersonation - Agents run as the session creator’s Unix user
User Management
When RBAC is enabled (worktree_rbac: true):
- Each Agor user gets a Unix account (auto-created or pre-provisioned)
- Format:
agor_<short-id>(e.g.,agor_03b62447) or custom username - All managed users added to
agor_usersgroup - Users can be impersonated by daemon for session execution
- Each user gets home directory with:
~/agor/worktrees/- Symlinks to authorized worktrees~/.ssh/- User’s SSH keys (isolated)~/.config/gh/- GitHub CLI credentials (isolated)~/.claude/- Claude SDK session state
Worktree Isolation
Each worktree gets OS-level protection:
- Unix Group - Dedicated group
agor_wt_<short-id> - Filesystem Permissions - Directory owned by group with proper mode
- Group Membership - Worktree owners added to group
- Home Symlinks - Owners get
~/agor/worktrees/<name>→ worktree path
Example:
# Worktree created
$ ls -la /var/agor/worktrees/wt-abc123/
drwxrwx--- alice agor_wt_abc123 my-project/
# Alice's home
$ ls -la ~/agor/worktrees/
lrwxrwxrwx alice alice my-project-abc123 -> /var/agor/worktrees/wt-abc123/my-project
# Bob added as owner
$ getent group agor_wt_abc123
agor_wt_abc123:x:1050:alice,bobPermission Levels
Agor defines three permission levels per worktree:
| Level | Filesystem Access | View Sessions | Prompt Sessions | Modify Worktree |
|---|---|---|---|---|
view | Read-only | ✅ | ❌ | ❌ |
prompt | No direct access | ✅ | ✅ | ❌ |
all | Read-write | ✅ | ✅ | ✅ |
Permission Grant Levels:
- Worktree Owners - Explicitly granted via
worktree_ownerstable - Non-Owners - Default level set by
others_canfield on worktree
Session Execution Context
Critical insight: Sessions are bound to their creator forever (immutable).
// Session record
{
session_id: "abc123",
created_by: alice_user_id, // IMMUTABLE
worktree_id: "wt-xyz789"
}
// When Bob prompts Alice's session:
// - Task creator: Bob (for attribution)
// - Execution user: Alice (session.created_by)
// - Working directory: Alice's worktree
// - Credentials used: Alice's ~/.ssh, ~/.config/ghWhy immutable?
- Claude SDK stores state in creator’s
~/.claude/ - Session continuity requires consistent user context
- Credentials belong to session creator
Troubleshooting
Daemon Can’t Create Users
Check sudoers configuration:
sudo -l -U agorPermission Denied on Worktree
Verify group membership:
id username
ls -la /path/to/worktreeSession Fails to Start
Check if user is in agor_users group:
getent group agor_usersRelated Docs
- Architecture - System design overview
- Advanced Features - Multiplayer terminal sessions
- Concepts - Understanding worktrees and sessions