Configuration

I like the idiom ‘configuration over code’ which means that the way you configure your editor and tools takes precedence over the code itself. I’m documenting various configurations here for posterity.

  1. environment
    1. server
    2. client
  2. development
    1. editor
    2. cms
    3. version control ( git )
      1. 📂 https://code.davidawindham.com/david/ssh-edit
      2. 📁 https://github.com/windhamdavid/srh-edit
  3. language
    1. perfs
  4. error reporting
  5. debugging
  6. logging

Environment -> Server


Because we’ll be using both Apache and nginx web servers for performance reasons, the configuration files for each can be server wide or target specific websites. Apache uses .htaccess and Nginx uses nginx.conf files

# .htaccess

# .htpasswd
<FilesMatch "(\.htaccess|\.htpasswd)">
  Order deny,allow
  Deny from all
</FilesMatch>

# Blocking bots
RewriteCond %{HTTP_USER_AGENT} (AdsBot-Google|AI2Bot|Ai2Bot-Dolma|Amazonbot|anthropic-ai|Applebot|Applebot-Extended|AwarioRssBot|AwarioSmartBot|Bytespider|CCBot|ChatGPT|ChatGPT-User|Claude-Web|ClaudeBot|cohere-ai|cohere-training-data-crawler|Crawlspace|DataForSeoBot|Diffbot|DuckAssistBot|FacebookBot|FriendlyCrawler|Google-Extended|GoogleOther|GoogleOther-Image|GoogleOther-Video|GPTBot|iaskspider/2.0|ICC-Crawler|ImagesiftBot|img2dataset|ISSCyberRiskCrawler|Kangaroo Bot|magpie-crawler|Meta-ExternalAgent|Meta-ExternalFetcher|OAI-SearchBot|omgili|omgilibot|PanguBot|peer39_crawler|PerplexityBot|PetalBot|Scrapy|SemrushBot|Sidetrade indexer bot|Timpibot|VelenPublicWebCrawler|Webzio-Extended|YouBot) [NC]
RewriteRule ^ – [F]

# Caching
<IfModule mod_headers.c>
  <FilesMatch "\.(ico|pdf|js|mjs|css|gif|png|jpg|jpeg|txt|woff2|woff)$">
    Header set Cache-Control "max-age=31536000, public"
  </FilesMatch>
</IfModule>

<IfModule mod_headers.c>
  <FilesMatch "\.(js|mjs|css|xml|gz)$">
    Header append Vary Accept-Encoding
  </FilesMatch>
</IfModule>

<IfModule mod_headers.c>
  <FilesMatch ".(js|mjs|css|xml|gz|html|woff|woff2|ttf)$">
    Header append Vary: Accept-Encoding
  </FilesMatch>
</IfModule>

# Keep Alive Header
<IfModule mod_headers.c>
  Header set Connection keep-alive
</IfModule>

# CORS
<IfModule mod_headers.c>
  <FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css|js|mjs|gif|png|jpe?g|svg|svgz|ico|webp)$">
  Header set Access-Control-Allow-Origin "*"
  </FilesMatch>
</IfModule>
# nginx.conf

# Security Headers
  add_header X-Frame-Options "SAMEORIGIN" always;
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-XSS-Protection "1; mode=block" always;
  add_header Referrer-Policy "strict-origin-when-cross-origin" always;
  add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:;" always;
  server_tokens off;

# compression
  gzip_vary on;
  gzip_comp_level 6;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
  gzip_proxied no-cache no-store private expired auth;
  gzip_disable "MSIE [1-6]\.";

Development -> WordPress


WordPress 6.3 introduced ‘development mode’ which avoids the theme.json caching.

define( 'WP_DEVELOPMENT_MODE', 'theme' );

define('WP_DEBUG', true);
define('WP_DEBUG_DISPLAY', true );
define('WP_DEBUG_LOG', '/_log/error.log');