Go button for Search using swish_e Go button for Search using Google
 
A comet
skyBuilders timeLines GNU/Linux/Apache/PHP/PostgreSQL Installation HOWTO

skyBuilders.com skyBuilders timeLines Installation Manual for RedHat 9.0
Updated for Fedora Core 6 (4/30/07)
Derek Doyle dtd at skyBuilders dot com


Unless otherwise noted, all commands in this manual are expected to be run as the root user.

Related documentation:
        Installing additional timeLines sites on an existing skyHost

1. Operating System Configuration
  This is the process for configuring a new RedHat 9 host to become a skyHost running (and developing) skyBuilders timeLines under GNU/Linux/Apache/PHP/PostgreSQL. No other distributions have been tested as of this date, but there are no known issues to prevent the Apache/PHP/PostgreSQL version of timeLines from running in any Linux or other Unix-like environment. There are a few required services and utilities:
  • An httpd service with Middleware: Apache mod_php
  • A Relational Database Service: PostgreSQL
  • Secure Sockets Layer: Apache mod_ssl and openssl for secure web communication
  • Editing and Network Utilities: the GNU Project system of software tools
  • And two that are recommended, but not required:
    • Secure Shell Service: openssh
    • Linux development tools, including the kernel source

  These services will require the following ports to be opened:

  • ssh: 22
  • http: 80
  • https: 443
  • postgresql: 5432

  Install RedHat 9
  See the RedHat site for full freely downloadable distribution and documentation.

  Partitioning recommendation:

name recommended format
/ 15% ext3
/boot 100MB ext3
/swap 2xRAM N/A (linux swap)
/tmp 2GB ext3
/home 15% ext3
/var 42% ext3
/usr 28% ext3

  Fedora (FC3 - FC5) Partitioning recommendation:

name recommended format
/boot 100MB ext3
/swap 2xRAM N/A (linux swap)
/ Remaining ext3

  * NB: Due to the possibility of unforseen file growth within partitions, we now recommend that all partitions, other than boot and swap, be consolidated into one super partition, '/'.

Fedora Core (3.0 - 5.0) Notes: It is advisable as a matter of general practice to disable the graphical login interface. To do this make the following edits.

  1. In /etc/grub.conf comment out the hidemenu line. (Set the timeout if you like also.)

  2. And also change the kernel line from (notice the removal of "rhgb quiet"):
        kernel /vmlinuz-2.6.9-1.667 ro root=/dev/VolGroup00/LogVol00 rhgb quiet
    to:
        kernel /vmlinuz-2.6.9-1.667 ro root=/dev/VolGroup00/LogVol00

  3. Then edit the /etc/inittab file, changing the runlevel from 5 to 3:
        id:5:initdefault:
    to:
        id:3:initdefault:

  4. Ensure that SELinux is disabled (important) edit the /etc/selinux/config file: set SELINUX=disabled.

  5. Also ensure that PEAR is completely installed - this is no longer done by default - by issuing the following command line:
    # yum -y install php-pear
  6. # pear install db
  7. # yum -y install php-mbstring (multi-byte support for UTF8 charset in php)
  8. # yum -y install php-xml (an XML parsing library for php)
  9. # yum -y install http (a library for making http requests)
  10. # yum -y install tidy (an html cleanup utility)

2. SSH Configuration
Enable ssh for all users who will require remote access.
  SSH lives in the directory /etc/ssh.
  Open the file /etc/ssh/sshd_config for editing in your favorite editor.
  Go to the end of the file.
  After the last line, add a line that reads "AllowUsers" followed by a tab followed by a space-delimited list of usernames to allow.
  Restart the ssh service:
    # service sshd restart
  The service should reply OK.
  Test login.
    # ssh <username>@localhost

3. Apache Configuration
Some general information about the service:
  • Nota Bene: It is imperative that the Apache extension package for PostgreSQL be installed. Make sure to install the RPM which may looks something like php-pgsql-4.3.4-11.rpm. (The command to install it is: % rpm -Uvh php-pgsql-4.3.4-11.rpm)
  • /etc/httpd is the program directory
  • /etc/httpd/conf/httpd.conf is the configuration file
  • /var/www/html is the wwwroot or home directory for the server
  • # service httpd [start|restart|stop|status] can be used to control the service. # man service for details.
