今日已更新 80 条资讯 | 累计 20052 条内容
关于我们

标签:#rdp

找到 39 篇相关文章

AI 资讯

WP-CLI : 20 commandes essentielles pour administrer WordPress en 2026

Cet article a été publié à l'origine sur WP Admin Lab , le journal du web technique en français. WP-CLI est l'interface en ligne de commande officielle de WordPress, un outil indispensable pour tout développeur ou administrateur gérant des sites WordPress en production. Contrairement à l'interface graphique du tableau de bord, WP-CLI permet d'exécuter des opérations en masse, d'automatiser des tâches répétitives et d'intervenir sur des sites inaccessibles via le navigateur. En 2026, maîtriser WP-CLI est devenu une compétence fondamentale pour la gestion professionnelle de parcs WordPress, que ce soit pour des agences gérant des dizaines de sites ou pour des développeurs travaillant sur des environnements de staging et de production. Installation et configuration de WP-CLI en 2026 L'installation de WP-CLI s'effectue en téléchargeant le fichier Phar officiel depuis le dépôt GitHub du projet et en le rendant exécutable à l'échelle du système. Sur les serveurs Linux mutualisés ou dédiés, la commande curl -O permet de récupérer le binaire, que l'on déplace ensuite vers /usr/local/bin/wp avec les droits d'exécution appropriés. Les hébergeurs comme Kinsta ou WP Engine proposent WP-CLI préinstallé dans leurs environnements SSH, facilitant la prise en main immédiate. La vérification de l'installation avec wp -info fournit les détails de version, l'interpréteur PHP utilisé et le chemin vers le fichier de configuration wp-config.php. La configuration avancée de WP-CLI passe par le fichier wp-cli.yml placé à la racine du projet WordPress. Ce fichier YAML permet de définir l'URL du site, le chemin d'installation, les alias de serveurs distants pour les déploiements SSH, et des paramètres par défaut pour certaines commandes. Les alias SSH dans wp-cli.yml sont particulièrement puissants : ils permettent d'exécuter des commandes WP-CLI sur un serveur distant exactement comme en local, avec une syntaxe du type wp @production plugin list. Cette fonctionnalité simplifie considérableme

2026-07-15 原文 →
AI 资讯

Seven things to check before a WordPress major upgrade — before "patch what breaks after" becomes a disaster

WordPress major version upgrades (5.x → 6.x, and eventually 6.x → 7.x) are a different animal from minor releases. Minor releases (like 6.4.1 → 6.4.2) are mostly bug fixes with low compatibility risk. Majors land API deprecations, raised PHP minimum requirements, and core block replacements all at once — and those things hit operations hard. The " just hit Update in the admin and patch whatever breaks " workflow can survive on a single personal site, but it tends to fall apart under multi-site maintenance — simultaneous failures across sites overwhelm root-cause triage. This post collects the things worth verifying before you run a major upgrade, as a seven-item checklist . 1. Has the minimum PHP version been raised? Major WordPress releases sometimes raise the minimum supported PHP version (6.6 lifted it to PHP 7.2.24, and a future 7.0 will very likely require PHP 8.x). What matters operationally isn't just the server's PHP version and WordPress's stated minimum — it's the intersection with the PHP versions your plugins and themes actually run on . You can usually upgrade your server's PHP, but older themes and plugins not running on new PHP isn't rare. A subtle failure mode here: traps like PHP 8.2+ deprecated warnings leaking into older WP-CLI JSON output , where nothing visibly errors but your operational tooling silently breaks. Before upgrading, run wp plugin list --format=json on the production PHP environment and verify you're getting clean JSON. That one check catches a lot of post-upgrade pain. 2. Audit "Tested up to" for every plugin Each plugin's readme.txt carries a Tested up to: X.X line — the developer's declaration of the highest WordPress version they've actually tested against . It's the first signal for major-upgrade compatibility audits. WP-CLI gives you the inventory in one shot: wp plugin list --fields = name,version,update_version,update --format = table Plugins where "Tested up to" is old AND no updates in the last year deserve scrutiny. Acti

2026-07-15 原文 →
AI 资讯

Building a Three.js 3D Product Configurator for WooCommerce: 4 Things I Didn't Expect

