Phabricator/Local Dev Environment

From mediawiki.org

This page started life as User:BBearnes (WMF)'s notes from setting up a local dev environment for Phabricator, with some additions by MModell.

The hostname used here is: http://phabricator.lan/

An alternative pre-configured environment exists, which allows to use our existing deployment to spin up a working local Phab/Phorge instance via Scap. See here.

Phabricator / Phorge installation[edit]

See Phabricator installation guide or Phorge installation guide for basics.

For stability, stick to PHP 7 and avoid distributions with PHP 8.1+ for the time being.

Install system dependency packages[edit]

  • On Debian Bullseye:
    sudo apt install php-gd php-zip php-apcu php-mysql php-mbstring php-curl nginx php-fpm mariadb-server
    (or replace nginx with apache2 when using Apache HTTPD)
  • On Fedora:
    sudo dnf install httpd mariadb-server php php-gd php-mbstring php-mysqlnd php-opcache php-pecl-apcu-bc php-pecl-zip php-xml php-process

When using Apache, install its php module. For PHP 7: sudo apt install libapache2-mod-php7.4

Pull Wikimedia Phabricator code[edit]

  • If not done yet, set up your SSH key in Wikimedia GitLab to git clone in the next step
  • cd ~/code/wmf/
  • git clone git@gitlab.wikimedia.org:repos/phabricator/deployment.git phab-deployment
  • cd phab-deployment/
  • git submodule init
  • git submodule update --force

Set up MySQL/MariaDB database privileges[edit]

  • sudo systemctl start mariadb
  • sudo mariadb
  • MariaDB [mysql]> CREATE USER 'phabricator'@'localhost' IDENTIFIED BY 'password';
  • MariaDB [mysql]> GRANT ALL PRIVILEGES ON *.* TO 'phabricator'@'localhost';
  • MariaDB [mysql]> FLUSH PRIVILEGES
  • MariaDB [mysql]> Bye

Initialize database[edit]

~/code/wmf/phab-deployment/phabricator/bin/storage upgrade --force

Configure database access[edit]

  • ~/code/wmf/phab-deployment/phabricator/bin/config set mysql.host "localhost"
  • ~/code/wmf/phab-deployment/phabricator/bin/config set mysql.user phabricator
  • ~/code/wmf/phab-deployment/phabricator/bin/config set mysql.pass 'password'

Enable Phabricator developer mode[edit]

  • ~/code/wmf/phab-deployment/phabricator/bin/config set phabricator.developer-mode true
  • Optionally, set a DB prefix to avoid conflicts when testing with several versions:
    ~/code/wmf/phab-deployment/phabricator/bin/config set storage.default-namespace "wmfphab"

Configure PHP[edit]

Per http://phabricator.lan/config/issue/extension.opcache.devmode/ shown in the installed instance, make the following changes on Debian in the file php.ini. (The command php --ini locates the configuration file.)

diff --git a/php/7.4/fpm/php.ini b/php/7.4/fpm/php.ini
index bb69a26..b8dcf47 100644
--- a/php/7.4/fpm/php.ini
+++ b/php/7.4/fpm/php.ini
@@ -1818,12 +1818,12 @@ ldap.max_links = -1
 
 ; When disabled, you must reset the OPcache manually or restart the
 ; webserver for changes to the filesystem to take effect.
-;opcache.validate_timestamps=1
+opcache.validate_timestamps=1
 
 ; How often (in seconds) to check file timestamps for changes to the shared
 ; memory storage allocation. ("1" means validate once per second, but only
 ; once per request. "0" means always validate)
-;opcache.revalidate_freq=2
+opcache.revalidate_freq=0
 
 ; Enables or disables file search in include_path optimization
 ;opcache.revalidate_path=0

Edit default Phabricator config file[edit]

Create (or edit) ~/code/wmf/phab-deployment/phabricator/conf/local/local.json with the following content:

{
"maniphest.custom-field-definitions": {
  "external_reference": {
    "caption": "Reference",
    "description": "Reference bug id for bugs imported from Bugzilla",
    "edit": false,
    "name": "Reference",
    "search": true,
    "type": "text",
    "view": true,
    "fulltext": false
  },
  "security_topic": {
    "default": "default",
    "description": "Obsolete.",
    "instructions": "Deprecated: this field no longer triggers special behavior. The field exists now only to retain historically relevant information.",
    "name": "Security",
    "options": {
      "default": "None",
      "security-bug": "Software security bug",
      "sensitive": "Other confidential issue",
      "ops-access-request": "Access Request"
    },
    "search": false,
    "view": false,
    "type": "select"
  },
  "release.version": {
    "name": "Release Version",
    "description": "Version number to be released or deployed",
    "search": false,
    "type": "text",
    "fulltext": true,
    "edit": true,
    "view": true,
    "copy": false
  },
  "release.date": {
    "name": "Release Date",
    "edit": true,
    "view": true,
    "description": "Scheduled date for the release or deployment",
    "search": false,
    "fulltext": false,
    "type": "text",
    "copy": false
  },
  "deadline.due": {
    "name": "Due Date",
    "view": true,
    "edit": true,
    "description": "Deadline for completing the task.",
    "search": false,
    "fulltext": true,
    "type": "date",
    "copy": true
  },
  "risk.summary": {
    "name": "Summary",
    "description": "Brief overview of issue.",
    "search": false,
    "type": "text",
    "fulltext": true,
    "copy": false
  },
  "risk.impacted": {
    "name": "Impacted",
    "description": "Hosts or endpoints exposed",
    "search": false,
    "type": "text",
    "fulltext": true,
    "copy": false
  },
  "risk.rating": {
    "name": "Risk Rating",
    "search": true,
    "type": "select",
    "options": {
      "": "N/A",
      "info": "Informational",
      "low": "Low",
      "medium": "Medium",
      "high": "High",
      "crit": "Critical"
    }
  },
  "error.reqid": {
    "name": "Request ID",
    "caption": "Error Code / Request ID",
    "description": "Unique identifier for the request",
    "search": true,
    "type": "text",
    "fulltext": true,
    "copy": true
  },
  "error.stack": {
    "name": "Stack Trace",
    "type": "remarkup",
    "caption": "Stack Trace (if available)",
    "description": "Stack trace (from logstash)",
    "fulltext": true,
    "search": false,
    "copy": false
  },
  "error.url": {
    "name": "Request URL",
    "placeholder": "Insert anonymized URL",
    "caption": "Anonymized Request URL (If available)",
    "search": false,
    "fulltext": true,
    "copy": false
  },
  "release.conductors": {
    "name": "Train Conductors",
    "type": "users",
    "limit": 2,
    "search": true,
    "fulltext": false,
    "copy": false,
    "caption": "See <a href='https://www.mediawiki.org/wiki/Wikimedia_Release_Engineering_Team/Roles#Train_Conductor'>Train Conductor</a>"
  }
  },
  "maniphest.subtypes": [
    {
      "key": "default",
      "name": "Task"
    },
    {
      "key": "bug",
      "name": "Bug"
    },
    {
      "key": "log",
      "name": "LogSpam"
    },
    {
      "key": "deadline",
      "name": "Deadline"
    }
  ]
}

Set Phabricator base URL[edit]

~/code/wmf/phab-deployment/phabricator/bin/config set phabricator.base-uri 'http://phabricator.lan/'

Define system host[edit]

Add to the file /etc/hosts the following line:
127.0.1.1 phabricator.lan

Configure webserver[edit]

Note: This section only applies when using Apache HTTPD instead of Nginx:

  • Enable the two required modules: a2enmod rewrite; a2enmod php7.4
  • Create the file /etc/apache2/sites-available/001-wmfphab.conf with the following content:
<VirtualHost *>
  ServerName phabricator.lan
  DocumentRoot ~/code/wmf/phab-deployment/phabricator/webroot
<Directory "~/code/wmf/phab-deployment/phabricator/webroot">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>
  RewriteEngine on
  RewriteRule ^/rsrc/(.*)    -                       [L,QSA]
  RewriteRule ^/favicon.ico  -                       [L,QSA] 
  RewriteRule ^/(.*)$       /index.php?__path__=/$1  [B,L,QSA]
</VirtualHost>
  • sudo ln -s /etc/apache2/sites-available/001-wmfphab.conf /etc/apache2/sites-enabled/001-wmfphab.conf
  • sudo rm /etc/apache2/sites-enabled/000-default.conf

Start webserver[edit]

sudo systemctl start nginx
(or
sudo systemctl start apache2
when using Apache HTTPD)

Load custom Phabricator extensions[edit]

For antivandalism, misc and translations:

~/code/wmf/phab-deployment/phabricator/bin/config set load-libraries '["~/code/wmf/phab-deployment/libext/ava/src","~/code/wmf/phab-deployment/libext/misc/src","~/code/wmf/phab-deployment/libext/translations/src"]'

Then config is under http://phabricator.lan/config/group/ , for example http://phabricator.lan/config/group/antivandalism/

Administration, etc.[edit]

Creating test data[edit]

This requires developer mode, but there's a `lipsum` command:

~/code/wmf/phab-deployment/phabricator/bin/lipsum generate tasks

Starting daemons[edit]

~/code/wmf/phab-deployment/phabricator/bin/phd start

Auth lock[edit]

Disallows configuring authentication methods in the user interface

~/code/wmf/phab-deployment/phabricator/bin/auth lock

Recover access to a local account[edit]

See https://we.phorge.it/book/phorge/article/configuring_accounts_and_registration/ , basically:

~/code/wmf/phab-deployment/phabricator/bin/auth recover someUsername