Set httpd to start on boot and start httpd.
To check the current setting:
    # chkconfig httpd --list
To set the service to start on boot:
    # chkconfig httpd --level 345 on

To check if the httpd service is running:
    # service httpd status
If it replies that httpd is stopped, then the httpd service is not running. To start it:
    # service httpd start
service should reply OK.

Make a new directory for the timeLines application to serve from.
  This directory should be named using the fully qualified domain name of the new site. For the examples in this manual, the example domain name "www.example.tld" will be used. The suggested location for the new directory is alongside the default web root (in this case /var/www/html/). Using the example the new directory would be at /var/www/www.example.tld/.
    # mkdir /var/www/www.example.tld

4. Secure Sockets Layer (SSL) Certificate Generation [Optional]
  SSL is only required for secure shopping cart transactions. This section can be skipped if your site will not have secure transactions. Likewise, the whole application would benefit from (and run properly) being run securely. Feel free to run the whole site under a secure certificate.
  SSL should automatically have been configured during OS installation. However, in order for the timeLines application to take advantage of SSL, a Secure Certificate Signing Request and associated Key must be generated. There is a requirement that in order to become a Secure Certificate, the Request must be digitally signed in order to operate, to authorize it. This does not add any security, rather it acts as a guarantor to strangers that the Certificate really belongs to the organization it says it does. Certificate Authorities such as VeriSign charge money for the identity verification and authentication service, but for an internal application like this one, their services are not strictly necessary, as a certificate can be "self-signed" (if you are interested in using their services, feel free; their site should have full instructions on generating a certificate and key which can be substituted for the indicated part of this section below). Self-signing allows the generating organization to enable their own, equally secure Certificates, generally only used internally, or by other trusting organizations.
  Thanks to Fermilab for their helpful, easy-to-follow instructions, which also link to further, more in depth material on the subject of SSL, for those who are interested.
  The process:
  1. Navigate to /etc/httpd/:
        # cd /etc/httpd
  2. Make a new directory called cert and navigate into it (this is where your certificate and key will be kept):
        # mkdir cert
        # cd cert
  3. Create the Certificate Request:
        # openssl req -new > sky.cert.csr
  4. The openssl command will now ask a few questions to identify the certificate. The crucial one is called Common Name. The value entered for Common Name must be the fully qualified host and domain name of the server. For this example, "www.example.tld" will be used. This name must perfectly match the name of the machine. The other key ones are the PEM pass phrase, which will be required in the following step of the process, and the Challenge Password, which should not be lost. Here is an example of its operation, with some example answers:
        # openssl req -new > sky.cert.csr
        Using configuration from /usr/share/ssl/openssl.cnf
        Generating a 1024 bit RSA private key
        .........+++++
        ....+++++
        writing new private key to 'privkey.pem'
        Enter PEM pass phrase: pick something
        Verifying password - Enter PEM pass phrase: pick something
        -----
        You are about to be asked to enter information that will be incorporated
        into your certificate request.
        What you are about to enter is what is called a Distinguished Name or a DN.
        There are quite a few fields but you can leave some blank
        For some fields there will be a default value,
        If you enter '.', the field will be left blank.
        -----
        Country Name (2 letter code) [AU]:US
        State or Province Name (full name) [Some-State]:Massachusetts
        Locality Name (eg, city) []:Boston
        Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example LLQ
        Organizational Unit Name (eg, section) []:IT Department
        Common Name (eg, YOUR name) []:www.example.tld
        Email Address []:dtd@example.tld
        
        Please enter the following 'extra' attributes
        to be sent with your certificate request
        A challenge password []:
        An optional company name []:
  5. The output of the previous step should be sky.cert.csr, the Request file, and privkey.pem, the PEM file that contains the Key. In this step, the pass phrase supplied above will be exported from the PEM file encrypted, so that the certificate can use it:
        # openssl rsa -in privkey.pem -out sky.cert.key
    The openssl command will now prompt you for the pass phrase to authorize the export, then generate the file sky.cert.key, the Key file.
  6. Sign the Request. Either self-sign it or get it signed by a Certificate Authority.
    To self-sign the Request:
        # openssl x509 -in sky.cert.csr -out sky.cert.crt -req -signkey sky.cert.key -days 365
    The openssl command should reply something like:
        Signature ok
        subject=/C=US/ST=Massachusetts/L=Boston/O=Example LLQ/OU=IT Department
        /CN=www.example.tld/Email=dtd@example.tld
        Getting Private key

    This should generate the file sky.cert.crt, the Certificate file.

    To submit the Request to a Certificate Authority:
    Either send the Request file to a Certificate Signing Authority as an email attachment or upload it through their web site.
    Put the resulting PEM file into the /etc/httpd/cert/ directory as sky.cert.crt
  7. The Certificate and Key have now been generated

