S3FS to Mount S3 Buckets (NFS)

S3FS NFS Mount S3 Bucket

This is not a reliable method for some critical situations, as the S3 Buckets are not exactly defined as NFS mountable filesystems.

For mission critical situations, it is better to sue the “aws” commands in a script.

However, this is extremely useful for mounting photo albums or other resources like documents, or even archived website images on to lower cost storage. If you have thousands of photos, you don’t want them on your standard GP3 hard disk.

The mount commands can fail, with the shell terminal freezing up. Sometimes an fusermount command can fix a problem. If you are “frozen” when trying to mount, and you then issue a command like ls or df, you can open a fresh terminal and try again.

If you reboot your instance, you should have scripts from crontab to remount the bucket(s) and manually check.

When you manually mount a bucket, say you attach it to /var, then things usually work better if you cd to /var first from your shell.

It is possible to mount a bucket from another region, but why? Non-local regions cost more. In WordPress, bucket files are accessed seomthing like this:

cd /var/www/html
ln -s /var/content content
ls -l
lrwxrwxrwx 1 root apache 12 Mar 21 09:36 content -> /var/content

Originally the group is probably root, but do not change the link’s ownership away from root. If you do, you may have to delete the soft link and recreate it.

What we will do

This article shows the use of https://mydomain.au/content rather than a subdomain https://content.mydomain.au. There is no need for a subdomain when using S3 files.

URL’s such as https://photographybyshaw.au/aws/content/brisbane-river-northshore/DSD_4626.jpg with my own files, are far better for search engines than a fully qualified S3 Bucket URL such as https://s3.ap-southeast-2.amazonaws.com/myS3bucketname/brisbane-river-northshore/DSD_4626.jpg.

The URL is able to keep protection so that it is only viewable from the website, rather than directly accessing the true bucket URL.

The information below shows how to install the s3fs software, the shell script required to mount it, the crontab error checking for infrequent situations where the “nfs” mount point is corrupt, and examples of how we may use the mount point to access documents or images.

As an aside, all of my archived websites place the wp-content/uploads files onto S3 buckets without any need for scripting.

That is, if we create a bucket, say s3mydomain.au, and create a mount point called /var/content that points to this bucket, we can create a soft link:

/var/www/html/some_archive/wp-content/uploads -> /var/content/some_archive/wp-content/uploads

For calling documents or photographs, we could use:

/var/www/html/content -> /var/content, and from there access subdirectories with images, such as /var/content/brisbane and so on, or
/var/www/html/content/mydocuments -> /var/content/mydocuments.

This gives a sense of what we are doing. There is no configuration of CDN in this case, or use of problematic WordPress plugins that access buckets.

Something to keep in mind, there is a limit on the size of a .tar backup file in an S3 bucket, so if you have thousands of photographs, you create several tar files. S3 bucket speed it great, and practical for use compared to other cloud systems I have tested.

Install and Configure

Install the software…

dnf -y install automake fuse fuse-devel gcc-c++ git libcurl-devel libxml2-devel make openssl-devel
cd /home/ec2-user
git clone https://github.com/s3fs-fuse/s3fs-fuse.git
cd s3fs-fuse
./autogen.sh 
./configure --prefix=/usr
make
make install

