Summary: How to create private groups on public wikis
Status: Stable
Version: 1
Prerequisites: pmwiki-2.0
Categories: Security
Votes: 5


How can I create a private group on my public wiki, which is invisible to the public?


Setting read protection to a group

To create a group that is not visible to the public, set a password for the read permission on the GroupAttributes page. Enter the following into the browser's address bar for a group PrivateGroup to access its group attributes (passwords):


Preventing private stuff from appearing in public search results and pagelists

Pmwiki prevents this by default. Read-protected pages and groups are not listed in search results and pagelists, unless the user has read permission for those pages and groups. PmWiki sets this by default with

So no action needs to be taken to prevent private pages from being listed in public.

NOTE: In my config.php this was NOT the default. The default allowed people to see the NAMES but not the CONTENT. I had to explicitly set this variable in order to take advantage of the greater privacy setting... Peter Bowers December 16, 2007, at 03:22 AM

Private stuff in RecentChanges

The page changes in the private group are posted to the group's RecentChanges page, but that is fine, as this page read protection is set as for all the pages in the group with GroupAttributes?action=attr

Preventing private stuff from appearing in AllRecentChanges

All page changes are posted to $SiteGroup.AllRecentChanges (default is Site.AllRecentChanges). This includes changes to pages in the private group. To prevent public view of references to changes in the private group, you have two options:

1. Restrict access to Site.AllRecentChanges by making it read-protected like the private group. You can do that using the following in the browser's address bar
Optionally you can create a Main.AllRecentChanges page for your non-private visitors. Here is some code for config.php that creates a Main.AllRecentChanges page excluding changes made in the private group:
$thisgroup = FmtPageName('$Group', $pagename);
if ($thisgroup != 'MyPrivateGroup') {
  $RecentChangesFmt['Main.AllRecentChanges'] =
    '* [[$Group.$Name]]  . . . $CurrentTime $[by] '
      .'$AuthorLink: [=$ChangeSummary=]';
} else { $RecentChangesFmt['Main.AllRecentChanges'] = ''; }
2. Prevent changes made in the private group(s) from appearing in Site.AllRecentChanges by either
2a. creating a local/PrivateGroup.php file (create a file for each private group) with this content:
<?php if (!defined('PmWiki')) exit();
##  This is here to kill recording of Private stuff in AllRecentChanges
2b. Or if you want to do it in local/config.php rather than in a separate script, try
$thisgroup = FmtPageName('$Group', $pagename);
if ($thisgroup == 'PrivateGroup') {
unset($RecentChangesFmt['$SiteGroup.AllRecentChanges']); }
How can you do this for all read-protected pages?
This is kind-of experimental, but what follows seems to work on some sites:
# Check if page has passwords for an access level
function HasPW($pagename, $level)
  { global $AllowPassword;
    $page = RetrieveAuthPage
      ( $pagename, 'read', false,  READPAGE_CURRENT );
    if( !$page )
      return true;
    $arr = $page["=passwd"][$level];
    if( $arr && !in_array("@$AllowPassword",$arr) )
      return true;
    return false;

# Don't record public changes for read-locked pages
if( HasPW($pagename,'read') )

Securing file uploads to the private group

By default all file uploads to all groups are publicly accessible. Two extra steps need to be taken in order to secure uploads:

  1. Set in config.php: $EnableDirectDownload = 0;
  2. Protect the uploads directory. The easiest way is often (for Apache servers) to create an .htaccess file in the uploads/ directory with this content:
Order Deny,Allow
Deny from all

Please see SecureAttachments for more details about this.

Note that uploads to a read-protected wikigroup are only as secure as the least-protected page in that group, so while it is technically possible to unprotect a single or select few pages within the group, doing so creates a window for public access to all file uploads to that group.


  • This recipe was last tested on PmWiki version:
  • This recipe requires at least PmWiki version: and (any other recipes)
  • This recipe, version...... was installed here the...(date)



I am having trouble with password-protecting the read action on certain groups. I'd like a user to be able to login on the main page of that group with [[Internal.HomePage?action=login | Login]], but I end up with the page loading up the password prompt recursively. On the other hand, it worked on a different installation, where I read-protected the Main.HomePage. In my opinion, even if I try to access a certain page out of a read-protected group, I should at least be able to get the password prompt without ending up in a recursive loop. Any ideas? ~Jonas April 23, 2009, at 03:15 AM

If you want to replace the standard Site.AllRecentChanges you should consider using $SiteGroup.AllRecentChanges, otherwise it don't override the config in pmwiki.php /PhakE

See Also


Category: Security

User notes? : If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.