Most WooCommerce product pages still show the same thing stores have shown for 20 years: a handful of flat photos. I spent the last few months building Noorifa, a plugin that replaces that with an interactive Three.js viewer — customers rotate the model, zoom in, and switch colors/materials on specific meshes in real time, synced to the store's actual WooCommerce variations. The 3D rendering part was the easy 20%. The other 80% was a series of small, specific problems that don't show up in a Three.js tutorial. Here are four of them. 1. A directional light rig can't light a face it can't see Early on, customers rotating a table model would find the underside of the tabletop rendering near-black — no matter how far I pushed the light intensity. The rig at the time was a single key light plus a hemisphere ambient: scene . add ( new THREE . HemisphereLight ( 0xffffff , 0x444444 , 1.2 ) ); const keyLight = new THREE . DirectionalLight ( 0xffffff , 1.2 ); keyLight . position . set ( 3 , 5 , 4 ); scene . add ( keyLight ); The bug was geometric, not a brightness problem: keyLight sits above the model, so its light direction only reaches surfaces whose normal faces back toward it. A downward-facing surface — the underside of an overhanging tabletop — can't receive any direct contribution from a light positioned above it, at any intensity. Cranking the brightness slider was scaling a number that was multiplying against zero. The fix was closer to actual three-point studio lighting: key, fill, and rim from above for shape and separation, plus a dedicated light from below, and a brighter hemisphere ground color to approximate bounced light: scene.add( new THREE.HemisphereLight( 0xffffff, 0x888888, 1.1 * brightness ) ); const keyLight = new THREE.DirectionalLight( 0xffffff, 1.1 * brightness ); keyLight.position.set( 3, 5, 4 ); const fillLight = new THREE.DirectionalLight( 0xffffff, 0.5 * brightness ); fillLight.position.set( -4, 2, 3 ); const rimLight = new THREE.DirectionalLigh

2026-07-13 原文 →
AI 资讯

A Free CBT Equation Editor for Math & Chemistry

While building a Computer-Based Testing (CBT) platform, I ran into an unexpected problem. Creating mathematics and chemistry questions wasn't nearly as straightforward as I expected. Although there are many excellent editors and open-source libraries available, I couldn't find one that brought everything together in a way that was simple, lightweight, and designed specifically for CBT systems. Instead of building everything from scratch, I took a different approach. I combined several powerful open-source technologies into a single editor that focuses on one job—making it easy to create mathematics and chemistry content for online examinations. The result is CBT Editor, a free and open-source equation editor built for developers, schools, and educational platforms. It supports common mathematical expressions, chemistry notation, scientific symbols, fractions, superscripts, subscripts, and more, while remaining easy to integrate into existing projects. This project isn't meant to replace the fantastic libraries that already exist. In fact, it depends on them. The goal is to provide a clean, unified experience so developers don't have to spend hours combining multiple tools just to support technical examination questions. If you're building a CBT platform, an online examination system, or any educational application that requires mathematics and chemistry editing, I'd love for you to give CBT Editor a try and share your feedback. 🔗 Live Demo: https://holygist.github.io/cbt-editor/ Open-source software grows through collaboration. If you find the project useful, feel free to contribute, report issues, suggest improvements, or simply share it with other developers.

2026-07-11 原文 →
开发者

How to Make Rank Math Sitemap Pages Load Faster

One common issue on WordPress websites with a large number of posts is that the Rank Math XML Sitemap can become slow to load. This happens because the sitemap is generated dynamically every time a visitor or search engine bot requests it. A simple solution is to use a static sitemap cache , allowing the web server to serve pre-generated XML files directly without executing PHP for every request. This significantly reduces server load and improves crawling performance. Benefits of Using a Static Sitemap Using a static sitemap cache provides several advantages: Faster sitemap loading times. Lower CPU and PHP worker usage. Improved crawling efficiency for Google and other search engines. Ideal for websites with thousands or even millions of URLs. Reduced server load when search engine bots frequently request sitemap files. 1. Setting RankMath Sitemap Cache The first step is to enable static sitemap generation using the Rank Math Sitemap Tweak plugin. The plugin automatically creates static copies of your XML sitemaps and stores them in the following directory: /wp-content/uploads/rank-math/ Instead of generating the sitemap dynamically through WordPress, your web server can serve these static files directly. 2. Configure Apache (.htaccess) If your website is running on Apache , add the following rules to your .htaccess file. # ========================== # XML cache # ========================== RewriteCond %{REQUEST_METHOD} GET RewriteCond %{QUERY_STRING} ^$ RewriteCond %{HTTP:Cookie} !wordpress_logged_in RewriteCond %{DOCUMENT_ROOT}/wp-content/uploads/rank-math/%{HTTP_HOST}%{REQUEST_URI} -f RewriteRule ^(.*)$ /wp-content/uploads/rank-math/%{HTTP_HOST}/$1 [L] These rules check whether a cached sitemap file exists. If it does, Apache serves the static file immediately without loading WordPress. 3. Configure Nginx If your server is using Nginx , add the following configuration inside your server block. # # Static cache # location / { try_files \ /wp-content/uploads/rank-

