Add Expires Headers to .htaccess File in WordPress

Making sure mod_expires is enabled

sudo a2enmod expires
systemctl restart apache2

Add Expires Headers to .htaccess

To add Expires Headers to your site, you need to edit the .htaccess file.

Simply download the .htaccess file from the root of your host (it may be hidden) and add the code below:

## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresDefault "access plus 2 days"
</IfModule>
## EXPIRES CACHING ##

References
https://electrictoolbox.com/apache-mod-expires-browser-caching/
https://betterstudio.com/blog/add-expires-headers-htaccess/

Disable Directory Browsing In WordPress

To disable directory browsing in WordPress all you need to do is add a single line of code in your WordPress site’s .htaccess file located in the root directory of your website.
Once connected to your website, you will find a .htaccess file in your site’s root directory. .htaccess is a hidden file, and if you can not find it on your server, you need to make sure that you have enabled your FTP client to show hidden files.
Now at the end of your WordPress generated code in the .htaccess file simply add this line at the bottom:

Options All -Indexes

References
https://bloggingwizard.com/disable-directory-browsing-wordpress/
https://www.wpbeginner.com/wp-tutorials/disable-directory-browsing-wordpress/

Host ASP.NET Core on Linux with Apache

Configure a proxy server

Invoke the UseForwardedHeaders method at the top of Startup.Configure before calling other middleware. Configure the middleware to forward the X-Forwarded-For and X-Forwarded-Proto headers:

// using Microsoft.AspNetCore.HttpOverrides;

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

app.UseAuthentication();
// using System.Net;

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});

References
https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-apache?view=aspnetcore-5.0

Apache reverse proxy configuration for socket.io

sudo a2enmod proxy_http
sudo a2enmod proxy_fcgi
sudo a2enmod proxy_wstunnel
# VirtualHost ms.example.net
<VirtualHost *:80>
  ServerName ms.example.net
  ProxyRequests Off
  ProxyPreserveHost On
  RemoteIPHeader X-Forwarded-For
  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>
  RewriteEngine On
  RewriteCond %{REQUEST_URI} ^/socket.io          [NC]
  RewriteCond %{QUERY_STRING} transport=websocket [NC]
  RewriteRule /(.*) ws://localhost:14102/$1        [P,L]

  ProxyPass /socket.io http://localhost:14102/socket.io
  ProxyPassReverse /socket.io http://localhost:14102/socket.io
</VirtualHost>

<VirtualHost *:443>
  ServerName ms.example.net
  ProxyRequests Off
  ProxyPreserveHost On
  RemoteIPHeader X-Forwarded-For
  RewriteEngine on
  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>
  SSLEngine On
  SSLCertificateFile /etc/letsencrypt/live/example.net/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/example.net/privkey.pem
  
  RewriteEngine On
  RewriteCond %{REQUEST_URI} ^/socket.io          [NC]
  RewriteCond %{QUERY_STRING} transport=websocket [NC]
  RewriteRule /(.*) ws://localhost:14102/$1        [P,L]
  ProxyPass /socket.io http://localhost:14102/socket.io
  ProxyPassReverse /socket.io http://localhost:14102/socket.io
  
</VirtualHost>

Use a secure URL for your initial connection, i.e. instead of “http://” use “https://”. If the WebSocket transport is chosen, then Socket.IO should automatically use “wss://” (SSL) for the WebSocket connection too.

var socket = io.connect('https://localhost', {secure: true});

References
http://xpo6.com/socket-io-via-apache-reverse-proxy/
https://stackoverflow.com/questions/36472920/apache-proxy-configuration-for-socket-io-project-not-in-root
https://gist.github.com/iacchus/954e0787d6893c5ab8e1
https://stackoverflow.com/questions/6599470/node-js-socket-io-with-ssl

Secure Apache with Let’s Encrypt on Ubuntu 18.04

Installing Certbot

sudo add-apt-repository ppa:certbot/certbot
sudo apt install python-certbot-apache

Set Up the SSL Certificate

Certbot needs to be able to find the correct virtual host in your Apache configuration for it to automatically configure SSL. Specifically, it does this by looking for a ServerName directive that matches the domain you request a certificate for.

Obtaining an SSL Certificate

sudo certbot --apache -d example.com -d www.example.com

This runs certbot with the --apache plugin, using -d to specify the names you’d like the certificate to be valid for.

Verifying Certbot Auto-Renewal

sudo certbot renew --dry-run

References
https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-18-04

Cannot access javascript folder on Apache

Go to /etc/apache2/conf-available/javascript-common.conf, you will find this:

Alias /javascript /usr/share/javascript/
<Directory "/usr/share/javascript/">
     Options FollowSymLinks MultiViews
</Directory>

So you just have to comment this lines (with the # char) (is not recommend to edit directly the file in conf-enabled) to avoid the forbidden error. After that, do this:

a2disconf javascript-common
a2enconf javascript-common

References
https://serverfault.com/questions/274254/cannot-access-javascript-folder