Due to the protection of selinux, simple web applications might report that they are not able to write to some directories, even if the regular UNIX permissions look sane. A quick inspection to /var/log/audit/audit.log might show the reason:

type=SYSCALL msg=audit(1382351978.112:2676): arch=c000003e syscall=21 success=no exit=-13 a0=7ff461f75898 a1=2 a2=0 a3=7ff46f6e25c0 items=0 ppid=12709 pid=12712 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 ses=4294967295 tty=(none) comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)

type=AVC msg=audit(1382351978.115:2677): avc:  denied  { write } for  pid=12712 comm="httpd" name="userdata" dev="dm-1" ino=1058476 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_sys_content_t:s0 tclass=dir

type=SYSCALL msg=audit(1382351978.115:2677): arch=c000003e syscall=21 success=no exit=-13 a0=7ff461df5b98 a1=2 a2=0 a3=7ff46f6e25c0 items=0 ppid=12709 pid=12712 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 ses=4294967295 tty=(none) comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)

type=AVC msg=audit(1382351978.115:2678): avc:  denied  { write } for  pid=12712 comm="httpd" name="configs" dev="dm-1" ino=1058477 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_sys_content_t:s0 tclass=dir

type=SYSCALL msg=audit(1382351978.115:2678): arch=c000003e syscall=21 success=no exit=-13 a0=7ff461f75898 a1=2 a2=0 a3=7ff46f6e25c0 items=0 ppid=12709 pid=12712 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 ses=4294967295 tty=(none) comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)

type=AVC msg=audit(1382351978.115:2679): avc:  denied  { write } for  pid=12712 comm="httpd" name="cache" dev="dm-1" ino=1058593 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_sys_content_t:s0 tclass=dir

Running the utility command audit2allow might actually do a bad thing, in allowing httpd to write to directories labeled httpd_sys_content_t:

#============= httpd_t ==============
allow httpd_t httpd_sys_content_t:dir write;

#!!!! This avc can be allowed using the boolean 'httpd_unified'
allow httpd_t httpd_sys_content_t:dir write;

What we really want is to properly label the directories that our web application needs write access to. In my case, with OpenPhoto, I needed to apply this to three directories:

# chcon --type=httpd_sys_rw_content_t /path/to/dir

As I prefer to have the things where they belong, I switch the default structure path to conform with the default Fedora packaging standards, and then apply the new labels:

# ln -s /var/cache/openphoto /var/www/openphoto/src/html/assets/cache
# ln -s /var/lib/openphoto/data /var/www/openphoto/src/userdata
# ln -s /etc/openphoto /var/www/openphoto/src/userdata/configs
# rmdir /var/www/openphoto/src/html/photos
# ln -s /var/lib/openphoto/data/photos /var/www/openphoto/src/html/photos
# chcon --type=httpd_sys_rw_content_t /var/cache/openphoto
# chcon --type=httpd_sys_rw_content_t /var/lib/openphoto/data
# chcon --type=httpd_sys_rw_content_t /etc/openphoto

With that, I can rest assured that selinux would still provide some layer of protection in case OpenPhoto has some security vulnerability that would allow an attacker to write/upload arbitrary things to my server.