2026-07-10 原文 →
AI 资讯

Improve WordPress Server Response Time by Optimizing Apache and Nginx Configuration

One of the most important performance metrics for a WordPress website is Server Response Time, commonly measured as Time to First Byte (TTFB). While caching plugins like WP Rocket significantly improve performance, many server configurations still route every request through PHP before serving the cached page. In reality, cached HTML files can be delivered directly by the web server (Apache or Nginx), completely bypassing PHP and WordPress. This approach reduces CPU usage, lowers the PHP-FPM workload, and improves overall server response time. This guide explains how to optimize both Apache (.htaccess) and Nginx so they can serve WP Rocket's static HTML cache directly. Why Is This Optimization Important? By default, a typical WordPress request follows this flow: Visitor │ ▼ Apache/Nginx │ ▼ PHP │ ▼ WordPress │ ▼ WP Rocket Cache │ ▼ HTML Response Even when a page has already been cached, the request still passes through PHP before the cached content is returned. With the following configuration, the request flow becomes: Visitor │ ▼ Apache/Nginx │ ▼ WP Rocket HTML Cache │ ▼ HTML Response PHP and WordPress are only executed when a cached file does not exist. Benefits Lower Time to First Byte (TTFB) Reduced CPU usage Less PHP-FPM processing Better performance during traffic spikes Ideal for VPS and dedicated servers Improved scalability with minimal configuration changes Apache (.htaccess) Optimization If your server runs Apache, insert the following block inside the WordPress rewrite section, immediately after: RewriteBase / and before: RewriteRule ^index\.php$ - [L] The resulting configuration should look like this: # BEGIN WordPress # Die Anweisungen (Zeilen) zwischen „BEGIN WordPress“ und „END WordPress“ sind # dynamisch generiert und sollten nur über WordPress-Filter geändert werden. # Alle Änderungen an den Anweisungen zwischen diesen Markierungen werden überschrieben. < IfModule mod_rewrite.c > RewriteEngine On RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Autho

2026-07-10 原文 →
AI 资讯

WordPress 7.0 Ships with AI Foundations in Core, a Modernized Admin, and New Design Tools

WordPress 7.0, released on May 20, 2026, includes new AI infrastructure, a redesigned admin interface, and updated design tools. Key features comprise an AI Client, Abilities API, and Command Palette, alongside increased PHP requirements. Community feedback is mixed, particularly regarding AI integration. Developers are advised to consult the official documentation for upgrade guidance. By Daniel Curtis

2026-07-10 原文 →
AI 资讯

How to Accept Crypto Payments on WooCommerce (Without a Custodial Processor)

You built your WooCommerce store. You've got products, a checkout flow, and customers who want to pay in crypto. The question is: which payment gateway do you actually trust with your money? Most crypto payment plugins for WooCommerce work the same way: they collect your customer's payment, hold it in their own wallet, and send you a payout — minus fees, minus a wait, minus any guarantee they won't freeze your account if something looks "suspicious." That's not crypto. That's a bank with extra steps. This guide covers how to accept crypto payments on WooCommerce the non-custodial way — funds go directly from your customer's wallet to yours, on-chain, with no middleman holding anything. What "non-custodial" actually means for your store When a customer pays through a custodial processor, the money lands in the processor's wallet first. You're trusting them to forward it. If they freeze your account, dispute a transaction, or go under, your money is stuck. Non-custodial means the smart contract routes the payment directly to your wallet address. QBitFlow never holds your funds — not for a second. Every payment has an on-chain transaction hash you can verify on Etherscan, Solscan, or BaseScan. There's no one to call to "release" your money because no one ever had it. For a WooCommerce merchant, this matters for three reasons: No chargebacks. Crypto transactions are final. A customer can't call their bank and reverse a payment you already received. No holds. There's no processor deciding whether your business is "high-risk" this week. No conversion. You receive exactly what the customer paid — USDC stays USDC, ETH stays ETH. No auto-swap, no slippage, no surprise exchange rate. What you need before you start A WooCommerce store (WordPress + WooCommerce plugin installed) A crypto wallet — MetaMask, Coinbase Wallet, or any wallet that works with Reown/AppKit (browser extension or mobile QR scan) About 10 minutes That's it. No business registration. No KYC. No waiting for