5. Application Site (Virtual Host) Configuration
Main Configuration
In /etc/httpd/conf/httpd.conf, add these lines to the virtual servers section (substituting the appropriate domain name and IP address), with an extra VirtualHost section for each timeLines installation. (Please note that the string "*:80" can usually be substitued for the IP numbers listed below.):

You will likely want to preface your VirtualHost block with the following:

   <Directory /var/www/>
     CheckSpelling on
     AcceptPathInfo on
     Options MultiViews
   </Directory>

   NameVirtualHost 10.10.10.1

   <VirtualHost 10.10.10.1>
     ServerName www.example.tld
     DocumentRoot /var/www/www.example.tld
     DirectoryIndex index.html
     AddType application/x-httpd-php .php .php4 .php3 .phtml .html .xsd .xml .rss .rdfs .rdf
   </VirtualHost>

Secure Configuration [Optional]
  SSL is only required for secure shopping cart transactions. This subsection can be skipped if your site will not have secure transactions. Likewise, the whole application would benefit from (and run properly) being run securely. Feel free to run the whole site under a secure certificate.
  Apache SSL configuration is managed in a file called /etc/httpd/conf.d/ssl.conf. This config file works in concert with httpd.conf, and shares its style and syntax. Specifically, this file already has a Listen 443 line in it, so there is no need to put one into httpd.conf.
  1. Apache SSL requires the installation of the mod_ssl package:
      # yum install mod_ssl
  2. Edit /etc/httpd/conf.d/ssl.conf
  3. Look for the section in the file with the heading "SSL Virtual Host Context". Beneath this heading should be a line that reads "<VirtualHost _default_:443>". Comment out the VirtualHost line by putting a # (the comment character) at the front of it. Directly after that line, enter a line that looks just like it, but repeat _default_:443, substituting the host's IP address in place of _default_. Using the example:
      <VirtualHost 10.10.10.1:443>
  4. In the subsection immediately follwing, called "General setup for the virtual host", comment out the lines that have the DocumentRoot, ServerName, and/or AddType directives and insert these lines (substituting your server name where appropriate):
      DocumentRoot "/var/www/www.example.tld/"
      ServerName www.example.tld
      DirectoryIndex index.html
      AddType application/x-httpd-php .php .php4 .php3 .phtml .html .html .xsd .xml .rss .rdfs .rdf
  5. At the bottom of a subsection (two or three subsections down) called "Server Certificate:", comment out the line with the SSLCertificateFile directive and insert the line:
      SSLCertificateFile /etc/httpd/cert/sky.cert.crt
  6. At the bottom of the subsection beneath that one called "Server Private Key:", comment out the line with the SSLCertificateKeyFile directive and insert the line:
      SSLCertificateKeyFile /etc/httpd/cert/sky.cert.key
  7. Save and exit
  8. Restart the server httpd:
      # service httpd restart
  9. The Application Site is now configured

6. PHP Configuration
Test PHP
  Change directory to the web root (in this case '/var/www/html/' by default)
  Create a file called test.php and put into it one line: '<?php phpinfo(); ?>'
  Direct a browser (like lynx) at http://localhost/test.php and check the output. It should display a series of tables describing the machine and its php installation (see the php.net docs page on phpInfo() for more info).


