Category: code

  • Interactive Blocks

    I built out two custom blocks that can be embedded into any layout, post, or page.

    Find Care Now

    Find
    Care Now

    Urgent Care

    Urgent Care →

    Primary Care

    Primary Care →

    Specialty Care

    Specialty Care →

    Telehealth

    Telehealth →

    Find Care Now

    Find
    Care Now

    Urgent Care

    Urgent Care →

    Primary Care

    Primary Care →

    Specialty Care

    Specialty Care →

    Telehealth

    Telehealth →

    Since the hard part is knocked out, we can go back in and give it a bit more style and work on some of the details. All of these are individually editable via the Gutenberg theme editor. The originals are locked down but you can duplicate and place anywhere in a layout.

    I added an off-canvas navigation block that’s in the current header. The bottom menus there are controlled by the secondary navigation in the admin.

    I added the JavaScript needed to auto-hide the navigation header up scrolling down and returning it upon scrolling up.

  • WordPress Config

    Place to put all WordPress specific configurations.

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

    define( 'WP_DEVELOPMENT_MODE', 'theme' );
    

    use debug logging on local and remote in development

    define('WP_DEBUG', true);
    define('WP_DEBUG_DISPLAY', true );
    define('WP_DEBUG_LOG', '/_log/error.log');
  • 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');
  • Server

    Setting up a new server for a project. This one has to be easily replicated and provide access to multiple systems level administrators. The named ‘squid’ 🦑 comes from a portmantuau of the hosting data center and because cephalopod intelligence is the best of the invertebrates.

    • HIPPA Compliance
    • Dedicated IPs
    • Managed
    • 24/7 Support
    • East Coast location
    - Processor: Intel(R) Xeon(R) E E-2456 (12 core)
    - RAM: 32GB DDR4 SDRAM
    - HD1: 2 x 960 GB SSD Hardware Raid 1
    - HD2: 1 x 1.92 TB SSD
    
    Static hostname: *****.*****.***
    Operating System: AlmaLinux 9.5 (Teal Serval)         
    CPE OS Name: cpe:/o:almalinux:almalinux:9::baseos
    Kernel: Linux 5.14.0-503.23.2.el9_5.x86_64
    Architecture: x86-64
    
    10 TB Outbound Bandwidth
    Gigabit Uplink Port
    

    System

    AlmaLinux 9 🐧

    Version 9 will have active support until 31 May 2027, and security support until 31 May 2032

    Twenty years ago I started out on CentOS for personal projects because my job was using RHEL. Switched to Debian because it seemed like all the smart folks were using it. Then I started dabbling in Ubuntu and switched because I liked the free security patch model from Canonical. I have an Ubuntu server that has been running for 13 years. CERN switching from Scientific Linux had an impacct and the community model seems better than Rocky which I’d guess might see some of the fate of CentOS. It also seems popular amongst the enterprise folks and the binary is compatible the Red Hat using the Fedora package manager.

    User

    disable root, add user, change ssh ports, add keys

    useradd ***********
    usermod -aG wheel ***********
    su - ***********
    sudo vi /etc/ssh/sshd_config
    # disable root login
    PermitRootLogin no
    # obscure ssh port
    Port ****
    sudo systemctl restart sshd

    add user to www-data
    psaserv ( /conf /httpdocs )
    psacln ( /)

    sudo usermod -a -G www-data ***********

    Shell

    change to oh-my-zsh

    sudo dnf install zsh
    chsh -s $(which zsh)
    # log out/in
    sudo dnf install git curl wget
    sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
    

    Packages

    sudo dnf clean all
    sudo dnf update
    dnf --help
    dnf history
    dnf list installed
    dnf [ search/install/info/list/remove/upgrade/history/repolist/deplist ]
    sudo dnf upgrade package_name
    sudo dnf upgrade
    
    sudo dnf install htop

    Systemd

    rsyslog

    Security

    Hardening

    Ports

    these are the default open ports for plesk

    - 53 - DNS (TCP and UDP)
    - 80 - HTTP (TCP)
    - 110 - POP3 (TCP)
    - 123 - NTP (UDP)
    - 143 - IMAP (TCP)
    - 443 - HTTPS (TCP) (mandatory licensing)
    - 465 - SMTPS (TCP)
    - 587 - SMTP (Submission) (TCP)
    - 953 - RNDC (TCP)
    - 990 - FTPS (TCP)
    - 993 - IMAPS (TCP)
    - 995 - POP3S (TCP)
    - 3306 - MySQL (remote only) (TCP)
    - 5432 - PostgreSQL (TCP)
    - 8443 - Plesk HTTPS (TCP)
    - 8447 - Plesk Installer (TCP)
    - 8880 - Plesk HTTP (TCP)
    - 49152 - 65535 - (TCP) for FTP passive mode - incoming only

    FirewallD

    # status
    sudo systemctl status firewalld
    # open port
    sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
    # close port
    sudo firewall-cmd --zone=public --remove-port=80/tcp --permanent
    # reload
    sudo firewall-cmd --reload
    # list all ports
    sudo netstat -tunlp
    
    ### Mail
    
    - Mail
        - _Fail_ for un-routable email.
        - _nobody_ user

    IPTables

    Blacklist

    Admin

    Backup

    Acronis Backups of full server everyday at 1:00am
    Keep – daily 7days – weekly 4wks – monthly 1mo

    Migrations

    Monitor

    Plesk

    Plesk is somewhat painful for me but I need to have a system that is migration capable in case it or me need to be replaced. I’d prefer a stripped down version of Linux variant but it isn’t the best choice in this case. I like to complain about it. What gets me most of all is the lack of a barrier to entry means a bunch of novice users junking up the forums and making it hard to find the good information easily. It’s highly opinionated in how it operates creating a messy web of permissions and configuration files in an effort to give those features to the GUI users.

    Admin

    # admin password
    plesk bin admin --info
    plesk bin --get-login-link
    plesk bin admin --set-admin-password -passwd **********
    plesk bin admin --set-login ********
    plesk bin admin --enable-access-domain **************.com

    Theme

    zip -r srh_theme.zip . -x '**/.DS_Store'
    plesk bin branding_theme -i -vendor ******* -source
    srh_theme.zip
    plesk bin branding_theme -u -name srh_theme

    Repair file system permissions

    sudo plesk repair fs
    sudo plesk repair fs -vhosts
    sudo plesk repair fs example.com -vhosts

    Extensions

    plesk bin extension --list
    plesk bin extension --install extension_name
    plesk bin extension --upgrade extension_name
    plesk bin extension --uninstall extension_name
    plesk bin extension --disable extension_name
    plesk bin extension --enable extension_name
    
    plesk bin extension --disable servershield
    plesk bin extension --disable laravel
    plesk bin extension --disable plesk-sitejet
    plesk bin extension --disable xovi
    plesk bin extension --disable nodejs
    plesk bin extension --disable composer
    plesk bin extension --disable wp-toolkit
    
    # default installs
    - acronis-backup - Acronis Backup
    - advisor - Advisor
    - composer - PHP Composer
    - configurations-troubleshooter - Webserver Configurations Troubleshooter
    - dnssec - Plesk DNSSEC
    - git - Git
    - heavy-metal-skin - Skins and Color Schemes
    - help-center - Help Center
    - imunify360 - Imunify
    - laravel - Laravel Toolkit
    - letsencrypt - Let's Encrypt
    - log-browser - Log Browser
    - mfa - Multi-Factor Authentication (MFA)
    - monitoring - Monitoring
    - nodejs - Node.js Toolkit
    - ntp-timesync - NTP Timesync
    - panel-ini-editor - Panel.ini Editor
    - plesk-sitejet - Sitejet Builder
    - repair-kit - Repair Kit
    - servershield - ServerShield by Cloudflare
    - site-import - Site Import
    - ssh-terminal - SSH Terminal
    - sslit - SSL It!
    - wp-toolkit - WP Toolkit
    - xovi- SEO Toolkit

    Mail

    🚫 I’ve maintained a lot of different servers over the years and the only thing I’ve constantly had issues with was email. I’ve also maintained servers dedicated just to email. I learned some years ago with my web servers to just wipe out the email systems and relay it to a third party. A lot of folks do this too… Google Cloud Platform, Amazon Web Services, and Microsoft Azure all blocks outbound traffic on port 25 which effectively blocks all email features. I no longer maintain any email servers and it’s one of the few services where I always rely on a third parties.

    Security

    Anyone who’s spent anytime in an enterprise IT environment can tell you that email phishing, compliance, training, and management is the bain of existence for sysadmins. Since email hacking tends to be the origin of a lot of bad stuff, I avoid the liability by refusing to manage anything other than pointing domain records elsewhere.

    # disable all mail services and ports

    SMTP

    Will need to create a couple SMTP relay accounts

    • sysadmin notifications
    • cms notifications
    • form notifications

    Webserver

    Apache

    Nginx

    Languages

    PHP

    v8.3.16 FPM
    ps -ylC php-fpm --sort:rss
    S UID PID PPID C PRI NI RSS SZ WCHAN TTY TIME CMD
    S 0 931 1 0 80 0 87040 99039 ep_pol ? 00:00:00 php-fpm

    pm.max_children = Total RAM / Max child process size

    Databases

    MariaDB

    • allow local connections only
     MariaDB v10.5.27