2026-07-09 原文 →
AI 资讯

A pending-plugin-count badge on the 🔌 button — reusing the dashboard cache instead of doubling state

A client asked: " After I run a cross-site update check, can each site show — right in the site list — how many plugin updates are still pending? " Visually the answer was obvious: a small red badge on the top-right of the 🔌 plugins button, like an unread-notification count. Easy to specify. The harder question was where the data comes from . We could have added a fresh API endpoint and a new cache to hold "pending count per site." But doing that would have doubled state management , and we already had a cache that knew this. We routed through the existing one. Here's the reasoning behind that decision. Reuse the dashboard cache as the data source The cross-site updates dashboard (the one we wrote about in killing the 24.5-second silence with a cache-first design ) already kept each site's pending plugins in a localStorage-backed state called _updatesDashState . Its shape: _updatesDashState = { sites : [ { site_id : " abc... " , plugins : [ {...}, {...}, {...} ] }, { site_id : " def... " , plugins : [ ... ] }, ], total_pending_count : 12 , loadedAt : 1748600000000 , } Look up by site_id , take plugins.length , and you have the badge's number. No new API, no new cache. The data that powers the cross-site dashboard is also the data that powers the site-list badge. The win of not adding state is quiet but real: When a maintenance run invalidates _updatesDashState , the badge disappears automatically (no sync code to write) The TTL (originally 7 days; later extended to 30 days with partial invalidation ) inherits from the existing design The badge and the underlying count can't drift — there's no second copy to fall out of step There's always a temptation to spin up a new endpoint for a new UI element. The rule we settled on: if the existing state answers it, don't add more. Attaching the badge — consolidate into helpers Both the list view and grid view need the same badge on the 🔌 button, so the logic lives in helpers. function _getPendingPluginCountForSite ( siteId )

2026-07-08 原文 →
AI 资讯

Syncing a wholesaler's API into WooCommerce without overselling or melting the server

A common WooCommerce brief looks like this: the store does not own its inventory. A distributor does. The shop is a storefront on top of a wholesaler whose catalog, stock levels, and prices change daily, exposed through some REST or XML web service. The job is to make the store reflect the supplier's reality automatically, and to never sell something the supplier cannot ship. We shipped exactly this for an automotive-parts store recently (client and supplier stay anonymous). Tens of thousands of indexes, a wholesaler REST API, and a hard requirement: no manual catalog work, and no orders for parts that are not actually in stock. Here is what the architecture looks like and the traps worth knowing before you start. The store is a view, the wholesaler is the source of truth The first mental shift is that WooCommerce is not the system of record for products. The distributor is. WooCommerce is a cache with a checkout attached. Once you accept that, the design falls out: a sync layer pulls from the supplier and writes into WooCommerce on a schedule, and you treat the WooCommerce product data as derived, not authored. The integration answers three questions, and you should answer them explicitly before writing code: What syncs - catalog, attributes, media, stock, price. Which direction - here it is one-way (supplier to store); orders stay in WooCommerce. How often - split it. Stock and price are cheap and change constantly, so poll them frequently. Full catalog and media are expensive, so refresh them rarely. Map fields declaratively, or you will rewrite it every month The supplier describes a product its way (its own index, EAN, attribute names, HTML description blobs, image URLs). WooCommerce wants its way (product, attributes, variations, media library). The bridge between them is a field map, and the single best decision we made was keeping that map declarative - a data structure, not a pile of if statements. When the wholesaler adds a new attribute, you extend the ma

2026-07-07 原文 →
AI 资讯

A "days since last maintenance" badge — color-coding staleness across many sites