Make appropriate changes to the file /etc/php.ini
  Here are the lines to look for that show their default values, each followed by the line that should replace it (the preferred method is to comment out the default line to preserve it, and put the new setting on the following line - the comment character is a semicolon ';'):
  1. error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_WARNING
  2. short_open_tag = On
    short_open_tag = Off
  3. memory_limit = 8M
    memory_limit = 16M
  4. magic_quotes_gpc = On
    magic_quotes_gpc = Off
  5. file_uploads = Off
    file_uploads = On
    [This may default to 'On' in other versions of PHP]
  6. upload_max_filesize = 2M
    upload_max_filesize = 2000M
  7. SMTP = localhost
    ; SMTP = localhost
  8. sendmail_from = me@localhost.com
    ; sendmail_from = me@localhost.com
  9. ; sendmail_path =
    sendmail_path = <path to sendmail>
    [in this case "/usr/sbin/sendmail -t -i"]
  10. display_errors = On
    display_errors = Off
  11. post_max_size = 2M
    post_max_size = 2000M
  12. default_charset = "utf-8"

Fedora Code 3.0 Installations and SELinux
  SELinux (Security Enhanced Linux - standard in Fedora Core 3.0) when in enforced mode will disable all system interfaces (writing to files, DBs, system command and program execution) available to php via apache. SELinux is built into the the Fedora 3.0 kernel and needs to set properly for timelines based websites to function properly.

In order to see look at the top of the out put from the command:

sestatus -v

Output:

SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: permissive


If the "Current mode" setting is showing a "permissive" setting that you will not need to make any adjustments. If "Current mode" is set to "enforcing" then you will need to change it. You can do so with the following command:

setenforce 0

You may need to edit /etc/selinux/config also:

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - SELinux is fully disabled.
SELINUX=enforcing
# SELINUXTYPE= type of policy in use. Possible values are:
# targeted - Only targeted network daemons are protected.
# strict - Full SELinux protection.
SELINUXTYPE=targeted


Change the line, SELINUX=enforcing, to read, SELINUX=permissive.

7. PostgreSQL Configuration
Set the postgresql service to start on boot
To check the current setting:
    # chkconfig postgresql --list
To set the service to start on boot:
    # chkconfig postgresql --level 345 on

Check whether postgresql is running:
    # service postgresql status
If the service command replies that postgresql is stopped, then:
    # service postgresql start
  service should reply OK

PostgreSQL helpful hints
  This subsection is just a few helpful pointers and links about how to handle you PostgreSQL installation. Actual instruction begins again in the next subsection (Enable proper logging for PostgreSQL).
  PostgreSQL configuration is in /var/lib/pgsql/data/postgresql.conf
  Host Based Access configuration file is in /var/lib/pgsql/data/pg_hba.conf
  To make a database (which will be owned by the operating system user who issues the command):
    bash-2.05b$ createdb <dbname>
  All user and db management can be done through the PostgreSQL interactive terminal (which accepts both SQL statements and PostgreSQL metacommands) called psql (man psql for reference):
    bash-2.05b$ psql <dbname>
  which takes you to a prompt which looks like:
    <dbname>=#
  To add/manage users:
  PGSQL User Management
  To create users:
    <dbname>=# CREATE USER <username>
  Every db must be VACUUMed at least once every billion transactions with the vacuum command in psql (or risk catastrophic data loss). See Routine Vacuuming.
  A few useful tools.
  To list all PostgreSQL users:
    <dbname>=> SELECT * FROM pg_user;
  To list all PostgreSQL databases:
    <dbname>=> SELECT * FROM pg_database;
  To find out the currently selected database, look at the name in the prompt:
    <dbname>=>

