1+ <!DOCTYPE html>
2+ < html lang ="en ">
3+
4+ < head >
5+ <!--
6+ FIELD NOTE TEMPLATE
7+ Duplicate this file for new Field Notes articles.
8+ -->
9+
10+ < meta charset ="UTF-8 ">
11+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
12+
13+ < title > A WordPress Infrastructure Review | Cliffable</ title >
14+
15+ < meta name ="description "
16+ content ="A security alert prompted a wider review of a WordPress site running on AWS Lightsail, leading to server, security, DNS and domain management improvements. ">
17+
18+ < meta name ="robots " content ="noindex, nofollow ">
19+
20+ < link rel ="canonical " href ="https://cliffable.com/field-notes/a-wordpress-infrastructure-review.html ">
21+
22+ <!-- Google Fonts -->
23+ < link rel ="preconnect " href ="https://fonts.googleapis.com ">
24+ < link rel ="preconnect " href ="https://fonts.gstatic.com " crossorigin >
25+ < link href ="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600&display=swap " rel ="stylesheet ">
26+
27+ < link rel ="stylesheet " href ="../styles.css ">
28+
29+ <!-- Favicons -->
30+ < link rel ="icon " type ="image/x-icon " href ="../favicon/favicon.ico ">
31+ < link rel ="icon " type ="image/png " sizes ="32x32 " href ="../favicon/favicon-32x32.png ">
32+ < link rel ="icon " type ="image/png " sizes ="16x16 " href ="../favicon/favicon-16x16.png ">
33+ < link rel ="apple-touch-icon " sizes ="180x180 " href ="../favicon/apple-touch-icon.png ">
34+
35+ <!-- Google Analytics -->
36+ < script async src ="https://www.googletagmanager.com/gtag/js?id=G-L41X6NGBMK "> </ script >
37+
38+ < script >
39+ window . dataLayer = window . dataLayer || [ ] ;
40+
41+ function gtag ( ) {
42+ dataLayer . push ( arguments ) ;
43+ }
44+
45+ gtag ( 'js' , new Date ( ) ) ;
46+
47+ gtag ( 'config' , 'G-L41X6NGBMK' ) ;
48+ </ script >
49+
50+ </ head >
51+
52+ < body >
53+
54+ < header >
55+ < div class ="container header-inner ">
56+
57+ < div class ="logo ">
58+ < a href ="/ ">
59+ < img src ="/assets/logos/cliffable-logo-white-v2.svg " alt ="Cliffable logo " height ="60 ">
60+ </ a >
61+ </ div >
62+
63+ < nav class ="main-nav ">
64+ < a href ="/projects/ "> Projects</ a >
65+ < a href ="/field-notes/ "> Field Notes</ a >
66+ < a href ="/about.html "> About</ a >
67+ < a href ="/contact.html "> Contact</ a >
68+ </ nav >
69+
70+ </ div >
71+ </ header >
72+
73+ < main >
74+
75+ <!-- HERO -->
76+
77+ < section class ="hero field-note-article-hero ">
78+ < div class ="container field-note-container ">
79+
80+ < p class ="field-note-article-meta ">
81+ WordPress • AWS Lightsail • Infrastructure
82+ </ p >
83+
84+ < p class ="field-note-date ">
85+ Published 12 June 2026
86+ </ p >
87+
88+ < h1 > A WordPress Infrastructure Review</ h1 >
89+
90+ < p class ="field-note-intro ">
91+ A security alert prompted a wider review of my WordPress infrastructure, leading to changes across
92+ server sizing, WordPress hardening, DNS management and domain operations.
93+ </ p >
94+
95+ </ div >
96+ </ section >
97+
98+ <!-- FEATURED IMAGE -->
99+
100+ < section class ="field-note-featured-image ">
101+ < div class ="container field-note-container ">
102+
103+ < a href ="../assets/images/field-notes/a-wordpress-infrastructure-review/wordpress-infrastructure-review-before-and-after.png "
104+ class ="lightbox-trigger ">
105+
106+ < img src ="../assets/images/field-notes/a-wordpress-infrastructure-review/wordpress-infrastructure-review-before-and-after.png "
107+ alt ="Before and after comparison of a WordPress infrastructure review ">
108+
109+ </ a >
110+
111+ < p class ="field-note-image-caption ">
112+ Infrastructure changes made following a review prompted by monitoring alerts, security concerns and
113+ domain management issues.
114+ </ p >
115+
116+ </ div >
117+ </ section >
118+
119+ <!-- ARTICLE CONTENT -->
120+
121+ < section class ="field-note-content-section ">
122+ < div class ="container field-note-container ">
123+
124+ < h2 > The trigger for the review</ h2 >
125+
126+ < p >
127+ After upgrading my WordPress site from a 1 GB Lightsail instance to a 2 GB instance, the platform
128+ appeared to be in a much better state. The earlier memory pressure had been reduced, monitoring was
129+ in place, and the site was running normally.
130+ </ p >
131+
132+ < p >
133+ A few days later, I received an unexpected WordPress password reset email. Around the same period,
134+ CloudWatch alarms and health checks also raised concerns about the behaviour of the site.
135+ </ p >
136+
137+ < p >
138+ The site did not appear to be compromised, but the combination of monitoring alerts and an
139+ unexpected
140+ security-related email was enough to prompt a wider review.
141+ </ p >
142+
143+ < h2 > Reviewing the WordPress server</ h2 >
144+
145+ < p >
146+ I started with the WordPress installation itself. The aim was to reduce unnecessary exposure, remove
147+ anything I did not need, and make the administrative surface of the site smaller.
148+ </ p >
149+
150+ < ul >
151+ < li > Created a new administrator account.</ li >
152+ < li > Removed the old administrator account.</ li >
153+ < li > Reviewed and removed unnecessary plugins.</ li >
154+ < li > Disabled public user enumeration via the WordPress REST API.</ li >
155+ < li > Reviewed logs and monitoring data after the alerts.</ li >
156+ < li > Adjusted Apache worker settings to reduce memory pressure.</ li >
157+ </ ul >
158+
159+ < p >
160+ None of these changes was especially complex on its own. The important lesson was that operating a
161+ live WordPress site is not just about keeping the instance running. The application, plugins, users,
162+ logs and server configuration all form part of the operational picture.
163+ </ p >
164+
165+ < h2 > Looking beyond the server</ h2 >
166+
167+ < p >
168+ Once the WordPress installation had been reviewed, I looked at the wider infrastructure around the
169+ site. The website
170+ itself was hosted in AWS Lightsail, but the domains were still registered with Xilo, DNS was managed
171+ through Xilo,
172+ and the .com redirect relied on Cloudflare.
173+ </ p >
174+
175+ < p >
176+ My goal was to simplify the overall architecture by moving more of the supporting infrastructure
177+ into AWS. The first
178+ step was migrating DNS for cliffsmithguitarlessons.co.uk into Route 53, giving me direct control of
179+ DNS alongside the
180+ rest of the AWS environment.
181+ </ p >
182+
183+ < p >
184+ I then began planning a wider migration that would eventually move the .com redirect into AWS using
185+ CloudFront and an
186+ S3 redirect bucket, while also transferring the domain registrations themselves away from Xilo.
187+ </ p >
188+
189+ < h2 > Registrar and transfer issues</ h2 >
190+
191+ < p >
192+ The domain work quickly became more complicated than expected. During the migration process, several
193+ domain
194+ management operations began failing with unclear error messages, including nameserver changes,
195+ registrar lock
196+ changes and contact validation updates.
197+ </ p >
198+
199+ <!-- OPTIONAL INLINE IMAGE -->
200+
201+ < div class ="field-note-inline-image ">
202+
203+ < a href ="../assets/images/field-notes/a-wordpress-infrastructure-review/xilo-domain-management-errors.png "
204+ class ="lightbox-trigger ">
205+
206+ < img src ="../assets/images/field-notes/a-wordpress-infrastructure-review/xilo-domain-management-errors.png "
207+ alt ="Examples of Xilo portal and domain management errors ">
208+
209+ </ a >
210+
211+ < p class ="field-note-image-caption ">
212+ Several domain management operations failed during the migration process. The root cause was
213+ eventually traced to a combination of registrar-side issues, an outdated registrant email
214+ address
215+ and registry restrictions triggered during the transfer process.
216+ </ p >
217+
218+ </ div >
219+
220+ < p >
221+ What initially looked like a DNS or registrar problem turned out to be an administrative one. The
222+ registrant email
223+ address on the domains was outdated, meaning transfer approval messages could not be received.
224+ </ p >
225+
226+ < p >
227+ Updating the registrant details resolved that issue, but it triggered a registry-imposed transfer
228+ lock that delayed
229+ the remaining migration work. As a result, the .co.uk domain now uses Route 53 for DNS, but the
230+ domain registrations
231+ remain with Xilo and the .com redirect continues to use Cloudflare for the time being.
232+ </ p >
233+
234+ < p >
235+ This was a useful reminder that infrastructure risk is not always caused by servers, code or cloud
236+ configuration.
237+ Sometimes the weak point is administrative information that has quietly become out of date.
238+ </ p >
239+
240+ < h2 > Current state</ h2 >
241+
242+ < p >
243+ The main WordPress site is now running on a larger Lightsail instance, with monitoring in place and
244+ a cleaner WordPress configuration. The .co.uk domain uses Route 53 for DNS, while the .com domain
245+ remains with Cloudflare for now because the registrar-side transfer process is delayed.
246+ </ p >
247+
248+ < p >
249+ The next planned improvement is to place the .co.uk WordPress site behind CloudFront and AWS WAF.
250+ That should reduce direct exposure of the Lightsail instance and provide a better place to apply
251+ managed security rules and rate limiting.
252+ </ p >
253+
254+ < h2 > Conclusion</ h2 >
255+
256+ < p >
257+ What started as a response to a single security alert became a broader infrastructure review. The
258+ process improved the WordPress installation, clarified the domain architecture, exposed weaknesses
259+ in
260+ the registrar setup, and created a clear next step for improving resilience with CloudFront and AWS
261+ WAF.
262+ </ p >
263+
264+ <!-- RELATED PROJECT -->
265+
266+ < h2 > Related project</ h2 >
267+
268+ < p class ="field-note-callout ">
269+ This work was implemented as part of the
270+ < a href ="../projects/csgl-lightsail-wordpress.html ">
271+ WordPress on AWS Lightsail
272+ </ a >
273+ project.
274+ </ p >
275+
276+ </ div >
277+ </ section >
278+
279+ </ main >
280+
281+ <!-- FOOTER -->
282+
283+ < footer >
284+ < div class ="container footer-content ">
285+
286+ < div class ="footer-contact ">
287+
288+ < p class ="footer-heading "> Contact</ p >
289+
290+ < div class ="footer-links ">
291+
292+ < a href ="mailto:mailcliffsmith@gmail.com ">
293+ Email
294+ </ a >
295+
296+ < a href ="https://www.linkedin.com/in/cliff-smith-london/ " target ="_blank " rel ="noopener noreferrer ">
297+ LinkedIn
298+ </ a >
299+
300+ < a href ="https://github.com/cliffable " target ="_blank " rel ="noopener noreferrer ">
301+ GitHub
302+ </ a >
303+
304+ </ div >
305+ </ div >
306+
307+ < div class ="footer-meta ">
308+ < p > © 2026 Cliff Smith</ p >
309+ </ div >
310+
311+ </ div >
312+ </ footer >
313+
314+ <!-- LIGHTBOX -->
315+
316+ < div id ="lightbox " class ="lightbox ">
317+ < img id ="lightbox-img " src ="" alt ="">
318+ </ div >
319+
320+ < script >
321+
322+ const lightboxTriggers = document . querySelectorAll ( '.lightbox-trigger' ) ;
323+
324+ const lightbox = document . getElementById ( 'lightbox' ) ;
325+
326+ const lightboxImg = document . getElementById ( 'lightbox-img' ) ;
327+
328+ lightboxTriggers . forEach ( trigger => {
329+
330+ trigger . addEventListener ( 'click' , event => {
331+
332+ event . preventDefault ( ) ;
333+
334+ lightbox . style . display = 'flex' ;
335+
336+ lightboxImg . src = trigger . href ;
337+
338+ } ) ;
339+
340+ } ) ;
341+
342+ lightbox . addEventListener ( 'click' , ( ) => {
343+
344+ lightbox . style . display = 'none' ;
345+
346+ lightboxImg . src = '' ;
347+
348+ } ) ;
349+
350+ </ script >
351+
352+ </ body >
353+
354+ </ html >
0 commit comments