When you maintain a number of WordPress sites, showing the "last maintenance date" in the site list is the obvious move. A column of dates like 2026-05-21 . But in actual use, that alone falls short. A client put it well: "Besides the last maintenance date, it'd help to also show how many days have passed . And it'd be even better if the color changed at 15 / 30 / 60 days so I can see the risk level ." This post walks through that step — from "absolute date" to "relative elapsed days + color" — including the small design details. Why a date alone isn't enough An absolute date like 2026-05-21 is precise, but it pushes the "difference from today" calculation onto the user's head . Fine for five sites; as the managed set grows, reading "which ones are getting neglected" off a column of dates gets hard. The point of a maintenance inventory is to grasp which sites need attention at a glance. If so, what you should surface is less the absolute date and more the relative quantity — " how many days since the last maintenance " — and ideally let color convey "how many days until it's risky." The client's request landed exactly on this "absolute → relative + risk" shift. Four-tier color coding We went with four tiers by elapsed days. A small badge like (15 days ago) sits right after the last-maintenance date, and the color changes by threshold. Elapsed tier color meaning 0–14 days fresh green recently maintained, fine 15–29 days normal gray standard 30–59 days warn amber needs attention 60+ days danger red needs action green → gray → amber → red — just scrolling the list, "lots of red here" or "a cluster of sites I haven't touched lately" jumps out visually. The badge also gets a hover tooltip ("N days since last maintenance") to back up the number's meaning. Consolidate into helper functions The display logic is called from multiple places (list view, grid view), so scattering inline day calculations would be a DRY violation. We consolidated into a set of helpers. // Returns

2026-07-07 原文 →
AI 资讯

Boundary 1.0 adds RDP session recording, previews AI-agent access controls

The 1.0 lands with session recording attached HashiCorp announced Boundary 1.0 on June 25. The operational headline is RDP session recording, and the version number is a distant second. Boundary is HashiCorp's privileged-access proxy, and until this release it did not record Remote Desktop sessions on its own. Teams that route Windows-side deploys through the proxy now have a first-party audit trail that ships with the product itself. The announcement bundles two other things on top of the RDP work. "Improved management" is HashiCorp's phrasing. Boundary 1.0 also previews work aimed at securing access for AI agents, which HashiCorp positions as a same-chokepoint answer for a new class of caller. What actually changes on the CD side For most teams the practical read is narrower than "1.0 shipped". Two things move. RDP sessions get recorded through the proxy. Windows targets have historically been the awkward part of a privileged-access story. SSH session recording and TLS-terminating proxies have been standard for years on Linux. RDP has been thinner. A CD pipeline that lands on a Windows host for a hotfix, an artifact promotion, or a release-time config change now has the same after-the-fact video that Linux jumpboxes have had for a long time. The AI-agent preview signals where Boundary wants to sit next. If CD tooling is starting to hand a shell to an agent, that agent needs a credential of some kind. HashiCorp is telling operators the plan is for Boundary to mediate that call the way it mediates a human on-caller today. This is a preview. Read it as a roadmap. Why the audit line matters for release engineering The audit case for session recording is easy to state and hard to argue with. When a bad change lands on a production Windows host at 2am, the post-incident question is always the same: what did the person on the console actually do, and can it be replayed? Without recording, on-call gets shell history if it is lucky and a change-management ticket if it is n

2026-07-07 原文 →
AI 资讯

Supracorona Login Gate: Simple Access Control for WordPress Sites

For internal websites, client portals, development environments, and WordPress projects that should not be publicly accessible. Not every private WordPress website needs a complete membership system. Sometimes there is no need to manage subscriptions, membership plans, payments, complex user roles, or dozens of content-access rules. Sometimes the requirement is much simpler: The website should only be accessible to logged-in users. That is the reason I created Supracorona Login Gate , a lightweight WordPress plugin that places a simple access gate in front of a website. When the plugin is enabled, logged-out visitors cannot browse protected site content. Instead, they are redirected to the standard WordPress login page or to a custom page selected by the site administrator. The plugin is now published on WordPress.org: Supracorona Login Gate The problem the plugin solves Many WordPress projects are not intended to be publicly accessible at every stage of their lifecycle. They may be: development or staging websites; internal company or organization websites; client portals; private knowledge bases; documentation websites intended only for team members; projects being prepared for launch; demo websites available only to selected users; websites temporarily closed during migration or reconstruction. WordPress provides privacy controls for individual posts, but that is not the same as restricting access to the entire website. Installing a full membership plugin is possible, but it is often far more than the project requires. Such systems may introduce additional database tables, large settings panels, custom profiles, login forms, subscription management, and complex rule engines that will never be used. Supracorona Login Gate has a much narrower responsibility. It is not intended to become a complete membership platform. It is intended to answer one clear question: Is the current visitor logged in? When the answer is yes, the website behaves normally. When the answer