Enable proper logging for the postgresql service
  1. Edit the file /etc/init.d/postgresql in your favorite editor (applies only to versions of PostgreSQL prior to version 7.4.3)
  2. Find the line that reads:
        su -l postgres -s /bin/sh -c "/usr/bin/pg_ctl -D $PGDATA -p /usr/bin/postmaster -o '-p ${PGPORT}' start > /dev/null 2>&1" < /dev/null
    Edit the line to read (changes marked in bold, note double greater than after 'start'):
        su -l postgres -s /bin/sh -c "/usr/bin/pg_ctl -D $PGDATA -p /usr/bin/postmaster -o '-i -p ${PGPORT}' start >> /var/log/pgsql 2>&1" < /dev/null
    NOTE: If you are running the Fedora Core 3 version of PostgreSQL (postgresql-7.4.6-1.FC3.1) you will need to make the following edit - change:
        $SU -l postgres -c "$PGENGINE/postmaster -p ${PGPORT} -D '${PGDATA}' ${PGOPTS } &" >> $PGLOG 2>&1 < /dev/null
    to:
        $SU -l postgres -c "$PGENGINE/postmaster -i -p ${PGPORT} -D '${PGDATA}' ${PGOPTS } &" >> /var/log/pgsql 2>&1 < /dev/null
  3. If you are running PostgreSQL version 7.4.3 or higher you will have to edit the /var/lib/pgsql/data/postgresql.conf as well:
    Look for the line     #tcpip_socket = false
    and make the following changes:
        # BEGIN skybuilders mod
        #tcpip_socket = false
        tcpip_socket = true
        max_connections = 100
            # note: increasing max_connections costs about 500 bytes of shared
            # memory per connection slot, in addition to costs from shared_buffers
            # and max_locks_per_transaction.
        #superuser_reserved_connections = 2
        #port = 5432
        port = 5432
        # END skybuilders mod


    If you are using PostgreSQL 8.0 or higher ensure that you have the following in place (substitue your relavent IP address).
    Configure PostgreSQL CONNECTIONS AND AUTHENTICATION
    listen_addresses = '10.10.40.29'
    port = 5432

  4. Save and exit
  5. Restart postgresql:
        # service postgresql restart
    service should reply OK
