: Apache FollowSymlinks works in DocumentRoot but 403s in subdirectories I'm trying to run the Piwigo gallery/digital asset manager on a Raspberry Pi using Apache 2.4 on Arch Linux ARM. Piwigo's
I'm trying to run the Piwigo gallery/digital asset manager on a Raspberry Pi using Apache 2.4 on Arch Linux ARM. Piwigo's running happily. For Windows file naming and CIFS reasons, I need to make thousands of symlinks to an outside directory into Piwigo's FTP upload directory. My script to do this works perfectly.
This is not another person trying to symlink their home directory without understanding permissions.
In troubleshooting down, I've found that symlinks work fine in DocumentRoot but fail with 403 in all subdirectories of DocumentRoot that I've tested. Nothing outside DocumentRoot is involved. Symlinks in new test directories which cannot possibly contain .ht* files also fail.
I've read a hundred or so of the most relevant-seeming of the 465 results on Server Fault for "apache symlink", as well as various other posts around the Web. Those answers as well as Apache documentation all say that directives should "apply only to the named file-system directory, sub-directories, and their contents." - the Option directive should propagate down unless overridden, and my config should prevent overriding in any case. If I can figure out why symlinks are failing inside DocumentRoot, I'm confident they'll link out.
Apache is freshly restarted.
[alarm@alarmpi ~]$ sudo systemctl restart httpd
[alarm@alarmpi ~]$ sudo systemctl status httpd
* httpd.service - Apache Web Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2017-12-09 14:18:43 EST; 1min 2s ago
Process: 8578 ExecStop=/usr/bin/httpd -k graceful-stop (code=exited, status=0/SUCCESS)
Process: 8099 ExecReload=/usr/bin/httpd -k graceful (code=exited, status=0/SUCCESS)
Main PID: 8583 (httpd)
Tasks: 6 (limit: 4915)
CGroup: /system.slice/httpd.service
|-8583 /usr/bin/httpd -k start -DFOREGROUND
|-8584 /usr/bin/httpd -k start -DFOREGROUND
|-8585 /usr/bin/httpd -k start -DFOREGROUND
|-8586 /usr/bin/httpd -k start -DFOREGROUND
|-8587 /usr/bin/httpd -k start -DFOREGROUND
`-8588 /usr/bin/httpd -k start -DFOREGROUND
Dec 09 14:18:43 alarmpi systemd[1]: Started Apache Web Server.
Dec 09 14:18:44 alarmpi httpd[8583]: AH00558: httpd: Could not reliably determine the server's fully qualified domain
And here's the httpd.conf, fed through awk to strip the comments and blank lines. Obviously, whatever's wrong is probably in here. If memory serves, the two additions to default are loading PHP7 and making .PHPs executable.
[alarm@alarmpi ~]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/httpd.conf
ServerRoot "/etc/httpd"
Listen 80
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
LoadModule include_module modules/mod_include.so
LoadModule filter_module modules/mod_filter.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule unique_id_module modules/mod_unique_id.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
<IfModule !mpm_prefork_module>
#LoadModule cgid_module modules/mod_cgid.so
</IfModule>
<IfModule mpm_prefork_module>
#LoadModule cgi_module modules/mod_cgi.so
</IfModule>
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
LoadModule userdir_module modules/mod_userdir.so
LoadModule alias_module modules/mod_alias.so
LoadModule php7_module modules/libphp7.so
<FilesMatch .php$>
SetHandler application/x-httpd-php
</FilesMatch>
<IfModule unixd_module>
User http
Group http
</IfModule>
ServerAdmin you@example.com
<Directory />
AllowOverride none
Require all denied
</Directory>
DocumentRoot "/srv/http"
<Directory "/srv/http">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
<Files ".ht*">
Require all denied
</Files>
ErrorLog "/var/log/httpd/error_log"
LogLevel warn
<IfModule log_config_module>
LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined
LogFormat "%h %l %u %t "%r" %>s %b" common
<IfModule logio_module>
LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i" %I %O" combinedio
</IfModule>
CustomLog "/var/log/httpd/access_log" common
</IfModule>
<IfModule alias_module>
ScriptAlias /cgi-bin/ "/srv/http/cgi-bin/"
</IfModule>
<IfModule cgid_module>
</IfModule>
<Directory "/srv/http/cgi-bin">
AllowOverride None
Options None
Require all granted
</Directory>
<IfModule headers_module>
RequestHeader unset Proxy early
</IfModule>
<IfModule mime_module>
TypesConfig conf/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
</IfModule>
Include conf/extra/httpd-mpm.conf
Include conf/extra/httpd-multilang-errordoc.conf
Include conf/extra/httpd-autoindex.conf
Include conf/extra/httpd-languages.conf
Include conf/extra/httpd-userdir.conf
Include conf/extra/httpd-default.conf
Include conf/extra/phpmyadmin.conf
<IfModule proxy_html_module>
Include conf/extra/proxy-html.conf
</IfModule>
Include conf/extra/php7_module.conf
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>
EDIT: Arch just puts one httpd.conf file in /etc/httpd/conf/ , then includes stuff from /etc/httpd/conf/extra . Here are the contents of all Included .conf files, in order of inclusion:
[alarm@alarmpi conf]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/httpd-mpm.conf
<IfModule !mpm_netware_module>
PidFile "/run/httpd/httpd.pid"
</IfModule>
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 250
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_worker_module>
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_event_module>
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_netware_module>
ThreadStackSize 65536
StartThreads 250
MinSpareThreads 25
MaxSpareThreads 250
MaxThreads 1000
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_mpmt_os2_module>
StartServers 2
MinSpareThreads 5
MaxSpareThreads 10
MaxConnectionsPerChild 0
</IfModule>
<IfModule mpm_winnt_module>
ThreadsPerChild 150
MaxConnectionsPerChild 0
</IfModule>
<IfModule !mpm_netware_module>
MaxMemFree 2048
</IfModule>
<IfModule mpm_netware_module>
MaxMemFree 100
</IfModule>
==================
[alarm@alarmpi conf]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/httpd-multilang-errordoc.conf
Alias /error/ "/usr/share/httpd/error/"
<Directory "/usr/share/httpd/error">
AllowOverride None
Options IncludesNoExec
AddOutputFilter Includes html
AddHandler type-map var
Require all granted
LanguagePriority en cs de es fr it ja ko nl pl pt-br ro sv tr
ForceLanguagePriority Prefer Fallback
</Directory>
ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
ErrorDocument 410 /error/HTTP_GONE.html.var
ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
==================
[alarm@alarmpi conf]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/httpd-autoindex.conf
IndexOptions FancyIndexing HTMLTable VersionSort
Alias /icons/ "/usr/share/httpd/icons/"
<Directory "/usr/share/httpd/icons">
Options Indexes MultiViews
AllowOverride None
Require all granted
</Directory>
AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
AddIconByType (TXT,/icons/text.gif) text/*
AddIconByType (IMG,/icons/image2.gif) image/*
AddIconByType (SND,/icons/sound2.gif) audio/*
AddIconByType (VID,/icons/movie.gif) video/*
AddIcon /icons/binary.gif .bin .exe
AddIcon /icons/binhex.gif .hqx
AddIcon /icons/tar.gif .tar
AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
AddIcon /icons/a.gif .ps .ai .eps
AddIcon /icons/layout.gif .html .shtml .htm .pdf
AddIcon /icons/text.gif .txt
AddIcon /icons/c.gif .c
AddIcon /icons/p.gif .pl .py
AddIcon /icons/f.gif .for
AddIcon /icons/dvi.gif .dvi
AddIcon /icons/uuencoded.gif .uu
AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
AddIcon /icons/tex.gif .tex
AddIcon /icons/bomb.gif core
AddIcon /icons/back.gif ..
AddIcon /icons/hand.right.gif README
AddIcon /icons/folder.gif ^^DIRECTORY^^
AddIcon /icons/blank.gif ^^BLANKICON^^
DefaultIcon /icons/unknown.gif
ReadmeName README.html
HeaderName HEADER.html
IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
==================
[alarm@alarmpi conf]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/httpd-languages.conf
AddLanguage ca .ca
AddLanguage cs .cz .cs
AddLanguage da .dk
AddLanguage de .de
AddLanguage el .el
AddLanguage en .en
AddLanguage eo .eo
AddLanguage es .es
AddLanguage et .et
AddLanguage fr .fr
AddLanguage he .he
AddLanguage hr .hr
AddLanguage it .it
AddLanguage ja .ja
AddLanguage ko .ko
AddLanguage ltz .ltz
AddLanguage nl .nl
AddLanguage nn .nn
AddLanguage no .no
AddLanguage pl .po
AddLanguage pt .pt
AddLanguage pt-BR .pt-br
AddLanguage ru .ru
AddLanguage sv .sv
AddLanguage tr .tr
AddLanguage zh-CN .zh-cn
AddLanguage zh-TW .zh-tw
LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv tr zh-CN zh-TW
ForceLanguagePriority Prefer Fallback
AddCharset us-ascii.ascii .us-ascii
AddCharset ISO-8859-1 .iso8859-1 .latin1
AddCharset ISO-8859-2 .iso8859-2 .latin2 .cen
AddCharset ISO-8859-3 .iso8859-3 .latin3
AddCharset ISO-8859-4 .iso8859-4 .latin4
AddCharset ISO-8859-5 .iso8859-5 .cyr .iso-ru
AddCharset ISO-8859-6 .iso8859-6 .arb .arabic
AddCharset ISO-8859-7 .iso8859-7 .grk .greek
AddCharset ISO-8859-8 .iso8859-8 .heb .hebrew
AddCharset ISO-8859-9 .iso8859-9 .latin5 .trk
AddCharset ISO-8859-10 .iso8859-10 .latin6
AddCharset ISO-8859-13 .iso8859-13
AddCharset ISO-8859-14 .iso8859-14 .latin8
AddCharset ISO-8859-15 .iso8859-15 .latin9
AddCharset ISO-8859-16 .iso8859-16 .latin10
AddCharset ISO-2022-JP .iso2022-jp .jis
AddCharset ISO-2022-KR .iso2022-kr .kis
AddCharset ISO-2022-CN .iso2022-cn .cis
AddCharset Big5.Big5 .big5 .b5
AddCharset cn-Big5 .cn-big5
AddCharset WINDOWS-1251 .cp-1251 .win-1251
AddCharset CP866 .cp866
AddCharset KOI8 .koi8
AddCharset KOI8-E .koi8-e
AddCharset KOI8-r .koi8-r .koi8-ru
AddCharset KOI8-U .koi8-u
AddCharset KOI8-ru .koi8-uk .ua
AddCharset ISO-10646-UCS-2 .ucs2
AddCharset ISO-10646-UCS-4 .ucs4
AddCharset UTF-7 .utf7
AddCharset UTF-8 .utf8
AddCharset UTF-16 .utf16
AddCharset UTF-16BE .utf16be
AddCharset UTF-16LE .utf16le
AddCharset UTF-32 .utf32
AddCharset UTF-32BE .utf32be
AddCharset UTF-32LE .utf32le
AddCharset euc-cn .euc-cn
AddCharset euc-gb .euc-gb
AddCharset euc-jp .euc-jp
AddCharset euc-kr .euc-kr
AddCharset EUC-TW .euc-tw
AddCharset gb2312 .gb2312 .gb
AddCharset iso-10646-ucs-2 .ucs-2 .iso-10646-ucs-2
AddCharset iso-10646-ucs-4 .ucs-4 .iso-10646-ucs-4
AddCharset shift_jis .shift_jis .sjis
==================
[alarm@alarmpi conf]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/httpd-userdir.conf
UserDir public_html
<Directory "/home/*/public_html">
AllowOverride FileInfo AuthConfig Limit Indexes
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
Require method GET POST OPTIONS
</Directory>
==================
[alarm@alarmpi conf]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/httpd-default.conf
Timeout 60
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
UseCanonicalName Off
AccessFileName .htaccess
ServerTokens Full
ServerSignature Off
HostnameLookups Off
<IfModule reqtimeout_module>
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
</IfModule>
==================
[alarm@alarmpi conf]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/phpmyadmin.conf
Alias /phpmyadmin "/usr/share/webapps/phpMyAdmin"
<Directory "/usr/share/webapps/phpMyAdmin">
DirectoryIndex index.php
AllowOverride All
Options FollowSymlinks
Require all granted
</Directory>
==================
[alarm@alarmpi conf]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/proxy-html.conf
ProxyHTMLLinks a href
ProxyHTMLLinks area href
ProxyHTMLLinks link href
ProxyHTMLLinks img src longdesc usemap
ProxyHTMLLinks object classid codebase data usemap
ProxyHTMLLinks q cite
ProxyHTMLLinks blockquote cite
ProxyHTMLLinks ins cite
ProxyHTMLLinks del cite
ProxyHTMLLinks form action
ProxyHTMLLinks input src usemap
ProxyHTMLLinks head profile
ProxyHTMLLinks base href
ProxyHTMLLinks script src for
ProxyHTMLEvents onclick ondblclick onmousedown onmouseup
onmouseover onmousemove onmouseout onkeypress
onkeydown onkeyup onfocus onblur onload
onunload onsubmit onreset onselect onchange
==================
[alarm@alarmpi conf]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/php7_module.conf
<IfModule dir_module>
<IfModule php7_module>
DirectoryIndex index.php index.html
<FilesMatch ".php$">
SetHandler application/x-httpd-php
</FilesMatch>
<FilesMatch ".phps$">
SetHandler application/x-httpd-php-source
</FilesMatch>
</IfModule>
</IfModule>
And the remainder of .conf files in /etc/httpd/conf/extra/ , in case one of those included files in turn includes them, in alphabetic order.
[alarm@alarmpi extra]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/httpd-dav.conf
DavLockDB "/etc/httpd/var/DavLock"
Alias /uploads "/etc/httpd/uploads"
<Directory "/etc/httpd/uploads">
Dav On
AuthType Digest
AuthName DAV-upload
AuthUserFile "/etc/httpd/user.passwd"
AuthDigestProvider file
<RequireAny>
Require method GET POST OPTIONS
Require user admin
</RequireAny>
</Directory>
BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
BrowserMatch "MS FrontPage" redirect-carefully
BrowserMatch "^WebDrive" redirect-carefully
BrowserMatch "^WebDAVFS/1.[01234]" redirect-carefully
BrowserMatch "^gnome-vfs/1.0" redirect-carefully
BrowserMatch "^XML Spy" redirect-carefully
BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
BrowserMatch " Konqueror/4" redirect-carefully
==================
[alarm@alarmpi extra]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/httpd-info.conf
<Location /server-status>
SetHandler server-status
Require host .example.com
Require ip 127
</Location>
<Location /server-info>
SetHandler server-info
Require host .example.com
Require ip 127
</Location>
==================
[alarm@alarmpi extra]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/httpd-manual.conf
AliasMatch ^/manual(?:/(?:da|de|en|es|fr|ja|ko|pt-br|ru|tr|zh-cn))?(/.*)?$ "/usr/share/httpd/manual"
<Directory "/usr/share/httpd/manual">
Options Indexes
AllowOverride None
Require all granted
<Files *.html>
SetHandler type-map
</Files>
<Files *.html.tr.utf8>
ForceType "text/html; charset=utf-8"
</Files>
AddLanguage da .da
SetEnvIf Request_URI ^/manual/(da|de|en|es|fr|ja|ko|pt-br|ru|tr|zh-cn)/ prefer-language=
RedirectMatch 301 ^/manual(?:/(da|de|en|es|fr|ja|ko|pt-br|ru|tr|zh-cn)){2,}(/.*)?$ /manual/
LanguagePriority en da de es fr ja ko pt-br ru tr
ForceLanguagePriority Prefer Fallback
</Directory>
==================
[alarm@alarmpi extra]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/httpd-ssl.conf
Listen 443
SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLHonorCipherOrder on
SSLProtocol all -SSLv3
SSLProxyProtocol all -SSLv3
SSLPassPhraseDialog builtin
SSLSessionCache "shmcb:/run/httpd/ssl_scache(512000)"
SSLSessionCacheTimeout 300
<VirtualHost _default_:443>
DocumentRoot "/srv/http"
ServerName example.com:443 ServerAdmin you@example.com
ErrorLog "/var/log/httpd/error_log"
TransferLog "/var/log/httpd/access_log"
SSLEngine on
SSLCertificateFile "/etc/httpd/conf/server.crt"
SSLCertificateKeyFile "/etc/httpd/conf/server.key"
<FilesMatch ".(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/srv/http/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-5]"
nokeepalive ssl-unclean-shutdown
downgrade-1.0 force-response-1.0
CustomLog "/var/log/httpd/ssl_request_log"
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x "%r" %b"
</VirtualHost>
==================
[alarm@alarmpi extra]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/extra/httpd-vhosts.conf
<VirtualHost *:80>
ServerAdmin webmaster@dummy-host.example.com
DocumentRoot "/etc/httpd/docs/dummy-host.example.com"
ServerName dummy-host.example.com
ServerAlias dummy-host.example.com ErrorLog "/var/log/httpd/dummy-host.example.com-error_log"
CustomLog "/var/log/httpd/dummy-host.example.com-access_log" common
</VirtualHost>
<VirtualHost *:80>
ServerAdmin webmaster@dummy-host2.example.com
DocumentRoot "/etc/httpd/docs/dummy-host2.example.com"
ServerName dummy-host2.example.com
ErrorLog "/var/log/httpd/dummy-host2.example.com-error_log"
CustomLog "/var/log/httpd/dummy-host2.example.com-access_log" common
</VirtualHost>
Just to express the problem more clearly than English grammar allows:
From now on, we're Apache's user. We own pretty much everything. No fancy ACL tools are installed. No plus signs in the permissions.
[alarm@alarmpi ~]$ sudo -u http -s
[http@alarmpi alarm]$ cd /srv/http/
[http@alarmpi ~]$ ls -al
total 348
drwxr-xr-x 7 http http 4096 Dec 9 19:40 .
drwxr-xr-x 4 root root 4096 Dec 10 2016 ..
-rw------- 1 http http 551 Dec 9 19:09 .bash_history
drwx------ 3 http http 4096 Nov 27 23:51 .config
drwx------ 3 http http 4096 Nov 26 19:39 .cache
drwx------ 3 http http 4096 Nov 26 19:39 .local
-rwxr-xr-x 1 http http 234673 Dec 9 14:39 PicSub.jpg
-rwxr-xr-x 1 http http 318682 Feb 22 2017 PicTop.jpg
-rw-r--r-- 1 http root 20 May 29 2017 info.php
drwxr-xr-x 15 http http 4096 Nov 26 18:23 piwigo
Let's make a directory. I've never made one named demodir before recording this example.
[http@alarmpi ~]$ mkdir -v demodir
mkdir: created directory 'demodir'
Move one of the pictures into the subdirectory, then create four symlinks - one within each directory, and one each going up and down directory levels.
[http@alarmpi ~]$ mv PicSub.jpg demodir/
[http@alarmpi ~]$ ln -s demodir/PicSub.jpg linkintoptosub.jpg
[http@alarmpi ~]$ ln -s PicTop.jpg linkintoptotop.jpg
[http@alarmpi ~]$ ln -s PicTop.jpg demodir/linkinsubtotop.jpg
[http@alarmpi ~]$ ln -s demodir/PicSub.jpg demodir/linkinsubtosub.jpg
EDIT: User http can read and execute demodir.
[alarm@alarmpi conf]$ sudo -u http -s
[http@alarmpi conf]$ cd /srv/http/
[http@alarmpi ~]$ ls -al
total 348
drwxr-xr-x 7 http http 4096 Dec 9 19:46 .
drwxr-xr-x 4 root root 4096 Dec 10 2016 ..
-rw------- 1 http http 1346 Dec 10 01:32 .bash_history
drwx------ 3 http http 4096 Nov 26 19:39 .cache
drwx------ 3 http http 4096 Nov 27 23:51 .config
drwx------ 3 http http 4096 Nov 26 19:39 .local
-rwxr-xr-x 1 http http 318682 Feb 22 2017 PicTop.jpg
drwxr-xr-x 2 http http 4096 Dec 9 19:47 demodir
-rw-r--r-- 1 http root 20 May 29 2017 info.php
lrwxrwxrwx 1 http http 18 Dec 9 19:45 linkintoptosub.jpg -> demodir/PicSub.jpg
lrwxrwxrwx 1 http http 10 Dec 9 19:46 linkintoptotop.jpg -> PicTop.jpg
drwxr-xr-x 15 http http 4096 Nov 26 18:23 piwigo
Files work no matter where they are. Symlinks work in DocumentRoot, no matter where they link to. Symlinks 403 in the subdirectory, no matter where they link to.
[http@alarmpi ~]$ curl -I 192.168.0.100/PicTop.jpg
HTTP/1.1 200 OK
Date: Sun, 10 Dec 2017 01:00:43 GMT
Server: Apache/2.4.25 (Unix) PHP/7.1.5
Last-Modified: Wed, 22 Feb 2017 19:23:20 GMT
ETag: "4dcda-549236de59a00"
Accept-Ranges: bytes
Content-Length: 318682
Content-Type: image/jpeg
[http@alarmpi ~]$ curl -I 192.168.0.100/demodir/PicSub.jpg
HTTP/1.1 200 OK
Date: Sun, 10 Dec 2017 01:00:48 GMT
Server: Apache/2.4.25 (Unix) PHP/7.1.5
Last-Modified: Sat, 09 Dec 2017 19:39:25 GMT
ETag: "394b1-55fed756f159d"
Accept-Ranges: bytes
Content-Length: 234673
Content-Type: image/jpeg
[http@alarmpi ~]$ curl -I 192.168.0.100/linkintoptotop.jpg
HTTP/1.1 200 OK
Date: Sun, 10 Dec 2017 01:01:52 GMT
Server: Apache/2.4.25 (Unix) PHP/7.1.5
Last-Modified: Wed, 22 Feb 2017 19:23:20 GMT
ETag: "4dcda-549236de59a00"
Accept-Ranges: bytes
Content-Length: 318682
Content-Type: image/jpeg
[http@alarmpi ~]$ curl -I 192.168.0.100/linkintoptosub.jpg
HTTP/1.1 200 OK
Date: Sun, 10 Dec 2017 01:02:27 GMT
Server: Apache/2.4.25 (Unix) PHP/7.1.5
Last-Modified: Sat, 09 Dec 2017 19:39:25 GMT
ETag: "394b1-55fed756f159d"
Accept-Ranges: bytes
Content-Length: 234673
Content-Type: image/jpeg
[http@alarmpi ~]$ curl -I 192.168.0.100/demodir/linkinsubtosub.jpg
HTTP/1.1 403 Forbidden
Date: Sun, 10 Dec 2017 01:03:09 GMT
Server: Apache/2.4.25 (Unix) PHP/7.1.5
Vary: accept-language,accept-charset
Accept-Ranges: bytes
Content-Type: text/html; charset=utf-8
Content-Language: en
[http@alarmpi ~]$ curl -I 192.168.0.100/demodir/linkinsubtotop.jpg
HTTP/1.1 403 Forbidden
Date: Sun, 10 Dec 2017 01:03:37 GMT
Server: Apache/2.4.25 (Unix) PHP/7.1.5
Vary: accept-language,accept-charset
Accept-Ranges: bytes
Content-Type: text/html; charset=utf-8
Content-Language: en
EDITed to split these error.log messages off from being hidden under the curl results.
[http@alarmpi ~]$ tail /var/log/httpd/error_log
PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php/modules/imagick.so' - /usr/lib/php/modules/imagick.so: cannot open shared object file: No such file or directory in Unknown on line 0
[Sat Dec 09 14:17:35.240202 2017] [mpm_prefork:notice] [pid 8565] AH00163: Apache/2.4.25 (Unix) PHP/7.1.5 configured -- resuming normal operations
[Sat Dec 09 14:17:35.300240 2017] [core:notice] [pid 8565] AH00094: Command line: '/usr/bin/httpd -D FOREGROUND'
[Sat Dec 09 14:18:42.441258 2017] [mpm_prefork:notice] [pid 8565] AH00170: caught SIGWINCH, shutting down gracefully
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::ba27:ebff:fee9:83f0. Set the 'ServerName' directive globally to suppress this message
PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php/modules/imagick.so' - /usr/lib/php/modules/imagick.so: cannot open shared object file: No such file or directory in Unknown on line 0
[Sat Dec 09 14:18:46.230867 2017] [mpm_prefork:notice] [pid 8583] AH00163: Apache/2.4.25 (Unix) PHP/7.1.5 configured -- resuming normal operations
[Sat Dec 09 14:18:46.231507 2017] [core:notice] [pid 8583] AH00094: Command line: '/usr/bin/httpd -D FOREGROUND'
[Sat Dec 09 20:03:09.745189 2017] [core:error] [pid 8587] [client 192.168.0.100:35756] AH00037: Symbolic link not allowed or link target not accessible: /srv/http/demodir/linkinsubtosub.jpg
[Sat Dec 09 20:03:37.784041 2017] [core:error] [pid 8588] [client 192.168.0.100:35758] AH00037: Symbolic link not allowed or link target not accessible: /srv/http/demodir/linkinsubtotop.jpg
In the examples I've read, 403s on symlinks, if they're not permissions/encrypton/ACL problems, are SELinux. SELinux isn't officially supported on Arch, let alone ALARM. It isn't listed by pacman. Unofficially installing it takes three pages of heinous hacking which I absolutely have not done. Anyway, its main diagnostic command is unrecognized.
[http@alarmpi ~]$ sestatus
-bash: sestatus: command not found
What am I missing, please?
Ideally this would be tagged with symlinks, but I'm new and can't make tags.
More posts by @Nimeshi995
1 Comments
Sorted by latest first Latest Oldest Best
The ln commands here look incorrect.
[http@alarmpi ~]$ mv PicSub.jpg demodir/
[http@alarmpi ~]$ ln -s demodir/PicSub.jpg linkintoptosub.jpg
[http@alarmpi ~]$ ln -s PicTop.jpg linkintoptotop.jpg
[http@alarmpi ~]$ ln -s PicTop.jpg demodir/linkinsubtotop.jpg
[http@alarmpi ~]$ ln -s demodir/PicSub.jpg demodir/linkinsubtosub.jpg
The linking to PicTop.jpg requires a ../ when done inside the demodir.
The linking to PicSub.jpg from within demodir must not includedemodir/.
(ok) [http@alarmpi ~]$ mv PicSub.jpg demodir/
(ok) [http@alarmpi ~]$ ln -s demodir/PicSub.jpg linkintoptosub.jpg
(ok) [http@alarmpi ~]$ ln -s PicTop.jpg linkintoptotop.jpg
(fix) [http@alarmpi ~]$ ln -s ../PicTop.jpg demodir/linkinsubtotop.jpg
(fix) [http@alarmpi ~]$ ln -s PicSub.jpg demodir/linkinsubtosub.jpg
That being said, ls -l shows me broken links in a different color on Ubuntu. Maybe Arch does not do that? I have not used that Linux Distro in ages. One way to test whether a softlink is valid is to use a command such as test -f <filename> or stat <filename>. It will return an error if the softlink does not point to the right place.
To recreate a softlink, make sure to remove the existing one first.
[http@alarmpi ~]$ rm demodir/linkinsubtotop.jpg
[http@alarmpi ~]$ ln -s ../PicTop.jpg demodir/linkinsubtotop.jpg
Terms of Use Create Support ticket Your support tickets Stock Market News! © vmapp.org2024 All Rights reserved.