2026-07-06 原文 →
AI 资讯

Quieting PHP 8.2+ deprecated noise from older WP-CLI — three layers to keep JSON parse clean

Our multi-site maintenance tool fires wp plugin list --format=json against the sites it manages. One day, against a specific shared host (Xserver in Japan), this call started failing — and the failure mode was unusually subtle. Both the SSH connection test and the WP-CLI path test ( wp --version ) came back green. Users saw "all diagnostics pass, but the actual operation fails," a frustrating asymmetry. Tracing it back, the root cause was PHP Deprecated warnings emitted by older WP-CLI (2.x) under PHP 8.2+ leaking into the JSON output. This post walks through the three-layer defense we used to structurally absorb the noise without losing real failures. What was happening — Deprecated warnings on stdout The raw output on a problem host looked like this: PHP Deprecated: Creation of dynamic property WP_CLI\Dispatcher\CompositeCommand::$longdesc is deprecated in phar:///usr/bin/wp/vendor/wp-cli/wp-cli/php/... [ {"name":"akismet","status":"active","update":"none", ...}, ... ] Since PHP 8.2, assigning to a dynamic property on a class without #[\AllowDynamicProperties] emits a Deprecated warning. Xserver's /usr/bin/wp (an older WP-CLI 2.x) leans on dynamic properties internally, so running it on PHP 8.2+ produces a steady stream of those warnings. Note: PHP 8.2's dynamic-property deprecation is a healthy direction for the language. But during the transition, you get many libraries that "warn but still work" — WP-CLI was one of them. The actual problem is the host's php.ini : depending on display_errors , those warnings end up on stdout instead of stderr . Calling wp plugin list --format=json returns stdout containing both the warnings and the JSON, and json_decode() fails on the mixed input. Why diagnostics stayed green but operations failed The frustrating asymmetry came from how each test was checking the output: SSH connection test : runs echo ok — passes as long as ok appears somewhere in stdout, extra lines are fine WP-CLI path test : runs wp --version — passes as lon

2026-07-05 原文 →
AI 资讯

Who's Online on the Site, Without Tidio: Live Presence and Visitor History with Firebase

A client wanted to know who was on their site and on which page, the way Tidio's widget showed them — but without paying for a Tidio subscription, on an external WordPress site that doesn't use Firebase. The result: an external tracker hooked to an independent Firebase project, live presence via onDisconnect , persistent history in Firestore with IP geolocation — and a final debugging session where a browser CORS error was masking a server crash caused by an empty string instead of null . The context The client already had a third-party live-chat script installed on their site, and that's where the idea came from: "can we see who's on the site and on which page, without using that service?" Two constraints made the request less trivial than usual: the site hadn't been migrated to my usual stack yet — it was still running on WordPress, on different hosting — and there was no intention of introducing Firebase on the WordPress side. Step 1 — understanding what a live-chat widget actually does Before building anything, it was worth looking at what the already-installed script actually did. The tag pasted into the site was just a small loader: it creates a hidden iframe, loads the widget's real "brain" inside it from the provider's servers, which then connects via websocket to their backend to stream presence, current page and events in real time. The interesting part — "see who's on the site and on which page" — isn't in the public script: it all lives server-side at the provider, behind authentication, a proprietary dashboard and a subscription. There was nothing to "detach" from that service: it's client code tied to someone else's backend by design. But the pattern itself — a script tag hooking into an external backend — is exactly what's needed to build the same feature independently, and it fits well with Firebase, which has a native presence mechanism built for precisely this. Step 2 — live presence with Firebase Realtime Database Firebase Realtime Database has a

2026-07-03 原文 →
AI 资讯

How to Fix Mixed Content & "Not Secure" SSL Errors in WordPress