[let's create a mount point...]

cd /var
mkdir content
chmod 2775 content
cd /var/www/html
ln -s /var/content content
ls -la

Now create an IAM role , with any name such as s3admin.

Give it these permission policies:

AmazonS3FullAccess
AdministratorAccess
CloudFrontFullAccess

I add Cloudfront in my own role as I use that elsewhere.

Now add this role to the EC2 instance under the EC2 console, Instances (then click on the instance) > Security > Modify IAM Role

Using the above examples, this is how you mount the bucket:
(You would use your own region, bucket name, and so on.)

s3fs -o iam_role="s3admin" -o use_path_request_style -o url="https://s3-ap-southeast-2.amazonaws.com" -o endpoint=ap-southeast-2 -o dbglevel=info -o curldbg -o allow_other -o use_cache="" s3mydomain.au /var/content

You may notice caching is set to null. Otherwise copies of files are made to your instance under /tmp, which is not good!

Then issue the Unix command to view the mount point.
df

You may add a test file to your bucket from the Amazon S3 console, and try viewing it with:

ls /var/content/*

If the mount point gets “twisted up” during your installation, you have to restart the instance from the instance console.

 

When you add files to the mount point, simply use Unix commands. For example:

cd /var/content

mkdir documents

chmod 2775 documents

cd /home/ec2-user

mv mydocument /var/content/documents

cd /var/content/documents

chmod 744s myfile

You can experiment with permissions.

Managing the mount point

Here is an example of crontab, to keep a check on the mount point:

15 1 * * 1 s3fs -o iam_role="s3admin" -o use_path_request_style -o url="https://s3-ap-southeast-2.amazonaws.com" -o endpoint=ap-southeast-2 -o dbglevel=info -o curldbg -o allow_other -o use_cache="" s3mydomain.au /var/content >/dev/null 2>&1

Here is a shell script you can manually use, /home/ec2-user/remount.sh with file permissions of 775.

#!/bin/sh
s3fs -o iam_role="s3admin" -o use_path_request_style -o url="https://s3-ap-southeast-2.amazonaws.com" -o endpoint=ap-southeast-2 -o dbglevel=info -o curldbg -o allow_other -o use_cache="" s3mydomain.au /var/content 
exit

Here is an example of a crontab entry to check the mount point is not corrupted, and if so to remount it and send you a courtest e-mail via postfix…

5 * * * * /home/ec2-user/mount_error.sh

Now create the shell scripts below. Let’s assume you have a general log file called /home/ec2-user/info.log that your shell scripts can use as required.

cd /home/ec2-user
touch t1.dat
vi /home/ec2-user/mount_error.sh

#!/bin/sh
:>/home/ec2-user/t1.dat
a="ok"

s3fs -o iam_role="s3admin" -o use_path_request_style -o url="https://s3-ap-southeast-2.amazonaws.com" -o endpoint=ap-southeast-2 -o dbglevel=info -o curldbg -o allow_other -o use_cache="" s3mydomain.au /var/content >/home/ec2-user/t1.dat 2>&1
a=`grep "Transport endpoint is not connected" /home/ec2-user/t1.dat|awk -F: {'print $3'}|awk  '{print $1}'`
if [ "$a" = "Transport" ] ;
then
        fusermount -u /var/content
    s3fs -o iam_role="s3admin" -o use_path_request_style -o url="https://s3-ap-southeast-2.amazonaws.com" -o endpoint=ap-southeast-2 -o dbglevel=info -o curldbg -o allow_other -o use_cache="" s3mydomain.au /var/content >/dev/null 2>&1
    d2=`date`
        echo "/var/content error" $d2 >> /home/ec2-user/info.log
sudo /usr/sbin/postfix start
sleep 2
sudo /usr/sbin/postfix reload
sleep 2
sudo /usr/sbin/sendmail -f admin@mydomain.au admin@mydomain.au < /home/ec2-user/mount_error.txt
sleep 5
sudo /usr/sbin/postfix stop
else
    :
fi

exit

[save and exit the editor]

vi mount_error.txt
From: admin <admin@mydomain.au>
Subject: mydomain.au s3fs was down
mydomain.au s3fs was down and is now remounted
.

[You must have a single blank line below the fullstop above. Save and exit the editor]
[You would of course use your own domain name and email address, and already have postfix running correctly.]

chown root mount_error.sh mount_error.txt t1.dat
chgrp ec2-user mount_error.sh mount_error.txt t1.dat
chmod 775 mount_error.sh
chmod 777 mount_error.txt t1.dat

[You may test the above script...]

sh -x ./mount_error.sh

Example - using the code to download file lists

We now come to the point of showing examples to use these mount points. This can be quite detailed and depends on your own programming skills.

 

Example 1 – list documents.

 

[Use your won font family, domain name, and icon images. I will supply the images as well for you.
We will call this script from PHP, so we use single quotes in many places ratehr than double quotes.]

cd /var/www/html
vi s3ls.sh

#!/bin/sh
IFS=$'\n'
font="Open&#32;Sans"
cd /var/content/$1
for a in `ls -l --time-style=+"%d %m %Y"`
do
p="                      "
b=`echo $a|awk '{print $5}'`
bt=`echo bytes: $b$p|cut -c 1-17`
bz=`echo $bt|awk '{print $2}'`
if [ "$bz" == "0" ] || [ "$bz" == "" ]
then
:
else
file=`echo $a|awk '{print $9" "$10" "$11" "$12" "$13" "$14" "$15}'|sed 's/^ *//;s/ *$//;s/  */ /;'`
e=""
e=`echo $file|awk -F. '{print $NF}'`

case $e in
pdf)
ext="<img src=https://mydomain.au/wp-content/uploads/adobe-reader.jpg width=20 height=20 alt=mydomain.au />"
;;
docx|doc)
ext="<img src=https://mydomain.au/wp-content/uploads/msword.jpg width=20 height=20 alt=mydomain.au />"
;;
xlsx|xls)
ext="<img src=https://mydomain.au/wp-content/uploads/excel-icon.jpg width=20 height=20 alt=mydomain.au />"
;;
pptx|ppt)
ext="<img src=https://mydomain.au/wp-content/uploads/ppt-icon.jpg width=20 height=20 alt=mydomain.au />"
;;
png|jpg)
ext="<img src=https://mydomain.au/wp-content/uploads/media-icon.jpg width=20 height=20 alt=mydomain.au />"
;;
mp3|aac|wav|m4a|mpeg|ogg)
ext="<img src=https://mydomain.au/wp-content/uploads/audio-icon.jpg width=20 height=20 alt=mydomain.au />"
;;
mov|avi|mp4|mpeg4|3gp|3gpp|3gpp2|3gp2|quicktime)
ext="<img src=https://mydomain.au/wp-content/uploads/movie-icon.jpg width=20 height=20 alt=mydomain.au />"
;;
*)
ext="<img src=https://mydomain.au/wp-content/uploads/file-icon.jpg width=20 height=20 alt=mydomain.au />"
;;
esac

