Allowing multiple developers to read/write to website via SFTP or FTP

This article simply exists to serve as a visual reference when I’m explaining permissions to others. If you are looking to apply the concepts in this article on a live site, make sure you create a backup of the permissions and ownerships before proceeding as this article could break a pre-existing site!

This is one of those things where there is more than one way to go about it. The goal here is to allow multiple users the ability to work with the site via FTP/SFTP using basic permissions and groups.

First, create the shared group. In this case, as my domain is going to be example.com, I will call it exampleadmins:

[root@web01 ~]# groupadd exampleadmins

Now add the preexisting users to the group

[root@web01 ~]# usermod -aG exampleadmins user01
[root@web01 ~]# usermod -aG exampleadmins user02

Now change the group ownership recursively on the website directory:

[root@web01 ~]# chgrp -R exampleadmins /var/www/vhosts/example.com

Since we want users in the exampleadmins group to have write access, set the group write permissions on the website directory by:

[root@web01 ~]# chmod -R g+w /var/www/vhosts/example.com

To ensure that any new files or directory inherit the group ownership, use the SetGID bit on the directory recursively:

[root@web01 ~]# find /var/www/vhosts/example.com -type d -exec chmod g+s "{}" \;

To ensure that files or directories the user creates or uploads are group writable by default, you need to adjust the default umask for the FTP and SFTP server. For vsftpd which is generally the default FTP server, change the default umask from 022 to 002 by:

[root@web01 ~]# vim /etc/vsftpd.conf
...
local_umask = 002
...
[root@web01 ~]# service vsftpd restart

When using SFTP, update the sftp subsystem within /etc/ssh/sshd_config to set a umask of 0002 by:

[root@web01 ~]# vim /etc/ssh/sshd_config
...
Subsystem       sftp    /usr/libexec/openssh/sftp-server -u 0002
...
# Append to bottom of file:
Match Group exampleadmins
   ForceCommand internal-sftp -u 0002
[root@web01 ~]# service sshd restart

Now whenever you need to add additional users, simply create the user with a membership to exampleadmins

[root@web01 ~]# useradd -s /sbin/nologin -d /var/www/vhosts/example.com -G exampleadmins user03

And if the user already exists, simply run:

[root@web01 ~]# usermod -aG exampleadmins user03

WordPress setup on CentOS 6

Setting up WordPress is a pretty common task. However all too often I see people installing WordPress, and setting the ownership to ‘apache:apache’ recursively. While this makes life easier for the administrator, it opens up a host of security issues.

Taken directly from WordPress’s best practice guide on permissions:

Typically, all files should be owned by your user (ftp) account on your web server, and should be writable by that account. On shared hosts, files should never be owned by the web server process itself (sometimes this is www, or apache, or nobody user).

Most people know that using FTP is bad. However if you plan on using the wp-admin portal for media uploads, plugin updates, and core updates, you MUST have an FTP server installed and running. Using the Pecl SSH2 library looks like it would work in theory, but in reality, it doesn’t. Or at least, I haven’t found a way to make it work for the wp-admin portal without giving permission errors for this, that and everything in between since it needs weaker permissions. So while your users can use SSH/SCP to upload content via the command line, if they choose to do most of the WordPress tasks through wp-admin like most people would, use the FTP option from within /wp-admin.

This guide is going to show how you can setup WordPress properly accordingly to the note above from WordPress’s best practices guide on permissions. This guide will assume that you already have a working LAMP stack installed.

FTP Server Setup

First, install an FTP server called vsftpd:

[root@web01 ~]# yum install vsftpd
[root@web01 ~]# chkconfig vsftpd on

Now disable anonymous logins since vsftpd enables this by default for some reason:

[root@web01 ~]# vim /etc/vsftpd/vsftpd.conf
...
anonymous_enable=NO
...
[root@web01 ~]# service vsftpd restart

Then confirm you have a firewall in place that has a default to deny policy. So in the example below, I am only allowing in ports 80 and 443 from the world. Then I have SSH restricted to my IP address. Everything else is blocked, including that FTP server.

[root@web01 ~]# vim /etc/sysconfig/iptables
# Generated by iptables-save v1.4.7 on Fri Nov 13 19:24:15 2015
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [2:328]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT 
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT 
-A INPUT -i eth0 -s xx.xx.xx.xx/32 -p tcp -m tcp --dport 22 -m comment --comment "Allow inbound SSH from remote ip" -j ACCEPT
-A INPUT -p icmp -j ACCEPT 
-A INPUT -i lo -j ACCEPT 
-A INPUT -j REJECT --reject-with icmp-host-prohibited 
-A FORWARD -j REJECT --reject-with icmp-host-prohibited 
COMMIT
# Completed on Fri Nov 13 19:24:15 2015