Originally published on wp-nota.com . You installed an SSL certificate and moved your WordPress site to HTTPS — but the browser still shows "Not Secure" in the address bar, or a padlock with a warning. This is the classic mixed content problem: your pages load over secure HTTPS, but some resources on them — images, scripts, or stylesheets — are still being requested over insecure HTTP. Browsers flag the whole page as not fully secure until every resource is served over HTTPS. Here's how to fix it for good. What "Mixed Content" Actually Means When a single page mixes secure (HTTPS) and insecure (HTTP) resources, that's mixed content. The page itself may be secure, but if it pulls in an image or script over http:// , the browser can't guarantee the whole page is safe — so it drops the padlock or shows a warning. The cause is almost always old http:// URLs still saved in your database or hardcoded in your theme. Step 1: Confirm the Certificate and Site URLs First, make sure the foundation is right. Your host must have a valid SSL certificate installed (most offer free Let's Encrypt certificates). Then, in WordPress, go to Settings → General and confirm both WordPress Address (URL) and Site Address (URL) start with https:// . If they still say http:// , update them, save, and log back in. Step 2: Find What's Loading Over HTTP To see exactly which resources are insecure, open the problem page in your browser, right-click and choose Inspect , and look at the Console tab. Mixed content warnings list each http:// resource by URL — often images in old posts, a hardcoded logo, or an asset from a plugin or theme. This tells you precisely what needs fixing. Step 3: Update Old HTTP URLs in the Database The most common fix is a database search-and-replace that swaps every http://yourdomain.com for https://yourdomain.com . Two safe ways to do it: The easy way — the free Really Simple SSL plugin detects insecure URLs and rewrites them to HTTPS automatically, which resolves most mix

2026-07-02 原文 →
AI 资讯

Maintaining WordPress sites behind HTTP Basic auth — Playwright, urllib, and encrypted credentials

It's pretty common to throw a layer of HTTP Basic auth on a WordPress site: a staging environment before launch, an internal test instance only employees should see, or any environment that wants an extra gate before the WordPress login screen itself. From a maintenance-tool point of view, this setup creates a peculiar "half-working, half-broken" asymmetry. The SSH/WP-CLI side runs fine. But everything HTTP-based — visual checks, thumbnail generation, browser-based fallback updates — hits 401 and dies. This post walks through how we resolved that asymmetry. What was breaking — two parallel paths, both blocked A maintenance tool actually touches a Basic-auth-protected site through two distinct paths: Playwright path : visual checks, thumbnail capture, browser fallback updates when SSH isn't available. browser.new_context() → navigation → screenshot urllib path : HTTP status checks (pre/post-update 200/5xx/4xx monitoring, rollback decisions) With no credentials, both paths see a 401 Unauthorized from the protected site. The Playwright symptom is the obvious one: the screenshot you save is the browser's "authentication required" dialog. The thumbnail grid fills with dark auth-prompt images, and you start wondering whether anything actually works. The urllib symptom is much worse — it silently breaks rollback decisions . A 401 baseline followed by another 401 after the update looks like "nothing changed = healthy." Real failures can hide behind that match, and the rollback that should have fired never does. The design — consolidate credential extraction into one helper When the same credentials need to flow through multiple code paths, picking them out of the site dict separately at each call site invites format-mismatch and missed-update bugs. So the first thing we did was build a small core/basic_auth_utils.py module that owns every form of credential extraction . # core/basic_auth_utils.py def get_basic_auth_tuple ( site ): """ Return (user, password), or None if not

2026-07-01 原文 →
AI 资讯

How to Know What Breaks Before You Upgrade WordPress to PHP 8.4

Every WordPress developer knows the feeling. A host emails: "PHP 7.4 reaches end of life — we're moving you to 8.x." Or you finally want the performance and security of PHP 8.4. You stage it, click upgrade, and… white screen. Somewhere in the 40 plugins and 3 themes on the site, something called a function PHP removed years ago — and now the whole site is down. The frustrating part: the broken code is almost never yours. It's buried in third-party plugins and themes you didn't write and can't easily read. So how do you find out what breaks before you upgrade, instead of after? This post walks through exactly that, using an open-source tool called Pressready . Why "just test it on staging" isn't enough Staging tells you that something broke, rarely what or where — and only for the code paths you happen to exercise. A fatal in an admin screen or a checkout edge case you didn't click won't surface until a real user hits it. You need something that reads all the code statically and reports every risky symbol, whether or not that path runs during your manual test. That's a job for static analysis across the whole stack. Two kinds of "breakage": PHP and WordPress Upgrades break sites along two axes, and a good audit covers both: The PHP axis — language features that get removed (e.g. create_function() is gone in PHP 8.0, each() in 8.0) or change behaviour between versions. The WordPress axis — core APIs that WordPress deprecates or removes from one release to the next. Pressready checks both in a single pass: it runs PHPCompatibility for the PHP axis and a custom PHP_CodeSniffer sniff — driven by a generated dataset of WordPress core deprecations — for the WordPress axis. Install it (pick whatever fits your setup) No Composer in the project? Use the standalone PHAR or Docker: # Standalone PHAR — single self-contained file, just needs PHP curl -L https://github.com/itzmekhokan/pressready/releases/latest/download/pressready.phar -o pressready.phar chmod +x pressready.phar #

