Apache, symlinks, 403

Last modified date

Comments: 0

tail -f /opt/lampp/logs/error_log

I’m still in the process of setting things up on this server. Web stuff via Apache on Ubuntu. I’m moderately familiar with the Apache setup as it comes with the Ubuntu distro, but recently had cause to install Apache + MariaDB(≈MySQL) + WordPress on a local machine. I’d recently stumbled on XAMPP (≈LAMPP), effectively a bundle of that lot^^ and installation went like a dream. So when I came to putting them on a remote server, followed the same path again.

Unprecedented Plague Mask, 1899

(image source)

XAMPP vs. Apache

I did want a little more than the minimal setup I’d got locally. Nothing particularly unusual : HTTPS, access to bespook services on other ports via (reverse/) proxy. I don’t know crypto, avoid it like the plague, so the SSL bits were a total nightmare until a kind soul on the Jena mailing list told me about Let’s Encrypt.

But a big stumbling block for me was that the config of Apache in XAMPP isn’t the same as what I was used to. Which isn’t saying that much, I’ve been a user of Apache for a long time, and every time I use it I find the configuration horrendous. With seemingly arbitrary changes for XAMPP (maybe this is how it’s done on a different, non-Debian-based distro?), this was another layer of hell.

Forget what you know, here it’s mostly done via:


which has a bunch of includes –


The symlinks/403 Thing

The XAMPP thing may or may not be relevant, but for me at least it was an extra uncertainty.

I want to symlink across from the Web Server root on the filesystem to other projects. Not unreasonable..?

Halloween came early.

From what I can gather, the key bit of setup for symlinks is along the lines of:

<Directory />
    Options FollowSymLinks
    Require all granted

Require all granted is apparently an improvement on earlier Apache version’s :

<Location />
    Options FollowSymLinks
    Order deny, allow
    Deny from all
    Allow from thisIP

Oh yes. Next time you’re at a customs, imagine :

Goods to Declare – Nothing to Declare – Require All Granted

(Brexit, innit)

Also, the Apache server must have appropriate rights to the bits being symlinked.

Ok, that makes sense. But it’s still arcane in implementation.

I’ve not entirely figured out what it takes to make it work, but –

The permissions on the parent directory of whatever’s symlinked is significant.

But there’s more.

The /root directory appears to be a special case. (No, wait, see final para ->)

A Plague on all your Houses

I spent a good 4 hours on this one little annoyance. This was a key breakthrough :

There is an option in the config files, eg. in httpd.conf

LogLevel warn

Possible values include: debug, info, notice, warn, error, crit, alert, emerg.

Right. So early on I tried this at debug. Maybe I missed something, but at the time didn’t see anything useful. Then (after 4 hours) on a whim, tried info. This gave me (in /opt/lampp/logs/error_log) :

[Fri Oct 22 13:52:49.507908 2021] [core:error] pid 227647Permission denied: [client] AH00035: access to /symlink/s/test.txt denied (filesystem path '/root/symlink') because search permissions are missing on a component of the path

Hah! Permissions after all. I’ve only been using Linux for about 25 years (?), hopefully can be forgiven for not knowing what ‘search permissions‘ are. Turns out they are execute permissions.

Not a great deal wiser, I’m sure I’d already tried parent/subdirectories with 777 permissions. But I could now be more systematic in my trial-and-error.

I created /home/www and put a test.txt there. chmod 777 on www then chmod 755 on test.txt. Symlinked to it.

It worked!!!

I must have overlooked something in the dir tree, but I’m pretty sure I had /root/symlink/s/test.txt all 777 from /symlink up. Maybe I symlinked to symlink rather than test.txt..?

Anyway, I suppose it kinda makes sense to not have a load of exposed stuff in /root.


I’m going to be messing with my live WordPress install so thought it would be a good idea to sort out backups of content (I do have the Linode server doing an image backup daily, but something more fine-grained seems a good idea). I found a script that looked about right at A Shell Script for a Complete WordPress Backup.

This has a couple of obvious typos in the mysqldump options, but another problem is that XAMPP (again) has it’s own ideas of where to put things. I got :

# mysql
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

(I think I had to add the mysql client app dir to the path…forgot to make a note)

The socket in use can be made available with:

ln -s /opt/lampp/var/mysql/mysql.sock /var/run/mysqld/mysqld.sock

Hmm…not sure of which user:pass to use…

Ok, changed the root MariaDB pass to one of my own.

Now that script isn’t working properly… mysqldump args not right…

Remembered to update password in


I appear have got it working using a suggestion here :

I’ve a file .sqlpwd, contents:


Tweaked script to have :

mysqldump --defaults-extra-file=/root/.sqlpwd bitnami_wordpress > $BACKUP_DIR/$DB_FILE

I’ve got it dumping to a security-by-obscurity location on the Web server so I can download.

Hungry now so cron job will have to wait.


Leave a Reply

Your email address will not be published. Required fields are marked *

Post comment