Obsidian Enterprise RBAC
Overview
Vault-level access control patterns for Obsidian in team environments. Covers folder-based permissions via .obsidian-permissions files, read-only enforcement for shared vaults, plugin allowlisting, and configuration lockdown through restricted mode.
Prerequisites
- Obsidian desktop app with a shared/synced vault
- Understanding of Obsidian's
.obsidian/ configuration directory
- A sync mechanism in place (Git, Obsidian Sync, or shared filesystem)
- Node.js 18+ for scripted permission enforcement
Instructions
Step 1: Define a Permission Model
Create .obsidian-permissions at the vault root. This JSON file maps roles to folder access:
{
"version": 1,
"roles": {
"admin": {
"folders": ["*"],
"permissions": ["read", "write", "delete", "manage"]
},
"editor": {
"folders": ["projects/*", "shared/*", "templates/*"],
"permissions": ["read", "write"]
},
"viewer": {
"folders": ["shared/*", "published/*"],
"permissions": ["read"]
}
},
"users": {
"alice@company.com": "admin",
"bob@company.com": "editor",
"charlie@company.com": "viewer"
}
}
Obsidian itself has no built-in RBAC, so this file is consumed by a custom plugin that intercepts file operations.
Step 2: Build the Permission Checker Plugin
Create a plugin that reads .obsidian-permissions and gates vault operations:
import { Plugin, TFile, Notice } from 'obsidian';
interface PermissionConfig {
version: number;
roles: Record<string, { folders: string[]; permissions: string[] }>;
users: Record<string, string>;
}
export default class RBACPlugin extends Plugin {
private config: PermissionConfig | null = null;
private currentUser: string = '';
async onload() {
await this.loadPermissions();
this.registerEvent(
this.app.vault.on('modify', (file) => {
if (!.(file.)) {
();
}
})
);
.(
...(, {
(file && !.(file.?. ?? )) {
();
...(file);
}
})
);
}
() {
permFile = ...();
(permFile ) {
content = ...(permFile);
. = .(content);
}
data = .();
. = data?. ?? ;
}
(: ): {
(!. || !.) ;
role = ..[.];
(!role) ;
roleDef = ..[role];
(!roleDef) ;
(!roleDef..()) ;
roleDef..( {
(pattern === ) ;
regex = ( + pattern.(, ) + );
regex.(path);
});
}
}
Step 3: Enforce Read-Only Mode on Shared Vaults
For vaults where most users should only read, set restricted mode in .obsidian/app.json:
{
"strictLineBreaks": false,
"readableLineLength": true,
"vimMode": false,
"livePreview": true
}
Then in your RBAC plugin, enforce read-only for non-editor roles by overriding the editor:
if (!this.canWrite('/')) {
this.registerEvent(
this.app.workspace.on('editor-change', (editor) => {
editor.undo();
new Notice('This vault is read-only for your role.');
})
);
}
Step 4: Plugin Allowlisting
Lock down which community plugins can be enabled. Edit .obsidian/community-plugins.json to contain only approved plugins:
["obsidian-git", "dataview", "templater-obsidian", "your-rbac-plugin"]
Then protect this file from modification by non-admins. In your RBAC plugin, watch for changes:
this.registerEvent(
this.app.vault.on('modify', async (file) => {
if (file.path === '.obsidian/community-plugins.json') {
const role = this.config?.users[this.currentUser];
if (role !== 'admin') {
const approved = await this.loadData();
await this.app.vault.modify(
file as TFile,
JSON.stringify(approved.allowedPlugins)
);
new Notice('Only admins can modify the plugin allowlist.');
}
}
})
);
Step 5: Configuration Lockdown via Restricted Mode
Obsidian's restricted mode disables all community plugins. For enterprise deployments, combine this with a config lockdown:
const LOCKED_CONFIGS = [
'.obsidian/app.json',
'.obsidian/appearance.json',
'.obsidian/hotkeys.json',
'.obsidian/community-plugins.json',
];
async lockdownConfigs() {
const hashes: Record<string, string> = {};
for (const path of LOCKED_CONFIGS) {
const file = this.app.vault.getAbstractFileByPath(path);
if (file instanceof TFile) {
const content = await this.app.vault.read(file);
hashes[path] = await this.hash(content);
}
}
await this.saveData({ ...await this.loadData(), configHashes: hashes });
}
async verifyConfigs(): Promise<string[]> {
const data = await .();
: [] = [];
( [path, expectedHash] .(data. ?? {})) {
file = ...(path);
(file ) {
content = ...(file);
actual = .(content);
(actual !== expectedHash) {
violations.(path);
}
}
}
violations;
}
(: ): <> {
encoder = ();
data = encoder.(content);
buf = crypto..(, data);
.( (buf)).( b.().(, )).();
}
Run verifyConfigs() on plugin load and periodically. Alert admins if violations are detected.
Output
.obsidian-permissions file defining roles, folder access, and user mappings
- RBAC plugin that intercepts create/modify/delete operations
- Read-only enforcement for non-editor roles
- Plugin allowlist protection in
community-plugins.json
- Configuration lockdown with hash verification for critical
.obsidian/ files
Error Handling
| Issue | Cause | Solution |
|---|
| Permission denied on all files | User email not set in plugin settings | Open RBAC plugin settings, enter your email |
| Allowlist keeps resetting | Non-admin edited community-plugins.json | Only admins can modify; check audit log |
| Config hash mismatch on every load | Config changed legitimately | Admin runs lockdownConfigs() to update hashes |
| Plugin not intercepting writes | Event handler registration failed | Check console for plugin load errors |
Sync conflicts on .obsidian-permissions | Multiple admins editing simultaneously | Use Git with merge strategy or Obsidian Sync |
Examples
Team vault with three roles: Deploy the .obsidian-permissions file above. Set each user's email in the RBAC plugin settings. Editors can modify projects/ and shared/ folders; viewers can only read shared/ and published/.
Locked-down training vault: Set all users to viewer role except instructors (editor). Lock config files with lockdownConfigs(). Students can read all materials but cannot modify notes or install plugins.
Plugin governance: Maintain an allowlist of 5 approved plugins in community-plugins.json. The RBAC plugin reverts any unauthorized additions. New plugin requests go through admin approval.
Resources
Next Steps
For data backup and sync patterns, see obsidian-data-handling. For multi-environment testing of RBAC rules, see obsidian-multi-env-setup.