From planning to production: Selected aspects of modern software delivery
Software delivery has never been more interlinked across strategy, planning and operations. Agile practices are adapting to hybrid work, AI is reshaping how teams plan and execute, and cloud platforms have become the default substrate for everything from build pipelines to runtime security. What follows traces a practical route through that terrain, drawing together current guidance, tools and community efforts so teams can make informed choices without having to assemble the big picture for themselves.
Work Management: Asana and Jira
Planning and coordination remain the foundation of any delivery effort, and the market still gravitates to two names for day-to-day project management: Asana and Jira. Each can bring order to multi-team projects and distributed work, yet they approach the job from very different histories.
With a history rooted in large DevOps teams and issue tracking, Jira carries that lineage into its Scrum and Kanban options, backlogs, sprints and a reporting catalogue that leans into metrics such as time in status, resolution percentages and created-versus-resolved trends. Built as a more general project manager from the outset, Asana shows its intent in the way users move from a decluttered home screen to “My Tasks”, switch among Kanban, Gantt and Calendar views using tabs, and add custom fields or rules from within the view rather than navigating to separate screens. The two now look similar at a glance, but their structure and presentation differ, and that influences how quickly a team settles into a rhythm.
Dashboards and Reporting
Those differences widen when examining dashboards and reporting. Jira allows users to create multiple dashboards and fill them with a large range of gadgets, including assigned issues, average time in status, bubble charts, heat maps and slideshows. The designs are sparse yet flexible, and administrators on company-managed accounts can add custom reporting, while the Atlassian Marketplace offers hundreds of additional reporting integrations.
By contrast, the home dashboard in Asana is intentionally pared back, with reports placed in their own section to keep personal task management separate from project or portfolio-level tracking. Its native reporting is broader and more polished out of the box, with pre-built views for progress, work health and resourcing, together with custom report creation that does not require admin-level access.
Interoperability
How well each tool connects to other systems also sets expectations. Jira, as part of Atlassian's suite, has a bustling marketplace with over a thousand apps for its cloud product, covering project management, IT service management, reporting and more. Asana's store is smaller, with under 400 apps at the time of writing, though it continues to grow and offers breadth across staples such as Slack, Teams and Adobe Creative Cloud, as well as a strong showing for IT and developer use cases.
Both tools connect to Zapier, which has also published a detailed comparison of the two platforms, opening pathways to thousands of further automations, such as creating Jira issues from Typeform submissions or making Asana tasks from Airtable records without writing integration code. In practice, many teams will get what they need natively and then extend in targeted ways, whether through marketplace add-ons or workflow automations.
Plans and AI
Plans and AI are where the most significant recent movement has occurred. On the Asana side, a free Personal tier leads into paid Starter and Advanced plans followed by Enterprise, with AI tools (branded "Asana Intelligence") included across paid plans. Those features help prioritise work, automate repetitive steps, suggest smart workflows and summarise discussions to reduce time spent on status communication.
Over at Jira, the structure runs from a free tier for small teams through Standard, Premium and Enterprise plans. "Atlassian Intelligence" focuses on generative support in the issue editor, AI summaries and AI-assisted sprint planning, adding predictive insights to help with resource allocation and automation. It is worth noting that Jira's entry-level paid plan appears cheaper on paper, but real-world total cost of ownership often rises once Marketplace apps, Confluence licences and security add-ons are factored in.
Choosing between the two typically comes down to need. If you want a task manager built for general use with crisp reporting and strong collaboration features, Asana presents itself clearly. If your roadmap lives and breathes Agile sprints, backlogs and issue workflows, and you need deep extensibility across a suite, Jira remains a natural fit.
Scrum: Back to Basics
Method matters as much as tooling. Scrum remains the most widely adopted Agile framework, and it is worth revisiting its essentials when translating plans into delivery. The DevOps Institute tracks the human side of this evolution, noting that skills, learning and collaboration are as central to DevOps success as the toolchain itself. A Scrum Team is cross-functional and self-organising, combining the Product Owner's focus on prioritising a transparent, value-ordered Product Backlog with a Development Team that turns backlog items into a potentially shippable increment every Sprint.
The Scrum Master keeps the framework alive, removes impediments, and coaches both the team and the wider organisation. Sprints run for no longer than four weeks and bundle Sprint Planning, Daily Scrums, a Sprint Review and a Retrospective, with online whiteboards increasingly used to run those ceremonies effectively across distributed and hybrid teams. The Sprint Goal provides a unifying target, and the Sprint Backlog breaks selected Product Backlog items into tasks and steps owned by the team.
Scrum Versus Waterfall
That cadence stands in deliberate contrast to classic waterfall approaches, where specification, design, implementation, testing and deployment proceed in long phases with significant hand-offs between each. Scrum replaces upfront specifications with user stories and collaborative refinement using the "three Cs" of Card, Conversation and Confirmation, so requirements can evolve alongside market needs. It places self-organisation ahead of management directives in deciding how work is done within a Sprint, and it raises transparency by making progress and problems visible every day rather than at phase gates.
Teams feel the shift when they commit to delivering a working increment each Sprint rather than aiming for a distant release, and when they see the cost of change flatten because feedback arrives through Reviews and Retrospectives rather than months after decisions have been made.
The State of Agile
Richer context for these shifts appears in longitudinal views of industry practice. The 18th State of Agile Report, published by Digital.ai in late 2025, observes that Agile is adapting rather than fading, with adoption remaining widespread while many organisations rebuild from the ground up to focus on measurable outcomes. The report, drawing on responses from approximately 350 practitioners, notes that AI and automation are accelerating change while introducing fresh expectations around data quality, decision-making and governance, and it emphasises that outcomes have become the currency connecting strategy, planning and execution.
That aligns with the Agile Alliance's ongoing work to re-examine Agile's core values for enterprise settings, as well as with the joint Manifesto for Enterprise Agility initiative with PMI{:target="_blank"}, which argues for adaptability as a strategic advantage rather than a team-level method choice. Significantly, the 18th report found that only 13% of respondents say Agile is deeply embedded across their business, and that only 15% of business leaders participate meaningfully in Agile practices, suggesting that leadership alignment remains one of the most persistent blockers to realising the framework's full potential.
Continuous Delivery and CI/CD Tooling
Getting from plan to production relies on engineering foundations that have matured alongside Agile. Continuous Delivery reframes deployment as a safe, rapid and sustainable capability by keeping code in a deployable state and eliminating the traditional post-"dev complete" phases of integration, testing and hardening. By building deployment pipelines that automate build, environment provisioning and regression testing, teams reduce risk, shorten lead time and can redirect human effort towards exploratory, usability, performance and security testing throughout delivery, not just at the end.
The results can be counterintuitive. High-performing teams deploy more frequently and more reliably, even in regulated settings because painful activities are made routine and small batches make feedback economical.
CI/CD in Practice
Contemporary CI/CD tools express that philosophy in developer-centred ways. Travis CI can often be described in minutes using minimal YAML configuration, specifying runtimes, caching dependencies, parallelising jobs and running tests across multiple language versions. Azure Pipelines, GitHub Actions and Azure DevOps provide similar capabilities at broader scale, with managed runners, gated releases, integrated artefact feeds, security scanning and policy controls that matter in larger enterprises.
The emphasis across these platforms is on speed to first pipeline, consistency across environments and adding guardrails such as signed artefacts, scoped credentials and secret management, so that velocity does not undercut safety.
Cloud Native Architecture
Architecture and platform choices amplify or constrain delivery flow. The cloud native ecosystem, curated by the Cloud Native Computing Foundation (CNCF) under the Linux Foundation, has become the common bedrock for organisations standardising on Kubernetes, service meshes and observability stacks. Hosting more than 200 projects across sandbox, incubating and graduated maturity levels, it spans everything from container orchestration to policy and tracing, and brings together vendors, end users and maintainers at events such as KubeCon + CloudNativeCon.
Sitting higher up the stack, Knative is a recent CNCF graduate that provides building blocks for HTTP-first, event-driven serverless workloads on Kubernetes. It unifies serving and eventing, so teams can scale to zero on demand while routing asynchronous events with the same fluency as web requests, and was created at Google before joining the CNCF as an incubating project and subsequently reaching graduation status. For teams that need to manage the underlying cluster infrastructure declaratively, Cluster API provides a Kubernetes-native way to provision, upgrade and operate clusters across cloud and on-premises environments, bringing the same declarative model used for application workloads to the infrastructure layer itself.
APIs and Developer Ecosystems
API-driven integration is part of the cloud native picture rather than an afterthought. The API Landscape compiled by Apidays shows the sheer diversity of stakeholders and tools across the programmable economy, from design and testing to gateways, security and orchestration. Developer ecosystems such as Cisco DevNet bring this to ground level by offering documentation, labs, sample code and sandboxes across networking, security and collaboration products, encouraging infrastructure as code with tools like Terraform and Ansible.
Version control and collaboration sit at the centre of modern delivery, and GitHub's documentation, spanning everything from Codespaces to REST and GraphQL APIs, reflects that centrality. The breadth of what is available through a single platform, from repository management to CI/CD workflows and AI-assisted coding, illustrates how much of the delivery stack can now be coordinated in one place.
Security: An End-to-End Discipline
Security threads through every layer and is increasingly treated as an end-to-end discipline rather than a late-stage gate. The Open-Source Security Foundation (OpenSSF) coordinates community efforts to secure open-source software for the public good, spanning working groups on AI and machine learning security, supply chain integrity and vulnerability disclosure, and offering guides, courses and annual reviews.
On the cloud side, a Cloud-Native Application Protection Platform (CNAPP) consolidates capabilities to protect applications across multi-cloud estates. Core components typically include Cloud Infrastructure Entitlement Management (to rein in excessive permissions), Kubernetes Security Posture Management (to maintain container orchestration best practices and flag misconfigurations), Data Security Posture Management (to classify and monitor sensitive data) and Cloud Detection and Response (to automate threat response and connect to security orchestration platforms).
Increasingly, AI-driven Security Posture Management sits across these layers to spot anomalies and predict risks from historical patterns, though this brings its own challenges around false positives and model bias that require careful adoption planning. Vendors such as Check Point offer CNAPP products including CloudGuard with unified management and compliance automation. While such examples illustrate what is available commercially, it is the architecture and functions described above that define the category itself.
Site Reliability Engineering
Reliability is not left to chance in well-run organisations. Site Reliability Engineering (SRE), pioneered and documented by Google, treats operations as a software problem and asks SRE's to protect, provide for and progress the systems that underpin user-facing services. The remit ranges from disk I/O considerations to continental-scale capacity planning, with a constant focus on availability, latency, performance and efficiency.
Error budgets, automation, toil reduction and blameless post-mortems become part of the vocabulary for teams that want to move fast without eroding trust. The approach complements Continuous Delivery by turning operational quality into something measurable and improvable, rather than a set of aspirations.
Code Quality, Testing and Documentation
For all the automation and platform power now available, the basics of code quality and testing still count. The Twelve-Factor App methodology remains relevant in encouraging declarative automation, clean contracts with the operating system, strict separation of build and run stages, stateless processes, externalised configuration, dev-prod parity and treating logs as event streams rather than files to be managed. It was first presented by developers at Heroku and continues to inform how teams design applications for cloud environments.
Documentation practices have also evolved, from literate programming's argument that source should be written as human-readable text with code woven through, to modern API documentation standards that keep codebases easier to change and onboard. General-purpose resources such as the long-running Software QA and Testing FAQ remind teams that verification and validation are distinct activities, that a spectrum of testing types is available and that common delivery problems have known countermeasures when documentation, estimation and test design are taken seriously.
AI in Software Delivery
No survey of modern software delivery can sidestep artificial intelligence. Adoption is now near-universal: the 2025 DORA State of AI-Assisted Software Development report, drawing on responses from almost 5,000 technology professionals worldwide, found that around 90% of developers now use AI as part of their daily work, with the median respondent spending roughly two hours per day interacting with AI tools. More than 80% report feeling more productive as a result. The picture is not straightforward, however. The same research found that AI adoption correlates with higher delivery instability, more change failures and longer cycle times for resolving issues because the acceleration AI brings upstream tends to expose bottlenecks in testing, code review and quality assurance that were previously hidden.
The report's central conclusion is that AI functions as an amplifier rather than a remedy. Strong teams with solid engineering foundations use it to accelerate further, while teams carrying technical debt or process dysfunction find those problems magnified rather than resolved. This means the strategic question is not simply which AI tools to adopt, but whether the underlying platform, workflow and culture are ready to benefit from them. The DORA AI Capabilities Model, published as a companion guide, identifies seven foundational practices that consistently improve AI outcomes, including a clear organisational stance on AI use, healthy data ecosystems, working in small batches and a user-centric focus. Teams without that last ingredient, the report warns, can actually see performance worsen after adopting AI.
At the tooling level, the landscape has moved quickly. Coding assistants such as GitHub Copilot have gone from novelty to standard practice in many engineering organisations, with newer entrants including Cursor, Windsurf and agentic tools like Claude Code pushing the category further. The shift from "copilot" to "agent" is significant: where earlier tools suggested completions as a developer typed, agentic systems accept a goal and execute a multistep plan to reach it, handling scaffolding, test generation, documentation and deployment checks with far less human intervention. That brings real efficiency gains and also new governance questions around traceability, code provenance and the trust that teams place in AI-generated output. Around 30% of DORA respondents reported little or no trust in code produced by AI, a figure that points to where the next wave of tooling and practice will need to focus.
Putting It Together
Translating all of this into practice looks different in every organisation, yet certain patterns recur. Teams choose a work management tool that matches the shape of their portfolio and the degree of Agile structure they need, whether that is Asana's lighter-weight task management with strong reporting or Jira's DevOps-aligned issue and sprint workflows with deep extensibility, then align on a Scrum-like cadence if iteration and feedback are priorities, or adopt hybrid approaches that sustain visibility while staying compatible with regulatory or vendor constraints.
Build, test and release are automated early so that pipelines, not people, become the route to production, and cloud native platforms keep environments reproducible and scalable across teams and geographies. Instrumentation ensures that security posture, reliability and cost are visible and managed continuously rather than episodically, and deliberate investment in engineering foundations, small batches, fast feedback and strong platform quality, creates the conditions that the evidence now shows are prerequisites for AI to deliver on its promise rather than amplify existing dysfunction.
If anything remains uncertain, it is often the sequencing rather than the destination. Few organisations can refit planning tools, delivery pipelines, platform architecture and security models all at once, and there is no definitive order that works everywhere. Starting where friction is highest and then iterating tends to be more durable than a one-shot transformation, and most of the resources cited here assume that change will be continuous rather than staged. Agile communities, cloud native foundations and security collaboratives exist because no single team has all the answers, and that may be the most practical lesson of all.
Managing Cron jobs on Linux systems
Cron jobs are often-used workhorses of Linux automation, running silently in the background to handle everything from nightly backups to log rotation. For system administrators, understanding how to list, inspect and modify these scheduled tasks is not merely useful knowledge, it is a core skill that keeps infrastructure running smoothly. Whether you are auditing an unfamiliar server or tracking down a misfiring script, knowing where to look and what commands to use will save you considerable time and frustration.
Listing Cron Jobs for the Current User
The starting point for any cron investigation is crontab -l, which displays the scheduled jobs belonging to the user who runs it. Running this command in a terminal will either show a list of entries or print a message such as no crontab for [username], confirming that no jobs have been set. Each line in the output represents a separate scheduled task, formatted with five time fields followed by the command to execute. If you are new to writing that five-field schedule expression, Crontab Guru is a useful browser-based tool that translates cron syntax into plain English as you type.
Listing Cron Jobs for Other Users
When you need to inspect jobs belonging to a different account, the crontab -u flag allows you to specify a username, though this requires root or sudo privileges. To audit every user on a system in one pass, administrators often pair the cut command with a loop that reads usernames from /etc/passwd, cycling through each account in turn. A simple shell loop to achieve this looks like the following:
for user in $(cut -f1 -d: /etc/passwd); do
echo "Crontab for $user:"
sudo crontab -u $user -l 2>/dev/null
echo
done
Running this as root will surface any scheduled task on the machine, regardless of which account owns it.
System-Wide Cron Locations
Beyond user-specific crontabs, several system-wide locations hold scheduled tasks that apply more broadly. The /etc/crontab file is the main system crontab, which differs from user crontabs in that it includes an additional field specifying which user should run each command. The /etc/cron.d/ directory serves a similar purpose, allowing packages and administrators to drop in individual configuration files rather than editing a single shared file. nixCraft's thorough guide to listing cron jobs covers all of these locations in detail and is a useful reference to keep to hand.
User crontab files are stored separately, typically under /var/spool/cron/crontabs/ on Debian and Ubuntu systems and under /var/spool/cron/ on Red Hat-based distributions such as CentOS and Fedora. Archiving both these directories and the /etc/cron* locations before a major system change is a sensible precaution, as it preserves a full picture of the scheduled workload.
A Critical Naming Convention
One pitfall that catches many administrators is the filename convention enforced by run-parts, a utility used to execute scripts in the /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly and /etc/cron.monthly directories. Filenames in these locations must consist entirely of upper and lower-case letters, digits, underscores and hyphens. This means that a script named myscript.sh will be silently ignored because the dot in the filename causes run-parts to skip it. Renaming the file as myscript is all that is needed to bring it back into service.
The same rule applies to files placed in /etc/cron.d/. The convention exists partly to prevent cron from acting on package management residue files such as .dpkg-dist backups, which can linger after software updates. It is worth running run-parts --test /etc/cron.daily to verify which scripts will actually execute before assuming that everything in a directory is active.
BusyBox Cron on Alpine Linux
The cron landscape changes on systems using BusyBox, the lightweight utility suite at the heart of Alpine Linux. The BusyBox crond implementation does not read from /etc/cron.d/ at all. Instead, it looks to /etc/crontabs/ for per-user crontab files and relies on /etc/periodic/ subdirectories (such as /etc/periodic/hourly and /etc/periodic/daily) for the familiar interval-based tasks. Any administrator accustomed to placing files in /etc/cron.d/ on a Debian or Red Hat system will find that approach simply does not work on Alpine, and must adapt accordingly.
The filename restriction for scripts in /etc/periodic/ directories is even stricter under the default BusyBox configuration. Scripts must not include a dot anywhere in their filename, meaning that even backup.sh will be overlooked. The safest approach is to use names such as backup or daily-backup, without any extension.
systemd Timers as a Modern Alternative
The rise of systemd has introduced a complementary approach to job scheduling through systemd.timer units. Each timer is paired with a corresponding service unit, giving the scheduled task all the benefits of a regular systemd service, including detailed logging via journalctl, dependency management and resource controls. Traditional cron daemons such as vixie-cron and its successors remain widely used, but systemd timers offer capabilities that cron cannot easily replicate, such as triggering a task a set interval after system boot rather than at a fixed clock time.
To view all active systemd timers on a machine, the following command lists them alongside the time of their last run and their next scheduled activation:
systemctl list-timers
This gives a single, clear view of systemd-managed schedules across the whole system. On systems that use both traditional cron and systemd timers, checking both sources is necessary for a complete picture of what is scheduled to run.
Combining the Approaches
A thorough audit of a Linux system therefore involves checking several locations: user crontabs via crontab -l or the loop described above, the system-wide /etc/crontab file, the files in /etc/cron.d/ and the periodic directories, and finally the output of systemctl list-timers. On Alpine Linux, the audit instead covers /etc/crontabs/ and the /etc/periodic/ directories. It is also worth verifying that the cron daemon itself is running, as a stopped service explains why perfectly valid job entries are not executing. On systemd-based distributions, this is checked with systemctl status cron (or systemctl status crond on Red Hat-based systems).
In Summary
Cron job management rewards attention to detail because the consequences of a missed naming convention or an overlooked directory can be silent and difficult to diagnose. The commands and locations covered here provide a reliable foundation for listing, auditing and verifying scheduled tasks across the main Linux environments in common use today. Combining familiarity with traditional cron, an understanding of BusyBox quirks for container and lightweight deployments and a working knowledge of systemd timers will equip any administrator to keep their automation running with confidence. For those who want to go deeper, A Comprehensive Guide to Using Cronjobs from SitePoint and Linuxize's guide on running cron jobs at specific short intervals are both worth reading once the fundamentals are in place.
Security or Control? The debate over Google's Android verification policy
A policy announced by Google in August 2025 has ignited one of the more substantive disputes in mobile technology in recent years. At its surface, the question is about app security. Beneath that, it touches on platform architecture, competition law, the long history of Android's unusual relationship with openness, and the future of independent software distribution. To understand why the debate is so charged, it helps to understand how Android actually works.
An Open Platform With a Proprietary Layer
Android presents a genuinely unusual situation in the technology industry. The base operating system is the Android Open-Source Project (AOSP), which is publicly available and usable by anyone. Manufacturers can take the codebase and build their own systems without involvement from Google, as Amazon has with Fire OS and as projects such as LineageOS and GrapheneOS have demonstrated.
Most commercial Android devices, however, do not run pure AOSP. They ship with a proprietary bundle called Google Mobile Services (GMS), which includes Google Play Store, Google Play Services, Google Maps, YouTube and a range of other applications and developer frameworks. These components are not open source and require a licence from Google. Because most popular applications depend on Play Services for functions such as push notifications, location services, in-app payments and authentication, shipping without them is commercially very difficult. This layered architecture gives Google considerable influence over Android without owning it in the traditional proprietary sense.
Google has further consolidated this influence through a series of technical initiatives. Project Treble separated Android's framework from hardware-specific components to make operating system updates easier to deploy. Project Mainline went further, turning important parts of the operating system, including components responsible for media processing, network security and cryptography, into modules that Google can update directly via the Play Store, bypassing manufacturers and mobile carriers entirely. The result is a platform that is open source in its code, but practically centralised in how it evolves and is maintained.
The Policy and Its Rationale
Against this backdrop, Google announced in August 2025 that it would extend its developer identity verification requirements beyond the Play Store to cover all Android apps, including those distributed through third-party stores and direct sideloading. From September 2026, any app installed on a certified Android device in Brazil, Indonesia, Singapore and Thailand must originate from a developer who has registered their identity with Google. A global rollout is planned from 2027 onwards.
Google's stated rationale is grounded in security evidence. The company's own analysis found over 50 times more malware from internet-sideloaded sources than from apps available through Google Play. In 2025, Google Play Protect blocked 266 million risky installation attempts and helped protect users from 872,000 unique high-risk applications. Google has also documented a specific and recurring attack pattern in Southeast Asia, in which scammers impersonate bank representatives during phone calls, coaching victims into sideloading a fraudulent application that then intercepts two-factor authentication codes to drain bank accounts. The company argues that anonymous developer accounts make this kind of attack far easier to sustain.
The registration process requires developers to create an Android Developer Console account, submit government-issued identification and pay a one-time fee of $25. Organisations must additionally supply a D-U-N-S Number from Dun & Bradstreet. Google has stated explicitly that verified developers will retain full freedom to distribute apps through any channel they choose, and is building an "advanced flow" that would allow experienced users to install unverified apps after working through a series of clear warnings. Developers and power users will also retain the ability to install apps via Android Debug Bridge (ADB). Brazil's banking federation FEBRABAN and Indonesia's Ministry of Communications and Digital Affairs have both publicly welcomed the policy as a proportionate response to documented fraud.
What This Means for F-Droid
F-Droid, founded by Ciaran Gultnieks in 2010, operates as a community-run repository of free and open-source software (FOSS) applications for Android. For 15 years, it has demonstrated that app distribution can be transparent, privacy-respecting and accountable, setting a standard that challenges the mobile ecosystem more broadly. Every application listed on the platform undergoes checks for security vulnerabilities, and apps carrying advertising, user tracking or dependence on non-free software are explicitly flagged with an "Anti-Features" label. The platform requires no user accounts and displays no advertising. It still needs some learning, as I found when adding an app through it for a secure email service.
F-Droid operates through an unusual technical model that is worth understanding in its own right. Rather than distributing APKs produced by individual developers, it builds applications itself from publicly available source code. The resulting APKs are signed with F-Droid's own keys and distributed through the F-Droid client. This approach prioritises supply-chain transparency, since users can in theory verify that a distributed binary corresponds to the published source code. However, it also means that updates can be slower than other distribution channels, and that apps distributed via F-Droid cannot be updated over a Play Store version. Some developers have also noted that subtle differences in build configuration can occasionally cause issues.
The new verification requirement creates a structural problem that F-Droid cannot resolve independently. Many of the developers who contribute to its repository are hobbyists, academics or privacy-conscious individuals with no commercial motive and no desire to submit government identification to a third party as a condition of sharing software. F-Droid cannot compel those developers to register, and taking over their application identifiers on their behalf would directly undermine the open-source authorship model it exists to protect.
F-Droid is not alone in this concern. The policy equally affects alternative distribution models that have emerged alongside it. Tools such as Obtainium allow users to track and install updates directly from developers' GitHub or GitLab release pages, bypassing app stores entirely. The IzzyOnDroid repository provides a curated alternative to F-Droid's main catalogue. Aurora Store allows users to access the Play Store's catalogue without Google account credentials. All of these models, to varying degrees, depend on the ability to distribute software independently of Google's centralised infrastructure.
The Organised Opposition
On the 24th of February 2026, more than 37 organisations signed an open letter addressed to Google's leadership and copied to competition regulators worldwide. Signatories included the Electronic Frontier Foundation, the Free Software Foundation Europe, the Software Freedom Conservancy, Proton AG, Nextcloud, The Tor Project, FastMail and Vivaldi. Their central argument is that the policy extends Google's gatekeeping authority beyond its own marketplace into distribution channels where it has no legitimate operational role, and that it imposes disproportionate burdens on independent developers, researchers and civil society projects that pose no security risk to users.
The Keep Android Open campaign, initiated by Marc Prud'hommeaux, an F-Droid board member and founder of the alternative app store for iOS, App Fair, has been in contact with regulators in the United States, Brazil and Europe. F-Droid's legal infrastructure has been strengthened in recent years in anticipation of challenges of this kind. The project operates under the legal umbrella of The Commons Conservancy, a nonprofit foundation based in the Netherlands, which provides a clearly defined jurisdiction and a framework for legal compliance.
The Genuine Tension
Both positions have merit, and the debate is not easily resolved. The malware problem Google describes is real. Social engineering attacks of the kind documented in Southeast Asia cause genuine financial harm to ordinary users, and the anonymity afforded by unverified sideloading makes it considerably easier for bad actors to operate at scale and reoffend after being removed. The introduction of similar requirements on the Play Store in 2023 appears to have had some measurable effect on reducing fraudulent developer accounts.
At the same time, critics are right to question whether the policy is proportionate to the problem it is addressing. The people most harmed by anonymous sideloading fraud are not, in the main, the people who use F-Droid. FOSS users tend to be technically experienced, privacy-aware and deliberate in their choices. The open letter from Keep Android Open also notes that Android already provides multiple security mechanisms that do not require central registration, including Play Protect scanning, permission systems and the existing installation warning framework. The argument that these existing mechanisms are insufficient to address sophisticated social engineering, where users are coached to bypass warnings, has some force. The argument that they are insufficient to address independent FOSS distribution is harder to sustain.
There is a further tension between Google's security claims and its competitive interests. Requiring all app developers to register with Google strengthens Google's position as the de facto authority over the Android ecosystem, regardless of whether a developer uses the Play Store. That outcome may be an incidental consequence of a genuine security initiative, or it may reflect a deliberate consolidation of control. The open letter's signatories argue the former cannot be assumed, particularly given that Google faces separate antitrust investigations in multiple jurisdictions.
The Antitrust Dimension
The policy sits in a legally sensitive area. Android holds approximately 72.77 per cent of the global mobile operating system market as of late 2025, running on roughly 3.9 billion active devices. Platforms with that scale of market presence attract a different level of regulatory scrutiny than those operating in competitive markets.
In Europe, the Digital Markets Act (DMA) specifically targets large platforms designated as "gatekeepers" and explicitly requires that third-party app stores must be permitted. If Google were to use developer verification requirements in a manner that effectively prevented alternative stores from operating, European regulators would have grounds to intervene. The 2018 European Commission ruling against Google, which resulted in a €4.34 billion fine for abusing Android's market position through pre-installation requirements, established that Android's dominant position carries real obligations. That decision was largely upheld by the European courts in 2022.
In the United States, the Department of Justice has been pursuing separate antitrust cases relating to Google's search and advertising dominance, within which Android's role in channelling users toward Google services has been a recurring theme. The open letter's decision to copy regulators worldwide was not accidental. Its signatories have concluded that public documentation before enforcement begins creates pressure that private correspondence does not.
The key regulatory question is whether the verification requirements are genuinely necessary for security, and whether less restrictive measures could achieve the same goal. If the answer to either part of that question is no, regulators may conclude that the policy disproportionately disadvantages competing distribution channels.
What the Huawei and Amazon Cases Reveal
The importance of Google's service layer, and the difficulty of replicating it, can be understood by examining what happened when two large technology companies attempted to operate outside it. Here, we come to the experiences of Amazon and Huawei.
Amazon launched Fire OS in 2011, based on AOSP but with all Google components replaced by Amazon's own services. The platform succeeded in Fire tablets and streaming devices, where users primarily want access to Amazon's content. It failed entirely in smartphones. The Amazon Fire Phone, launched in 2014 and discontinued within a year, could not attract enough developer support to make it viable as a general-purpose device. The absence of Google Play Services meant that many popular applications were missing or required separate builds. This experience showed that Android's openness, at the operating system level, does not automatically translate into a competitive ecosystem. The real power lies in the service layer and the developer infrastructure built around it.
The Huawei case illustrates the same point more sharply. In May 2019, the United States government placed Huawei on its Entity List, restricting American firms from supplying technology to the company. Huawei had a 20 per cent global smartphone market share in 2019, which dropped to virtually zero after the restrictions took effect. Since Huawei could still use the AOSP codebase, the operating system was not the problem. The problem was Google Mobile Services. Without access to the Play Store, Google Maps, YouTube and the developer APIs that underpin much of the application ecosystem, Huawei phones became commercially unviable in international markets that expected those services.
Huawei's international smartphone market share, which had been among the top three, rapidly fell to outside the top five. The company's consumer business revenue declined by nearly 50 per cent in 2021. Huawei's subsequent efforts to build its own replacement ecosystem, Huawei Mobile Services and AppGallery, achieved limited success outside China, where the domestic mobile ecosystem already operates largely independently of Google. Both the Amazon and Huawei cases confirm that Android's formal openness does not neutralise Google's practical influence over the platform.
The Comparison With Apple
It is worth noting where the comparison with Apple, often invoked in these debates, holds and where it breaks down. Apple designs its hardware, controls its operating system, and has historically permitted application installation only through its App Store. That degree of vertical integration meant that, under the DMA, Apple faced requirements to allow alternative app marketplaces and sideloading mechanisms that represented fundamental changes to how iOS operates. Google already permits these behaviours on Android, which is why the DMA's impact on its platform is more limited.
However, the direction of travel matters. Critics argue that policies like mandatory developer verification, combined with Google's control of the update pipeline and the practical dependency of the ecosystem on Play Services, are gradually moving Android toward a model that is more controlled in practice than its open-source origins would suggest. The formal difference between Android and iOS may be narrowing, even if it has not disappeared.
Where Things Stand
The verification scheme opened to all developers in March 2026, with enforcement beginning in September 2026 in four initial countries. Google has offered assurances that sideloading is not being eliminated and that experienced users will retain a route to install unverified software. Critics point out that this route has not yet been specified clearly enough for independent organisations to assess whether it would serve as a workable mechanism for FOSS distribution. Until it is demonstrated and tested in practice, F-Droid and its allies have concluded that it cannot be relied upon.
F-Droid is not facing immediate closure. It continues to host over 3,800 applications and its governance and infrastructure have been strengthened in recent years. Its continued existence, and the existence of the broader ecosystem of independent Android distribution tools, depends on sideloading remaining practically viable. The outcome will be shaped by how Google implements the advanced flow provision, by the response of competition regulators in Europe and elsewhere, and by whether independent developers in sufficient numbers choose to comply with, work around or resist the new requirements.
Its story is, in this respect, a concrete test case for a broader question: whether the formal openness of a platform is sufficient to guarantee genuine openness in practice, or whether the combination of service dependencies, update mechanisms and registration requirements can produce a functionally closed system without formally becoming one. The answer will have implications well beyond a single FOSS app repository.
Sending email reliably from Linux web servers and WordPress websites
Setting up a new VPS brought with it the need to get email services working at the operating system level, and that particular endeavour proved stubbornly resistant to resolution. What eventually broke the deadlock was stepping back from the OS entirely and turning to the Post SMTP plugin for WordPress, which handled the complexity of Gmail authentication cleanly and got things moving. Since then, things have moved on again: Proton Mail, with a subscription upgrade that adds a custom domain and an associated address, now handles outgoing mail seamlessly.
Sending email from a server involves block lists, authentication requirements and cloud provider restrictions that have a habit of turning a simple task into an extended troubleshooting session. That even applies with well-established approaches using Postfix or Sendmail, relaying through Gmail or specialist SMTP providers, continue to serve administrators reliably with minimal overhead. The list of things to do and manage is not a short one at the server level.
What follows draws together practical guidance from the Linode documentation on configuring Postfix with external SMTP servers, the Linode guide on relaying through Gmail specifically, the Cloudways walkthrough for Post SMTP on WordPress and the linuxconfig.org guide to Sendmail with Gmail, keeping to fundamentals that have changed little even as the surrounding tooling has moved on. In some ways, the sources are disparate yet complementary, something that is reflected in the rest of what you find below. The whole intent is that all this is in file for everyone.
Starting with the Environment
A sensible first step is to examine the environment in which the server runs. Some cloud platforms, including Akamai Cloud's Linode Compute Instances for certain new accounts, block outbound SMTP ports 25, 465 and 587 by default to combat abuse. This blocking prevents applications from sending any email until the restrictions are lifted. The remedy is procedural rather than technical: platform documentation explains how to request removal of these restrictions after acknowledging the provider's email policies. Tackling this early avoids fruitless troubleshooting later on.
Alongside the port restriction check, it is worth setting a proper fully qualified domain name (FQDN) on the host and applying all available system updates. A correctly configured hostname reduces delays during mailer start-up and helps ensure that headers and logs appear coherent to downstream systems. Basic checks, such as confirming that you can log in to the mail account you intend to use as a relay, will also spare time later.
Configuring Postfix on Debian and Ubuntu
On Debian or Ubuntu, Postfix offers a straightforward route to sending mail via a relay. Installing the required packages begins with apt-get update followed by apt-get install of libsasl2-modules and postfix. The installer will prompt for a general type of mail configuration, and choosing "Internet Site" is appropriate in this scenario. The System Mail Name should then be set to the domain through which you intend to send.
After installation, verify that the myhostname parameter in /etc/postfix/main.cf reflects the server's FQDN, for example:
myhostname = fqdn.example.com
This setting anchors Postfix's identity and helps downstream receivers interpret messages correctly. The myhostname value is also used in outgoing SMTP greetings, so accuracy matters.
Relaying through Gmail
Relaying through Gmail or Google Workspace adds a layer of security considerations that are worth understanding before proceeding. Google retired its "less secure apps" feature in 2024, which had previously allowed basic username-and-password authentication over SMTP. All third-party SMTP connections now require either OAuth or an app password, and traditional password-based authentication is no longer accepted. Google is also pushing towards passkeys as a replacement for passwords at the account sign-in level, though their practical applicability to server-level SMTP relay remains limited for now. App passwords, whilst still available, are presented by Google as a transitional measure rather than a long-term solution, so OAuth is the more future-proof path where it is supported.
Where two-step verification is enabled on a Google account, the recommended approach for Postfix relay is to generate an app password. Within the Google Account security settings, enabling two-step verification unlocks the ability to create app passwords under the "How you sign in to Google" section. Choosing a descriptive name such as "Postfix" keeps records intelligible, and the resulting 16-character password should be stored securely since it will not be displayed again. This app password is then used in place of your regular account password throughout the Postfix configuration.
Storing SMTP Credentials
With credentials in hand, Postfix needs to know how to authenticate to the relay. Depending on the guide you follow, credentials may be stored at /etc/postfix/sasl/sasl_passwd or at /etc/postfix/sasl_passwd. Either location works as long as the corresponding path is referenced correctly in main.cf. In the credentials file, the entry for Gmail using STARTTLS on port 587 takes this form:
[smtp.gmail.com]:587 username@gmail.com:app-password
The square brackets around the hostname instruct Postfix not to perform MX lookups for that host, ensuring it connects directly to the submission server. After saving the file, create the hash database with postmap, using whichever path you chose:
sudo postmap /etc/postfix/sasl/sasl_passwd
This produces a .db file that Postfix consults at run-time. Because both the plain-text file and the .db file contain credentials, you should tighten permissions so that only root can read or write them:
sudo chown root:root /etc/postfix/sasl/sasl_passwd /etc/postfix/sasl/sasl_passwd.db
sudo chmod 0600 /etc/postfix/sasl/sasl_passwd /etc/postfix/sasl/sasl_passwd.db
Configuring the Gmail Relay
The relay configuration in /etc/postfix/main.cf forms the core of the setup. Setting relayhost to [smtp.gmail.com]:587 instructs Postfix to deliver all mail via Google's submission server. At the end of the file, the following block enables SASL authentication and STARTTLS, points to the hash file created earlier, disallows anonymous mechanisms and specifies the CA bundle for TLS verification:
relayhost = [smtp.gmail.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl/sasl_passwd
smtp_tls_security_level = encrypt
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
Restarting Postfix applies the changes:
sudo systemctl restart postfix
A simple test uses Postfix's built-in sendmail implementation. Invoking sendmail recipient@elsewhere.com, then entering From: and Subject: headers followed by a message body and a single dot on a line by itself, is sufficient to trigger a delivery attempt. Watching sudo tail -f /var/log/syslog (or /var/log/mail.log on some distributions) while testing helps confirm that authentication and delivery are succeeding, and the way back to the shell from sendmail is Ctrl+C.
Using Third-Party SMTP Providers
The same relay pattern works with third-party SMTP providers that specialise in transactional delivery. Service-specific details differ only in hostnames and credentials, while the underlying mechanism remains identical.
For Mandrill (Mailchimp's transactional email service), the credentials file would contain:
[smtp.mandrillapp.com]:587 USERNAME:API_KEY
The relayhost line in main.cf becomes [smtp.mandrillapp.com]:587. Note that the password field takes an API key, not your Mailchimp account password. Running postmap on the credentials file and restarting Postfix completes the switch.
For SendGrid, the entry for credentials is:
[smtp.sendgrid.net]:587 apikey:YOUR_API_KEY
Here, the username is the literal string apikey (not your account name), and the password is the API key generated within your SendGrid account. The relayhost becomes [smtp.sendgrid.net]:587, followed by the same postmap and restart sequence.
One practical point worth noting: some guides place the credentials file directly under /etc/postfix/sasl_passwd, whilst the Linode Gmail relay guide uses the subdirectory path /etc/postfix/sasl/sasl_passwd. Either location is valid, but the path set in smtp_sasl_password_maps within main.cf must match whichever you choose. A mismatch produces unhelpful "file not found" errors at send time that can take some effort to diagnose.
Configuring Sendmail as an Alternative
Some administrators prefer Sendmail, particularly on distributions where it remains the default. Relaying through Gmail with Sendmail follows its own clear sequence. Installing the required packages varies by distribution: on Ubuntu, Debian and Linux Mint the command is apt install sendmail mailutils sendmail-bin, whilst on CentOS, Fedora, AlmaLinux and Red Hat systems, dnf install sendmail is used instead.
Authentication details live in an authinfo map under /etc/mail/authinfo. Creating that directory with restricted permissions and then adding a file such as gmail-auth allows the following entry to be stored:
AuthInfo: "U:root" "I:YOUR_GMAIL_EMAIL_ADDRESS" "P:YOUR_APP_PASSWORD"
The quotes here are significant: the P: is a literal prefix for the password field, not part of the password itself. Building the database with makemap hash gmail-auth < gmail-auth produces gmail-auth.db in the same directory, which Sendmail will consult when connecting to the smart host.
Sendmail's configuration is macro-driven and centred on /etc/mail/sendmail.mc. Placing the relay and authentication directives just above the first MAILER definition ensures they are processed correctly when sendmail.cf is rebuilt. The key definitions set SMART_HOST to [smtp.gmail.com], force the submission port by defining RELAY_MAILER_ARGS and ESMTP_MAILER_ARGS as TCP $h 587, enable authentication with confAUTH_OPTIONS set to A p, and wire in the authinfo map with:
FEATURE('authinfo', 'hash -o /etc/mail/authinfo/gmail-auth.db')
After saving those changes, running make -C /etc/mail regenerates sendmail.cf and systemctl restart sendmail brings the service up with the new configuration. Hosts without a resolvable FQDN may pause briefly at start-up, but the service typically continues after a short delay.
WordPress and the Post SMTP Plugin
Web applications introduce different constraints, particularly where user authentication is delegated to a third party. For WordPress sites, the Post SMTP plugin (originally forked from Postman SMTP) modernises the classic approach and integrates OAuth 2.0 so that Gmail and Google Workspace can be used without storing a mailbox password. With Google having retired basic password authentication for SMTP, an OAuth-based approach is now the standard requirement rather than an optional convenience.
The process begins with installation and activation of the plugin, after which its setup wizard auto-detects smtp.gmail.com and recommends SMTP-STARTTLS with OAuth 2.0 authentication on port 587. At this point, the wizard asks for a Client ID and Client Secret, which are obtained from the Google Cloud Console rather than the Gmail settings page. Creating a project in the console, enabling the Gmail API, and completing the OAuth consent screen with basic application information lays the necessary groundwork. Selecting "Web application" as the application type then allows you to enter the Authorised JavaScript origins and Authorised redirect URIs that the plugin displays during its setup step. Completing this creation reveals the Client ID and Client Secret, which are pasted back into the plugin wizard to proceed.
Before the plugin can authorise fully, the publishing status of the OAuth consent screen must usually be changed from "Testing" to "Production" (or "In production"). This step matters more than it might appear: whilst an app remains in "Testing" status, Google's authorisation tokens expire after just seven days, which means the connection will silently stop working and require reauthorisation on a weekly basis. Moving to "In production" removes this expiry, and refresh tokens then remain valid indefinitely unless revoked. The Google console provides a "Publish App" option on the OAuth consent screen page to make this change. Once published, returning to the WordPress dashboard and clicking "Grant permission with Google" allows you to select the desired account and accept the requested permissions. The plugin's status view then confirms that authorisation has succeeded. A test email through the plugin's own action validates that messages are leaving the site as expected.
This OAuth-based arrangement aligns with Google's current security model, avoids the need for app passwords, and reduces the risk of unauthorised access if a site is compromised. General security hardening of the WordPress installation itself remains essential regardless.
The Underlying Protocols
Underpinning all of these approaches are protocols that remain stable and well understood. SMTP still carries the mail, STARTTLS upgrades plaintext connections to encrypted channels either opportunistically or by policy, and DNS resolves relay hostnames to IP addresses. The role of DNS here is easy to overlook, but it is foundational: as The TCP/IP Guide sets out in its coverage of SMTP and related protocols, correct name resolution underpins every step of message delivery. If a relay hostname cannot be resolved, nothing else will proceed. If the certificate bundle pointed to by smtp_tls_CAfile is missing or outdated, STARTTLS negotiation will fail. Logs record these conditions at the time they occur, which is precisely why watching syslog during tests is more informative than simply checking whether a message arrives in an inbox.
A few operational considerations round out a dependable setup. Permission hygiene on credential files protects against accidental disclosure during audits or backups, and commands that manipulate maps (such as postmap and makemap) must be re-run after any edit to their corresponding source files. Consistency between the port specified in the credentials file and the one set in main.cf's relayhost parameter also matters: mismatches lead to confusing connection attempts. Postfix's postconf command lists all current configuration values, making it a convenient way to verify that paths and flags are set as expected.
On Reflection
Reliable email from servers involves the installation of supporting right component software, authentication in the way the provider expects, encrypting the submission channel, keeping credentials safe and testing with your eyes on the logs. This list makes it sound like the complex endeavour that it is. Thus, If your remit extends to a WordPress dashboard, it is better to use a plugin that speaks OAuth 2.0 and complete the corresponding setup in the Google Cloud Console so that everything flows cleanly.
Windows 11 virtualisation on Linux using KVM and QEMU
Windows 11 arrived in October 2021 with a requirement that posed a challenge to many virtualisation users: TPM 2.0 was mandatory, not optional. For anyone running Windows in a virtual machine, that meant their hypervisor needed to emulate a Trusted Platform Module convincingly enough to satisfy the installer.
VirtualBox, which had been my go-to choice for desktop virtualisation for years, could not do this in its 6.1.x series. Support arrived only with VirtualBox 7.0 in October 2022, meaning anyone who needed Windows 11 in a VM faced roughly a year with no straightforward path through their existing tool.
That gap prompted a look at KVM (Kernel-based Virtual Machine), which could handle the TPM requirement through software emulation. This article documents what that investigation found, what the rough edges were at the time, and how the situation has developed in the years since.
What KVM Actually Is
KVM is not a standalone application. It is a virtualisation infrastructure built directly into the Linux kernel, and has been since the module was merged between 2006 and 2007. Rather than sitting on top of the operating system as a separate layer, it turns the Linux kernel itself into a hypervisor. This makes KVM a type-1 hypervisor in practice, even when running on a desktop machine, which is part of why its performance characteristics compare favourably with hosted solutions.
In use, KVM operates alongside QEMU for hardware emulation, libvirt for virtual machine management and virt-manager as a graphical front end. The distinction matters because problems and improvements tend to originate in different parts of that stack. KVM itself is rarely the issue; QEMU and libvirt are where the day-to-day configuration lives.
To confirm that the host CPU supports hardware virtualisation before beginning, the following command checks for the relevant flags:
egrep -c '(vmx|svm)' /proc/cpuinfo
Any result above zero means the hardware is capable. Intel processors expose the vmx flag and AMD processors expose svm.
Installing the Required Packages
The installation is straightforward on any major distribution.
On Debian and Ubuntu:
sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager
On Fedora:
sudo dnf install @virtualization
On Arch Linux:
sudo pacman -S qemu libvirt virt-manager bridge-utils
After installation, the current user needs to be added to the libvirt and kvm groups before the tools will work without root privileges:
sudo usermod -aG libvirt,kvm $(whoami)
Logging out and back in instates the group membership.
Configuring Network Bridging
The default network configuration in libvirt uses NAT, which is sufficient for most purposes and requires no additional setup. The VM can reach the internet and the host, but the host cannot initiate connections to the VM. For a Windows 11 guest used primarily for application compatibility, NAT works without complaint.
A bridged network, which places the VM on the same network segment as the host, requires a wired Ethernet connection. Wireless interfaces do not support bridging in the standard Linux networking stack due to how 802.11 handles MAC addresses. For those on a wired connection, a bridge can be defined with a file named bridge.xml:
<network>
<name>br0</name>
<forward mode="bridge"/>
<bridge name="br0"/>
</network>
The bridge is then activated with:
sudo virsh net-define bridge.xml
sudo virsh net-start br0
sudo virsh net-autostart br0
Installing Windows 11
Windows 11 requires TPM 2.0 and Secure Boot. Neither is present in a default KVM configuration, and both need to be added explicitly.
The swtpm package provides software TPM emulation:
sudo apt install swtpm swtpm-tools # Debian/Ubuntu
sudo dnf install swtpm swtpm-tools # Fedora
UEFI firmware is provided by the ovmf package, which supplies the file that virt-manager needs for Secure Boot:
sudo apt install ovmf # Debian/Ubuntu
sudo dnf install edk2-ovmf # Fedora
In virt-manager, when creating the VM, the firmware should be set to UEFI x86_64: /usr/share/OVMF/OVMF_CODE.fd rather than the default BIOS option. A TPM 2.0 device should be added in the hardware configuration before the VM is started. With those two elements in place, the Windows 11 installer proceeds without complaint about the hardware requirements.
The VirtIO drivers ISO should be attached as a second virtual CD-ROM drive during installation. The installer will not find the storage device otherwise because the VirtIO disk controller is not a standard device that Windows recognises without a driver. When prompted to select an installation location and no disks appear, clicking "Load driver" and browsing to the VirtIO ISO resolves it.
During the out-of-box experience, Windows 11 requires a Microsoft account and an internet connection by default. To bypass this and create a local account instead, opening a command prompt with Shift+F10 and running the following works on the Home edition:
oobebypassNRO
The machine restarts and presents an option to proceed without internet access.
Performance Considerations
KVM performance for a Windows 11 guest is generally good, but one factor specific to Windows 11 is worth understanding. Memory Integrity, also referred to as Hypervisor-Protected Code Integrity (HVCI), is a Windows security feature that uses virtualisation to protect the kernel. Running it inside a virtual machine creates nested virtualisation overhead because the guest is attempting to run its own virtualisation layer inside the host's. The performance impact is more pronounced on processors predating Intel Kaby Lake or AMD Zen 2, where the hardware support for nested virtualisation is less capable.
The CPU type selection in virt-manager also matters more than it might appear. Setting the CPU model to host-passthrough exposes the actual host CPU flags to the guest, which improves performance compared to emulated CPU models, at the cost of reduced portability if the VM image is ever moved to a different machine.
Host File System Access and Clipboard Sharing
This was where the experience diverged most noticeably from VirtualBox. VirtualBox Guest Additions handle shared folders and clipboard integration as a single installation, and the result works reliably with minimal configuration. KVM requires separate solutions for each, and in 2022 neither was as seamless as it has since become.
Clipboard Sharing via SPICE
Clipboard sharing uses the SPICE display protocol rather than VNC. The VM needs a SPICE display and a virtio-serial controller, which virt-manager adds automatically when SPICE is selected. Within the Windows guest, the installer for SPICE guest tools provides the clipboard agent. Once installed, clipboard text passes between host and guest in both directions.
The critical dependency that caused problems in 2022 was the virtio-serial channel. Without a com.redhat.spice.0 character device present in the VM configuration, the clipboard agent installs successfully but does nothing. Virt-manager now adds this automatically when SPICE is selected, which removes one of the more common failure points.
Host Directory Sharing via Virtiofs
At the time of this investigation, the practical option for sharing files between the Linux host and a Windows guest was WebDAV, which worked but felt like a workaround. The proper solution, virtiofs, existed but was not yet well-supported on Windows guests. The situation has since improved to the point where virtiofs is now the standard recommended approach.
It requires three components: the virtiofsd daemon on the host (included in recent QEMU packages), the virtiofs driver from the VirtIO Windows drivers package and WinFsp, which is the Windows equivalent of FUSE. Once configured through virt-manager's file system hardware settings, the shared directory appears as a mapped drive in Windows Explorer. The virtiofsd daemon was also rewritten in Rust in the intervening period, improving both its reliability and performance.
To configure a shared directory, shared memory must first be enabled in the VM's memory settings, then a file system device added with the driver set to virtiofs, a source path on the host and an arbitrary mount tag. The corresponding libvirt XML looks like this:
<memoryBacking>
<source type='memfd'/>
<access mode='shared'/>
</memoryBacking>
<filesystem type='mount' accessmode='passthrough'>
<driver type='virtiofs' queue='1024'/>
<source dir='/home/user/shared'/>
<target dir='host_share'/>
</filesystem>
This was the area where VirtualBox held a clear practical advantage in 2022. The gap has since narrowed considerably.
Migrating from VirtualBox
Moving existing VirtualBox VMs to KVM is possible using qemu-img, which converts between disk image formats. The straightforward conversion from VDI to QCOW2 is:
qemu-img convert -f vdi -O qcow2 windows11.vdi windows11.qcow2
For large images or where reliability is a concern, converting via an intermediate RAW format reduces the risk of issues:
qemu-img convert -f vdi -O raw windows11.vdi windows11.raw
qemu-img convert -f raw -O qcow2 windows11.raw windows11.qcow2
The resulting QCOW2 file can then be used when creating a new VM in virt-manager, selecting "Import existing disk image" rather than creating a new one.
How the Landscape Has Shifted Since
The investigation described here took place during a specific window: VirtualBox 6.1.x was the current release, Windows 11 had just launched, and KVM was the most practical route to TPM emulation on Linux. That context has changed in several ways worth noting for anyone reading this in 2026.
VirtualBox 7.0 arrived in October 2022 with TPM 1.2 and 2.0 support, Secure Boot and a number of additional improvements. The original reason for investigating KVM was resolved, and for those who had moved across during the gap period, returning to VirtualBox for Windows guests made sense given its more straightforward Guest Additions integration.
QEMU reached version 10.0 in April 2025, a significant milestone reflecting years of accumulated improvements to hardware emulation, storage performance and x86 guest support. Libvirt has kept pace, adding reliable internal snapshots for UEFI-based VMs, evdev input device hot plug and improved unprivileged user support. The virtiofs situation for Windows guests has moved from "technically possible but awkward" to "the recommended approach with good documentation and a rewritten daemon", which addresses the most significant practical shortcoming from 2022 directly.
The broader desktop virtualisation landscape shifted when VMware Workstation Pro became free for all users, including commercial ones, in November 2024. VMware Workstation Player was discontinued as a separate product at the same time, having become redundant once Workstation Pro was available at no cost. This gave desktop users a third credible option alongside VirtualBox and KVM, with VMware's historically strong Windows guest integration now accessible without a licence fee, though users of the free version are not entitled to support through the global support team.
The miniature PC market also expanded considerably from 2023 onwards, with Intel N100-based and AMD Ryzen Embedded systems offering enough performance to run Windows natively at modest cost. For many people, that proves a cleaner solution than any hypervisor, eliminating the integration limitations entirely by giving Windows its own dedicated hardware.
Final Assessment
KVM handled Windows 11 competently during a period when the alternatives could not, and the platform has continued to improve in the years since. The two areas that fell short in 2022, host file sharing and clipboard integration, have been addressed by developments in virtiofs and the SPICE tooling, and a new user starting today may find the experience noticeably smoother.
Whether KVM is the right choice in 2026 depends on the use case. For Linux-native workloads and server-style VM management, it remains the strongest option on Linux. For a Windows desktop guest where ease of integration matters most, VirtualBox 7.x and VMware Workstation Pro are both strong alternatives, with the latter now free to use for both commercial and personal purposes. The question that drove this investigation was answered by VirtualBox itself in October 2022. KVM provided a workable solution in the meantime, and the platform has only become more capable since then.
Additional Reading
How To Convert VirtualBox Disk Image (VDI) to Qcow2 format
How to enable TPM and secure boot on KVM?
Windows 11 on KVM – How to Install Step by Step?
Enable Virtualization-based Protection of Code Integrity in Microsoft Windows
An unseen arsenal: How web developers can use specialised tools to build better websites
Modern web development takes place within an ecosystem of tools so precisely suited to individual tasks that they often go unnoticed by anyone outside the profession. These utilities, spanning performance analysers, security checkers and colour palette generators, form the backbone of a workflow that must balance speed, security and visual consistency. For an industry where user experience and technical efficiency are inseparable priorities, such tools are far from optional luxuries.
Performance Testing and Page Speed Analysis
The first hurdle most developers encounter is performance measurement, and several tools have established themselves as essential in this space. GTmetrix, Google PageSpeed Insights and WebPageTest each draw on Google's open-source Lighthouse framework to varying degrees, though each approaches the task differently.
A performance grade alongside separate scores for page speed and structural quality is what GTmetrix produces for any URL submitted to it. It measures Core Web Vitals, including Largest Contentful Paint (LCP), Total Blocking Time (TBT) and Cumulative Layout Shift (CLS), which are the same metrics Google uses as ranking signals in search. The tool can run tests from multiple global server locations and simulates a real browser loading your page, producing a waterfall chart and a video replay of the load process, so developers can identify precisely which elements are causing delays.
Maintained directly by Google, PageSpeed Insights analyses pages against both laboratory data generated through Lighthouse and real-world field data drawn from the Chrome User Experience Report (CrUX). It provides separate performance scores for mobile and desktop, which is significant given that Google confirmed page speed as a ranking factor for mobile searches in July 2018. Both GTmetrix and PageSpeed Insights go well beyond raw figures, mapping out a prioritised list of optimisations so that developers can address the most impactful issues first.
A different position in the toolkit is occupied by WebPageTest, originally created by Patrick Meenan and open-sourced in 2008, and acquired by Catchpoint in 2020. Rather than returning a simple score, it runs tests from a choice of locations across the globe using real browsers at actual connection speeds, and produces detailed waterfall charts that break down every individual network request. This makes it the tool of choice when the question is not just how fast a page is, but precisely why a particular element is slow.
One of the longer-established names in website speed testing, Pingdom offers a free tool that remains widely used for its accessible reporting. Tests can be run from seven global server locations, and results are presented in four sections: a waterfall breakdown, a performance grade, a page analysis and a historical record of previous tests. The page analysis breaks down asset sizes by domain and content type, which is useful for comparing the weight of CDN-served assets against those served directly. Pingdom is based on the YSlow open-source project and does not currently measure the Core Web Vitals metrics that Google uses as ranking signals, so it is best treated as a quick and readable first pass rather than a definitive audit.
Security and Infrastructure Diagnostics
Performance alone cannot sustain a trustworthy website, as a misconfigured certificate, an insecure resource or a flagged IP address can each undermine user confidence and search visibility. One of the most frustrating post-migration problems is the disappearance of the HTTPS padlock despite an SSL certificate being in place, and Why No Padlock? exists specifically to address it. The cause is almost always mixed content, where a page served over HTTPS loads at least one resource (an image, a script or a stylesheet) over plain HTTP. Why No Padlock? scans any HTTPS URL and returns a list of every insecure resource found, along with the HTML element responsible, making it straightforward to trace and resolve the problem. Google has used HTTPS as a ranking signal since 2014, so unresolved mixed content issues carry an SEO cost as well as a security one.
For traffic-level threats, AbuseIPDB operates as a community-maintained IP blacklist. Managed by Marathon Studios Inc., the project allows system administrators and webmasters to report IP addresses involved in malicious behaviour, including hacking attempts, spam campaigns, DDoS attacks and phishing, and to check any IP address against the database before acting on traffic from it. A free API is available for integration with server tools such as Fail2Ban, enabling automatic reporting and real-time checks.
Bot traffic and automated form submissions are a persistent nuisance for any site that accepts user input, and hCaptcha addresses this by presenting challenges that are straightforward for human visitors but reliably difficult for automated scripts. Operated by Intuition Machines, it positions itself as a privacy-focused alternative to reCAPTCHA, collecting minimal data and retaining no personally identifiable information beyond what is necessary to complete a challenge. It is compliant with GDPR, CCPA and several other international privacy frameworks, and holds both ISO 27001 and SOC 2 Type II certifications. A free tier is available, with a Pro plan covering 100,000 evaluations per month, and an Enterprise tier offering additional controls including data localisation and zero-PII processing modes.
Red Sift offers two distinct products that address different aspects of infrastructure security, both relevant to the day-to-day operation of a website. Red Sift OnDMARC automates the configuration and monitoring of DMARC, SPF, DKIM, BIMI and MTA-STS, which are the protocols that collectively prevent attackers from sending spoofed emails that appear to originate from a legitimate domain. This is the basis for most phishing and business email compromise (BEC) attacks, and OnDMARC guides teams to full enforcement typically within six to eight weeks. Red Sift Certificates Lite addresses a separate but equally critical concern, monitoring SSL/TLS certificates for upcoming expiry and alerting administrators seven days ahead of time. It is free for up to 250 certificates and has been formally recommended by Let's Encrypt as its preferred monitoring service, following the retirement of Let's Encrypt's own expiry notification emails. The product was built on the foundation of Hardenize, which Red Sift acquired in 2022, a company founded by Ivan Ristić, creator of SSL Labs.
Colour Management and Visual Design
A website's visual coherence depends heavily on colour consistency, and the distance between a palette sketched on paper and one that functions in code can be significant. With over two million active users, Coolors is a fast and intuitive palette generator built around a simple interaction: pressing the space bar produces a new five-colour palette derived from colour theory algorithms. The platform includes an accessibility checker that calculates contrast ratios against WCAG standards and a colour extractor that derives palettes from uploaded photographs. It also offers interoperability with Figma, Adobe Creative Suite and the Chrome browser. A free tier is available, with a Pro plan at approximately $3 per month for unlimited saving and export options.
A quite different approach is taken by Colormind, which uses a deep learning model based on Generative Adversarial Networks (GANs) to generate harmonious colour schemes. The model is trained on datasets drawn from photographs, films, popular art and website designs, and is updated daily with fresh material. A particularly useful feature allows users to preview how a generated palette would look applied to a website layout, which is a more direct test of practicality than viewing swatches in isolation. A REST API is available for personal and non-commercial use. For converting between colour formats, tools such as Color-Hex, RGBtoHex and the WebFX Hex to RGB converter bridge the gap between design decisions and code implementation, translating colour values in both directions between the hexadecimal and RGB formats that CSS requires.
Optimisation and Code Utilities
Lean, efficient code is a direct contributor to load speed, and unused CSS is a surprisingly common source of unnecessary page weight that PurifyCSS Online addresses by scanning a website's HTML and JavaScript source against its stylesheets to identify selectors that are never used. CSS frameworks such as Bootstrap or Tailwind ship with many utility classes, and most websites use only a small fraction of them. Removing the unused rules can reduce stylesheet file size substantially, which in turn shortens the time a browser spends processing styles before rendering a page. The online version requires no build pipeline or command-line tools, making it accessible to developers at any workflow stage.
Image compression is equally important, as unoptimised images are among the most common causes of slow load times. ImageCompressor handles JPEG, PNG, WebP, GIF and SVG files in the browser, applying lossy or lossless algorithms with adjustable quality settings to reduce file sizes without visible degradation, and processes everything locally, which means that no images are uploaded to an external server. Contact forms and directory listings on websites are a persistent target for spam harvesters, and Email Obfuscator encodes email addresses into a format that is readable by browsers but opaque to most automated scrapers, generating both a plain HTML entity version and a JavaScript-dependent alternative for stronger protection.
For websites that publish mathematical or scientific content, QuickLaTeX provides a practical solution to embedding equations in web pages without a local LaTeX installation. Authors write standard LaTeX expressions directly in their content, and the service renders them as high-quality images that are cached and returned via URL for embedding. Its companion WordPress plugin, WP QuickLaTeX, handles this process automatically within the editor, supporting inline formulas, numbered displayed equations and TikZ graphics.
Server Response and Infrastructure Monitoring
Infrastructure performance sits beneath the layer that most visitors ever see, yet it determines how quickly any content reaches a browser at all, and the Time to First Byte (TTFB) is the metric that captures this most directly. It measures the interval between a browser sending an HTTP request and receiving the first byte of data from the server, and ByteCheck exists solely to measure it. This metric captures the combined effect of DNS resolution time, TCP connection time, SSL negotiation time and server processing time. Google considers a TTFB of 200ms or below to be good, and Byte Check breaks the total down into each constituent step, so developers can identify precisely where delays are occurring. Slow TTFB is often a server-side issue, such as inadequate caching, an overloaded database or a lack of a content delivery network (CDN).
Analytics and Content Evaluation
The final layer of tooling concerns understanding what content a site serves and how it performs in context. Dandelion is a natural language processing API developed by SpazioDati that can extract entities, classify text and analyse the semantic content of web pages, which has applications in content tagging, SEO auditing and editorial quality control. A free tier, covering up to 1,000 API units per day, is available without a credit card, making it accessible for developers who need semantic analysis at low to moderate volume.
Quiet Workhorses of the Web
Individually, each of these tools addresses a specific and well-defined problem. Taken together, they form a coherent toolkit that covers the full lifecycle of a web project, from initial performance diagnosis through to deployment of a secure, efficiently coded and visually consistent site. They do not replace professional judgement but extend it, handling time-consuming checks and conversions that would otherwise consume the attention needed for more complex work. As websites grow in complexity and user expectations continue to rise, familiarity with this kind of specialist tooling becomes a practical necessity rather than an optional extra.
Getting to know Jira, its workflows, test management capabilities and the need for governance
Developed by Atlassian and first released in 2002 as a straightforward bug and issue tracker aimed at software developers, Jira has since grown into a platform used for project management across a wide range of industries and disciplines. The name itself is a truncation of Gojira, the Japanese word for Godzilla, originating as an internal nickname used by Atlassian developers for Bugzilla, the bug-tracking tool they had previously relied upon.
A Family of Products, Each With a Purpose
The Jira ecosystem has expanded well beyond its original single offering, and it is worth understanding what each product is designed to do. Jira (formerly marketed as Jira Software, now unified with Jira Work Management) remains the flagship, built around agile project management with Scrum and Kanban boards at its core. Jira Service Management serves IT operations and service desk teams, handling ticketing and customer support workflows; it originated as Jira Service Desk in 2013, following Atlassian's discovery that nearly 40 per cent of their customers had already adapted the base product for service requests, and it was rebranded in 2020. At the enterprise level, Jira Align connects team delivery to strategic business goals, while Jira Product Discovery helps product teams capture feedback, prioritise ideas and build roadmaps. Together, these products span the full organisational hierarchy, from individual contributors up to executive portfolio management.
Core Features
Agile Boards and Backlog Management
Jira supports a range of agile methodologies, with two primary project templates available to teams. The Scrum template is designed for teams that deliver work in time-boxed sprints, providing backlog management, sprint planning and capacity tracking in a single view. The Kanban template, by contrast, is built around a continuous flow of work, helping teams visualise tasks as they move through each stage of a process without the constraint of fixed iterations. Both templates support custom configurations for teams whose ways of working do not map neatly to either model.
Reporting and Analytics
Jira's reporting suite provides visibility into project progress through various charts and metrics. The Burndown chart tracks remaining story points against the time left in a sprint, offering an indication of whether the team is on course to complete its committed work. The Burnup chart takes a complementary view, tracking how much work has been completed over time and making it straightforward to compare planned scope against actual delivery. These tools are useful for identifying patterns in team performance, though they are most informative when used consistently over several sprints rather than in isolation.
Custom Workflows
Teams can design workflows that reflect their own processes, defining the states an issue passes through and the transitions between them. Automation rules can be applied to handle repetitive steps without manual intervention, reducing administrative overhead on routine tasks. This flexibility is one of the more frequently cited reasons for adopting Jira, though it does require ongoing governance to prevent workflows from becoming inconsistent or unwieldy as teams and processes evolve.
Jira Query Language
Jira Query Language (JQL) provides a structured way to search and filter issues across projects, enabling teams to construct precise queries based on any combination of fields, statuses, assignees, dates and custom attributes. For organisations that invest time in learning it, JQL is a practical tool for building custom reports and dashboards. It is also the underlying mechanism for many of Jira's more advanced filtering and automation features.
Integration Options
Jira connects with a range of tools both within and outside the Atlassian ecosystem. Confluence handles documentation, Bitbucket manages code repositories and links commits directly to Jira issues, and Loom, acquired by Atlassian in 2023, adds asynchronous video communication. Third-party integrations, including Zoom and a broad catalogue of tools available through the Atlassian Marketplace, extend this further for teams with specific requirements.
Test Management With Xray
Jira does not include dedicated test management functionality by default, and teams that need to manage structured test cases alongside their development work typically turn to the Xray plugin, one of the most widely used additions in the Atlassian Marketplace. Xray operates as a native Jira application, meaning it adds new issue types directly to the Jira instance rather than sitting as a separate external tool. The issue types it introduces include Test, Test Set, Test Plan and Test Execution, all of which behave like standard Jira issues and can be searched, filtered and reported on using JQL.
A key capability is requirements traceability: Xray links test cases directly to the user stories and requirements they cover, and connects those in turn to any defects raised during execution. This gives teams a clear picture of test coverage and release readiness without having to leave Jira or reconcile data from separate systems. Test executions can be manual or automated, and Xray integrates with CI/CD toolchains (including Jenkins and Robot Framework) via a REST API, allowing automated test results to be published back into Jira and associated with the relevant requirements.
Xray also supports Behaviour-Driven Development (BDD), enabling teams to write tests in Gherkin syntax and manage them alongside their other Jira work. For organisations already using Jira as their central project management tool, Xray offers a practical route to bringing QA activities into the same workflow rather than maintaining a separate test management system.
Who is Jira Best Suited For?
Jira is generally considered most suitable for larger teams that require detailed control over workflows, reporting and resource allocation, and that have the capacity to dedicate administrative effort to the platform. Smaller teams or those without a dedicated Jira administrator may find the learning curve significant, particularly when configuring custom workflows or working with more advanced reporting features. Pricing is subscription-based, with tiers determined by user count and deployment model (cloud-hosted or self-managed), which means costs can increase substantially as an organisation grows.
Project Types: Tailoring Access to Needs
Jira divides its project spaces into two categories that serve different audiences. Team-managed projects offer simplified configuration for smaller, autonomous teams that want to get started without involving a Jira administrator. Company-managed projects grant administrators full control over customisation, permissions and settings, making them more appropriate for enterprises with complex requirements and multiple teams operating within the same instance. The two types can coexist within the same deployment, giving organisations the option to apply different governance models to different teams as their needs dictate.
Strengths and Limitations
Jira's scalability is one of its more consistent strengths, in terms of both the size of the user base it can support and the complexity of workflows it can accommodate. Its query functions give teams a precise way to interrogate project data, and its breadth of integrations means it can be connected to most standard development and collaboration toolchains.
A significant consideration for any Jira deployment is the degree of upfront decision-making it requires. Because the platform places few constraints on how it is configured, teams must establish their own conventions around workflow design, issue hierarchy, naming and permissions before adoption begins in earnest. Without that groundwork, it is straightforward for individual teams to configure Jira in incompatible ways, making cross-team reporting difficult and creating inconsistencies that become harder to unpick over time. Organisations that treat Jira as something to be governed, rather than simply installed, tend to get considerably more out of it.
The principal technical limitation is its dependence on the wider Atlassian ecosystem. Advanced portfolio planning, capacity forecasting and cross-programme dependency management typically require either a higher-tier plan or additional tooling. Advanced Roadmaps (now called Plans) are available natively within Jira Premium and Enterprise, providing cross-team timeline planning and scenario modelling. For capacity planning, budget tracking and timesheet management, many organisations turn to third-party Marketplace tools such as Tempo. Teams evaluating Jira should factor in both the cost of the appropriate licence tier and any supplementary tooling they are likely to need.
Where to Go From Here
Jira has grown considerably from the issue tracker it was when first released in 2002, and is now used by over 300,000 organisations worldwide. Its capabilities are broad, and its configurability makes it adaptable to a wide range of team structures and workflows. That same configurability, however, means the platform rewards investment in setup and ongoing administration, and organisations should assess whether they have the resources to realise that potential before committing. For those looking to explore further, Atlassian's official guides, its wider documentation, the support portal, the Atlassian Community and the developer documentation are useful starting points, and there are courses from an independent provider too.
Technology retail in North America: Five retailers worth knowing
The technology retail landscape in North America is shaped by a tension between convenience, expertise and competitive pricing. From sprawling big-box chains to specialist online stores, the sector contains a varied mix of established names and niche operators, each competing for customers who expect rapid delivery, accurate product information and reliable after-sales support. Five retailers stand out for the distinctly different approaches they take to serving that audience: Tech-America, Best Buy, Newegg, PC-Canada and Micro Center.
Tech-America
Tech-America presents itself as a direct-to-consumer online retailer covering a broad range of electronics and computer components. Its selling points include a large inventory and an emphasis on prompt shipping, with the site targeting a mix of hobbyists and small businesses. Questions have been raised about the company's legitimacy, with multiple consumer forums and review aggregators reflecting mixed opinions on its reliability and operational structure. Prospective customers are advised to research the retailer carefully before committing to a purchase, as third-party assessments remain inconclusive.
Best Buy
Best Buy is one of the most recognisable names in North American consumer electronics retail, and its history stretches back further than many of its customers might expect. The company was founded by Richard M. Schulze and James Wheeler in 1966 as an audio speciality store called Sound of Music, operating its first location in St. Paul, Minnesota. It was rebranded as Best Buy in 1983, at which point it had seven stores and around $10 million in annual sales, and it subsequently expanded its product range well beyond audio equipment to become a broad-based electronics retailer.
Today, Best Buy operates over 1,000 stores across the United States and Canada, combining physical retail with online sales in a model that the company describes as omnichannel. A key differentiator is its Geek Squad service division, which provides technical support, repairs and installation services across all store locations, and which has become a recognisable brand in its own right since being acquired by Best Buy in 2002. That combination of an extensive retail footprint and in-house technical services has allowed the company to retain a large and varied customer base that includes households, businesses and educational institutions.
Newegg
Newegg occupies a distinct position as a specialist online retailer focused primarily on computer hardware and components. Founded in 2001 by Fred Chang, a Taiwanese-American entrepreneur who had previously run ABS Computer Technologies, the company was established in California and initially targeted PC builders and enthusiasts who wanted detailed product information and user reviews alongside their purchases. The name itself was chosen to suggest new hope for e-commerce at a time when many dot-com businesses were struggling to survive.
Newegg operates a hybrid model that combines first-party sales with a marketplace for third-party sellers, expanding available inventory without the company needing to hold all stock itself. This approach has attracted a loyal community of technically minded buyers who value the depth of product listings on the platform. However, the marketplace model also introduces variability in seller quality, and some customers have noted inconsistencies in their experiences depending on which seller fulfilled their order. Newegg has been publicly listed on the Nasdaq under the ticker NEGG since May 2021, following a reverse merger with a Chinese special-purpose acquisition company.
PC-Canada
PC-Canada is a Waterloo, Ontario-based retailer that has served both individual consumers and business customers since its founding in 2003, making it one of Canada's longer-standing e-commerce technology retailers. The company offers a broad catalogue of IT products and components, and it holds an A+ rating from the Better Business Bureau, having been accredited since December 2015. Customer reviews present a more mixed picture, with some praising competitive pricing and fast shipping, while others have reported issues around order fulfilment and pricing changes after purchase. That gap between institutional accreditation and individual customer experience is a useful reminder that smaller regional retailers can face difficulties scaling consistently as their customer base grows.
Micro Center
Micro Center has taken a path that runs counter to the broader shift towards online-only retail, continuing to invest in physical stores and in-person expertise. The company currently operates 30 locations across the United States, with recent openings in Charlotte, Miami and Santa Clara adding to its footprint. Each store carries over 25,000 products and is staffed by associates who are recruited specifically for their technical knowledge, rather than general retail experience.
A notable feature of every Micro Center location is the Knowledge Bar, a dedicated in-store support desk offering diagnostics, repairs, authorised servicing for brands including Apple and Dell, and consultations for customers building their own PCs. The concept was introduced in 2007 and has since become central to the company's identity. Micro Center was ranked the number one tech retailer in the United States by PC Magazine in 2024, a recognition that reflects the premium its customers place on accessible, knowledgeable in-store service.
Closing Remarks
Each of these five retailers demonstrates a different answer to the same underlying question: what do technology buyers actually value? Tech-America and Newegg lean on the convenience and inventory breadth that online retail makes possible, while Best Buy and Micro Center make the case that physical presence and expert service remain compelling. PC-Canada illustrates the particular pressures facing regional players operating in a market where large international competitors set the expectations for pricing and delivery speed. As consumer habits continue to evolve, the retailers that balance adaptability with a clearly defined offering are likely to be the ones that endure.
Hardening WordPress on Ubuntu and Apache: A practical layered approach
Protecting a WordPress site rarely depends on a single control. Practical hardening layers network filtering, a web application firewall (WAF), careful browser-side restrictions and sensible log-driven tuning. What follows brings together several well-tested techniques and the precise commands needed to get them working, while also calling out caveats and known changes that can catch administrators out. The focus is on Ubuntu and Apache with ModSecurity and the OWASP Core Rule Set for WordPress, but complementary measures round out a cohesive approach. These include a strict Content Security Policy, Cloudflare or Nginx rules for form spam, firewall housekeeping for UFW and Docker, targeted network blocks and automated abuse reporting with Fail2Ban. Where solutions have moved on, that is noted so you do not pursue dead ends.
The Web Application Firewall
ModSecurity and the OWASP Core Rule Set
ModSecurity remains the most widespread open-source web application firewall and has been under the custodianship of the OWASP Foundation since January 2024, having previously been stewarded by Trustwave for over a decade. It integrates closely with the OWASP Core Rule Set (CRS), which aims to shield web applications from a wide range of attacks including the OWASP Top Ten, while keeping false alerts to a minimum. There are two actively maintained engines: 2.9.x is the classic Apache module and 3.x is the newer, cross-platform variant. Whichever engine you pick, the rule set is the essential companion. One important update is worth stating at the outset: CRS 4 replaces exclusion lists with plugins, so older instructions that toggle CRS 3's exclusions no longer apply as written.
Installing ModSecurity on Ubuntu
On Ubuntu 24.04 LTS, installing the Apache module is straightforward. The universe repository ships libapache2-mod-security2 at version 2.9.7, which meets the 2.9.6 minimum required by CRS 4.x, so no third-party repository is needed. You can fetch and enable ModSecurity with the following commands:
sudo apt install libapache2-mod-security2
sudo a2enmod security2
sudo systemctl restart apache2
It is worth confirming the module is loaded before you proceed:
apache2ctl -M | grep security
The default configuration runs in detection-only mode, which does not block anything. Copy the recommended file into place and then edit it so that SecRuleEngine On replaces SecRuleEngine DetectionOnly:
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
Open /etc/modsecurity/modsecurity.conf and make the change, then restart Apache once more to apply it.
Pulling in the Core Rule Set
The next step is to pull in the latest Core Rule Set and wire it up. A typical approach is to clone the upstream repository, move the example setup into place and move the directory named rules into /etc/modsecurity:
cd
git clone https://github.com/coreruleset/coreruleset.git
cd coreruleset
sudo mv crs-setup.conf.example /etc/modsecurity/crs-setup.conf
sudo mv rules/ /etc/modsecurity/
Now adjust the Apache ModSecurity include so that the new crs-setup.conf and all files in /etc/modsecurity/rules are loaded. On Ubuntu, that is governed by /etc/apache2/mods-enabled/security2.conf. Edit this file to reference the new paths, remove any older CRS include lines that might conflict, and then run:
sudo systemctl restart apache2
On Ubuntu 26.04 (due for release in April 2026), the default installation includes a pre-existing CRS configuration at /etc/modsecurity/crs/crs-setup.conf. If this is left in place alongside your own cloned CRS, Apache will fail to start with a Found another rule with the same id error. Remove it before restarting:
sudo rm -f /etc/modsecurity/crs/crs-setup.conf
WordPress-Specific Allowances in CRS 3
WordPress tends to work far better with CRS when its application-specific allowances are enabled. With CRS 3, a variable named tx.crs_exclusions_wordpress can be set in crs-setup.conf to activate those allowances. The commented "exclusions" block in that file includes a template SecAction with ID 900130 that sets application exclusions. Uncomment it and reduce it to the single line that enables the WordPress flag:
SecAction
"id:900130,
phase:1,
nolog,
pass,
t:none,
setvar:tx.crs_exclusions_wordpress=1"
Reload Apache afterwards with sudo service apache2 reload. If you are on CRS 4, do not use this older mechanism. The project has replaced exclusions with a dedicated WordPress rule exclusions plugin, so follow the CRS 4 plugin documentation instead. The WPSec guide to ModSecurity and CRS covers both the CRS 3 and CRS 4 approaches side by side if you need a reference that bridges the two versions.
Log Retention and WAF Tuning
Once the WAF is enforcing, logs become central to tuning. Retention is important for forensics as well as for understanding false positives over time, so do not settle for the default two weeks. On Ubuntu, you can extend Apache's logrotate configuration at /etc/logrotate.d/apache2 to keep weekly logs for 52 weeks, giving you a year of history to hand.
If you see Execution error – PCRE limits exceeded (-8) in the ModSecurity log, increase the following in /etc/modsecurity/modsecurity.conf to give the regular expression engine more headroom:
SecPcreMatchLimit 1000000
SecPcreMatchLimitRecursion 1000000
File uploads can generate an Access denied with code 403 (phase 2). Match of "eq 0" against "MULTIPART_UNMATCHED_BOUNDARY" required error. One remedy used in practice is to comment out the offending check around line 86 of modsecurity.conf and then reload. The built-in Theme Editor can trigger Request body no files data length is larger than the configured limit. Bumping SecRequestBodyLimit to 6000000 addresses that, again followed by a reload of Apache.
Whitelisting Rule IDs for Specific Endpoints
There are occasions where whitelisting specific rule IDs for specific WordPress endpoints is the most pragmatic way to remove false positives without weakening protection elsewhere. Creating a per-site or server-wide include works well; on Ubuntu, a common location is /etc/apache2/conf-enabled/whitelist.conf. For the Theme Editor, adding a LocationMatch block for /wp-admin/theme-editor.php that removes a small set of well-known noisy IDs can help:
<LocationMatch "/wp-admin/theme-editor.php">
SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904 959006 980130
</LocationMatch>
For AJAX requests handled at /wp-admin/admin-ajax.php, the same set with 981173 added is often used. This style of targeted exclusion mirrors long-standing community advice: find the rule ID in logs, remove it only where it is truly safe to do so, and never disable ModSecurity outright. If you need help finding noisy rules, the following command (also documented by InMotion Hosting) summarises IDs, hostnames and URIs seen in errors:
grep ModSecurity /usr/local/apache/logs/error_log | grep "[id" |
sed -E -e 's#^.*[id "([0-9]*).*hostname "([a-z0-9-_.]*)"].*uri "(.*?)".*"#1 2 3#' |
cut -d" -f1 | sort -n | uniq -c | sort -n
Add a matching SecRuleRemoveById line in your include and restart Apache.
Browser-Side Controls: Content Security Policy
Beyond the WAF, browser-side controls significantly reduce the harm from injected content and cross-site scripting. A Content Security Policy (CSP) is both simple to begin and very effective when tightened. An easy starting point is a report-only header that blocks nothing but shows you what would have been stopped. Adding the following to your site lets you open the browser's developer console and watch violations scroll by as you navigate:
Content-Security-Policy-Report-Only: default-src 'self'; font-src 'self'; img-src 'self'; script-src 'self'; style-src 'self'
From there, iteratively allowlist the external origins your site legitimately uses and prefer strict matches. If a script is loaded from a CDN such as cdnjs.cloudflare.com, referencing the exact file or at least the specific directory, rather than the whole domain, reduces exposure to unrelated content hosted there. Inline code is best moved to external files. If that is not possible, hashes can allowlist specific inline blocks and nonces can authorise dynamically generated ones, though the latter must be unpredictable and unique per request. The 'unsafe-inline' escape hatch exists but undermines much of CSP's value and is best avoided.
Once the console is clean, you can add real-time reporting to a service such as URIports (their guide to building a solid CSP is also worth reading) by extending the header:
Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri https://example.uriports.com/reports/report; report-to default
Pair this with a Report-To header so that you can monitor and prioritise violations at scale. When you are satisfied, switch the key from Content-Security-Policy-Report-Only to Content-Security-Policy to enforce the policy, at which point browsers will block non-compliant content.
Server Fingerprints and Security Headers
While working on HTTPS and header hardening, it is useful to trim server fingerprints and raise other browser defences, and this Apache security headers walkthrough covers the rationale behind each directive clearly. Apache's ServerTokens directive can be set in /etc/apache2/apache.conf to mask version details. Options range from Full to Prod, with the latter sending only Server: Apache. Unsetting X-Powered-By in /etc/apache2/httpd.conf removes PHP version leakage. Adding the following headers in the same configuration file keeps responses out of hostile frames, asks browsers to block detected XSS and prevents MIME type sniffing:
X-Frame-Options SAMEORIGIN
X-XSS-Protection 1;mode=block
X-Content-Type-Options nosniff
These are not replacements for fixes in application code, but they do give the browser more to work with. If you are behind antivirus products or corporate HTTPS interception, bear in mind that these can cause certificate errors such as SEC_ERROR_UNKNOWN_ISSUER or MOZILLA_PKIX_ERROR_MITM_DETECTED in Firefox. Disabling encrypted traffic scanning in products like Avast, Bitdefender or Kaspersky, or ensuring enterprise interception certificates are correctly installed in Firefox's trust store, resolves those issues. Some errors cannot be bypassed when HSTS is used or when policies disable bypasses, which is the intended behaviour for high-value sites.
Contact Form Spam
Contact form spam is a different but common headache. Analysing access logs often reveals that many automated submissions arrive over HTTP/1.1 while legitimate traffic uses HTTP/2 with modern browser stacks, and this GridPane analysis of a real spam campaign confirms the pattern in detail. That difference gives you something to work with.
Filtering by Protocol in Cloudflare
You can block or challenge HTTP/1.x access to contact pages at the edge with Cloudflare's WAF by crafting an expression that matches both the old protocol and a target URI, while exempting major crawlers. A representative filter looks like this:
(http.request.version in {"HTTP/1.0" "HTTP/1.1" "HTTP/1.2"}
and http.request.uri eq "/contact/"
and not http.user_agent contains "Googlebot"
and not http.user_agent contains "Bingbot"
and not http.user_agent contains "DuckDuckBot"
and not http.user_agent contains "facebot"
and not http.user_agent contains "Slurp"
and not http.user_agent contains "Alexa")
Set the action to block or to a managed challenge as appropriate.
Blocking Direct POST Requests Without a Valid Referrer
Another useful approach is to cut off direct POST requests to /wp-admin/admin-ajax.php and /wp-comments-post.php when the Referer does not contain your domain. In Cloudflare, this becomes:
(http.request.uri contains "/wp-admin/admin-ajax.php"
and http.request.method eq "POST"
and not http.referer contains "yourwebsitehere.com")
or
(http.request.uri contains "/wp-comments-post.php"
and http.request.method eq "POST"
and not http.referer contains "yourwebsitehere.com")
The same logic can be applied in Nginx with small site includes that set variables based on $server_protocol and $http_user_agent, then return 403 if a combination such as HTTP/1.1 on /contact/ by a non-whitelisted bot is met. It is sensible to verify with Google Search Console or similar that legitimate crawlers are not impeded once rules are live.
Complementary Mitigations Inside WordPress
Three complementary tools work well alongside the server-side measures already covered. The first is WP Armour, a free honeypot anti-spam plugin that adds a hidden field to comment forms, contact forms and registration pages using JavaScript. Because spambots cannot execute JavaScript, the field is never present in a genuine submission, and any bot that attempts to fill it is rejected silently. No CAPTCHA, API key or subscription is required, and the plugin is GDPR-compliant with no external server calls.
The second measure is entirely native to WordPress. Navigate to Settings, then Discussion and tick "Automatically close comments on articles older than X days." Spammers disproportionately target older content because it tends to be less actively monitored, so setting this to 180 days significantly reduces spam without affecting newer posts where discussion is still active. The value can be adjusted to suit the publishing cadence of the site.
The third layer is Akismet, developed by Automattic. Akismet passes each comment through its cloud-based filter and marks likely spam before it ever appears in the moderation queue. It is free for personal sites and requires an API key obtained from the Akismet website. Used alongside WP Armour, the two cover different vectors: WP Armour stops most bot submissions before they are processed at all, while Akismet catches those that reach the comment pipeline regardless of origin. Complementing both, reCAPTCHA v3 or hCaptcha (where privacy demands it) and simple "bot test" questions remain useful additions, though any solution that adds heavy database load warrants testing before large-scale deployment.
Host-Level Firewalls: UFW and Docker
Host-level firewalls remain important, particularly when Docker is in the mix. Ubuntu's UFW is convenient, but Docker's default iptables rules can bypass UFW and expose published ports to the public network even when ufw deny appears to be in place. One maintained solution uses the kernel's DOCKER-USER chain, so UFW regains control without disabling Docker's iptables management.
Appending a short block to /etc/ufw/after.rules that defines ufw-user-forward, a ufw-docker-logging-deny target and a DOCKER-USER chain, then jumps from DOCKER-USER into ufw-user-forward, allows UFW to govern forwarded traffic. Returning early for RELATED,ESTABLISHED connections, dropping invalid ones, accepting docker0-to-docker0 traffic and returning for RFC 1918 source ranges preserves internal communications. New connection attempts from public networks destined for private address ranges are logged and dropped, with a final RETURN handing off to Docker's own rules for permitted flows.
Restart UFW to activate the change:
sudo systemctl restart ufw
# or
sudo ufw reload
From that point, you can allow external access to a container's service port:
ufw route allow proto tcp from any to any port 80
Or scope to a specific container IP if needed:
ufw route allow proto tcp from any to 172.17.0.2 port 80
UDP rules follow the same pattern. If you prefer not to edit by hand, the UFW-docker helper script can install, check and manage these rules for you. It supports options to auto-detect Docker subnets, supports IPv6 by enabling ip6tables and a ULA (Unique Local Address) range in /etc/docker/daemon.json and can manage Swarm service exposure from manager nodes.
Should you instead use Firewalld, note that it provides a dynamically managed firewall with zones, a D-Bus API and runtime versus permanent configuration separation. It is the default in distributions such as RHEL, CentOS, Fedora and SUSE, and it also works with Docker's iptables backend, though the interaction model differs from UFW's.
Keeping Firewall Rules Tidy
Keeping firewall rules tidy is a small but useful habit. UFW can show verbose and numbered views of its state, as Linuxize's UFW rules guide explains in full:
sudo ufw status verbose
sudo ufw status numbered
Delete rules safely by number or by specification:
sudo ufw delete 4
sudo ufw delete allow 80/tcp
If you are scripting changes, the --force flag suppresses the interactive prompt. Take care never to remove your SSH allow rule when connected remotely, and remember that rule numbers change after deletions, so it is best to list again before removing the next one.
Logging Abusers with Fail2Ban and AbuseIPDB
Logging abusers and reporting them can reduce repeat visits. Fail2Ban watches logs for repeated failures and bans IPs by updating firewall rules for a set period. It can also report to AbuseIPDB via an action that was introduced in v0.10.0 (January 2017), which many installations have today.
Confirm that /etc/fail2ban/action.d/abuseipdb.conf exists and that your /etc/fail2ban/jail.local defines action_abuseipdb = abuseipdb. Within each jail that you want reported, add the following alongside your normal ban action, using categories that match the jail's purpose, such as SSH brute forcing:
%(action_abuseipdb)s[abuseipdb_apikey="my-api-key", abuseipdb_category="18,22"]
Reload with fail2ban-client reload and watch your AbuseIPDB reported IPs page to confirm submissions are flowing. If reports do not arrive, check /var/log/fail2ban.log for cURL errors and ensure your API key is correct, bearing in mind default API limits and throttling. Newer Fail2Ban versions (0.9.0 and above) use a persistent database, so re-reported IPs after restart are less of a concern. If you run older releases, a wrapper script can avoid duplicates by checking ban times before calling the API.
Blocking Provider Ranges
Occasionally, administrators choose to block traffic from entire provider ranges that are persistent sources of scanning or abuse. There are scripts such as the AWS-blocker tool that fetch the official AWS IPv4 and IPv6 ranges and insert iptables rules to block them all, and community posts such as this rundown of poneytelecom.eu ranges that shares specific ranges associated with problematic hosts for people who have seen repeated attacks from those networks. Measures like these are blunt instruments that can have side effects, so they warrant careful consideration and ongoing maintenance if used at all. Where possible, it is preferable to block based on behaviour, authentication failures and reputation rather than on broad ownership alone.
Final ModSecurity Notes: Chasing False Positives
Two final ModSecurity notes help when chasing false positives. First, WordPress comments and posting endpoints can trip generic SQL injection protections such as rule 300016 when text includes patterns that appear dangerous to a naive filter, a well-documented occurrence that catches many administrators out. Watching /etc/httpd/logs/modsec_audit.log or the Apache error log immediately after triggering the offending behaviour, and then scoping SecRuleRemoveById lines to the relevant WordPress locations such as /wp-comments-post.php and /wp-admin/post.php, clears real-world issues without turning off protections globally. Second, when very large responses are legitimately expected in parts of wp-admin, increasing SecResponseBodyLimit in an Apache or Nginx ModSecurity context can be more proportionate than whitelisting many checks at once. Always restart or reload Apache after changes so that your edits take effect.
Defence in Depth
Taken together, these layers complement each other well. ModSecurity with CRS gives you broad, configurable protection at the HTTP layer. CSP and security headers narrow the browser's attack surface and put guardrails in place for any client-side content issues. Targeted edge and server rules dampen automated spam without hindering real users or crawlers. Firewalls remain the bedrock, but modern container tooling means integrating UFW or Firewalld with Docker requires a small amount of extra care. Logs feed both your WAF tuning and your ban lists, and when you report abusers you contribute to a wider pool of threat intelligence. None of this removes the need to keep WordPress core, themes and plugins up to date, but it does mean the same attacks are far less likely to succeed or even to reach your application in the first place.
Running LanguageTool locally for privacy and unlimited checking
The search for a Grammarly replacement that offered more flexibility led here: LanguageTool, a capable grammar, spelling and style checker that works across a wide range of platforms. After some research, it emerged as the right fit, and it has been working well in daily use since, covering both browser extensions for general writing and a local instance for editing in VS Code. It supports more than 30 languages and integrates with browsers including Chrome, Chromium, Ungoogled-Chromium, Edge, Firefox and Opera, with mail clients such as Gmail and Thunderbird, and with office suites including LibreOffice, Apache OpenOffice, Microsoft Word and Google Docs. Whilst the service can be used via cloud APIs, there are many reasons to run it locally, among them the removal of text length limits that apply to cloud requests and the benefit of keeping content on the machine in question rather than sending it to remote servers.
The LibreOffice 7.4 Change and Why Local Matters
A change in LibreOffice from version 7.4 highlights why a local server is attractive. LanguageTool stopped being an add-on and became part of LibreOffice's code, but that shift brought constraints. Where the old add-on imposed no text size cap, the integrated checker limits free requests to 10,000 characters and Premium to 100,000 characters, and it sends content to LanguageTool's servers in Germany for processing, which many will consider a privacy concern. Similar cloud-based behaviour is the default for browser and mail client extensions, and running a small HTTP server locally avoids these issues entirely, restoring unlimited text size and keeping all checking on the machine.
Setting Up the Java Server
The simplest way to install LanguageTool on both Linux and macOS is via Homebrew. The formula handles Java automatically, removing the need to install or manage a runtime separately. Two commands are all that is required:
brew install languagetool
brew services start languagetool
The second command registers LanguageTool as a managed service so that it starts automatically at login, with no need for a separate startup script. The server listens on port 8081 by default. Updates are then handled in the same way as any other Homebrew package:
brew update && brew upgrade languagetool
Manual Installation via ZIP
For those who prefer not to use Homebrew, the manual route remains available. The Linux Mint forum tutorial linked above covers each step in full. Java 8 or later is required, and the openjdk-11-jre package in Linux Mint's repositories suffices for this purpose. The LanguageTool desktop bundle can be downloaded as LanguageTool-stable.zip, and the archive extracts to a versioned directory such as LanguageTool-5.9. Moving that directory to /home/username/opt and renaming it to LanguageTool simplifies paths considerably.
A file named LTserver.sh in /home/username/opt can then launch the server:
nohup java -cp ~/opt/LanguageTool/languagetool-server.jar org.languagetool.server.HTTPServer --port 8081 --allow-origin > /dev/null 2>&1 &
The nohup command at the start and the & at the end keep the service alive after its terminal closes and start it in the background, whilst > /dev/null 2>&1 silences output. Making the script executable and adding it to Startup Applications in a desktop environment such as MATE (with a brief delay after login) produces an automatic launch on sign-in. Those who prefer a manual approach can omit nohup … & and simply close the terminal to stop the server.
Confirming the Server Is Working
A simple request confirms that everything is working. Visiting the test URL in a browser returns JSON output showing the software version and a sample match, explaining that the sentence should begin with an uppercase letter. If the server is not running, the browser will show a connection refused message instead. On one user's hardware, the idle server consumed roughly 816 MB of RAM, which rose slightly during active checking.
With the process confirmed, browser and mail extensions can be directed away from the cloud to the local endpoint by opening their advanced options and selecting the local server at localhost. LibreOffice 7.4 users can also connect the integrated checker to the local service by setting the base URL to http://localhost:8081/v2 under Tools > Options > Languages and Locales > LanguageTool Server.
A Note on Startup Reliability (Manual Installation)
For those using the manual ZIP installation, there is a small operational note worth knowing from community experience. One user reported that the server did not start automatically at login despite the startup entry being present, and adding a short diagnostic to the beginning of the script caused it to start reliably. The following lines served only to write a timestamp to a log file, yet after inserting them the server came up as expected:
dt=$(date '+%d/%m/%Y %H:%M:%S')
echo "LanguageTool started successfully at" "$dt" >> /home/username/bin/LTserver.log
The underlying cause was not identified and could have been a subtle formatting or timing quirk, but the observation may help others encountering the same behaviour. It is worth trying this addition if automatic startup proves unreliable.
Network Security and Keeping the Server Updated
LanguageTool's HTTP server offers further configuration that affects accessibility. A single-user setup should keep the machine's firewall blocking incoming connections so that only localhost can reach the service. If the machine is to host LanguageTool for an internal network, adding --public to the server command line allows access from other devices, making the full command:
nohup java -cp ~/opt/LanguageTool/languagetool-server.jar org.languagetool.server.HTTPServer --port 8081 --allow-origin --public > /dev/null 2>&1 &
In that case, the firewall should allow incoming connections to port 8081 from local addresses, whilst denying others. Any instance reachable from the wider internet is best placed behind an Apache or nginx reverse proxy with TLS. Updates are handled by checking the download page periodically, extracting the latest LanguageTool-stable.zip and copying its contents into ~/opt/LanguageTool.
Running LanguageTool via Docker
Those who prefer containerised services can run LanguageTool under Docker and still keep traffic within a home or office network. A widely used image is erikvl87/languagetool, which exposes the HTTP server on port 8010 and accepts optional configuration via environment variables. A concise docker-compose.yml maps the port, binds a volume for optional n-gram data and tunes the Java heap, as shown below:
version: "3"
services:
languagetool:
image: erikvl87/languagetool
ports:
- 8010:8010
environment:
- langtool_languageModel=/ngrams
- Java_Xms=512m
- Java_Xmx=1g
volumes:
- ./ngrams:/ngrams
The langtool_languageModel=/ngrams environment variable enables the large n-gram data sets for German, English, Spanish, French and Dutch, which help with commonly confused words such as "their" and "there". The image defaults to a 256 MB minimum heap and a 512 MB maximum, and the settings above increase those values. To bind only to the local machine, changing the published port to localhost:8010:8010 prevents remote access. With the compose file in place, sudo docker-compose up -d starts the service in the background.
Integrating with Visual Studio Code
The VS Code integration is the centrepiece of this setup for local editing. A practical walkthrough on GNU/Linux.ch covers exactly this configuration, using the same Docker image described above. In Visual Studio Code, the LanguageTool Linter extension by David L. Day integrates checking into the editor. Installation can be done through the Extensions view or by running ext install davidlday.languagetool-linter from VS Code's command palette (Ctrl+P).
The extension's settings then need the LanguageTool server address, which should be set to http://127.0.0.1:8010 when the container runs on the same machine, or to the server's IP and port (for example http://192.168.0.2:8010) when it runs elsewhere on the local network. For a quick trial without running a server, the public API can be selected, though that brings the same limitations and privacy considerations as any cloud use. With the local endpoint configured, open Markdown files are checked continually, and possible issues are flagged with quick fixes available from within the editor.
Managing Rules and Disabling Checks
LanguageTool allows fine-grained control over which checks are active, and the official guide to enabling and disabling rules sets out five important points before getting into the steps. Rules cover grammar, spelling, punctuation and style, and they are all enabled by default. Some are available only to Premium users. Turning off "Picky Mode" automatically disables certain classes such as style suggestions, so behaviour may change noticeably after doing so. Rules can be disabled in add-ons and extensions, and once turned off there, they can only be re-enabled via those same add-ons.
In LanguageTool's online editor, clicking "Ignore" in the dialogue box that appears will disable a rule only for the current text, and the same applies if "Ignore in this text" is chosen from the list of issues on the right-hand panel. When a permanent toggle is wanted during browser-based use, selecting "Turn off rule everywhere" in the add-on disables it across documents until it is switched back on.
Re-enabling Disabled Rules
Re-enabling rules in an add-on follows a consistent pattern. In the Chrome extension on a Google Doc, clicking the LanguageTool icon or the error indicator opens the panel, and the settings cog at the bottom right leads to configuration. Scrolling down reveals the "Disabled rules" section, and hovering over an entry shows "Click to enable rule", which restores the individual check immediately. If a broad reset is needed, choosing "Enable all" turns everything back on at once, and the same approach applies across the other add-ons even if the precise placement varies slightly.
Command-Line Use for Bulk Text and Automation
For those who want to use LanguageTool on the command line, the Tips and Tricks page documents several switches and workflows that help with bulk text and automation. The tagger can be run without rule checking by adding --taggeronly or -t, which is useful when tagging large corpora. Input can also come from standard input by using - as the filename, so LanguageTool can sit in a pipeline. The following command processes substantial input and has been used with multi-gigabyte text:
java -jar languagetool-commandline.jar -l <language> -c <encoding> -t <corpus_file> > <tagged_corpus_file>
Automatic application of suggestions is enabled with --apply or -a, in which case only the first suggestion per rule is used, and the output is the corrected text. Because only a basic check ensures that the original error is still present before a suggestion is applied, it is wise to enable only reliable rules with -e or disable known problematic ones with -d. If a round of changes would introduce issues that other rules would catch, running LanguageTool again on the output resolves them in a second pass.
Collecting matches and tags for separate analysis is equally simple with the following command:
java -jar languagetool-commandline.jar -l <language> -c <encoding> <file> > results.txt 2> tags.txt
This writes rule matches to results.txt and part-of-speech tags to tags.txt. Developers working on rules will find that verbose mode (invoked with -v) prints helpful metadata including the XML line number for a rule or subrule inside a <rulegroup>, which pinpoints the exact location when debugging.
Adding Custom Rules Without Modifying Core Files
Adding or packaging rules for long-term reuse is supported without modifying core files, as the Tips and Tricks page explains in detail. From version 6.0, LanguageTool loads an optional grammar_custom.xml placed alongside a language's grammar.xml, and the custom file can define rules that survive upgrades provided their IDs do not collide with existing ones. Alternatively, an external file can be referenced by declaring an entity near the top of grammar.xml:
<!ENTITY UserRules SYSTEM "file:///path/to/user-rules.xml">
Inserting &UserRules; inside an appropriate <category> then pulls in those rules. For external rules, setting external="yes" on each category suppresses the link to community rule details, which would otherwise be shown in the stand-alone GUI.
Writing and Testing Rules
Writing robust rules involves understanding negation and structural nuances. Negation can apply to tokens, to parts of speech, or via exceptions, though care is needed because negating a token with a SENT_END tag will match any end-of-sentence token rather than excluding it. Tokens can be constrained by whether whitespace precedes them using the spacebefore attribute, which helps when matching punctuation or quotation marks. Suggestions can adjust case with case_conversion, and more involved changes can rely on regular expressions inside a <match> element to alter parts of a word whilst preserving intended capitalisation.
Testing rules pays dividends during development. The bundled testrules.sh (or its Windows counterpart) runs unit-style checks and validates XML, and passing a two-letter language code limits the run to a single language. Maven can also be used with mvn clean test. When a suggestion is generated programmatically rather than as a fixed string, adding a correction attribute to an incorrect example asserts what the final suggestion should be and causes a test failure if it diverges. Context-sensitive rules for commonly confused words can avoid false positives by including exceptions for words that indicate the correct usage, as in a Dutch example distinguishing "aanvaart" and "aanvaardt" where the presence of "boot" or "haven" suppresses the warning.
Finding Good Rule Examples with Corpus Tools
Finding good examples for rule development benefits from corpus tools, and the Tips and Tricks page covers this and much more besides. For English, the Google Web 1T 5-Gram Database can be queried by searching for `xyz *` to see common following words or `* xyz` to see common preceding words, which grounds a rule in real usage rather than conjecture. The Corpus of Contemporary American English offers KWIC display to view neighbour words around a query and may request registration after several searches.
Both the 1T data and COCA skew towards American English, however, so those working on British English rules will find the British National Corpus more appropriate, being 100 million words of British English searchable through the same interface. For a broader view across multiple varieties of English, including British, Australian, Irish and South African, the Corpus of Global Web-Based English covers 20 national varieties and is freely available on the same platform. For other languages that LanguageTool supports, corpus availability varies considerably, and the LanguageTool developer documentation is the best starting point for finding suitable resources for a given language.
A Private, Flexible and Useful Toolkit
What began as a search for a more flexible Grammarly alternative has settled into a setup that covers two distinct use cases: browser extensions for everyday writing in web applications, and a local server feeding the VS Code extension for longer-form editing. A local LanguageTool server removes size limits and keeps content on the machine, fitting neatly behind LibreOffice's integrated checker, within browser and mail extensions and inside editors such as VS Code. The sources gathered during those early days of getting this running are what inform this account, and the configuration has been working well enough for the purpose since. Rules can be tuned or switched off where they hinder rather than help, then restored easily when needed. Keeping the server updated and placed behind sensible network boundaries rounds out a setup that serves everyday writing as well as more specialised tasks.