{"id":676,"date":"2026-08-21T19:28:26","date_gmt":"2026-08-21T16:28:26","guid":{"rendered":"https:\/\/ahaddad-wp.duckdns.org\/my\/mylogbook\/?post_type=doc_article&#038;p=676"},"modified":"2026-08-21T19:29:22","modified_gmt":"2026-08-21T16:29:22","slug":"ip-change-runbook","status":"publish","type":"doc_article","link":"https:\/\/ahaddad-wp.duckdns.org\/my\/mylogbook\/docs\/ip-change-runbook\/","title":{"rendered":"IP Change Runbook"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">When the Home IP Changes<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The recovery sequence for Nextcloud and the WordPress sites whenever the ISP-issued public IP changes \u2014 written for tomorrow&#8217;s router replacement, but good for any future IP change too.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Covers:&nbsp;<strong>ahaddad.duckdns.org<\/strong>&nbsp;&amp;&nbsp;<strong>ahaddad-wp.duckdns.org<\/strong>Server:&nbsp;<strong>192.168.100.13<\/strong>Last verified:&nbsp;<strong>2026-08-21<\/strong><\/p>\n\n\n\n<div class=\"runbook\">\n<style>\n  @import url('https:\/\/fonts.googleapis.com\/css2?family=IBM+Plex+Sans:wght@400;500;600;700&family=Source+Sans+3:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500;600&display=swap');\n\n  .runbook{\n    --paper: #EEF1F3;\n    --surface: #FFFFFF;\n    --surface-2: #E4E9EC;\n    --ink: #17212B;\n    --ink-soft: #4C5A67;\n    --line: #D6DCE2;\n    --accent: #C9781E;\n    --accent-ink: #7A4A11;\n    --accent-2: #1F8A72;\n    --warn: #B23B3B;\n    --warn-bg: #F7E9E4;\n    --mono-bg: #E7EBEE;\n    --step-num-ink: #1a1408;\n    --shadow: 0 1px 2px rgba(23,33,43,0.06), 0 8px 24px -12px rgba(23,33,43,0.18);\n\n    background: var(--paper);\n    color: var(--ink);\n    font-family: \"Source Sans 3\", ui-sans-serif, system-ui, sans-serif;\n    font-size: 16.5px;\n    line-height: 1.6;\n    padding: 32px 20px 56px;\n    display: block;\n  }\n\n  @media (prefers-color-scheme: dar\n    .runbook{\n      --paper: #10161D;\n      --surface: #19222C;\n      --surface-2: #212C38;\n      --ink: #E6EAEE;\n      --ink-soft: #A7B3BE;\n      --line: #2A3542;\n      --accent: #E2A03D;\n      --accent-ink: #F4CE8E;\n      --accent-2: #3FB39B;\n      --warn: #E4807A;\n      --warn-bg: #33201F;\n      --mono-bg: #141C24;\n      --step-num-ink: #241b06;\n      --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 12px 28px -14px rgba(0,0,0,0.6);\n    }\n  }\n\n  .runbook *{ box-sizing: border-box; }\n  .runbook main{\n    max-width: 760px;\n    margin: 0 auto;\n    display: flex;\n    flex-direction: column;\n    gap: 40px;\n  }\n\n  .runbook h1, .runbook h2, .runboo\n    font-family: \"IBM Plex Sans\", ui-sans-serif, system-ui, sans-serif;\n    text-wrap: balance;\n    margin: 0;\n    color: var(--ink);\n  }\n  .runbook code, .runbook .mono, .ref td:nth-child(1){\n    font-family: \"IBM Plex Mono\", ui-monospace, \"SFMono-Regular\", monospace;\n    font-variant-numeric: tabular-n\n  }\n\n  .runbook header{ display:flex; flex-direction: column; gap: 10px; }\n  .runbook .eyebrow{\n    font-family: \"IBM Plex Mono\", monospace;\n    font-size: 12.5px;\n    letter-spacing: 0.09em;\n    text-transform: uppercase;\n    color: var(--accent-ink);\n    font-weight: 600;\n  }\n  .runbook h1{ font-size: clamp(28p00; letter-spacing: -0.01em; }\n  .runbook .dek{ color: var(--ink-soft); font-size: 17px; max-width: 62ch; }\n  .runbook .meta{\n    display:flex; gap: 18px; flex-wrap: wrap;\n    font-size: 13.5px; color: var(-\n    padding-top: 6px; border-top: 1px solid var(--line); margin-top: 4px;\n  }\n  .runbook .meta span b{ color: var(--ink); font-weight: 600; }\n\n  .runbook figure{ margin:0; display:flex; flex-direction:column; gap:12px; }\n  .runbook .diagram-frame{\n    background: var(--surface);\n    border: 1px solid var(--line);\n    border-radius: 10px;\n    padding: 18px 12px;\n    box-shadow: var(--shadow);\n    overflow-x: auto;\n  }\n  .runbook .diagram-frame svg{ dispx-width: 100%; height: auto; }\n  .runbook figcaption{ font-size: 13.5px; color: var(--ink-soft); text-align:center; }\n  .runbook figcaption b{ color: var\n\n  .runbook .asks{\n    background: var(--warn-bg);\n    border: 1px solid var(--warn);\n    border-radius: 12px;\n    padding: 20px 22px;\n    display:flex; flex-direction:column; gap:14px;\n  }\n  .runbook .asks h2{ font-size: 15px; text-transform: uppercase; letter-spacing: .06em; color:\nvar(--warn); font-weight:700; }\n  .runbook .ask-item{ display:flex; gap:12px; }\n  .runbook .ask-num{\n    flex: none; width: 24px; height:24px; border-radius:50%;\n    background: var(--warn); color:\n    display:flex; align-items:center; justify-content:center;\n    font-family:\"IBM Plex Mono\",monweight:600;\n  }\n  .runbook .ask-item p{ margin:0; }\n  .runbook .ask-item .why{ color: var(--ink-soft); font-size: 14.5px; margin-top:4px; }\n\n  .runbook .sequence{ display:flex; flex-direction:column; gap:22px; }\n  .runbook .sequence > h2{\n    font-size: 13px; text-transform:uppercase; letter-spacing:.08em;\n    color: var(--ink-soft); font-weolid var(--line);padding-bottom:10px;\n  }\n  .runbook .step{\n    display:grid;\n    grid-template-columns: 40px 1fr;\n    gap: 16px;\n    background: var(--surface);\n    border: 1px solid var(--line);\n    border-radius: 12px;\n    padding: 20px 22px 22px;\n    box-shadow: var(--shadow);\n  }\n  .runbook .step-num{\n    width:40px; height:40px; border\n    background: var(--accent); color: var(--step-num-ink);\n    display:flex; align-items:cente\n    font-family:\"IBM Plex Mono\",monospace; font-weight:700; font-size:16px;\n  }\n  .runbook .step-body{ display:flex; flex-direction:column; gap:12px; min-width:0; }\n  .runbook .step h3{ font-size: 18.\n  .runbook .why{\n    font-size: 14.5px; color: var(-\n    border-left: 2px solid var(--accent-2);\n    padding-left: 12px;\n  }\n  .runbook .why b{ color: var(--ink\n  .runbook .action-label{\n    font-size:12px; text-transform:em;\n    color: var(--ink-soft); font-weight:600; margin-top:2px;\n  }\n  .runbook pre.cmd{\n    background: var(--mono-bg);\n    border: 1px solid var(--line);\n    border-radius: 8px;\n    padding: 12px 14px;\n    overflow-x: auto;\n    margin:0;\n    font-size: 13.5px;\n    line-height:1.55;\n  }\n  .runbook pre.cmd code{ color: var(--ink); white-space:pre; }\n  .runbook pre.cmd .rem{ color: var\n  .runbook .expect{\n    font-size: 13.5px; color: var(-:8px; align-items:baseline;\n  }\n  .runbook .expect b{ font-weight:7\n\n  .runbook .ref-wrap{ display:flex;4px; }\n  .runbook .ref-wrap h2{ font-size: 20px; font-weight:700; }\n  .runbook .table-scroll{ overflow---line); border-radius:12px;box-shadow: var(--shadow); }\n  .runbook table.ref{ border-collapwidth: 620px;background:var(--surface); }\n  .runbook table.ref th{\n    text-align:left; font-size:12px; text-transform:uppercase; letter-spacing:.06em;\n    color: var(--ink-soft); font-weborder-bottom:1px solid var(--line);\n    background: var(--surface-2);\n  }\n  .runbook table.ref td{ padding:13px 16px; border-bottom:1px solid var(--line); font-size:14.5px;\nvertical-align:top; }\n  .runbook table.ref tr:last-child td{ border-bottom:none; }\n  .runbook table.ref td:nth-child(1(--accent-ink); white-space:nowrap;}\n  .runbook table.ref td:nth-child(3\n\n  .runbook footer{ text-align:cente(--ink-soft); padding-top:8px; }\n<\/style>\n\n<main>\n\n  <header>\n    <div class=\"eyebrow\">ubuntu-serv>\n    <h1>When the Home IP Changes<\/h1>\n    <p class=\"dek\">The recovery seqordPress sites whenever theISP-issued public IP changes \u2014 written for the router replacement, but good for any future IP change\ntoo.<\/p>\n    <div class=\"meta\">\n      <span>Covers: <b>ahaddad.duckwp.duckdns.org<\/b><\/span>\n      <span>Server: <b>192.168.100.13<\/b><\/span>\n      <span>Last verified: <b>2026-\n    <\/div>\n  <\/header>\n\n  <figure>\n    <div class=\"diagram-frame\">\n      <svg viewBox=\"0 0 700 700\" ros: the solid traffic path a requesttakes from a browser through the ISP router, the switch, the server, and npm, to Nextcloud or\nWordPress; and a dashed DNS control job updates DuckDNS, which thebrowser queries before the traffic path begins.\">\n        <defs>\n          <marker id=\"rbArrow\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\"\nmarkerHeight=\"7\" orient=\"auto-start\n            <path d=\"M0,0 L10,5 L0,10 z\" fill=\"currentColor\"\/>\n          <\/marker>\n          <marker id=\"rbArrowAccent\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\"\nmarkerHeight=\"7\" orient=\"auto-start\n            <path d=\"M0,0 L10,5 L0,10 z\" fill=\"var(--accent)\"\/>\n          <\/marker>\n        <\/defs>\n\n        <g font-family=\"IBM Plex Sans, sans-serif\">\n\n          <rect x=\"190\" y=\"16\" width=\"320\" height=\"58\" rx=\"8\" fill=\"none\" stroke=\"currentColor\"\nstroke-width=\"1.4\"\/>\n          <text x=\"350\" y=\"40\" text-anchor=\"middle\" font-size=\"15\" font-weight=\"600\"\nfill=\"currentColor\">Browser \/ visit\n          <text x=\"350\" y=\"59\" text-anchor=\"middle\" font-size=\"11.5\" fill=\"currentColor\"\nopacity=\"0.6\">anywhere on the inter\n\n          <line x1=\"350\" y1=\"74\" x2ntColor\" stroke-width=\"1.4\"marker-end=\"url(#rbArrow)\"\/>\n          <text x=\"362\" y=\"100\" fonr\" opacity=\"0.75\">connects to yourpublic IP<\/text>\n\n          <rect x=\"190\" y=\"120\" width=\"320\" height=\"58\" rx=\"8\" fill=\"none\" stroke=\"currentColor\"\nstroke-width=\"1.4\"\/>\n          <text x=\"350\" y=\"144\" text-anchor=\"middle\" font-size=\"15\" font-weight=\"600\"\nfill=\"currentColor\">ISP router<\/tex\n          <text x=\"350\" y=\"163\" text-anchor=\"middle\" font-size=\"11.5\" fill=\"currentColor\"\nopacity=\"0.6\">NAT + port-forward 80\n\n          <line x1=\"350\" y1=\"178\" x--accent)\" stroke-width=\"1.8\"marker-end=\"url(#rbArrowAccent)\"\/>\n          <text x=\"362\" y=\"204\" font-ink)\" font-weight=\"600\">rule:80\/443 &#8594; 192.168.100.13<\/text>\n\n          <rect x=\"190\" y=\"224\" width=\"320\" height=\"58\" rx=\"8\" fill=\"none\" stroke=\"var(--accent)\"\nstroke-width=\"1.8\"\/>\n          <text x=\"350\" y=\"248\" text-anchor=\"middle\" font-size=\"15\" font-weight=\"600\"\nfill=\"currentColor\">HP switch<\/text\n          <text x=\"350\" y=\"267\" text-anchor=\"middle\" font-size=\"11.5\" fill=\"var(--accent-ink)\"\nfont-weight=\"600\">&#9888; port 9 orh;8 are 100Mb<\/text>\n\n          <line x1=\"350\" y1=\"282\" xentColor\" stroke-width=\"1.4\"marker-end=\"url(#rbArrow)\"\/>\n          <text x=\"362\" y=\"308\" fonr\" opacity=\"0.75\">ethernet,gigabit<\/text>\n\n          <rect x=\"190\" y=\"328\" width=\"320\" height=\"58\" rx=\"8\" fill=\"none\" stroke=\"currentColor\"\nstroke-width=\"1.4\"\/>\n          <text x=\"350\" y=\"352\" text-anchor=\"middle\" font-size=\"15\" font-weight=\"600\"\nfill=\"currentColor\">Ubuntu server<\/\n          <text x=\"350\" y=\"371\" text-anchor=\"middle\" font-size=\"11.5\" fill=\"currentColor\"\nopacity=\"0.6\">static &#183; 192.168\n\n          <line x1=\"350\" y1=\"386\" xentColor\" stroke-width=\"1.4\"marker-end=\"url(#rbArrow)\"\/>\n          <text x=\"362\" y=\"412\" fonr\" opacity=\"0.75\">listens on 80 \/443<\/text>\n\n          <rect x=\"190\" y=\"432\" width=\"320\" height=\"58\" rx=\"8\" fill=\"none\" stroke=\"currentColor\"\nstroke-width=\"1.4\"\/>\n          <text x=\"350\" y=\"456\" text-anchor=\"middle\" font-size=\"15\" font-weight=\"600\"\nfill=\"currentColor\">npm reverse pro\n          <text x=\"350\" y=\"475\" text-anchor=\"middle\" font-size=\"11.5\" fill=\"currentColor\"\nopacity=\"0.6\">routes by hostname (S\n\n          <line x1=\"350\" y1=\"490\" xentColor\" stroke-width=\"1.4\"\/>\n          <line x1=\"140\" y1=\"520\" x2=\"560\" y2=\"520\" stroke=\"currentColor\" stroke-width=\"1.4\"\/>\n          <line x1=\"140\" y1=\"520\" xentColor\" stroke-width=\"1.4\"marker-end=\"url(#rbArrow)\"\/>\n          <line x1=\"560\" y1=\"520\" xentColor\" stroke-width=\"1.4\"marker-end=\"url(#rbArrow)\"\/>\n\n          <rect x=\"20\" y=\"554\" width=\"240\" height=\"58\" rx=\"8\" fill=\"none\" stroke=\"currentColor\"\nstroke-width=\"1.4\"\/>\n          <text x=\"140\" y=\"580\" text-anchor=\"middle\" font-size=\"14.5\" font-weight=\"600\"\nfill=\"currentColor\">Nextcloud<\/text\n          <text x=\"140\" y=\"598\" text-anchor=\"middle\" font-size=\"11\" fill=\"currentColor\"\nopacity=\"0.6\">ahaddad.duckdns.org<\/\n\n          <rect x=\"440\" y=\"554\" widill=\"none\" stroke=\"currentColor\"stroke-width=\"1.4\"\/>\n          <text x=\"560\" y=\"580\" tex14.5\" font-weight=\"600\"fill=\"currentColor\">WordPress sites<\/text>\n          <text x=\"560\" y=\"598\" tex11\" fill=\"currentColor\"opacity=\"0.6\">ahaddad-wp.duckdns.org<\/text>\n\n          <rect x=\"520\" y=\"150\" width=\"150\" height=\"56\" rx=\"8\" fill=\"none\" stroke=\"var(--accent-2)\"\nstroke-width=\"1.6\" stroke-dasharray\n          <text x=\"595\" y=\"173\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"600\"\nfill=\"var(--accent-2)\">DuckDNS<\/tex\n          <text x=\"595\" y=\"191\" text-anchor=\"middle\" font-size=\"10.5\" fill=\"var(--accent-2)\"\nopacity=\"0.85\">dynamic DNS record<\/\n\n          <path d=\"M 510 357 H 640 ke=\"var(--accent-2)\"stroke-width=\"1.4\" stroke-dasharray=\"4 3\" marker-end=\"url(#rbArrow)\" color=\"var(--accent-2)\"\/>\n          <text x=\"646\" y=\"270\" fonent-2)\" text-anchor=\"middle\"transform=\"rotate(-90 646 270)\">cron &#183; duck.sh &#183; every 5 min<\/text>\n\n          <path d=\"M 595 148 V 96 H 512\" fill=\"none\" stroke=\"var(--accent-2)\" stroke-width=\"1.4\"\nstroke-dasharray=\"4 3\" marker-end=\"ccent-2)\"\/>\n          <text x=\"600\" y=\"118\" font-size=\"10.5\" fill=\"var(--accent-2)\">resolves hostname &#8594;\ncurrent IP<\/text>\n\n        <\/g>\n      <\/svg>\n    <\/div>\n    <figcaption>Solid line: the path a request actually takes. Dashed line: the separate control\nloop that keeps the hostname pointethis now runs on its own via cron,every 5 minutes.<\/b><\/figcaption>\n  <\/figure>\n\n  <section class=\"asks\">\n    <h2>Before the technician leaves<\/h2>\n    <div class=\"ask-item\">\n      <div class=\"ask-num\">1<\/div>\n      <div>\n        <p><b>Ask them to keep the LAN on <span class=\"mono\">192.168.100.0\/24<\/span>, gateway <span\nclass=\"mono\">192.168.100.1<\/span>.<\n        <p class=\"why\">Every static address in the house &mdash; the server, the switch&#8217;s own admin\nIP &mdash; assumes exactly this ranto <spanclass=\"mono\">192.168.1.0\/24<\/span> out of the box; if the new one does, it breaks the whole LAN at\nonce, not just the sites.<\/p>\n      <\/div>\n    <\/div>\n    <div class=\"ask-item\">\n      <div class=\"ask-num\">2<\/div>\n      <div>\n        <p><b>Plug the new router i>port 9 or 10<\/span> &mdash; never1&ndash;8.<\/b><\/p>\n        <p class=\"why\">Ports 1&#038;ndasware-limited to 100Mb, permanently,no setting fixes it. Landing the router there silently caps your whole connection again, exactly\nlike before.<\/p>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <div class=\"sequence\">\n    <h2>Recovery sequence, in order\n\n    <div class=\"step\">\n      <div class=\"step-num\">1<\/div>\n      <div class=\"step-body\">\n        <h3>Confirm the server still has a network<\/h3>\n        <p class=\"why\">Checks the pfails, nothing below it can work&mdash; and the fix is the LAN\/router setup, not DNS or Docker.<\/p>\n        <div class=\"action-label\">R\n        <pre class=\"cmd\"><code>ip -br addr show usb-eth-hub\nping -c 3 192.168.100.1     <span c>\nping -c 3 8.8.8.8           <span class=\"rem\"># the internet<\/span><\/code><\/pre>\n        <div class=\"expect\">&#038;#10003ucceed. If the router ping fails,the LAN subnet likely doesn&#8217;t match &mdash; revisit ask&nbsp;1.<\/div>\n      <\/div>\n    <\/div>\n\n    <div class=\"step\">\n      <div class=\"step-num\">2<\/div>\n      <div class=\"step-body\">\n        <h3>Re-create port forwardi\n        <p class=\"why\">The old router&#8217;s forwarding rules live <b>inside that specific device<\/b>. A\nfull replacement means a blank routash; DNS can be perfect and theserver perfectly healthy, and the outside world still can&#8217;t get in without this.<\/p>\n        <div class=\"action-label\">Aouter&#8217;s admin page<\/div>\n        <pre class=\"cmd\"><code>External 80\/tcp  &#8594;  192.168.100.13:80\nExternal 443\/tcp &#8594;  192.168.1\n      <\/div>\n    <\/div>\n\n    <div class=\"step\">\n      <div class=\"step-num\">3<\/div>\n      <div class=\"step-body\">\n        <h3>Let the DNS auto-update happen &mdash; or trigger it yourself<\/h3>\n        <p class=\"why\">Both domains public IP before anyone, includingyou, can reach the sites by name. A cron job runs <span class=\"mono\">duck.sh<\/span> every 5 minutes\nand self-corrects.<\/p>\n        <div class=\"action-label\">Just wait up to 5 minutes. To check or force it sooner<\/div>\n        <pre class=\"cmd\"><code>curl    <span class=\"rem\"># today'sactual public IP<\/span>\ngetent hosts ahaddad.duckdns.org   S currently says<\/span>\n~\/duckdns\/duck.sh                    <span class=\"rem\"># force an update right\nnow<\/span><\/code><\/pre>\n        <div class=\"expect\">&#10003; <b>Expect:<\/b> the two values match. If they still don't after\n5+ minutes, see the reference table\n      <\/div>\n    <\/div>\n\n    <div class=\"step\">\n      <div class=\"step-num\">4<\/div>\n      <div class=\"step-body\">\n        <h3>Verify the sites are actually reachable<\/h3>\n        <p class=\"why\">Each test be; DNS, port-forward, or the appitself &mdash; so a failure tells you exactly where to look.<\/p>\n        <div class=\"action-label\">Lely<\/div>\n        <pre class=\"cmd\"><code>curl -sk -o \/dev\/null -w \"HTTP %{http_code}\\n\" \\\n  --resolve ahaddad.duckdns.org:443\n  https:\/\/ahaddad.duckdns.org\/<\/code><\/pre>\n        <div class=\"expect\">&#10003\"mono\">HTTP 302<\/span><\/div>\n        <div class=\"action-label\">External test<\/div>\n        <p style=\"margin:0\">Open <sdad.duckdns.org\/<\/span> and <spanclass=\"mono\">https:\/\/ahaddad-wp.duckdns.org\/<\/span> in a browser, ideally on a phone off Wi-Fi (real\noutside path).<\/p>\n        <div class=\"action-label\">If anything looks wrong, check container health<\/div>\n        <pre class=\"cmd\"><code>dockames}}\\t{{.Status}}\"<\/code><\/pre>\n        <div class=\"expect\">&#10003; <b>Expect:<\/b> every row reads <span class=\"mono\">Up<\/span> \/\n<span class=\"mono\">(healthy)<\/span>\n      <\/div>\n    <\/div>\n\n    <div class=\"step\">\n      <div class=\"step-num\">5<\/div>\n      <div class=\"step-body\">\n        <h3>Nextcloud's trusted-domains list &mdash; no action needed<\/h3>\n        <p class=\"why\">Nextcloud one<\/b> it's accessed by, <spanclass=\"mono\">ahaddad.duckdns.org<\/span>, never the IP behind it. That hostname doesn't change, only\nwhat it resolves to. This step is hi> to go looking for something tofix inside Nextcloud.<\/p>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <div class=\"ref-wrap\">\n    <h2>If something's still broken<\/h2>\n    <div class=\"table-scroll\">\n      <table class=\"ref\">\n        <thead>\n          <tr><th>Symptom<\/th><th>Layer<\/th><th>Check<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr>\n            <td>Can't ping 192.168.100.1 at all<\/td>\n            <td>LAN \/ router config\n            <td>New router likely defaulted to a different subnet &mdash; revisit ask&nbsp;1<\/td>\n          <\/tr>\n          <tr>\n            <td>Local test passes,\n            <td>Port forwarding<\/td>\n            <td>Re-check the two NAep&nbsp;2)<\/td>\n          <\/tr>\n          <tr>\n            <td>DNS still shows the old IP after 5+ min<\/td>\n            <td>DNS \/ cron<\/td>\n            <td><span class=\"mono\">~\/duckdns\/duck.sh<\/span>, then <span class=\"mono\">crontab\n-l<\/span> and <span class=\"mono\">catd>\n          <\/tr>\n          <tr>\n            <td>Resolves and connects, but shows 502<\/td>\n            <td>Docker containers<\/\n            <td><span class=\"mono\">docker ps -a<\/span> &mdash; restart whichever isn't healthy<\/td>\n          <\/tr>\n          <tr>\n            <td>Everything works bu>\n            <td>Switch port<\/td>\n            <td>Confirm router and t 9 or 10, not 1&ndash;8<\/td>\n          <\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n  <\/div>\n\n  <footer>ubuntu-server &middot; home network runbook &middot; written 2026-08-21<\/footer>\n\n<\/main>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>When the Home IP Changes The recovery sequence for Nextcloud and the WordPress sites whenever the ISP-issued public IP changes \u2014 written for tomorrow&#8217;s router replacement, but good for any future IP change too. Covers:&nbsp;ahaddad.duckdns.org&nbsp;&amp;&nbsp;ahaddad-wp.duckdns.orgServer:&nbsp;192.168.100.13Last verified:&nbsp;2026-08-21 ubuntu-serv> When the Home IP Changes The recovery seqordPress sites whenever theISP-issued public IP changes \u2014 written for the [&hellip;]<\/p>\n","protected":false},"featured_media":677,"template":"","project_category":[123,152],"class_list":["post-676","doc_article","type-doc_article","status-publish","has-post-thumbnail","hentry","project_category-docs","project_category-guides"],"_links":{"self":[{"href":"https:\/\/ahaddad-wp.duckdns.org\/my\/mylogbook\/wp-json\/wp\/v2\/doc_article\/676","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ahaddad-wp.duckdns.org\/my\/mylogbook\/wp-json\/wp\/v2\/doc_article"}],"about":[{"href":"https:\/\/ahaddad-wp.duckdns.org\/my\/mylogbook\/wp-json\/wp\/v2\/types\/doc_article"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ahaddad-wp.duckdns.org\/my\/mylogbook\/wp-json\/wp\/v2\/media\/677"}],"wp:attachment":[{"href":"https:\/\/ahaddad-wp.duckdns.org\/my\/mylogbook\/wp-json\/wp\/v2\/media?parent=676"}],"wp:term":[{"taxonomy":"project_category","embeddable":true,"href":"https:\/\/ahaddad-wp.duckdns.org\/my\/mylogbook\/wp-json\/wp\/v2\/project_category?post=676"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}