vhost templates

Discussion in 'General' started by nhybgtvfr, Sep 23, 2024.

  1. nhybgtvfr

    nhybgtvfr Well-Known Member HowtoForge Supporter

    Hi,
    looking at switching from apache to nginx.. testing is going well so far.. i can get 100 for both website and email configs at internet.nl
    now looking at easy ways to make those secure configs the default for new vhosts..
    when comparing the apache and nginx vhost templates, i can see there's stuff in the apache templates for enabling HSTS (strict-transport-security) and OCSP stapling, but nothing at all for either of these in the nginx template.

    i know i can copy the nginx template to conf-custom and add these settings there:
    Code:
            add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
            ssl_stapling on;
            ssl_stapling_verify on;
    
    just wondering if there's any reason there's nothing about any of these settings in the default ispconfig nginx vhost template?

    also, i know some changes to the nginx vhost config is needed for wordpress to work properly.
    what does everyone use? i've already got it working, but would like to know if there's anything that could help improve it.. caching, expiry settings etc.. i'm hoping to get all sites using the nginx fastcgi cache....
     
  2. till

    till Super Moderator Staff Member ISPConfig Developer

    I don't think there is a special reason for that. It is likely that the contributor who implemented that used Apache only, and we did not notice it to keep it in sync with the Nginx template. We should try to keep both configs in sync though.

    You need additional settings for most CMS, especially if they use some kind if 'nice URL' feature. Basically, everything in a website's .htaccess file must be converted to Nginx syntax and then added to the website's Nginx directives field.

    Personally, I do not use a lot of additional global config, just things like WordPress plugin specific configs e.g. from WP caching plugins. fastcgi cache might be a bit tricky, if i remember correctly, you must configure a part of it for each site outside of the server { ... } context, so you can not add everything in the website's nginx directives field. So, the fastcgi cache might require adding this as a feature in ISPConfig.
     
  3. ahrasis

    ahrasis Well-Known Member HowtoForge Supporter

    In my practise, I put that and some others in nginx default file rather than into the individual vhost files via the master template.

    Basically all things that I want to be applied on all, are in the said default file, so in won't be repeated in each vhost files via due to adding them in master template.

    Share yours in here and I will share mine too though that may not be the best for all.
     
  4. ahrasis

    ahrasis Well-Known Member HowtoForge Supporter

    I noticed that no one really cares about nginx that much, nor many are using it, so I don't want to touch about nginx that much in the git, but kept any improvements made limited to personal use only for now, though they are actually not much either, and mostly adaptable from various online resources, so none of that is really urgent.
     
  5. nhybgtvfr

    nhybgtvfr Well-Known Member HowtoForge Supporter

    i don't really have much outside the default vhost config at the moment..

    main differences i've made so far, are to uncomment '# server_tokens off;' in /etc/nginx/nginx.conf
    adding security.txt as from here: https://forum.howtoforge.com/threads/server-wide-security-txt.90153/
    so adding 'include /etc/nginx/snippets/securitytxt.conf;' into the vhost config.


    and also want to get at least most of the following in there, but i'm aware that not all these settings would be appropriate for some sites..

    Code:
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Xss-Protection "1; mode=block" always;
    ssl_stapling on;
    ssl_stapling_verify on;
    add_header Referrer-Policy 'same-origin';
    add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; frame-src 'self'; frame-ancestors 'self'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; form-action 'self';" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    
    also, possibly adding this before the server block:

    Code:
    # Expires map
    map $sent_http_content_type $expires {
        default                    off;
        text/html                  epoch;
        text/css                   max;
        application/javascript     max;
        ~image/                    max;
        ~font/                     max;
    }
    
    with this in the server block: 'expires $expires;'


    and for the fastcgi cache, adding something like
    Code:
    fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=wpcache:200m max_size=10g inactive=2h use_temp_path=off;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
    
    before the server block, although i believe the first line can only be set once, so probably best in the main config

    with this in the server block:
    Code:
    set $skip_cache 0;
        if ($request_method = POST) {
            set $skip_cache 1;
        }
        if ($query_string != "") {
            set $skip_cache 1;
        }
        if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|^/feed/*|/tag/.*/feed/*|index.php|/.*sitemap.*\.(xml|xsl)") {
            set $skip_cache 1;
        }
        if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
            set $skip_cache 1;
        }
    
    although i think i still need to work out some more settings to skip caching for woocommerce prices, cart etc..

    and something like this after the pre-existing settings in 'location ~ \.php$ {
    Code:
    fastcgi_cache wpcache;
    fastcgi_cache_valid 200 301 302 2h;
    fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
    fastcgi_cache_min_uses 1;
    fastcgi_cache_lock on;
    fastcgi_cache_bypass $skip_cache;
    fastcgi_no_cache $skip_cache;
    add_header X-FastCGI-Cache $upstream_cache_status;
    

    but i'm still just testing most stuff at the moment, not a lot of experience with nginx, so would like to get a good starting point from those with more knowledge and experience with it.
     
    ahrasis and till like this.
  6. till

    till Super Moderator Staff Member ISPConfig Developer

    I guess you have to find a way to give the caches a unique name, otherwise the cache might overwrite results of another website. So instead of using wcache you could try something like:

    Code:
    wpcache{tmpl_var name="domain_id"}
    so that the cache name is unique.
     
    ahrasis likes this.
  7. nhybgtvfr

    nhybgtvfr Well-Known Member HowtoForge Supporter

    good idea.. i'll try that
    i've only tried a single test site so far, so no idea what it does with multiple sites..

    as far as i can tell from what i've read so far, it sounds like it might only allow a single cache.. but people have got it working with multiple sites, so i was assuming that
    Code:
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    
    the $host part in here would be the requested website, so each vhost would have that, making their entries in the cache unique.
     
    ahrasis likes this.
  8. nhybgtvfr

    nhybgtvfr Well-Known Member HowtoForge Supporter

    i've got most of this working.. can get 100 on domain/site testing at internet.nl

    although some settings might need tweaking for eg redis object cache key expiries etc..
    only got it on testing at the moment.. so no idea on best timeout settings for live sites, default seems to be non-expiring. so you can't eg, re-login to WP after changing your password..

    can set multiple caches, but they need to be set in nginx.conf http section, or in a included conf.d/ or snippets/ file.. to go in that section
    or can set one cache, with different keyzones for each site.

    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    sets each individual key as eg httpsGET<domain.tld><uri-path>
    so each individual key is site specific.

    need testing to work out if separate cache per website, single cache with multiple keyzones. or single cache with one keyzone is best.
    i suspect the last one will be fastest.. but most likely cause problems with cache flushing, data bleeding etc..

    only big issue now is flushing the fastcgi cache from a wp backend.. keys seem to get removed fine when hitting the inactive timeout, but don't get removed from the cache when manually flushing..

    plus it's all manual config.. would be nice to make it part of the ispconfig gui... maybe checkboxes on the website config page for using the redis object cache and/or the nginx fastcgi cache.. which would add the settings to the nginx conf file or the wp-config file..

    i'll add the details for what i've done and where, on here once i've got the cache flushing issue worked out.
     
    remkoh, till and ahrasis like this.
  9. nhybgtvfr

    nhybgtvfr Well-Known Member HowtoForge Supporter

    ok. if anyone has got nginx fastcgi caching working, especially with php-fpm and wordpress... i definitely need some help..
    i've been going around in circles with it all week. i can get close.. but just can't get that last little bit..
    sorry, this is going to be a long one...


    i've tried 3 different wp plugins,
    nginx preload & purge : https://www.psauxit.com/optimizing-wordpress-and-woocommerce-with-nginx-fastcgi-cache/
    nginx helper: https://en-gb.wordpress.org/plugins/nginx-helper/
    nginx-cache : https://wordpress.org/plugins/nginx-cache/

    i've followed various guides and tutorials. nothing seems to work properly. one guide suggested removing nginx and installing their custom version with their own nginx cache purge module, which doesn't seem to have been updated at all for over 10 years.. definitely not keen on that..

    so. the closest i've got so far:
    default ubuntu OS install (24.04) with nginx from default repo, all installed using the auto-installer..
    plug installed libnginx-mod-http-cache-purge

    this is using the nginx-cache plugin

    in the http section of /etc/nginx/nginx.conf, caches are configured using:
    Code:
    fastcgi_cache_path /var/www/clients/client1/web252/cache levels=1:2 keys_zone=test1:100m max_size=1g inactive=2h use_temp_path=off;
    fastcgi_cache_path /var/www/clients/client1/web253/cache levels=1:2 keys_zone=test2:100m max_size=1g inactive=1m use_temp_path=off;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    

    i've created the folder 'cache' in /var/www/clients/client#/web#/
    drwxrws--- 18 web253 client1 4096 Oct 16 14:03 cache
    permissions are 770.. for reasons explained below.. plus also did 'chmod g+s cache'

    i've tried getting the cache working using various permutations of www-data or web# as the owner, and www-data or client# as the group.
    along with folder permission for the cache folder set to 755 or 770.
    in most cases, either nginx could not write anything to the cache, or wordpress complained that it couldn't access the cache folder...
    and even when wordpress can access the cache, it can't purge anything.

    hope that above comes out readable... can't see any options for pre-formatting text here.

    with those last 3 options, nginx can write to the cache, and the wordpress plugins can access the cache, no complaints about it not existing, not found, not writable etc.

    the cache creates a folder, and subfolder in the cache, and the actual cached file itself.
    cache is using two levels, so folder structure is cache/<single digit folder name>/<two digit folder name>/<md5 hash named file>
    the folders are created with permission 700, and owner/group www-data:www-data, files with permission 600, owner/group www-data:www-data
    i set g+s to the cache folder to try to get everything the cache creates closer to the parent folder settings/permissions.

    now it creates them as, in /var/www/clients/client#/web#/cache:

    drwx--S--- 43 www-data client1 4096 Oct 16 14:52 7
    drwx--S--- 47 www-data client1 4096 Oct 16 14:52 1
    drwx--S--- 46 www-data client1 4096 Oct 16 14:52 3

    in the next level, /var/www/clients/client#/web#/cache/3
    drwx--S--- 2 www-data client1 4096 Oct 16 14:46 09
    drwx--S--- 2 www-data client1 4096 Oct 16 14:45 05
    drwx--S--- 2 www-data client1 4096 Oct 16 14:21 00

    and then the actual file in eg /var/www/clients/client#/web#/cache/3/00:
    -rw------- 1 www-data client1 79202 Oct 16 14:21 e4b38748afd41b6515a82bf2fab9a003

    which is the closest i've got to it all working so far..
    wordpress / php-fpm cannot purge anything.
    but the inactive time etting on cached files is working, once the inactive time has passed, nginx is removing that file from the cache, although it is leaving the two parent directories in place.. i believe this is it's normal procedure.

    the plugin is set to purge the cache on content changes


    but content changes don't remove the cached version of the page/post from the cache, and purging all deletes nothing.

    yet if, from within the cache folder, i change all the directory permissions, using
    Code:
    find. -type d -exec chmod 770 {} \;
    
    then clicking the purge cache button does delete everything from that cache.

    i believe the whole problem comes down to, what one of those plugin links states as:

    Problem Statement
    • WEBSERVER-USER: Responsible for creating cache folders and files with strict permissions.
    • PHP-FPM-USER: Handles cache purge operations but lacks privileges
    Challenges
    • Permission Issues: Adding PHP-FPM-USER to the WEBSERVER-GROUP doesn’t resolve permission conflicts.
    • Nginx Overrides: Nginx overrides default setfacl settings, ignoring ACLs. Nginx creates cache folders and files with strict permissions.
    Surprisingly, Nginx cache doesn’t adhere to DEFAULT ACLs.

    they link to a script to help with this, and although the script seemed to run fine, i still couldn't get wordpress to purge anything.
    i've attached the script.. so you can see what it attempts to do... i don't pretend to understand it all..
    ** notice to users -- don't run scripts unless you know what they do.. i only did this as it's on a server built specifically to test nginx and fastcgi and will get wiped.


    so that's where i'm at now.. not particularly happy with the cache folder having 770 permissions, but the nginx side of it is at least working.
    any help getting the php/wordpress purging side working, and ideally getting the folder permissions down to 755 or 750 would be greatly appreciated.
     

    Attached Files:

  10. remkoh

    remkoh Active Member

    Did you add your cache folder in the "PHP open_basedir" field on the Options tab of your website?
    If you'd done that and set permission on the cache folder the same as web, private etc. the folder should have been accessible.
     
  11. nhybgtvfr

    nhybgtvfr Well-Known Member HowtoForge Supporter

    yep.. did that... well.. during testing just manually added it to the etc/php/*.*/fpm/pool.d/web#.conf file
    added it as :/var/www/clients/client#/web#/cache:/var/www/<domain.tld>/cache:/cache
    so whatever path/symlink or chrooted php options are set should work.

    and it is accessible, at least readable, by php/wordpress. they just can't delete anything unless i change the folders to 770,
    problem is nginx keeps creating new subfolders as 700 and as www-data:www-data by default or www-data:client# with g+s set on the cache folder.


    some things i've seen/read suggest using setting ACL's, or setting umask 0002 for the nginx service might help..
    but i've got no experience with doing anthing with either of those, and whilst i can experiment with those, and possibly get it working.
    i'd have no idea if i'd just made the whole lot totally insecure.
     
    ahrasis likes this.
  12. remkoh

    remkoh Active Member

    If subfolders are created as www-data:www-data it looks like php isn't running as your web user.
    In other words, isn't running from etc/php/*.*/fpm/pool.d/web#.conf and for that matter not using /var/run/php/web#.sock but using the default socket.
     
  13. till

    till Super Moderator Staff Member ISPConfig Developer

    Is PHP creating that cache or Nginx? I would guess Nginx creates that cache, and Nginx runs as a www-data user. PHP runs a user of the site and that's why it can't purge the cache created by Nginx.
     
  14. nhybgtvfr

    nhybgtvfr Well-Known Member HowtoForge Supporter

    yep. it's nginx creating the subfolders in the cache, and the cached files.. so it can still serve those cached pages even if php isn't running.

    it's appears nginx will do it's own thing..
    so somehow i need to (safely) give the php-fpm user access to delete the nginx files.
     

Share This Page