2026-06-30 原文 →
AI 资讯

When paramiko's defaults silently get your IP banned — the look_for_keys and allow_agent trap

One day a multi-site administrator reported a strange bug: "After running the app's SSH connection test 2-3 times, my IP can't reach SSH on that server for a long while ." The errors came back as Connection refused or Connection closed by ... . The server wasn't down, and SSH from a different IP worked fine. The source IP was being temporarily banned at the server. Two external investigation reports gave the cause: server-side protection mechanisms ( fail2ban or PerSourcePenalties in OpenSSH 25+) detect short-windowed authentication failure spikes and temporarily ban the source IP. But the user had only clicked the test button 2-3 times — why were failures "spiking"? The answer turned out to be paramiko's default behavior . paramiko's default — trying many keys per connection paramiko.SSHClient.connect() defaults two options to True : client . connect ( ' host ' , pkey = my_key , # The following are True by default: # look_for_keys=True, # also try ~/.ssh/id_* files # allow_agent=True, # also try ssh-agent registered keys ) When the explicitly passed pkey fails, paramiko falls back through ssh-agent registered keys → ~/.ssh/id_* files → password auth in order. Convenient for developers with a single key. Disastrous for a multi-site administrator: The SSH agent has multiple per-site keys registered ~/.ssh/ holds several id_rsa / id_ed25519 files A single connect call ends up trying 5-10 keys in sequence That blows past the server's MaxAuthTries (default 6) on a single connection So what looked to the user like "one connection test" was being seen by the server as " a suspicious IP racking up 5-10 auth failures in a row ." Repeat that 2-3 times and the protection mechanism declares the IP "exceeded threshold" and bans it. The fix — look_for_keys=False and allow_agent=False paramiko exposes options to scope key trial. We set them explicitly in connect_kwargs : connect_kwargs = { ' pkey ' : my_key , ' look_for_keys ' : False , # don't try ~/.ssh/id_* ' allow_agent ' : F

2026-06-30 原文 →
AI 资讯

Contact Form 7 sent the email — but did it arrive? You have no way to know

Contact Form 7 runs on millions of sites for a good reason: it's free, light, and gets out of your way. I shipped it on client sites for years. The problem isn't that CF7 is bad — it's that it answers exactly one question ("did the form submit?") and stays completely silent on the one that actually matters in production: did the notification arrive? Here's the call every developer who maintains WP sites has taken at least once: "I filled in your contact form last week and never heard back." You check. The form is fine. JavaScript fires, the success message shows, no console errors. CF7 did its job — it handed the message to wp_mail() and forgot it ever existed. There's no record the submission happened, and no log of whether the email was delivered, bounced, or quietly dropped by the host's unauthenticated sendmail. The lead is just gone, and you have nothing to debug with. The three gaps that bite in production No submissions database. CF7 sends an email and discards the data. If the email fails or lands in spam, the submission never existed. (Flamingo helps, but it's a bolt-on — separate screen, no filtering or export out of the box, not tied to your form config.) No delivery log. You can't tell whether mail was sent, rejected, or bounced. "I never got it" has no audit trail to check against. No native block. CF7 is still a shortcode — [contact-form-7 id="123"] . You can't drop it into a block template, control its layout with block spacing, or edit it inline in Gutenberg. You paste a shortcode and hope. None of these are dealbreakers for a throwaway contact form. All three are dealbreakers when a missed submission is a missed sale. Migrating without rebuilding by hand The reason most people put off switching isn't the feature gap — it's the thought of rebuilding every form field by field. That's the part I wanted to skip. The migration path I use reads CF7's stored form definitions directly and recreates them as native forms. What comes across automatically: All

2026-06-29 原文 →