pre="<img src=https://photographybyshaw.au/aws/wp-content/uploads/null-icon.jpg width=0 height=0 alt=axoncpn />"
d1=`echo $a|awk  '{print $6}'`
d2=`echo $a|awk  '{print $7}'`
d3=`echo $a|awk  '{print $8}'`
dt="date: $d1 $d2 $d3"
# echo $dt $a
echo "$dt $bt $ext file: <a href='https://mydomain.au/content/$1/$file' target=_blank><span style=text-decoration:underline;color:#444;font-family:$font;>$pre$file</span></a>"
fi
done
exit

I create a PHP shortcode with the following code. I use the plugin called ‘Add Shortcodes Actions And Filters’ from the author Michael Simpson. There are other plugins that do the same thing. Let’s call it ‘s3listfiles’.
This plugin will need you to tick the boxes, Activated, Shortcode, Code echoes output.

$place = "$atts[opt]";
$command = "/var/www/html/s3ls.sh $place 2>/dev/null";
$output = shell_exec($command);
echo "$output";
PHP_EOL;

You will notice how there is only one echo output.
Once this is done, you call the shortcode on a WordPress page.
For example:
[s3listfiles opt=”mydocuments”] where you place these square brackets around this code.
We have only programmed for one subdirectory below the bucket’s root directory. So, you could have directories like, personal, public, projectX, projectY and so on, but not /var/content/public/projectX. Rather, you would have /var/content/projectX.

I format the shortcode into a table format. For example:

<div style="background-color: #d6d6d6; padding-left: 20px; padding-right: 20px;">
<table style="text-align: left; background-color: #d6d6d6;">
<thead>
<tr>
<th style="color: #333; text-align: left; padding-top: 20px;" align="left">My Documents</th>
</tr>
</thead>
<tbody>
<tr style="text-align: left;">
<td style="color: #444; text-align: left; font-family: Courier, Times,sans-serif;" align="left">
<pre>[s3listfiles opt="mydocuments"]</pre>
</td>
</tr>
</tbody>
</table>
</div>

I refrain from giving a full example of creating scripts to display photographic galleries as the extent of work is considerable. My website
photographybyshaw.au shows how it is used.
If very interested, I can respond to an email request to give examples of how I do it. I was using html code relevant to the Avada theme, but I inserted the code from Jupiter as it displays galleries in a faster, better way, and for mobile phone displays and zoom.

Start typing and press Enter to search