Configure PostgreSQL users and databases
Assign a password to the PostgreSQL administration user
  First, the user called postgres, who is the superuser for the postgresql service, must have a new, secure password assigned both in the operating system and in the postgresql service. Next, a file called 'admins' must be created to indicate that the postgres user can connect to any database with a password challenge. Then, a user must be added to pgsql for the timeLines application. Finally, the new database(s) for the skyPipes application must be created.

  Create the PostgreSQL admin user and set its password both in the system and in PostgreSQL:

  1. As the root user, change the password for user postgres in the operating system by using the command passwd:
        # passwd postgres
    This command will now challenge you for the new secure database admin password which should be carefully kept track of, with the usual precautions of length, and a mix of letters, numbers, and symbols. This password will be needed again in step 4.
  2. Run a shell (a command line terminal) as the postgres user:
        # su postgres
    which takes you to a prompt which looks something like:
        bash-2.05b$
  3. Connect to template1 (PostgreSQL's template database) as user postgres by using the command psql, which opens the PostgreSQL interactive terminal. (Whenever in the psql terminal, be sure to expect confirmations of any action; a null response is a sure sign of no action performed.)
        bash-2.05b$ psql template1
  4. Change the password for user postgres in the PostgreSQL service by using the 'ALTER USER' command. Be sure to surround the password with single quotes/apostrophes as shown. The terminal should confirm by replying 'ALTER USER'. When using the following example, <newpassword> should be replaced with the new, secure password assigned in step 1. above. (Note that unlike the passwd command above, 'ALTER USER' will not automatically conceal the password as it is being typed. Be sure to enter it only in a secure environment.)
        template1=# ALTER USER postgres WITH PASSWORD '<newpassword>';
  5. Exit psql.
        template1=# \q
  6. Exit postgres user session.
        bash-2.05b$ exit
Set permissions for the PostgreSQL admin users
  Initially, PostgreSQL allows anyone from the local machine to connect to the databases without a password challenge, so as to allow the administrator to set the password for the postgres user. Once that has been done, access to the databases must be securely restricted. This is controlled from the file /var/lib/pgsql/data/pg_hba.conf.
  1. Open /var/lib/pgsql/data/pg_hba.conf in your favorite editor and make the following edits (be sure to use the new host's IP address in place of the example 10.10.10.1):
    1. Comment out any uncommented lines of the file (the default permissions) by putting a # at the start of each line.
    2. Copy the following text and paste it in after the last line of the file:
          local sameuser all md5
          local template1 all md5
          local all postgres md5
          host all all 127.0.0.1 255.255.255.255 md5
          host all all <ip address> 255.255.255.255 md5
  2. These configuration changes will only be applied the next time the service is restarted.
  3. Restart the postgresql service.
        # service postgresql restart
Create new users and databases
  1. Run a shell (a command line terminal) as the user postgres to do some user management.
        # su postgres
    Create a new database user. The name of this new user should correspond to the fully qualified domain name of the site that the database will be supporting, substituting underscores for the dots. For example, if your domain name is "www.example.tld", the corresponding user name should be "www_example_tld". This should also be the name of the database. Permissioning restricts users other than the admin user postgres to connect only to "template1" and the database with the same name as the user.
    The command to make users (outside psql) as user postgres looks like:
        bash-2.05a$ createuser <options> <username>
    The options that should be used are:
    -d = allowed to create databases
    -P = prompt for a password
    -A = not allowed to create users
    Using the example:
        bash-2.05a$ createuser -d -P -A www_example_tld
    The password for the new user will now be prompted for. This should be another equally secure password, preferably different from the postgres user password. This password will be required by the timeLines installation script later in order to initialize the database and enable the application.
    The password will be challenged for a second time for confirmation.
    Finally the postgres admin password will be asked for, to authorize the new user.
    createuser should reply "CREATE USER" (or in later versions "CREATE ROLE")
    The new user has now been created!
    (man createuser for details, dropuser to delete users, and ALTER USER from inside psql to change settings for a user)
  2. Exit the postgres shell to get back out to the root shell.
  3. Connect to template1 as the new database user. You will be challanged for the new user's password. (Notice that the terminal prompt ends with a ">" rather than a "#", to show that you are not a superuser (postgres).)
        # psql template1 <username>
  4. Create the database for this user, named with the new user's username. Ownership of the new database is automatically assigned to its creator. The terminal should respond "CREATE DATABASE".
        template1=# CREATE DATABASE <username>;
    Using the example:
        template1=# CREATE DATABASE www_example_tld;
  5. Connect to the new database. This will confirm its existence. The terminal should respond "You are now connected to database <dbname>."
        template1=> \c <dbname>;
  6. The database for this timeLines installation has now been created!
  7. Exit the psql terminal to return to the root shell:
        template1=> \q
  8. PostgreSQL users and databases are now configured.

8. Download timeLines Distribution
  Download the timeLines distribution archive file and extract it into the application site directory:
  1. Navigate into the new application site directory made in the Apache Configuration section above (/var/www/www.example.tld/ from the example).
  2. Download the installation archive file from downloads.skybuilders.com.
  3. Decompress the installation archive into the the new directory (for this example sky.tar.gz is the name of the downloaded archive file):
        # tar -xvf sky.tar.gz -z
    All necessary application server pages, directories, and image files will now be in place in the timelines subdirectory.
  4. Permissions must be set on the application directory. Create a group called "skyapp", if it has not yet been created. This will be the group that gives anonymous and administrator access to the application site.
        # /usr/sbin/groupadd skyapp
  5. Add users to this group. The apache user (in this case "apache") must be added so that requests to the web server will have permission to operate on the site. Other users that may need to be added to this group are any non-root administrators of the machine or the site, or any users who require ftp or sftp access (though any users who require different permissioning from the web users should be permissioned separately).
        # /usr/sbin/usermod -G skyapp apache
        # /usr/sbin/usermod -G skyapp <username>
  6. Change the group setting for the site directory (recursively, for all the files and directories below it).
        # cd /var/www
        # chown -R apache:skyapp www.example.tld
  7. Set permissions for the site directory (recursively, for all the files and directories below it).
        # chmod -R 770 www.example.tld
  8. Restart the web server httpd.
        # service httpd restart

9. Post Installation Packages Required for timelines/PHP5, etc.
  1. # yum -y install php-mbstring.rpm
  2. # yum -y install php-xml.rpm

Make sure to restart the apache server (# service httpd restart) after installing these packages.

10. Install timeLines application

  Run the timeLines installation script
  This script will build the new database's schema and populate it with initial data. Open a timeLines-compatible browser (Mozilla > 1.1, Netscape > 4.0, Internet Explorer > 4) and navigate to the following URL (where <domain name> is the domain name of your new site):
    http://<domain name>/timelines/Install.html
  The timeLines application will now challenge for the database password for the new site (as set in the PostgreSQL subsection "Configure PostgreSQL users and databases"). Initialization should take around two minutes.

  skyBuilders timeLines installation should now be complete!
  Please report any bugs at our interactive Bug Report. Thank you.

Edit  |  Subscribe  |
 Comments (0)
Requests
 Version: 5479 | Series: 37124