Database Setup

Create a database for your new WordPress site by:

[root@web01 ~]# mysql
mysql> create database your_database;

Now grant access for that database to a user:

[root@web01 ~]# mysql
mysql> grant all on your_database.* to 'your_db_user'@'localhost' identified by 'your_secure_db_password';
mysql> flush privileges;
mysql> quit

Apache Setup

First, create a FTP/SCP user:

[root@web01 ~]# mkdir -p /var/www/vhosts/example.com
[root@web01 ~]# chmod 755 /var/www/vhosts/example.com
[root@web01 ~]# useradd -d /var/www/vhosts/example.com example_site_user
[root@web01 ~]# passwd example_site_user

Now setup the Apache vhost:

[root@web01 ~]# vim /etc/httpd/vhost.d/example.com.conf
<VirtualHost *:80>
        ServerName example.com
        ServerAlias www.example.com
        #### This is where you put your files for that domain
        DocumentRoot /var/www/vhosts/example.com

        ### Enable this if you are using a SSL terminated Load Balancer
        SetEnvIf X-Forwarded-Proto https HTTPS=on

	#RewriteEngine On
	#RewriteCond %{HTTP_HOST} ^example.com
	#RewriteRule ^(.*)$ http://www.example.com [R=301,L]

        <Directory /var/www/vhosts/example.com>
                Options -Indexes +FollowSymLinks -MultiViews
                AllowOverride All
		Order deny,allow
		Allow from all
        </Directory>
        CustomLog /var/log/httpd/example.com-access.log combined
        ErrorLog /var/log/httpd/example.com-error.log
        # New Relic PHP override
        <IfModule php5_module>
               php_value newrelic.appname example.com
        </IfModule>
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn
</VirtualHost>


##
# To install the SSL certificate, please place the certificates in the following files:
# >> SSLCertificateFile    /etc/pki/tls/certs/example.com.crt
# >> SSLCertificateKeyFile    /etc/pki/tls/private/example.com.key
# >> SSLCACertificateFile    /etc/pki/tls/certs/example.com.ca.crt
#
# After these files have been created, and ONLY AFTER, then run this and restart Apache:
#
# To remove these comments and use the virtual host, use the following:
# VI   -  :39,$ s/^#//g
# RedHat Bash -  sed -i '39,$ s/^#//g' /etc/httpd/vhost.d/example.com.conf && service httpd reload
# Debian Bash -  sed -i '39,$ s/^#//g' /etc/apache2/sites-available/example.com && service apache2 reload
##

# <VirtualHost _default_:443>
#        ServerName example.com
#        ServerAlias www.example.com
#        DocumentRoot /var/www/vhosts/example.com
#        <Directory /var/www/vhosts/example.com>
#                Options -Indexes +FollowSymLinks -MultiViews
#                AllowOverride All
#        </Directory>
#
#        CustomLog /var/log/httpd/example.com-ssl-access.log combined
#        ErrorLog /var/log/httpd/example.com-ssl-error.log
#
#        # Possible values include: debug, info, notice, warn, error, crit,
#        # alert, emerg.
#        LogLevel warn
#
#        SSLEngine on
#        SSLCertificateFile    /etc/pki/tls/certs/2016-example.com.crt
#        SSLCertificateKeyFile /etc/pki/tls/private/2016-example.com.key
#        SSLCACertificateFile /etc/pki/tls/certs/2016-example.com.ca.crt
#
#        <IfModule php5_module>
#                php_value newrelic.appname example.com
#        </IfModule>
#        <FilesMatch \"\.(cgi|shtml|phtml|php)$\">
#                SSLOptions +StdEnvVars
#        </FilesMatch>
#
#        BrowserMatch \"MSIE [2-6]\" \
#                nokeepalive ssl-unclean-shutdown \
#                downgrade-1.0 force-response-1.0
#        BrowserMatch \"MSIE [17-9]\" ssl-unclean-shutdown
#</VirtualHost>

Then restart Apache to apply the changes:

[root@web01 ~]# service httpd restart

WordPress Setup

Download a copy of WordPress, uncompress, and move the files into place by:

