_       _       
  (_) ___ | |_ ____
  | |/ _ \| __|_  /
  | | (_) | |_ / / 
 _/ |\___/ \__/___|
|__/               

Enable userdir in Apache on localhost

The following assumes a user with the username "user":

# Enable userdir module in Apache
sudo su
a2enmod userdir
systemctl restart apache2
exit

# create user's web folder and a simple web page
cd ~
chmod 711 .
mkdir public_html
cd public_html
cat > index.php << EOF
<html><head></head><body><p>Hello.</p></body></html>
EOF

Point browser to localhost/~user and the web page should appear.

To enable PHP in user directories, you need to edit /etc/apache2/mods-enabled/php8.2.conf

As root, change the last bit from this...

# Running PHP scripts in user directories is disabled by default
# 
# To re-enable PHP in user directories comment the following lines
# (from <IfModule ...> to </IfModule>.) Do NOT set it to On as it
# prevents .htaccess files from disabling it.
<IfModule mod_userdir.c>
    <Directory /home/*/public_html>
        php_admin_flag engine Off
    </Directory>
</IfModule>

...to this...

# Running PHP scripts in user directories is disabled by default
# 
# To re-enable PHP in user directories comment the following lines
# (from <IfModule ...> to </IfModule>.) Do NOT set it to On as it
# prevents .htaccess files from disabling it.
# <IfModule mod_userdir.c>
#     <Directory /home/*/public_html>
#         php_admin_flag engine Off
#     </Directory>
# </IfModule>

Restart Apache as follows (not sure if this is necessary or not):

sudo systemctl restart apache2

Allow .htaccess files to override PHP options

To limit the filesize that PHP is allowed to upload, I'm using a .htaccess file in each user's folder, like the following:

# Set file upload size limit
php_value upload_max_filesize 4M
php_value post_max_size 4M

However, the default apache config on localhost seems to prevent .htaccess setting php_value options (and other things). To allow it, I had to add "Options" to the "AllowOverride" line in "/etc/apache2/mods-enabled/userdir.conf", as shown below:

UserDir public_html
UserDir disabled root

<Directory /home/*/public_html>
    AllowOverride Options FileInfo AuthConfig Limit Indexes
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    Require method GET POST OPTIONS
</Directory>

Unpacking a Jotz CMS installation onto localhost

The way I'm unpacking my bare-bones Jotz CMS installation onto localhost for development work is by unpacking it in a subdirectory in /home/user/public_html/

Since I abandoned trying to get suexec working on localhost, I just have to chown folders and files as required so that PHP can write files into the Jotz tree, even though it's running as "www-data" rather than as "user". This is a little bit messy, but seems to be working ok for now. I haven't tried uploading the whole tree to Hetzner yet though, so it remains to be seen whether the ownership and permissions of the files and folders in the tree will be problematic.

To recursively chown all files and directories in a tree, do something like the following (sets user and group of each file/folder):

sudo chown -R www-data:www-data public_html 

ABANDONED APPROACH: Enabling suEXEC to replicate Hetzner's apache2 config

As I understand it, suexec allows (and forces) PHP scripts to run as the user who created them, rather than as the user that apache2 runs as.

sudo a2enmod suexec
sudo systemctl restart apache2