[root@web01 ~]# cd /var/www/vhosts/example.com
[root@web01 ~]# wget http://wordpress.org/latest.tar.gz && tar -xzf latest.tar.gz
[root@web01 ~]# mv wordpress/* ./ && rmdir ./wordpress && rm -f latest.tar.gz

Update the files and directories ownership to lock it down accordingly:

[root@web01 ~]# chown -R example_site_user:example_site_user /var/www/vhosts/example.com

Then open up a few files so wp-admin can manage the .htaccess, and so it can install plugins, upload media, and use the cache if you choose to configure it:

[root@web01 ~]# mkdir /var/www/vhosts/example.com/wp-content/uploads
[root@web01 ~]# mkdir /var/www/vhosts/example.com/wp-content/cache
[root@web01 ~]# touch /var/www/vhosts/example.com/.htaccess
[root@web01 ~]# chown apache:apache /var/www/vhosts/example.com/wp-content/uploads
[root@web01 ~]# chown apache:apache /var/www/vhosts/example.com/wp-content/cache
[root@web01 ~]# chown apache:apache /var/www/vhosts/example.com/.htaccess

And thats it! Once you have the domain setup in DNS, you should be able to navigate to the domain, and follow the WordPress installation wizard to complete the setup. Afterwards, log into wp-admin, and try to update a plugin, or install a new one. When it prompts you for the FTP information, be sure to use:

Hostname:  localhost
FTP Username:  example_site_user
FTP Username:  example_site_user_pw
Connection Type:  FTP

RHCSA Study Guide – Objective 7 : File Sharing

############################
Everything below are my raw notes that I took while attending an unofficial RHCSA training session.  I am posting them here in hopes they will assist others who may be preparing to take this exam.  

My notes are my own interpretation of the lectures, and are certainly not a replacement to classroom training either through your company, or by taking the official RHCSA classes offered through Red Hat.  If you are new to the Red Hat world, I strongly suggest looking into their training courses over at Red Hat.
############################

NFS

The network file service (NFS) is used to share data with other servers.

To see if the NFS server has the ports listening:

[root@web01 ~]# rpcinfo -p server1

To see what shares are setup on the NFS server:

[root@web01 ~]# showmount -e server1

To mount the NFS share:

[root@web01 ~]# mount x.x.x.x:/share1 /mnt

To make it persistent across reboots:

[root@web01 ~]# vi /etc/fstab
...
x.x.x.x:/share /mnt nfs defaults 0 0
...

EXAM NOTE: You just need to know how to mount a share for the rhcsa. No real nfs configuration needed

Lab

Mount the /share NFS share from server1, and add it to your fstab for persistence across reboots
[root@web01 ~]# mount -t nfs server1:/share /mnt
[root@web01 ~]# vim /etc/fstab
...
server1:/share  /mnt nfs defaults 0 0
...

VSFTPD

The default FTP server is vsftpd. The primary configuration file is:

/etc/vsftpd/vsftpd.conf

Two types of access are allowed:

1.  Anonymous : By default, these users are chrooted to /var/ftp for security.  (NOTE for SElinux), could use that --reference flag if changing dir
2.  User :  By default, users do not get chrooted.

Indivudual users can be denied by placing their names in:

[root@web01 ~]# vim /etc/vsftpd/ftpusers

Lab

1.  Configure VSFTPd to only allow the user 'richard' to ftp to your server
[root@web01 ~]# yum install vsftpd
[root@web01 ~]# chkconfig vsftpd on

# Now, need to set selinux to allow users to write to their homedir
[root@web01 ~]# getsebool -a |grep ftp
[root@web01 ~]# setsebool -P ftp_home_dir on
[root@web01 ~]# setsebool -P sftpd_enable_homedirs on

# EXAM NOTE: DO NOT FORGET TO SPECIFY THE -P SO THE CHANGE IS PERSISTENT ACROSS REBOOTS!

# Now, set vsftpd to only allow richard in:
[root@web01 ~]# vi /etc/vsftpd/vsftpd.conf
...
userlist_enable=NO
...

[root@web01 ~]# vi /etc/vsftpd/user_list
# Remove everything and add
richard

# Test by:
[root@web01 ~]# ftp localhost

2.  Browse through the man page on vsftpd.conf
[root@web01 ~]# man vsftpd.conf

3.  Make sure vsftpd is started at boot time
[root@web01 ~]# chkconfig vsftpd on