<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>GzDyi&apos;s Blog</title><description>Code, Life, and Everything in Between</description><link>https://blog.zinzin.cc/</link><templateTheme>Firefly</templateTheme><templateThemeVersion>6.14.5</templateThemeVersion><templateThemeUrl>https://github.com/CuteLeaf/Firefly</templateThemeUrl><lastBuildDate>August 30, 2026 at 12:41:34 PM</lastBuildDate><item><title>Tianyi TEWA-7500V ONT: Super Password &amp; IPv6 Firewall</title><link>https://blog.zinzin.cc/posts/hsan-hgs-ont-super-password-ipv6-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/hsan-hgs-ont-super-password-ipv6-en/</guid><description>China Mobile Tianyi TEWA-7500V (HiSilicon hsan + HGS new firmware): challenge-response login, hidden TELNET page, setObjs for telnet, read lastgood.xml for super password, hbus API to loosen IPv6 ingress — full reproducible guide.</description><pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;p&gt;Tested &amp;amp; verified on 2026-08-30. For personal home-network tuning only. Do not use for illegal purposes; obtaining root-level access carries risks — evaluate on your own (ISP may throttle or suspend your line, you’ve been warned).&lt;/p&gt;&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;section&gt;&lt;h1&gt;Part 1: Reproducible Walkthrough&lt;a href=&quot;#part-1-reproducible-walkthrough&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;0. Confirm You Have the Same Firmware&lt;a href=&quot;#0-confirm-you-have-the-same-firmware&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;This guide targets &lt;strong&gt;China Mobile ONTs running the HiSilicon hsan platform + HGS new Web firmware&lt;/strong&gt;. Quick verification:&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Check&lt;/th&gt;&lt;th&gt;Command / Method&lt;/th&gt;&lt;th&gt;Typical Result&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Web homepage size&lt;/td&gt;&lt;td&gt;`curl -s &lt;a href=&quot;http://192.168.1.1/&quot; target=&quot;_blank&quot;&gt;http://192.168.1.1/&lt;/a&gt;&lt;/td&gt;&lt;td&gt;wc -c`&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Config dict exists&lt;/td&gt;&lt;td&gt;`curl -s &lt;a href=&quot;http://192.168.1.1/json/config.json&quot; target=&quot;_blank&quot;&gt;http://192.168.1.1/json/config.json&lt;/a&gt;&lt;/td&gt;&lt;td&gt;wc -c`&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Old firmware backdoors&lt;/td&gt;&lt;td&gt;&lt;code&gt;getpage.gch&lt;/code&gt; / &lt;code&gt;cgi-bin/telnetenable.cgi&lt;/code&gt;&lt;/td&gt;&lt;td&gt;All 404 (old guides on the web do NOT apply)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;telnet banner&lt;/td&gt;&lt;td&gt;&lt;code&gt;telnet 192.168.1.1&lt;/code&gt; after enabling&lt;/td&gt;&lt;td&gt;&lt;code&gt;hsan login:&lt;/code&gt; (HiSilicon banner, &lt;strong&gt;no&lt;/strong&gt; &lt;code&gt;load_cli factory&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Applicable devices: &lt;strong&gt;Tianyi TEWA-7500V&lt;/strong&gt; (10G XG-PON ONT, HiSilicon hsan platform). Other TEWA-700 / 7500 series HiSilicon ONTs from China Mobile can likely follow the same path (Broadcom variants use &lt;code&gt;load_cli factory&lt;/code&gt; — not covered here).&lt;/p&gt;&lt;p&gt;Prerequisites:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Normal user credentials&lt;/strong&gt; printed on the ONT label (usually &lt;code&gt;user / &amp;lt;8-char alphanumeric&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A Linux box on the same LAN that can reach &lt;code&gt;192.168.1.1&lt;/code&gt;, with Python 3 (use &lt;code&gt;docker exec &amp;lt;container&amp;gt; python3&lt;/code&gt; if no host interpreter)&lt;/li&gt;
&lt;li&gt;The ONT HTTP stack is very brittle (see caveats below) — &lt;strong&gt;every request must be wrapped in retries&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;1. Normal-User Login (Challenge-Response)&lt;a href=&quot;#1-normal-user-login-challenge-response&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Login uses challenge-response: fetch a challenge first, then reply with &lt;code&gt;md5(challenge:password)&lt;/code&gt;. &lt;strong&gt;No cookies required&lt;/strong&gt; — the server tracks sessions by source IP.&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; urllib.request, urllib.parse, hashlib, json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;BASE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;http://192.168.1.1&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;USER&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;user&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;PWD&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;the normal-user password on your ONT label&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;op &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; urllib.request.&lt;/span&gt;&lt;span&gt;build_opener&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;op.addheaders &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;User-Agent&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;Mozilla/5.0&quot;&lt;/span&gt;&lt;span&gt;), (&lt;/span&gt;&lt;span&gt;&quot;Referer&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;BASE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;/&quot;&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;d &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; json.&lt;/span&gt;&lt;span&gt;loads&lt;/span&gt;&lt;span&gt;(op.&lt;/span&gt;&lt;span&gt;open&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;BASE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;/getChallengeStr&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;timeout&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;read&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;decode&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# returns: {&quot;challenge&quot;: &quot;...&quot;, &quot;session&quot;: &quot;...&quot;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;resp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; hashlib.&lt;/span&gt;&lt;span&gt;md5&lt;/span&gt;&lt;span&gt;((d[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;challenge&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;:&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PWD&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;encode&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span&gt;hexdigest&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;url &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;BASE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;/lgDevice?userName=&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; urllib.parse.&lt;/span&gt;&lt;span&gt;quote&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;USER&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&amp;amp;responseChallenge=&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; resp&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&amp;amp;session=&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; urllib.parse.&lt;/span&gt;&lt;span&gt;quote&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;span&gt;&lt;span&gt;(d.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;session&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt;))))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;r &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; json.&lt;/span&gt;&lt;span&gt;loads&lt;/span&gt;&lt;span&gt;(op.&lt;/span&gt;&lt;span&gt;open&lt;/span&gt;&lt;span&gt;(url, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;timeout&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;read&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;decode&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# r[&quot;errorCode&quot;] == 0 means login OK&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Gotcha: the response is &lt;strong&gt;tab-indented pretty JSON&lt;/strong&gt; (&lt;code&gt;&quot;errorCode&quot;:\t0&lt;/code&gt;). Never string-match &lt;code&gt;&apos;errorCode&quot;: 0&apos;&lt;/code&gt; — always use &lt;code&gt;json.loads&lt;/code&gt;.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;2. Find the Hidden TELNET Page&lt;a href=&quot;#2-find-the-hidden-telnet-page&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The TELNET toggle is actually present in the main page HTML, just hidden by a CSS class:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-s&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;http://192.168.1.1/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;index.html&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;grep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;FEATURE_TELNET[^&amp;gt;]*&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;index.html&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;grep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;hgs_key=&quot;Telnet[A-Za-z]*&quot;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;index.html&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# You&apos;ll see: TelnetEnable / TelnetWANEnable / TelnetUserName / TelnetPassword&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Pull the config dictionary to confirm the object name and R/W paths:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-s&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;http://192.168.1.1/json/config.json&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;config.json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;grep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-A&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;HGS_TELNET_CFG&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;config.json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Key info (&lt;code&gt;/json/config.json&lt;/code&gt; + &lt;code&gt;/json/tableCfg.json&lt;/code&gt; are the authoritative dictionaries for every object / path):&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Object: &lt;code&gt;HGS_TELNET_CFG&lt;/code&gt;, lives under &lt;code&gt;InternetGatewayDevice.DeviceInfo.X_CMCC_ServiceManage.&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;customerCheckout&lt;/code&gt; msgType=220 (&lt;code&gt;POST /getObjs&lt;/code&gt;), &lt;code&gt;customerCheckin&lt;/code&gt; msgType=221 (&lt;code&gt;POST /setObjs&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;3. Call the API to Enable Telnet&lt;a href=&quot;#3-call-the-api-to-enable-telnet&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Read the current state first (endpoint on &lt;strong&gt;port 80&lt;/strong&gt;, not 8080):&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;full &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;InternetGatewayDevice.DeviceInfo.X_CMCC_ServiceManage.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;body &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [{&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;fullPath&quot;&lt;/span&gt;&lt;span&gt;: full}]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;POST&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;http://192.168.1.1/getObjs?waitTimeoutMs=5000&quot;&lt;/span&gt;&lt;span&gt;, body)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Typical factory response:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[{&lt;/span&gt;&lt;span&gt;&quot;fullPath&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;InternetGatewayDevice.DeviceInfo.X_CMCC_ServiceManage.&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;TelnetEnable&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;0&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;TelnetWANEnable&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;TelnetUserName&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;CMCCAdmin&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;TelnetPassword&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;aDm8H%MdA&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;TelnetPort&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;23&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;SSHEnable&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;0&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;}]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Write to enable telnet (&lt;strong&gt;all values are strings&lt;/strong&gt;; set your own credentials):&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;body &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [{&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;fullPath&quot;&lt;/span&gt;&lt;span&gt;: full,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;&quot;TelnetEnable&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;1&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;&quot;TelnetWANEnable&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;0&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;&quot;TelnetUserName&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;your-telnet-username&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;&quot;TelnetPassword&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;your-strong-password&quot;&lt;/span&gt;&lt;span&gt;}]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;POST&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;http://192.168.1.1/setObjs?waitTimeoutMs=5000&quot;&lt;/span&gt;&lt;span&gt;, body)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Returns [0] on success, telnetd starts immediately&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;p&gt;The generic &lt;code&gt;cgi-bin/telnetenable.cgi?telnetenable=1&amp;amp;key=MAC&lt;/code&gt; trick returns 404 on new firmware. The &lt;code&gt;Fh@+last6ofMAC&lt;/code&gt; default telnet password belongs to older / other firmwares. Set your own on the new HGS builds.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Verify with &lt;code&gt;nc -zv 192.168.1.1 23&lt;/code&gt;, then &lt;code&gt;telnet&lt;/code&gt; in.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;4. Telnet In &amp;amp; Read the Super Password from Config&lt;a href=&quot;#4-telnet-in--read-the-super-password-from-config&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;telnet&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;192.168.1.1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# login: &amp;lt;your-telnet-username&amp;gt;   Password: &amp;lt;your-telnet-password&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;You land in HiSilicon hsan busybox ash (prompt &lt;code&gt;/ $&lt;/code&gt;). There is &lt;strong&gt;no&lt;/strong&gt; &lt;code&gt;load_cli factory&lt;/code&gt;, &lt;code&gt;cfg_cmd&lt;/code&gt;, &lt;code&gt;qoecmd&lt;/code&gt;, or &lt;code&gt;cli&lt;/code&gt;, and &lt;code&gt;su&lt;/code&gt;’s password can’t be computed with Broadcom-style algorithms. Don’t waste time — just read the raw config file:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cat&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/config/work/lastgood.xml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;This is the &lt;strong&gt;plaintext running config XML&lt;/strong&gt; (~166KB). Note that busybox grep doesn’t support &lt;code&gt;\{0,400\}&lt;/code&gt; range regexes. The most reliable approach is to cat the whole file into your terminal log, copy it back locally, then grep:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;grep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;SYSMNG_ACCOUNT_ATTR_TAB&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-A&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lastgood.log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;You’ll hit the account table:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Dir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;SYSMNG_ACCOUNT_ATTR_TAB&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;ucTeleAccountEnable&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;aucTeleAccountName&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;CMCCAdmin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;aucTeleAccountPassword&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;SUPER_PASSWORD_HERE&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;   ← super-admin password&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;aucUserAccountName&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;user&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;aucUserAccountPassword&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;matches_your_ONT_label&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;   ← sanity check&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;Dir&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;p&gt;The super password is very often randomized by TR069 (if the defaults like &lt;code&gt;aDm8H%MdA&lt;/code&gt; don’t work, that’s exactly what happened). Always read the file for the real value; never guess.&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;5. Log Into the Web Backend as Super Admin&lt;a href=&quot;#5-log-into-the-web-backend-as-super-admin&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Use the same challenge-response login from step 1, but swap &lt;code&gt;userName&lt;/code&gt; to &lt;code&gt;CMCCAdmin&lt;/code&gt; and the password to the one you just extracted. Then open &lt;code&gt;http://192.168.1.1&lt;/code&gt; in your browser — all hidden menus (Security, Telnet, WAN, etc.) are now visible.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;6. Read &amp;amp; Modify Security Config (Loosen IPv6 Ingress)&lt;a href=&quot;#6-read--modify-security-config-loosen-ipv6-ingress&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Security config lives at the &lt;code&gt;hbus://mdm/InternetGatewayDevice.X_CMCC_Security.&lt;/code&gt; node via the hbus protocol (&lt;strong&gt;append the path as-is to the URL, do NOT urlencode it&lt;/strong&gt;):&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;HBUS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;hbus://mdm/InternetGatewayDevice.X_CMCC_Security.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Read (msgType=211)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;GET&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;http://192.168.1.1/getHbusData?path=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;HBUS&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&amp;amp;msgType=211&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Write (msgType=212, method=set, body carries path+para)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;body &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;path&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;HBUS&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;para&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;span&gt;&quot;FirewallLevel&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;0&quot;&lt;/span&gt;&lt;span&gt;}}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;POST&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;http://192.168.1.1/setHbusData?path=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;HBUS&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&amp;amp;method=set&amp;amp;msgType=212&quot;&lt;/span&gt;&lt;span&gt;, body)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;All fields and reference values:&lt;/p&gt;




















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Field&lt;/th&gt;&lt;th&gt;Meaning&lt;/th&gt;&lt;th&gt;Factory Value&lt;/th&gt;&lt;th&gt;Recommendation&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;FirewallEnable&lt;/td&gt;&lt;td&gt;Global firewall toggle&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1 (keep it on)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;FirewallLevel&lt;/td&gt;&lt;td&gt;Level: 0=Low / 1=Medium / 2=High&lt;/td&gt;&lt;td&gt;1 (Medium)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;0 (Low)&lt;/strong&gt; (loosens IPv4 ingress filter)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;DoSEnable&lt;/td&gt;&lt;td&gt;DoS protection&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1 (keep it on)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;PortScanEnable&lt;/td&gt;&lt;td&gt;Port-scan protection&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;IPv6SessionSecurityEnable&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;IPv6 session security (v6 ingress filter)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0 (already off; leave alone)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;IPFilterIn/OutEnable, UrlFilter, MacFilter&lt;/td&gt;&lt;td&gt;Various filters&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LockNetEnable&lt;/td&gt;&lt;td&gt;ISP line lock&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Read back to confirm &lt;code&gt;FirewallLevel&lt;/code&gt; is &lt;code&gt;&quot;0&quot;&lt;/code&gt;, then test ingress from outside (disconnect from WiFi, use mobile data).&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;Part 2: Caveats &amp;amp; Lessons Learned&lt;a href=&quot;#part-2-caveats--lessons-learned&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;Stability Pitfalls (Scripts Must Handle These)&lt;a href=&quot;#stability-pitfalls-scripts-must-handle-these&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Brittle HTTP stack.&lt;/strong&gt; Large downloads and rapid requests hit &lt;code&gt;ConnectionReset&lt;/code&gt; constantly — even a dozen consecutive failures is normal. Wrap every request in retries (15 attempts × 2s interval worked for me). A single &lt;code&gt;curl -s&lt;/code&gt; is a coin flip.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Response format.&lt;/strong&gt; JSON is tab-indented pretty-print. Use &lt;code&gt;json.loads&lt;/code&gt; to check success, never string matching.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No cookies / tokens.&lt;/strong&gt; Session is bound to source IP. Complete the whole “login → action” chain in one script; never switch your egress IP mid-flight (Docker container, host, and mobile hotspot all have different ones).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Login rate-limiting.&lt;/strong&gt; 3 wrong passwords per minute → 60s lockout (&lt;code&gt;lgErrCnt&lt;/code&gt; counter). &lt;code&gt;/lgDevice?task=logout&lt;/code&gt; counts toward your quota — &lt;strong&gt;never use it&lt;/strong&gt;. Use a 65s wait in retry loops.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stale session lock.&lt;/strong&gt; If another device is already logged into the Web UI, &lt;code&gt;getChallengeStr&lt;/code&gt; returns errorCode 1 (“another device is logged in”). Ask household members to close the ONT admin page before running.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connection contention.&lt;/strong&gt; Telnet and Web sessions generally don’t interfere, but after toggling telnet repeatedly, wait a couple seconds before hitting port 23 again.&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Methodological Pitfalls&lt;a href=&quot;#methodological-pitfalls&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Identify your firmware before copying guides.&lt;/strong&gt; The online classics — &lt;code&gt;telnetenable.cgi&lt;/code&gt;, &lt;code&gt;load_cli factory&lt;/code&gt;, &lt;code&gt;Fh@+last6ofMAC&lt;/code&gt;, Tianyi Broadcom SU-password generators — &lt;strong&gt;all fail&lt;/strong&gt; on HiSilicon hsan + HGS new firmware. The path in this guide (hidden page → setObjs → read lastgood.xml) is the current general-purpose approach.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Busybox tools are castrated.&lt;/strong&gt; Grep has no range regex support; &lt;code&gt;2&amp;gt;/dev/null&lt;/code&gt; redirection can error with &lt;code&gt;can&apos;t create /dev/null: Permission denied&lt;/code&gt; in the restricted shell (the command still runs though). Don’t rely on shell tricks — just cat the file back to your local machine and analyze there.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;/json/config.json&lt;/code&gt; is the master key.&lt;/strong&gt; With it, you know exactly which object, which hbus path, and which msgType to use for every feature. Anything the Web UI can do, you can API-ize.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reading the file beats guessing passwords.&lt;/strong&gt; TR069 randomizing the default super password (&lt;code&gt;aDm8H%MdA&lt;/code&gt; etc.) is the norm. The file always holds the truth.&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Security &amp;amp; Cleanup&lt;a href=&quot;#security--cleanup&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Telnet cuts both ways.&lt;/strong&gt; &lt;code&gt;telnetd -b 192.168.1.1 -p 23&lt;/code&gt; only binds to LAN, but plaintext + weak creds is still a risk. When done, flip &lt;code&gt;TelnetEnable&lt;/code&gt; back to &lt;code&gt;&quot;0&quot;&lt;/code&gt; via setObjs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Don’t expose your Web UI.&lt;/strong&gt; After loosening ingress, downstream DNAT6 rules on your router/host may accidentally forward admin ports too — check with &lt;code&gt;ip6tables -t nat -S&lt;/code&gt;. Keep only the ports you actually need; delete or block the rest.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TR069 / RMS will roll you back.&lt;/strong&gt; The ISP can push configs remotely. If a few days later your firewall level reverts to “Medium” or telnet turns off by itself, that’s RMS overwriting — just re-run your script, it’s normal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost of lowering firewall level.&lt;/strong&gt; Setting to “Low” reduces the ONT’s IPv4 protection (NAT still saves you, mostly). Keep DoS enabled. Audit other exposed services (Alist, PhotoPrism, etc.) after the change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ONT-side loosen ≠ ingress works.&lt;/strong&gt; The Web UI comments say firewall level only controls IPv4, and &lt;code&gt;IPv6SessionSecurityEnable&lt;/code&gt; is already off — so the ONT itself might not be your blocker. If external tests still fail, check in order: your downstream router’s “IPv6 firewall” toggle → upstream ISP ACL (cross-validate by swapping ports).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write down your changes.&lt;/strong&gt; Typical set: FirewallLevel 1→0, TelnetEnable 1, custom telnet credentials. Anything you did via hbus API can be reverted the same way.&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Three Years After Graduation: A Second Look</title><link>https://blog.zinzin.cc/posts/looking-back-three-years-after-graduation-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/looking-back-three-years-after-graduation-en/</guid><description>Revisiting the mindset shifts three years after graduation — on environment, discipline, boundaries, and what truly matters.</description><pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Three Years After Graduation: A Second Look&lt;a href=&quot;#three-years-after-graduation-a-second-look&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;A sudden urge to write — to capture the shifts in my mindset over the three years since graduating.&lt;/p&gt;&lt;p&gt;It seems we always put a filter over our past environments and stages of life. In university, I compared it to vocational school. Fresh out of college, I compared it to campus. After switching companies, I started comparing the new one to the old. The good things about a new environment never quite hit as hard, while the bad parts of the old one get romanticized over time — because those unpleasant things no longer poke at you every day. Meanwhile, the downsides of the present, sharpened by contrast, loom larger than they really are.&lt;/p&gt;&lt;p&gt;So now, looking back at university, I think of myself back then as someone who was remarkably disciplined.&lt;/p&gt;&lt;p&gt;But if I’m being honest, that’s not the whole story.&lt;/p&gt;&lt;p&gt;During those three years in college, my environment was fairly stable — nothing like the constant change I experience now. Where I went each day, where I sat, who I saw, what I did — it all followed a steady rhythm. And when your environment is stable, habits settle in naturally.&lt;/p&gt;&lt;p&gt;For example, I used to bring my laptop to the library every day. The library had limited power outlets, so to secure a spot with one, I gradually found a very concrete reason to wake up early.&lt;/p&gt;&lt;p&gt;It wasn’t that I loved waking up early. It was that I knew if I went later, there’d be no outlet left.&lt;/p&gt;&lt;p&gt;Looking back, that’s pretty interesting.&lt;/p&gt;&lt;p&gt;A lot of so-called discipline isn’t born out of sheer willpower. You need a reason, a stable environment, something that gives you immediate feedback. Back in university, I went to the library every day, got to know the regulars, and eventually even landed a part-time job there because I was always around.&lt;/p&gt;&lt;p&gt;The job was simple — cleaning up before the library closed. Thirteen yuan an hour, but it was easy, took about ten minutes, and let me stay a little longer in the library every day.&lt;/p&gt;&lt;p&gt;On top of that, the campus was locked down during the pandemic, so there wasn’t anywhere else to go anyway. I worked almost every single month.&lt;/p&gt;&lt;p&gt;I even interviewed for a librarian position later on.&lt;/p&gt;&lt;p&gt;But my family’s business was busy at the time, and they thought the pay was too low. They couldn’t understand why I’d spend time on something like that, so they talked me out of it. I never explained the real reason to the teacher who interviewed me. Looking back, I still feel a bit bad about it — the teacher probably thought I’d just flaked after passing the interview.&lt;/p&gt;&lt;p&gt;Now, when I look back, life was really simple back then.&lt;/p&gt;&lt;p&gt;Every day, I went to the library. I had a fixed spot, familiar faces, books to read, online courses to study, and my own things to work on. Around 9&amp;lt;30&amp;gt; PM, I’d finish cleaning the library and go out for a five-kilometer run.&lt;/p&gt;&lt;p&gt;The feeling after those runs was incredible. My body was tired, but my mind felt amazing.&lt;/p&gt;&lt;p&gt;Now, if someone told me to run five kilometers at 9&amp;lt;30&amp;gt; PM, I’d first think about what time I’d finish work, then whether I had anything else to do at home, then probably end up sitting on my bed scrolling through my phone, telling myself I’ll run tomorrow.&lt;/p&gt;&lt;p&gt;Your environment really changes you.&lt;/p&gt;&lt;p&gt;I used to think discipline was mostly about willpower. Now I’m increasingly convinced that environment plays a much bigger role.&lt;/p&gt;&lt;p&gt;There’s a saying: “Heaven’s timing, earthly advantage, human harmony.” I used to understand it superficially, but now I believe “earthly advantage” is exactly that — your environment. When you’re in a good environment, human effort becomes exponentially more effective. The environment itself helps you form habits.&lt;/p&gt;&lt;p&gt;When the environment isn’t right, you need to expend much more “human harmony” just to push against the current.&lt;/p&gt;&lt;p&gt;I didn’t truly understand this until after graduation.&lt;/p&gt;&lt;p&gt;In the first six months after graduating, I tried to maintain the lifestyle I had in university. I thought, if I could run, study, and read every day back then, surely I could do the same while working.&lt;/p&gt;&lt;p&gt;But reality hit hard. Work drained most of my energy, and overtime was not uncommon. By the time I got home, there was hardly any time left that truly belonged to me. So to reclaim some of that time, I started staying up late.&lt;/p&gt;&lt;p&gt;At first, it was just a little later. Slowly, it became later and later.&lt;/p&gt;&lt;p&gt;The most ironic part? I used to think “going to bed early” was the most natural thing in the world. Then I realized I’d lost even that most basic form of discipline.&lt;/p&gt;&lt;p&gt;I even forced myself to keep exercising during those first six months. But then my chest started hurting — a pain that lasted for months before gradually fading. I had no idea what was wrong at the time. Looking back, I think I was experiencing a kind of inner burnout — maybe even a somatic manifestation of emotional and psychological stress.&lt;/p&gt;&lt;p&gt;The old me would have just said I wasn’t trying hard enough.&lt;/p&gt;&lt;p&gt;Now I can’t help but wonder: maybe it wasn’t about persistence. Maybe the environment itself was constantly draining me.&lt;/p&gt;&lt;p&gt;In university, finishing my cleaning at 9&amp;lt;30&amp;gt; PM and going for a five-kilometer run felt amazing.&lt;/p&gt;&lt;p&gt;After graduation, the same routine felt like a chore I had to grit my teeth through.&lt;/p&gt;&lt;p&gt;These two versions of “discipline” looked the same on the surface, but they were completely different states of being.&lt;/p&gt;&lt;p&gt;Now, sitting at a desk all day, I exercise less, my weight has crept up, and my digestion has gotten worse.&lt;/p&gt;&lt;p&gt;But here’s the funny thing: when I go home for a long holiday, eating and drinking without a care, doing nothing productive — theoretically less healthy — I actually lose a bit of weight and my stomach feels better.&lt;/p&gt;&lt;p&gt;This has made me realize that our bodies and minds are more honest than we give them credit for.&lt;/p&gt;&lt;p&gt;They know whether you’re tired or comfortable long before your brain does.&lt;/p&gt;&lt;p&gt;So now, looking back at my university self, I feel a mix of emotions.&lt;/p&gt;&lt;p&gt;I envy that version of me.&lt;/p&gt;&lt;p&gt;He could go to the library every day, immerse himself in books, watch online courses, run, and slowly build good habits.&lt;/p&gt;&lt;p&gt;But I also know that version of me had his own pressures.&lt;/p&gt;&lt;p&gt;I wasn’t exactly carefree when I woke up each morning back then. It’s just that, years later, the daily stress has faded, and what’s left are the beautiful memories.&lt;/p&gt;&lt;p&gt;Maybe that’s why we always put a filter on the past.&lt;/p&gt;&lt;p&gt;I still go to the library occasionally.&lt;/p&gt;&lt;p&gt;But one thing has changed noticeably: I can’t stay focused as long as I used to.&lt;/p&gt;&lt;p&gt;Back then, I could sit for hours — reading slowly, learning at my own pace.&lt;/p&gt;&lt;p&gt;Now, after a short while, my mind starts wandering to my phone, to other things, to work.&lt;/p&gt;&lt;p&gt;It’s in moments like these that I realize how much more those university years left me than I ever knew at the time.&lt;/p&gt;&lt;p&gt;I watched countless courses and read many books back then — etiquette, public speaking, communication, and a lot of professional knowledge.&lt;/p&gt;&lt;p&gt;At the time, I thought I was just “learning.”&lt;/p&gt;&lt;p&gt;But after graduation, I discovered that some of those things have been quietly shaping me ever since.&lt;/p&gt;&lt;p&gt;My professional knowledge, in particular, continues to benefit me to this day.&lt;/p&gt;&lt;p&gt;Sometimes I suddenly notice that the way I handle a situation, communicate with someone, or choose my words — it all traces back to those seemingly useless accumulations from university.&lt;/p&gt;&lt;p&gt;I used to think of them as “techniques.”&lt;/p&gt;&lt;p&gt;How to learn, how to express yourself, how to manage time, how to improve yourself — all techniques.&lt;/p&gt;&lt;p&gt;But now I feel that the things that truly stay with you don’t announce themselves.&lt;/p&gt;&lt;p&gt;The ideas that have genuinely become part of you don’t remind you every day, “I am now practicing this principle.”&lt;/p&gt;&lt;p&gt;They’ve become part of who you are.&lt;/p&gt;&lt;p&gt;What society and the workplace have taught me is different.&lt;/p&gt;&lt;p&gt;If university taught me how to enrich myself, accumulate knowledge, and build foundational habits, then entering society taught me about boundaries.&lt;/p&gt;&lt;p&gt;Back in school, relationships were simple.&lt;/p&gt;&lt;p&gt;You went to class together, ate together, went to the library together — sometimes you spent most of your day in the same circle.&lt;/p&gt;&lt;p&gt;After entering society, I realized that people need boundaries.&lt;/p&gt;&lt;p&gt;What to say, what not to say. What to help with, what not to take on. How to separate work and life. The difference between others’ expectations of you and your own responsibilities.&lt;/p&gt;&lt;p&gt;These aren’t things you can learn directly from a university textbook.&lt;/p&gt;&lt;p&gt;But society will teach you — fast.&lt;/p&gt;&lt;p&gt;It’s just that society’s lessons are rarely as gentle as the library’s.&lt;/p&gt;&lt;p&gt;Three years after graduation, I’ve noticed myself being gradually assimilated by my environment.&lt;/p&gt;&lt;p&gt;Sometimes, reflecting on how I handle things, I even catch traces of behaviors I used to criticize as “bureaucratic” or “phony.”&lt;/p&gt;&lt;p&gt;That’s actually quite interesting.&lt;/p&gt;&lt;p&gt;I used to stand on the sidelines and judge others — “How can this person be like this?”&lt;/p&gt;&lt;p&gt;Then one day, I realized I was starting to act the same way.&lt;/p&gt;&lt;p&gt;That’s just how it is.&lt;/p&gt;&lt;p&gt;You think you’re observing your environment, but your environment is also observing you — slowly, piece by piece, turning you into part of it.&lt;/p&gt;&lt;p&gt;So now I find myself agreeing more and more with the importance of environment.&lt;/p&gt;&lt;p&gt;Of course, you can’t blame everything on your environment.&lt;/p&gt;&lt;p&gt;A bad environment doesn’t mean you have to go with the flow.&lt;/p&gt;&lt;p&gt;But if an environment is slowly making you less like yourself, it’s worth asking: is it really you who’s the problem, or is the environment simply not right for you?&lt;/p&gt;&lt;p&gt;Sometimes we feel we’re not disciplined enough, not hardworking enough, not ambitious enough, and we keep piling on expectations.&lt;/p&gt;&lt;p&gt;But maybe what we really need to do isn’t just push ourselves harder — it’s to change our environment.&lt;/p&gt;&lt;p&gt;Because in a good environment, your efforts multiply. In a bad one, you’re spending all your willpower just fighting the current.&lt;/p&gt;&lt;p&gt;In the end, it comes back to you.&lt;/p&gt;&lt;p&gt;We want too much and do too little.&lt;/p&gt;&lt;p&gt;And more often than not, what we think we want isn’t really what we want.&lt;/p&gt;&lt;p&gt;It’s what society told you to want. What your parents told you. What your relatives and friends expected.&lt;/p&gt;&lt;p&gt;How much money you should make, what position you should reach, how you should live, when you should get married, how excellent you should become.&lt;/p&gt;&lt;p&gt;With all these “shoulds” piling up, it’s easy to forget the simplest question:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;What do I actually want?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Three years after graduation, I haven’t found the answer.&lt;/p&gt;&lt;p&gt;In fact, I feel like I’ve only just started learning to ask the question.&lt;/p&gt;&lt;p&gt;I hope that from now on, in my actions and my dealings with others, I can have fewer “what others think I should do” and more “what I truly want to do.”&lt;/p&gt;&lt;p&gt;The pure “me” might not be someone completely free from environmental influence. Rather, it’s someone who, even after being shaped by the environment, can still tell the difference:&lt;/p&gt;&lt;p&gt;What I truly want.&lt;/p&gt;&lt;p&gt;What others want me to have.&lt;/p&gt;&lt;p&gt;What’s worth holding onto.&lt;/p&gt;&lt;p&gt;What I can let go of.&lt;/p&gt;&lt;p&gt;What those three years in university taught me is still shaping me today.&lt;/p&gt;&lt;p&gt;Three years after graduation, I think what I want to learn is no longer more “techniques.”&lt;/p&gt;&lt;p&gt;It’s to slowly hold onto what truly matters, and find an environment that fits.&lt;/p&gt;&lt;p&gt;And then — become the person I truly want to be.&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>Random Thoughts: Three Years After Graduation</title><link>https://blog.zinzin.cc/posts/three-years-after-graduation-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/three-years-after-graduation-en/</guid><description>Reflections on the mindset shifts three years after graduation — about environment, discipline, and being true to oneself.</description><pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Random Thoughts: Three Years After Graduation&lt;a href=&quot;#random-thoughts-three-years-after-graduation&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;A sudden urge to write — to capture how I feel right now, and how my mindset has shifted over the three years since graduation. It seems we always look at our past environment through a filter. In university, I compared it to vocational school. Fresh out of college, I compared it to campus life. After switching companies, I compared the new one to the old. The good parts of a new environment never quite hit as hard, while the bad parts of the old one get romanticized — because I no longer have to deal with them. And the drawbacks of the present? They loom larger, sharpened by direct contrast.&lt;/p&gt;&lt;p&gt;From being a fresh graduate intern to someone who now mentors interns, I’ve noticed myself gradually being assimilated by my surroundings. Sometimes I catch a certain “bureaucratic” tone in how I handle things, and it forces me to recognize just how much environment shapes a person. The saying “Heaven’s timing, earthly advantage, human harmony” — I’ve come to believe that “earthly advantage” is exactly this: the environment. When the environment is right, human effort becomes exponentially more effective. But when the environment can’t be changed, you need a tenfold dose of “human harmony” just to push against the current.&lt;/p&gt;&lt;p&gt;I often find myself nostalgic for the discipline I had in university — how I admired that version of myself. But I also remember the weight I woke up with every single day back then. The details may blur, but the feeling is etched into my bones. Right after graduation, when my salary was low, I still held onto that discipline. But as work stabilized, as life got comfortable and the pay improved, my discipline crumbled like a dam bursting open. Success, I think, is sometimes just about holding on a little longer than others. I read a lot in college, picked up many good habits and techniques — yet none of them seem to have stuck. Then again, the ideas that truly become part of you, flowing in your blood, you don’t even notice them anymore.&lt;/p&gt;&lt;p&gt;We want too much and do too little. We let ourselves be pushed around by society’s standards, parents’ expectations, the yardsticks of relatives and friends. I hope that from now on — in my actions and my dealings with others — I can be a pure person, standing and speaking from the standard of a genuine “me.”&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>Docker Pull Stuck on Windows: A Proxy Configuration Horror Story</title><link>https://blog.zinzin.cc/posts/docker-pull-proxy-pitfalls-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/docker-pull-proxy-pitfalls-en/</guid><description>TUN mode won&apos;t save your Docker daemon, the real config lives in settings-store.json, and dead mirror registries will eat your afternoon. A first-hand account.</description><pubDate>Sun, 02 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Docker Pull Stuck on Windows: A Proxy Configuration Horror Story&lt;a href=&quot;#docker-pull-stuck-on-windows-a-proxy-configuration-horror-story&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Pulling a single image (&lt;code&gt;snowdreamtech/frpc&lt;/code&gt;) ate my whole afternoon today. &lt;code&gt;docker pull&lt;/code&gt; would either sit at &lt;code&gt;Waiting&lt;/code&gt; and never move, or die with a &lt;code&gt;dial tcp ... timeout&lt;/code&gt;. My first instinct was “bad network, retry,” but after the third attempt with no progress I started to suspect something more interesting was going on.&lt;/p&gt;&lt;section&gt;&lt;h2&gt;Trap 1: TUN mode doesn’t touch Docker Desktop&lt;a href=&quot;#trap-1-tun-mode-doesnt-touch-docker-desktop&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I run sing-box on Windows with TUN mode on, and browsing was perfectly fine, so I assumed my proxy covered everything. Nope. TUN mode intercepts traffic on the host’s network stack, but the Docker daemon runs inside the WSL2 VM — and the VM’s outbound traffic never goes through the host’s TUN interface. A working browser proves nothing about Docker. The daemon needs its own proxy configuration.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Trap 2: The real config file is settings-store.json&lt;a href=&quot;#trap-2-the-real-config-file-is-settings-storejson&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The old tutorials all tell you to edit &lt;code&gt;settings.json&lt;/code&gt;, but modern Docker Desktop reads &lt;code&gt;%APPDATA%\Docker\settings-store.json&lt;/code&gt;. I had to add three keys:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&quot;ProxyHTTPMode&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;manual&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&quot;OverrideProxyHTTP&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;http://127.0.0.1:49456&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&quot;OverrideProxyHTTPS&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;http://127.0.0.1:49456&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;One thing that caught me: restarting containers isn’t enough. You need &lt;code&gt;docker desktop restart&lt;/code&gt; for the new settings to actually apply. Also, Docker Desktop has two proxy layers — an app proxy and a containers proxy — and &lt;code&gt;docker pull&lt;/code&gt; goes through the containers one. Configure the wrong layer and nothing happens.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Trap 3: Which port is an actual proxy?&lt;a href=&quot;#trap-3-which-port-is-an-actual-proxy&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Before configuring anything you need to know which local port is a real proxy. sing-box and v2rayN listen on a bunch of ports, and not all of them are meant for proxying. I first tried port 10814, and still got 405s everywhere.&lt;/p&gt;&lt;p&gt;The test is dead simple: open a raw TCP connection and send a &lt;code&gt;CONNECT&lt;/code&gt; request:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;printf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;CONNECT www.google.com:443 HTTP/1.1\r\nHost: www.google.com:443\r\n\r\n&apos;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;nc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;127.0.0.1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;49456&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;A real proxy answers &lt;code&gt;200 Connection established&lt;/code&gt; — in my case that was xray’s port 49456. Port 10814 turned out to be a local HTTP service that replies to CONNECT with &lt;code&gt;405 Method Not Allowed&lt;/code&gt; and an &lt;code&gt;Allow: GET&lt;/code&gt; header. It was never a proxy. Don’t assume a listening port is a proxy port.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Trap 4: Dead mirror registries are still in daemon.json&lt;a href=&quot;#trap-4-dead-mirror-registries-are-still-in-daemonjson&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;With the proxy working it was still slow, which made me look at &lt;code&gt;~/.docker/daemon.json&lt;/code&gt; and its &lt;code&gt;registry-mirrors&lt;/code&gt; entry. Two of my three mirrors (USTC and 163) had quietly died — connections time out — and &lt;code&gt;docker pull&lt;/code&gt; was hanging on those timeouts. One of the survivors (daocloud) even answers requests carrying a &lt;code&gt;?ns=docker.io&lt;/code&gt; parameter with &lt;code&gt;405 Method Not Allowed&lt;/code&gt;. In the end I deleted &lt;code&gt;registry-mirrors&lt;/code&gt; entirely and went straight to Docker Hub through the proxy. Fastest and most reliable.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Bonus trap: host.docker.internal resolved to IPv6&lt;a href=&quot;#bonus-trap-hostdockerinternal-resolved-to-ipv6&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Finally got the image, only to see frpc containers fail to reach the backend, with frps logging 503s. The culprit: inside the container &lt;code&gt;host.docker.internal&lt;/code&gt; resolved to an IPv6 address in the &lt;code&gt;fdc4:...&lt;/code&gt; range, and IPv6 routing in the container network simply doesn’t work — the packets went nowhere. Switching to the host’s actual IPv4 address, or the Docker Desktop VM gateway (&lt;code&gt;192.168.65.254&lt;/code&gt;), fixed it instantly.&lt;/p&gt;&lt;p&gt;If I had to boil this afternoon down to two lessons: TUN mode can’t see inside the WSL2 VM, so configure a proxy for Docker itself; and when you’re unsure whether a port is a proxy, send it a CONNECT and read the response.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Running frpc in Docker on Windows: Every Pitfall I Hit</title><link>https://blog.zinzin.cc/posts/frpc-docker-tunnel-pitfalls-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/frpc-docker-tunnel-pitfalls-en/</guid><description>A sequel to the image-pull story: the frp tunnel itself — where proxies are actually defined, a hardcoded config path, host.docker.internal resolving to IPv6, Docker Desktop&apos;s proxy hijacking port 80, and a cloud firewall that nearly ended me.</description><pubDate>Sun, 02 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Running frpc in Docker on Windows: Every Pitfall I Hit&lt;a href=&quot;#running-frpc-in-docker-on-windows-every-pitfall-i-hit&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;In my last post I documented the ordeal of pulling images with Docker Desktop on Windows. This one is a direct sequel: once the images finally came down, I had to actually get frp working — and the tunnel itself turned out to be its own little minefield.&lt;/p&gt;&lt;p&gt;The setup: a local Windows machine running a RuoYi admin system (Vue dev server on port 80) that I wanted to expose to the public internet via frp. The frps server ran in a Docker container on a Tencent Cloud VPS, and frpc ran locally in another Docker container. Sounds straightforward. It cost me most of an afternoon.&lt;/p&gt;&lt;section&gt;&lt;h2&gt;Pitfall 1: Proxies are defined on the frpc side, not the frps side&lt;a href=&quot;#pitfall-1-proxies-are-defined-on-the-frpc-side-not-the-frps-side&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Like most people (including me at first), I assumed that opening a new tunnel meant editing the frps config and restarting its container. Wrong. In frp’s architecture, &lt;strong&gt;all proxies are defined on the frpc client&lt;/strong&gt;. frps just receives and forwards traffic, and by default it accepts any port unless you’ve configured an &lt;code&gt;allowPorts&lt;/code&gt; whitelist. Adding a new tunnel is now just a config edit plus a reload on the client; the server stays untouched.&lt;/p&gt;&lt;p&gt;It’s genuinely counterintuitive — the server looks like the side that should control ports, but the client holds all the power.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Pitfall 2: The frpc config path is hardcoded&lt;a href=&quot;#pitfall-2-the-frpc-config-path-is-hardcoded&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The snowdreamtech/frpc image hardcodes its startup script to read &lt;code&gt;/etc/frp/frpc.toml&lt;/code&gt;. My first attempt mounted my config somewhere arbitrary, and the container immediately complained it couldn’t find the file. You have to mount to that exact path:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;frpc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unless-stopped&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;C:&lt;/span&gt;&lt;span&gt;\f&lt;/span&gt;&lt;span&gt;rp&lt;/span&gt;&lt;span&gt;\f&lt;/span&gt;&lt;span&gt;rpc.toml:/etc/frp/frpc.toml&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;snowdreamtech/frpc:0.70.1-debian&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Pitfall 3: host.docker.internal resolved to IPv6 inside the container&lt;a href=&quot;#pitfall-3-hostdockerinternal-resolved-to-ipv6-inside-the-container&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I initially set &lt;code&gt;localIP&lt;/code&gt; to &lt;code&gt;host.docker.internal&lt;/code&gt; — the usual way for a container to reach its host. The frps side kept reporting 503/403, backend unreachable.&lt;/p&gt;&lt;p&gt;The culprit was IPv6: inside the container, &lt;code&gt;host.docker.internal&lt;/code&gt; resolved to an address in the &lt;code&gt;fdc4:...&lt;/code&gt; range, and IPv6 routing in the container network simply doesn’t work, so the packets were silently dropped. The fix is to just hardcode an IPv4 address:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;proxies&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;win-ruoyi&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;tcp&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;localIP&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;192.168.65.254&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;localPort&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;remotePort&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;6100&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;192.168.65.254&lt;/code&gt; is the Docker Desktop VM gateway — containers can reach the host through it. Your host’s actual LAN IP works too.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Pitfall 4: Docker Desktop’s HTTP proxy hijacked traffic to the host’s port 80&lt;a href=&quot;#pitfall-4-docker-desktops-http-proxy-hijacked-traffic-to-the-hosts-port-80&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Remember the manual proxy I configured for Docker Desktop in the previous post (to pull images)? It came back to bite me. Containers hitting the host’s port 80 were being intercepted by Docker Desktop’s transparent HTTP proxy — responses came back with a &lt;code&gt;Proxy-Connection&lt;/code&gt; header and a 503/403, the error text even containing Windows-flavored &lt;code&gt;connectex&lt;/code&gt; wording. Port 9000 (non-standard) worked fine.&lt;/p&gt;&lt;p&gt;To detect it: exec into the container, curl the host on port 80, and check the response headers. If you see &lt;code&gt;Proxy-Connection&lt;/code&gt;, the proxy layer is intercepting. The fix is annoyingly simple — once your images are pulled, clear the Docker Desktop proxy config (remove &lt;code&gt;OverrideProxyHTTP&lt;/code&gt; / &lt;code&gt;OverrideProxyHTTPS&lt;/code&gt; / &lt;code&gt;ProxyHTTPMode&lt;/code&gt; from &lt;code&gt;%APPDATA%\Docker\settings-store.json&lt;/code&gt;) and container traffic goes straight to the host again. This one was the sneakiest and took the longest to pin down.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Pitfall 5: The cloud firewall needs its own port opened&lt;a href=&quot;#pitfall-5-the-cloud-firewall-needs-its-own-port-opened&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;At this point the whole chain was working locally: frps logs showed &lt;code&gt;get a user connection&lt;/code&gt;, and curling from the VPS itself returned 200. But from the public internet it was still a timeout. The last culprit was the Tencent Cloud lightweight-server console firewall — port 6100 simply wasn’t allowed in. One inbound rule later, done.&lt;/p&gt;&lt;p&gt;Lesson: the tunnel crosses three firewall layers — OS firewall (ufw/iptables), cloud security group, and frps itself. Any one of them can silently kill your connection, and all three look like “network problems” from the outside.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Wrap-up: debug the tunnel in three segments&lt;a href=&quot;#wrap-up-debug-the-tunnel-in-three-segments&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The biggest takeaway was a debugging method: split the frp tunnel into three segments — &lt;strong&gt;public internet → frps, frps → frpc, frpc → local service&lt;/strong&gt;. Each segment has its own symptoms: timeouts point to network/firewall issues, 403 is frp’s internal error page, 503 means frpc can’t reach the backend. Map the symptom to a segment and you’ll find the problem much faster. Three of my five pitfalls lived in the last segment (frpc → local service) — the easiest one to overlook.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Battling Google Search Console with OpenCode: Taking Over a Real Chrome Browser</title><link>https://blog.zinzin.cc/posts/stealth-chrome-mcp-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/stealth-chrome-mcp-en/</guid><description>Adding a user in Search Console — one click. Let AI automate it, they said. Then Google slapped me with a captcha.</description><pubDate>Wed, 29 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h2&gt;The Backstory&lt;a href=&quot;#the-backstory&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I had just set up two new blogs (one Chinese, one English) and needed to add them to Google Search Console, then invite a service account as a user. One “Add User” dialog. A couple of clicks. Simple enough.&lt;/p&gt;&lt;p&gt;Let OpenCode automate it, I thought.&lt;/p&gt;&lt;p&gt;The built-in &lt;code&gt;browser-control&lt;/code&gt; MCP (backed by &lt;code&gt;playwright-core&lt;/code&gt;) fired up a headless browser, navigated to Search Console, and — captcha. Switched to Puppeteer. Still captcha. Tried Playwright’s stealth plugin. Same thing.&lt;/p&gt;&lt;p&gt;After half an hour of banging my head against automation detection, it dawned on me: &lt;strong&gt;My real Chrome was already logged into Google right there on my desktop. Why was I trying to open a new one?&lt;/strong&gt;&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;The Solution: stealth-chrome MCP&lt;a href=&quot;#the-solution-stealth-chrome-mcp&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The idea is embarrassingly simple once you say it out loud: &lt;strong&gt;don’t spin up a new browser, take over the one that’s already running.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Chrome DevTools Protocol (CDP) exists exactly for this. Your login sessions, cookies, extensions — all of them are already there, no setup needed.&lt;/p&gt;&lt;p&gt;I wrote a ~50-line MCP server using &lt;code&gt;chrome-launcher&lt;/code&gt;, wrapped the CDP connection, and registered it in OpenCode’s MCP config:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;~/.config/opencode/opencode.jsonc&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;mcp&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;stealth-chrome&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;local&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;command&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;node&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;/path/to/stealth-mcp-server.mjs&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;description&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Real Chrome takeover, persistent session&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Then I removed the old &lt;code&gt;browser-control&lt;/code&gt; entry entirely.&lt;/p&gt;&lt;p&gt;First connection: Search Console opened already logged in. Zero captchas. Zero friction. It just worked — like I was clicking around myself.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;War Stories&lt;a href=&quot;#war-stories&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Of course it wasn’t all smooth sailing. Here are five real gotchas I hit.&lt;/p&gt;&lt;section&gt;&lt;h3&gt;1. Click That Wouldn’t Click&lt;a href=&quot;#1-click-that-wouldnt-click&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The “Add User” button in Search Console — clicking it with &lt;code&gt;stealth-chrome_click&lt;/code&gt; navigated to a completely unrelated page every single time. I retried four times before giving up.&lt;/p&gt;&lt;p&gt;Switched to &lt;code&gt;stealth-chrome_evaluate&lt;/code&gt; and called &lt;code&gt;element.click()&lt;/code&gt; from JavaScript. The dialog popped right open.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; SPA event handlers don’t always respond to synthesized CDP clicks. When click fails, &lt;code&gt;evaluate&lt;/code&gt; + native &lt;code&gt;element.click()&lt;/code&gt; is your fallback.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;2. Ref IDs Are Ephemeral&lt;a href=&quot;#2-ref-ids-are-ephemeral&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Every time you snapshot a page, elements get fresh ref IDs (e42, e106, etc.). Navigate away and back? Different refs.&lt;/p&gt;&lt;p&gt;First time I hit this I thought I was losing my mind.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Don’t hardcode refs across page transitions. Use JS selectors for anything that spans multiple interactions.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;3. You Picked the Wrong Dialog&lt;a href=&quot;#3-you-picked-the-wrong-dialog&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Search Console has two &lt;code&gt;[role=&quot;dialog&quot;]&lt;/code&gt; elements on the same page — one for the sidebar nav, one for the actual modal dialog. &lt;code&gt;document.querySelector(&apos;[role=&quot;dialog&quot;]&apos;)&lt;/code&gt; consistently grabbed the sidebar.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Use &lt;code&gt;document.querySelectorAll(...)&lt;/code&gt; and grab the last one.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;4. Input Value Set, SPA Didn’t Care&lt;a href=&quot;#4-input-value-set-spa-didnt-care&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;I set &lt;code&gt;input.value = &apos;service-account@...&apos;&lt;/code&gt; and clicked “Add”. It told me the email was invalid. The value was clearly there in the DOM.&lt;/p&gt;&lt;p&gt;SPA frameworks listen for &lt;code&gt;input&lt;/code&gt; events, not property changes. Setting &lt;code&gt;.value&lt;/code&gt; silently doesn’t fire anything.&lt;/p&gt;&lt;p&gt;The fix:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;blog-seo@xxx.iam.gserviceaccount.com&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;dispatchEvent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Event&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;input&apos;&lt;/span&gt;&lt;span&gt;, { &lt;/span&gt;&lt;span&gt;bubbles&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; }));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;dispatchEvent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Event&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;change&apos;&lt;/span&gt;&lt;span&gt;, { &lt;/span&gt;&lt;span&gt;bubbles&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; }));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;5. Link or Button? Guess.&lt;a href=&quot;#5-link-or-button-guess&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;In Search Console’s settings page, “Users and Permissions” looks like something you click to expand a section. Turns out it’s an honest-to-god &lt;code&gt;&amp;lt;a href=&quot;...&quot;&amp;gt;&lt;/code&gt; link that navigates to a different page entirely.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Inspect &lt;code&gt;a.href&lt;/code&gt; before you click. Not everything in a SPA is SPA-routed.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Tools I Actually Used&lt;a href=&quot;#tools-i-actually-used&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;




























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Tool&lt;/th&gt;&lt;th&gt;What For&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;stealth-chrome_navigate&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Go to Search Console&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;stealth-chrome_snapshot&lt;/code&gt;&lt;/td&gt;&lt;td&gt;See what’s clickable&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;stealth-chrome_click&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Simple buttons&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;stealth-chrome_evaluate&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Workhorse — JS for everything tricky&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;stealth-chrome_screenshot&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Verify state visually&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;When to Use This&lt;a href=&quot;#when-to-use-this&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Any site that needs you to be logged in — Search Console, Cloudflare Dashboard, Gmail, you name it. Stealth-chrome handles it because it &lt;em&gt;is&lt;/em&gt; your browser. Just keep Chrome running.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;TL;DR&lt;a href=&quot;#tldr&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Don’t fight browser automation detection. &lt;strong&gt;Use the browser you’re already logged into.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Set it up once, leave the MCP server running, and never think about headless Chrome again. Just don’t close your browser.&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>2025 Year in Review</title><link>https://blog.zinzin.cc/posts/2025-year-review-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/2025-year-review-en/</guid><description>Reflections on 2025 — covering work, learning, health, books, games, anime, and travel.</description><pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;2025 Year in Review&lt;a href=&quot;#2025-year-in-review&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Memory is like a glass of water, time like an open faucet — the water in the glass grows fainter with each passing day. Before I knew it, it was the end of 2025 again. I’d planned a mid-year review back in 2024, but procrastination got the better of me. Life settled into a comfort zone — work consumed most of my days under fluorescent office lights, blurring the line between day and night. What little free time I had, I wanted to spend outdoors with friends. Today is the fourth day of my sick leave from the flu, and I hope to capture some memorable and meaningful moments before the clarity that illness brings is washed away by the joy of recovery.&lt;/p&gt;&lt;section&gt;&lt;h2&gt;Work&lt;a href=&quot;#work&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Work this year was steady — methodical, rigorous, improving technically, and striving for excellence. Compared to last year, the biggest change has been how AI tools have transformed coding. With major improvements in context awareness, agent capabilities, and automated search, the hottest trend right now is &lt;strong&gt;vibe coding&lt;/strong&gt; — completing coding, debugging, and testing entirely through natural language conversations. This has freed up a lot of mental bandwidth, letting AI handle repetitive, predictable tasks perfectly. On the backend, complex logic still needs careful checking, but on the frontend, simply articulating your ideas clearly can often yield perfect results from AI in one pass.&lt;/p&gt;&lt;p&gt;While AI has dramatically boosted productivity, new tools always bring disruption. AI has leveled the playing field for experience to a large extent, without creating many new job opportunities. As an ordinary person riding this wave, the best approach is probably to embrace change as much as possible and build a financial cushion for the uncertainties ahead.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Learning&lt;a href=&quot;#learning&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;This year’s learning was decent — I passed four exams in my self-study program. Not that I expect these credentials to be particularly useful, but they give me tangible milestones on my lifelong learning journey. Through exam preparation, I systematically revisited modern Chinese history and Marxist principles. While I only scratched the surface, I gained a lot. Marxist philosophy taught me to look at problems from a more abstract, higher-dimensional perspective, and modern Chinese history gave me a fresh understanding of the timeline and the role of key conferences.&lt;/p&gt;&lt;p&gt;I also learned about personal finance and savings, and my savings goals for the year are on track. My investments had ups and downs, but overall I’m in the green — though unrealized gains are just paper profits.&lt;/p&gt;&lt;p&gt;On learning methods: for unfamiliar domains, I now start with videos and beginner-friendly articles, saving books for in-depth reference and gap-filling. I try to apply the principle of negation of negation when encountering differing viewpoints.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Health&lt;a href=&quot;#health&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Exercise this year was a mess — otherwise I wouldn’t have caught colds repeatedly within a month. After getting two impacted wisdom teeth pulled during summer break, I completely gave up on working out. My annual checkup showed various minor abnormalities — partly from poor diet, partly from staying up late. Living alone gives too much freedom, and the combination of constant air conditioning, lack of outdoor activity, and late-night doom-scrolling took its toll.&lt;/p&gt;&lt;p&gt;Improving my fitness will be a core priority for 2026: regular作息, creating a calorie deficit to lose weight, and disciplining my diet and exercise.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Books&lt;a href=&quot;#books&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;Money Money Money (Kira and the Kurrawong Club)&lt;a href=&quot;#money-money-money-kira-and-the-kurrawong-club&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;When you set a big goal, you must put in much more effort than others.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;A children’s book, but an excellent introduction for anyone completely new to personal finance. Following the methods in this book, I completed my savings plan two months ahead of schedule.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;You Are What You Eat 2&lt;a href=&quot;#you-are-what-you-eat-2&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;Don’t be extreme in your diet — eat a diverse mix of everything.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;This book reinforced my belief that matter determines consciousness and consciousness acts on matter. I’ve been gaining weight since starting work, mainly because of prolonged sitting, slow metabolism, and the habit of treating myself after work. Lack of sunlight in the office leads to vitamin D deficiency and a weakened immune system.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;MongoDB: Advanced Practices&lt;a href=&quot;#mongodb-advanced-practices&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;MongoDB’s indexing, storage engine, concurrency (MVCC), locking mechanism, and oplog design share many principles with MySQL.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;You never miss knowledge until you need it. Taking time to fill gaps in my understanding made working with related documentation much smoother.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Zen and the Art of Motorcycle Maintenance&lt;a href=&quot;#zen-and-the-art-of-motorcycle-maintenance&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;When you’re in a hurry to get something done, it means you no longer care about it and want to do something else.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;The book is about a motorcycle road trip and repairs, but the philosophy applies to all technical work. A deeply insightful read.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;A Short History of Chinese Philosophy&lt;a href=&quot;#a-short-history-of-chinese-philosophy&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;One must first speak many words, then remain silent.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I picked this up when I had ideological conflicts with my parents, hoping to understand why they think the way they do. Many of their ideas are deeply ingrained in their upbringing, and this book helped me connect the dots.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Games&lt;a href=&quot;#games&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Aokana: Four Rhythm Across the Blue&lt;/strong&gt;: Top-tier story and music across the board. All four heroines are exceptionally well-written. Appreciating art like this is a genuine pleasure.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Honor of Kings&lt;/strong&gt;: I play a couple of matches every month or two as a lunch-break pastime. Ranking up too high brings out the try-hard mentality.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Delta Force: Hawk Ops&lt;/strong&gt;: About 90 hours played. A great way to decompress on days off. No pay-to-win pressure, and bot matches make it easy to pick up.&lt;/p&gt;&lt;p&gt;At the end of the day, gaming is best when shared with friends.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Anime&lt;a href=&quot;#anime&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I watched quite a lot this year. I realized I don’t dislike anime — I’m just not into most new seasonal shows. Most of what I watched were older series.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Yamada-kun and the Seven Witches&lt;/li&gt;
&lt;li&gt;The Rising of the Shield Hero&lt;/li&gt;
&lt;li&gt;The Magical Revolution of the Reincarnated Princess and the Genius Young Lady&lt;/li&gt;
&lt;li&gt;Classroom of the Elite Season 3&lt;/li&gt;
&lt;li&gt;A Mortal’s Journey to Immortality&lt;/li&gt;
&lt;li&gt;Shrouding the Heavens&lt;/li&gt;
&lt;li&gt;Wandering Witch: The Journey of Elaina&lt;/li&gt;
&lt;li&gt;The Eminence in Shadow&lt;/li&gt;
&lt;li&gt;My Teen Romantic Comedy SNAFU (rewatch)&lt;/li&gt;
&lt;li&gt;Knight’s &amp;amp; Magic (rewatch)&lt;/li&gt;
&lt;li&gt;That Time I Got Reincarnated as a Slime&lt;/li&gt;
&lt;li&gt;Onimai: I’m Now Your Sister! (rewatch)&lt;/li&gt;
&lt;li&gt;Uncle from Another World&lt;/li&gt;
&lt;li&gt;Puella Magi Madoka Magica series&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Movies&lt;a href=&quot;#movies&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Detective Conan: Crossroad in the Ancient Capital&lt;/li&gt;
&lt;li&gt;Nezha: The Devil’s Child Stirs Up the Sea&lt;/li&gt;
&lt;li&gt;Malignant&lt;/li&gt;
&lt;li&gt;Detective Conan: The Afterimage of a Single Eye&lt;/li&gt;
&lt;li&gt;Final Destination: Bloodlines&lt;/li&gt;
&lt;li&gt;Dream Cure&lt;/li&gt;
&lt;li&gt;Operation蛟龙&lt;/li&gt;
&lt;li&gt;Demon Slayer: Infinity Castle&lt;/li&gt;
&lt;li&gt;Zootopia 2&lt;/li&gt;
&lt;li&gt;Scent of a Woman&lt;/li&gt;
&lt;li&gt;Detective Chinatown 1900&lt;/li&gt;
&lt;li&gt;Under the Haze (play at Luojia Mountain Theater)&lt;/li&gt;
&lt;li&gt;Happy Dinner (play at Hubei Theater)&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Travel&lt;a href=&quot;#travel&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The more you go out, the more you suffer along the way — but the novelty you encounter on the road is something you’ll never experience close to home.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Mount Lu, Jiangxi&lt;/strong&gt;: I went during the off-season when it was free. The sun was warm at the foot of the mountain, but the summit was covered in snow. The ice on the steps forced us to walk on tiptoe. Unfortunately, the trip was rushed — after climbing the Five Old Men Peak, we were too exhausted to reach the Three Fold Spring.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Changsha, Hunan&lt;/strong&gt;: I took an overnight green-train after work. The smell of feet and smoke on the train is still unforgettable. My second visit to Changsha opened a whole new door — I experienced what nightlife really means: 24-hour hotpot restaurants, 24-hour Mixue ice cream shops. This time I made it to the top of Yuelu Mountain, which I’d missed before. The mountain breeze and the panoramic view of downtown Changsha were unmatched.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tiantangzhai (Heavenly Village), Anhui&lt;/strong&gt;: I went during National Day. On the way up, the road disappeared into thick clouds with terrible visibility and rain. Then, after passing through a tunnel, the sky suddenly cleared. The walkways were built along cliff faces, swaying with the crowds — quite scary. The air at the summit was the freshest I’ve ever breathed. The cable car ride down was a bit too thrilling for someone who’d just read about cable car mechanics two days earlier.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Request Wildcard SSL Certificates with acme.sh</title><link>https://blog.zinzin.cc/posts/acme-wildcard-ssl-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/acme-wildcard-ssl-en/</guid><description>Get free Let&apos;s Encrypt wildcard certificates via acme.sh + Cloudflare DNS API with automatic renewal.</description><pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Request Wildcard SSL Certificates with acme.sh&lt;a href=&quot;#request-wildcard-ssl-certificates-with-acmesh&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Let’s Encrypt provides free wildcard certificates. Combined with the acme.sh script, you can fully automate issuance and renewal — perfect for personal sites.&lt;/p&gt;&lt;section&gt;&lt;h2&gt;Install acme.sh&lt;a href=&quot;#install-acmesh&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://get.acme.sh&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-s&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;email=my@example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Issue a Certificate (Cloudflare DNS API)&lt;a href=&quot;#issue-a-certificate-cloudflare-dns-api&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;1. Get Your Cloudflare API Key&lt;a href=&quot;#1-get-your-cloudflare-api-key&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Log in to &lt;a href=&quot;https://dash.cloudflare.com/profile/api-tokens&quot; target=&quot;_blank&quot;&gt;Cloudflare Dashboard&lt;/a&gt;, go to API Tokens, and get your Global API Key.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;2. Configure the API Key&lt;a href=&quot;#2-configure-the-api-key&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CF_Key&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;your-cloudflare-api-key&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CF_Email&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;your-cloudflare-email&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;3. Issue the Wildcard Certificate&lt;a href=&quot;#3-issue-the-wildcard-certificate&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Replace with your domain&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;./acme.sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--issue&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--dns&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dns_cf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;example.com&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;.example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;4. Verification&lt;a href=&quot;#4-verification&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The certificate will be installed to &lt;code&gt;~/.acme.sh/&lt;/code&gt;. Check the auto-renewal cron job:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;crontab&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-l&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;acme.sh automatically adds a scheduled task for renewal before expiration.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Working with Nginx Proxy Manager&lt;a href=&quot;#working-with-nginx-proxy-manager&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Copy the generated certificate files to NPM’s directory, or upload them manually through NPM’s web interface.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Notes&lt;a href=&quot;#notes&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Alibaba Cloud DNS, Tencent Cloud DNS, etc., also have their own DNS API scripts available in the &lt;a href=&quot;https://github.com/acmesh-official/acme.sh&quot; target=&quot;_blank&quot;&gt;acme.sh official repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Wildcard certificates only support DNS verification, not HTTP&lt;/li&gt;
&lt;li&gt;Certificates are valid for 90 days; acme.sh handles renewal automatically&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;References&lt;a href=&quot;#references&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Neilpang/acme.sh&quot; target=&quot;_blank&quot;&gt;acme.sh official documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/acmesh-official/acme.sh/blob/master/dnsapi/dns_cf.sh&quot; target=&quot;_blank&quot;&gt;Cloudflare DNS API script&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Docker Image and Container Export/Import Commands Explained</title><link>https://blog.zinzin.cc/posts/docker-export-import-diff-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/docker-export-import-diff-en/</guid><description>Clarifying the differences between docker commit/export/import/save/load and when to use each one.</description><pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Docker Image and Container Export/Import Commands Explained&lt;a href=&quot;#docker-image-and-container-exportimport-commands-explained&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Docker provides several commands for exporting and importing images and containers, which can be confusing for beginners. This article breaks down the key differences.&lt;/p&gt;&lt;section&gt;&lt;h2&gt;docker export / docker import&lt;a href=&quot;#docker-export--docker-import&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;These operate on &lt;strong&gt;containers&lt;/strong&gt; and export a snapshot of the container’s current filesystem.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Export container snapshot&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;container-id&lt;/span&gt;&lt;span&gt; &amp;gt; &lt;/span&gt;&lt;span&gt;snapshot.tar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Import as an image&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;snapshot.tar&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new-image-name:tag&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Only retains filesystem changes made from container start to export — &lt;strong&gt;discards history layers and metadata&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Smaller file size (single filesystem layer)&lt;/li&gt;
&lt;li&gt;Must specify a new image name and tag on import&lt;/li&gt;
&lt;li&gt;Imported images require &lt;code&gt;/bin/bash&lt;/code&gt; or another entrypoint on start&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Creating base images. For example, start a container from ubuntu, install software, then export it as a distributable base image.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;docker commit&lt;a href=&quot;#docker-commit&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Operates on &lt;strong&gt;containers&lt;/strong&gt;, saving modifications as a new image.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;container-id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new-image-name:tag&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Common options:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-a&lt;/code&gt;: Author information&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-m&lt;/code&gt;: Commit message&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-p&lt;/code&gt;: Pause the container during commit&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Preserves the container’s writable layer plus the original image’s history layers&lt;/li&gt;
&lt;li&gt;An N-layer image becomes N+1 layers after commit&lt;/li&gt;
&lt;li&gt;Retains metadata like the entrypoint command&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Quickly save changes from a debugging environment to create a reusable image.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;docker save / docker load&lt;a href=&quot;#docker-save--docker-load&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Operate on &lt;strong&gt;images&lt;/strong&gt;, exporting the complete layer structure.&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Save an image&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;save&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;image.tar&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;image-name:tag&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Load an image&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;image.tar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Preserves the full layer structure and metadata&lt;/li&gt;
&lt;li&gt;Larger file size than export (includes all history layers)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;load&lt;/code&gt; cannot rename the image, while &lt;code&gt;import&lt;/code&gt; can assign a new name&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Offline image migration. On a server without internet, pull the image on a connected machine, save it, copy the archive, then load it on the target server.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Comparison Summary&lt;a href=&quot;#comparison-summary&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;














































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Command&lt;/th&gt;&lt;th&gt;Target&lt;/th&gt;&lt;th&gt;History Layers&lt;/th&gt;&lt;th&gt;File Size&lt;/th&gt;&lt;th&gt;Rename on Import&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;docker export&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Container&lt;/td&gt;&lt;td&gt;❌ Single layer only&lt;/td&gt;&lt;td&gt;Small&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;docker commit&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Container&lt;/td&gt;&lt;td&gt;✅ Adds one layer&lt;/td&gt;&lt;td&gt;Medium&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;docker save&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Image&lt;/td&gt;&lt;td&gt;✅ Full preservation&lt;/td&gt;&lt;td&gt;Large&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;docker load&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Image&lt;/td&gt;&lt;td&gt;✅ Full preservation&lt;/td&gt;&lt;td&gt;Large&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;docker import&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Snapshot file&lt;/td&gt;&lt;td&gt;❌ Single layer only&lt;/td&gt;&lt;td&gt;Small&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;strong&gt;Quick memory aid:&lt;/strong&gt; save/load work with &lt;strong&gt;images&lt;/strong&gt;, export/import work with &lt;strong&gt;containers&lt;/strong&gt;, and commit is the bridge from container → image.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Deploy a Nacos Cluster with Docker</title><link>https://blog.zinzin.cc/posts/docker-nacos-cluster-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/docker-nacos-cluster-en/</guid><description>A complete guide to deploying a 3-node Nacos 2.2 cluster with Docker, using MySQL for persistence and Nginx for load balancing.</description><pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Deploy a Nacos Cluster with Docker&lt;a href=&quot;#deploy-a-nacos-cluster-with-docker&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;Pull the Image&lt;a href=&quot;#pull-the-image&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nacos/nacos-server:v2.2.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;p&gt;Avoid pulling the &lt;code&gt;latest&lt;/code&gt; tag — always pin a specific version for production.&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Database Setup&lt;a href=&quot;#database-setup&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Nacos cluster requires MySQL to store configuration data. MySQL 5.7 is recommended.&lt;/p&gt;&lt;p&gt;Create a database named &lt;code&gt;nacos_config&lt;/code&gt; and run the official initialization script (located in the Nacos source at &lt;code&gt;distribution/conf/nacos-mysql.sql&lt;/code&gt;, which creates &lt;code&gt;config_info&lt;/code&gt;, &lt;code&gt;config_info_aggr&lt;/code&gt;, &lt;code&gt;users&lt;/code&gt;, &lt;code&gt;roles&lt;/code&gt;, and other core tables).&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Create Nacos Containers&lt;a href=&quot;#create-nacos-containers&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Create three Nacos instances to form the cluster. Replace IP addresses in the commands below with your server’s IP.&lt;/p&gt;&lt;section&gt;&lt;h3&gt;Node 1 (Port 8848)&lt;a href=&quot;#node-1-port-8848&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PREFER_HOST_MODE=hostname&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MODE=cluster&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NACOS_APPLICATION_PORT=&lt;/span&gt;&lt;span&gt;8848&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NACOS_SERVERS=&quot;your-server-ip:8848 your-server-ip:8858 your-server-ip:8868&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SPRING_DATASOURCE_PLATFORM=mysql&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_HOST=your-server-ip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_PORT=&lt;/span&gt;&lt;span&gt;3306&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_USER=root&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_PASSWORD=your-password&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_DB_NAME=nacos_config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NACOS_SERVER_IP=your-server-ip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;8848:8848&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;9848:9848&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;9849:9849&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-nacos1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;nacos/nacos-server:v2.2.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Node 2 (Port 8858)&lt;a href=&quot;#node-2-port-8858&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PREFER_HOST_MODE=hostname&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MODE=cluster&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NACOS_APPLICATION_PORT=&lt;/span&gt;&lt;span&gt;8858&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NACOS_SERVERS=&quot;your-server-ip:8848 your-server-ip:8858 your-server-ip:8868&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SPRING_DATASOURCE_PLATFORM=mysql&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_HOST=your-server-ip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_PORT=&lt;/span&gt;&lt;span&gt;3306&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_USER=root&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_PASSWORD=your-password&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_DB_NAME=nacos_config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NACOS_SERVER_IP=your-server-ip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;8858:8858&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;9858:9858&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;9859:9859&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-nacos2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;nacos/nacos-server:v2.2.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Node 3 (Port 8868)&lt;a href=&quot;#node-3-port-8868&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;PREFER_HOST_MODE=hostname&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MODE=cluster&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NACOS_APPLICATION_PORT=&lt;/span&gt;&lt;span&gt;8868&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NACOS_SERVERS=&quot;your-server-ip:8848 your-server-ip:8858 your-server-ip:8868&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SPRING_DATASOURCE_PLATFORM=mysql&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_HOST=your-server-ip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_PORT=&lt;/span&gt;&lt;span&gt;3306&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_USER=root&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_PASSWORD=your-password&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MYSQL_SERVICE_DB_NAME=nacos_config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NACOS_SERVER_IP=your-server-ip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;8868:8868&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;9868:9868&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;9869:9869&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-nacos3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;nacos/nacos-server:v2.2.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Verify the Cluster&lt;a href=&quot;#verify-the-cluster&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Visit &lt;code&gt;http://ip:port/nacos&lt;/code&gt; on any node. The default credentials are &lt;code&gt;nacos/nacos&lt;/code&gt;. You should see all three nodes listed in the Cluster Management page.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Nginx Load Balancing&lt;a href=&quot;#nginx-load-balancing&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;Configure the Upstream&lt;a href=&quot;#configure-the-upstream&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Create a custom configuration in your Nginx Proxy Manager installation directory:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;/path/to/npm/data/nginx/custom/http.conf&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;upstream&lt;/span&gt;&lt;span&gt; nacos {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt; your-server-ip:8848;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt; your-server-ip:8858;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt; your-server-ip:8868;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Configure the Reverse Proxy&lt;a href=&quot;#configure-the-reverse-proxy&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Add a proxy in NPM’s web interface:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Domain: nacos.your-domain.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Forward Hostname: 127.0.0.1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Forward Port: 80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Then add this in the Advanced tab:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;location&lt;/span&gt;&lt;span&gt; / {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;proxy_pass &lt;/span&gt;&lt;span&gt;http://nacos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;After configuring an SSL certificate, you can access the Nacos console at &lt;code&gt;https://nacos.your-domain.com/nacos&lt;/code&gt;.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Note: When using Nginx Proxy Manager, create &lt;code&gt;http.conf&lt;/code&gt; under the &lt;code&gt;nginx/custom/&lt;/code&gt; directory in the container mount. NPM will automatically include this file in the global configuration.&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;References&lt;a href=&quot;#references&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://juejin.cn/post/7175387128648433719&quot; target=&quot;_blank&quot;&gt;Docker Nacos Cluster Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Ee35VIpbBPU&quot; target=&quot;_blank&quot;&gt;Nginx Proxy Manager Load Balancing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Switch Java (JDK) Versions Freely with Scoop</title><link>https://blog.zinzin.cc/posts/scoop-switch-jdk-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/scoop-switch-jdk-en/</guid><description>Install multiple JDK versions on Windows using Scoop package manager and switch between them with a single command — no more manual environment variable tweaking.</description><pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Switch Java (JDK) Versions Freely with Scoop&lt;a href=&quot;#switch-java-jdk-versions-freely-with-scoop&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;In daily development, you often need to switch between different JDK versions like Java 8, Java 11, Java 17, or Java 21. Manual uninstallation and cleanup of registry entries is painful. Scoop makes this effortless.&lt;/p&gt;&lt;section&gt;&lt;h2&gt;Install Scoop&lt;a href=&quot;#install-scoop&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Open PowerShell and run:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Allow local script execution&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Set-ExecutionPolicy&lt;/span&gt;&lt;span&gt;&lt;span&gt; RemoteSigned &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;Scope CurrentUser&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Install Scoop&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;iwr &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;useb get.scoop.sh | iex&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Verify installation&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;scoop help&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Install Multiple JDK Versions&lt;a href=&quot;#install-multiple-jdk-versions&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;1. Add the Java Bucket&lt;a href=&quot;#1-add-the-java-bucket&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;scoop bucket add java&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;2. List Available JDK Versions&lt;a href=&quot;#2-list-available-jdk-versions&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;scoop search jdk&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;3. Install Different Versions&lt;a href=&quot;#3-install-different-versions&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Install OpenJDK 8&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;scoop install openjdk8&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;redhat&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Install OpenJDK 21&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;scoop install openjdk21&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;4. Switch JDK Versions&lt;a href=&quot;#4-switch-jdk-versions&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Switch to JDK 8&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;scoop reset openjdk8&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;redhat&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Switch to JDK 21&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;scoop reset openjdk21&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Switch to GraalVM 21&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;scoop reset graalvm21&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;jdk21&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;p&gt;If you previously installed JDK manually, consider removing the system &lt;code&gt;JAVA_HOME&lt;/code&gt; environment variable — Scoop manages user-level &lt;code&gt;JAVA_HOME&lt;/code&gt; automatically.&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;How It Works&lt;a href=&quot;#how-it-works&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;scoop reset&lt;/code&gt; updates the user’s &lt;code&gt;JAVA_HOME&lt;/code&gt; and &lt;code&gt;PATH&lt;/code&gt; environment variables to point to the selected JDK directory. Changes take effect immediately in new terminal windows — no restart needed.&lt;/p&gt;&lt;p&gt;Similarly, Python, Ruby, Node.js, and other runtimes can be managed with Scoop for effortless version switching.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Server Initialization Guide</title><link>https://blog.zinzin.cc/posts/server-init-guide-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/server-init-guide-en/</guid><description>A checklist for securing and setting up a new Linux server, including SSH hardening, Docker, NPM, and more.</description><pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Server Initialization Guide&lt;a href=&quot;#server-initialization-guide&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;1. System Update&lt;a href=&quot;#1-system-update&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;upgrade&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-y&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;2. Security Hardening&lt;a href=&quot;#2-security-hardening&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;Change the SSH Port&lt;a href=&quot;#change-the-ssh-port&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Edit the SSH config file &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; and change the default port 22:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vim&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/ssh/sshd_config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Find #Port 22, change to Port your-port&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Save and restart the service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ssh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Create a Non-root User&lt;a href=&quot;#create-a-non-root-user&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Create a new user&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;adduser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;your-username&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Install sudo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Add the user to the sudo group&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;usermod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-aG&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;your-username&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Or edit /etc/sudoers to add:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# your-username ALL=(ALL) NOPASSWD: ALL&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Disable Root Remote Login&lt;a href=&quot;#disable-root-remote-login&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# In /etc/ssh/sshd_config, set:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;PermitRootLogin&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;no&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;SSH Key Authentication + Disable Passwords&lt;a href=&quot;#ssh-key-authentication--disable-passwords&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Generate a key pair locally, then copy the public key to the server&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ssh-copy-id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;your-username@your-server-ip&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# In /etc/ssh/sshd_config:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;PasswordAuthentication&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;no&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;PubkeyAuthentication&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;yes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Restart the service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ssh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;3. Install Common Software&lt;a href=&quot;#3-install-common-software&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;Docker&lt;a href=&quot;#docker&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Refer to the &lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/&quot; target=&quot;_blank&quot;&gt;official Docker documentation&lt;/a&gt; for installation.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Nginx Proxy Manager&lt;a href=&quot;#nginx-proxy-manager&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Install NPM via Docker for a web UI to manage reverse proxies and SSL certificates.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;SSL Certificates&lt;a href=&quot;#ssl-certificates&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Use acme.sh + Cloudflare DNS API to issue wildcard certificates with auto-renewal.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Internal Network Tunneling (frp)&lt;a href=&quot;#internal-network-tunneling-frp&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Use frp for internal network tunneling. Newer versions use TOML configuration.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Alist&lt;a href=&quot;#alist&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Multi-storage mounting tool with one-click Docker deployment. See &lt;a href=&quot;https://alist-doc.nn.ci/&quot; target=&quot;_blank&quot;&gt;Alist documentation&lt;/a&gt; for details.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Firewall&lt;a href=&quot;#firewall&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Remember to allow the new SSH port in the firewall&lt;/li&gt;
&lt;li&gt;Use iptables to mitigate SYN and CC attacks&lt;/li&gt;
&lt;li&gt;Only expose necessary ports (80, 443, SSH, etc.)&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>SpringBoot Email Sending with @Async Optimization</title><link>https://blog.zinzin.cc/posts/springboot-email-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/springboot-email-en/</guid><description>Integrate email sending in Spring Boot, implement async email with @Async, and troubleshoot common @Async pitfalls.</description><pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;SpringBoot Email Sending with @Async Optimization&lt;a href=&quot;#springboot-email-sending-with-async-optimization&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;Basic Configuration&lt;a href=&quot;#basic-configuration&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;1. Add the Dependency&lt;a href=&quot;#1-add-the-dependency&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-mail&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;2. Configure Mail Properties&lt;a href=&quot;#2-configure-mail-properties&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;mail&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;your-email@example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;your-auth-code&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;host&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;smtp.163.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;p&gt;The password field requires an &lt;strong&gt;authorization code&lt;/strong&gt;, not your email login password. For 163 mail, enable POP3/SMTP/IMAP in settings and generate an auth code.&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;3. Send a Simple Email&lt;a href=&quot;#3-send-a-simple-email&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequiredArgsConstructor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;EmailController&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;final&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;JavaMailSender&lt;/span&gt;&lt;span&gt; javaMailSender&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/send-email&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sendEmail&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;email&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;SimpleMailMessage&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SimpleMailMessage&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setFrom&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;your-name&amp;lt;your-email@example.com&amp;gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setTo&lt;/span&gt;&lt;span&gt;(email);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setSubject&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Verification Code&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setText&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Your code is: 123456&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;javaMailSender&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;send&lt;/span&gt;&lt;span&gt;(message);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;ok&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Async Sending with @Async&lt;a href=&quot;#async-sending-with-async&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Synchronous email sending blocks the request thread. For high-concurrency scenarios, async is recommended.&lt;/p&gt;&lt;section&gt;&lt;h3&gt;1. Enable Async Support&lt;a href=&quot;#1-enable-async-support&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;SpringBootApplication&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;EnableAsync&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Application&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;static&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;SpringApplication&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;Application&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;, args);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;2. Async Email Service&lt;a href=&quot;#2-async-email-service&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Slf4j&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;EmailService&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Autowired&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;JavaMailSender&lt;/span&gt;&lt;span&gt; javaMailSender&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Autowired&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;StringRedisTemplate&lt;/span&gt;&lt;span&gt; stringRedisTemplate&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Async&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sendVerificationCode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;email&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;code&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;UUID&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;randomUUID&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;toString&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;substring&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;SimpleMailMessage&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SimpleMailMessage&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setFrom&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;your-name&amp;lt;your-email@example.com&amp;gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setTo&lt;/span&gt;&lt;span&gt;(email);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setSubject&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Verification Code&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setText&lt;/span&gt;&lt;span&gt;(code);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;stringRedisTemplate&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;boundValueOps&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;code:&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; email)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;(code, &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;TimeUnit&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;MINUTES&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;javaMailSender&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;send&lt;/span&gt;&lt;span&gt;(message);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;info&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Verification code sent to: {}&quot;&lt;/span&gt;&lt;span&gt;, email);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;3. Custom Thread Pool&lt;a href=&quot;#3-custom-thread-pool&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The default async thread pool has a core pool size of 8. Adjust it as needed:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;task&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;execution&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;pool&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;core-size&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Or via Java configuration:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ThreadPoolTaskExecutor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;threadPoolExecutor&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ThreadPoolTaskExecutor&lt;/span&gt;&lt;span&gt; executor &lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ThreadPoolTaskExecutor&lt;/span&gt;&lt;span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;executor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setCorePoolSize&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;executor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setMaxPoolSize&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;executor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setQueueCapacity&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;executor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setThreadNamePrefix&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;mail-executor-&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;executor&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;initialize&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; executor&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Common @Async Pitfalls&lt;a href=&quot;#common-async-pitfalls&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;@Async&lt;/code&gt; won’t work in these cases:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;The method is not &lt;code&gt;public&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Return type is not &lt;code&gt;void&lt;/code&gt; or &lt;code&gt;Future&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The method is &lt;code&gt;static&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Spring cannot scan the class (missing &lt;code&gt;@Component&lt;/code&gt;/&lt;code&gt;@Service&lt;/code&gt; etc.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Caller and callee are in the same class&lt;/strong&gt; — Spring AOP proxies can’t intercept internal calls&lt;/li&gt;
&lt;li&gt;Creating the object with &lt;code&gt;new&lt;/code&gt; instead of dependency injection&lt;/li&gt;
&lt;li&gt;Adding &lt;code&gt;@Transactional&lt;/code&gt; directly on an &lt;code&gt;@Async&lt;/code&gt; method — put &lt;code&gt;@Transactional&lt;/code&gt; on the called method instead&lt;/li&gt;
&lt;/ol&gt;&lt;blockquote&gt;&lt;p&gt;Reference: &lt;a href=&quot;https://blog.csdn.net/u011413452/article/details/124844941&quot; target=&quot;_blank&quot;&gt;https://blog.csdn.net/u011413452/article/details/124844941&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Send SMS via Tencent Cloud API with Spring Boot</title><link>https://blog.zinzin.cc/posts/springboot-tencent-sms-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/springboot-tencent-sms-en/</guid><description>A progressive guide from raw API debugging to a clean Spring Boot utility class, covering configuration property binding and static utility design.</description><pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Send SMS via Tencent Cloud API with Spring Boot&lt;a href=&quot;#send-sms-via-tencent-cloud-api-with-spring-boot&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;Step 1: Apply for SMS Service&lt;a href=&quot;#step-1-apply-for-sms-service&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Open the Tencent Cloud console, apply for an SMS application, signature, and template.&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Step 2: API Debugging&lt;a href=&quot;#step-2-api-debugging&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You can quickly generate calling code on the &lt;a href=&quot;https://console.cloud.tencent.com/api/explorer?Product=sms&quot; target=&quot;_blank&quot;&gt;Tencent Cloud API Explorer&lt;/a&gt; page.&lt;/p&gt;&lt;section&gt;&lt;h3&gt;Add the Dependency&lt;a href=&quot;#add-the-dependency&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.tencentcloudapi&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;tencentcloud-sdk-java&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.1.838&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Raw Calling Code&lt;a href=&quot;#raw-calling-code&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SendSms&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;static&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;Credential&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cred&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Credential&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;SecretId&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;SecretKey&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;HttpProfile&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;httpProfile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HttpProfile&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;httpProfile&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setEndpoint&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;sms.tencentcloudapi.com&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;ClientProfile&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;clientProfile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ClientProfile&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;clientProfile&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setHttpProfile&lt;/span&gt;&lt;span&gt;(httpProfile);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;SmsClient&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SmsClient&lt;/span&gt;&lt;span&gt;(cred, &lt;/span&gt;&lt;span&gt;&quot;ap-beijing&quot;&lt;/span&gt;&lt;span&gt;, clientProfile);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;SendSmsRequest&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SendSmsRequest&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;phoneNumberSet1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;your-phone-number&quot;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setPhoneNumberSet&lt;/span&gt;&lt;span&gt;(phoneNumberSet1);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setSmsSdkAppId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;1400849908&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setSignName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;your-sign-name&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setTemplateId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;1907520&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;templateParamSet1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;6666&quot;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setTemplateParamSet&lt;/span&gt;&lt;span&gt;(templateParamSet1);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;SendSmsResponse&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SendSms&lt;/span&gt;&lt;span&gt;(req);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;System&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;SendSmsResponse&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;toJsonString&lt;/span&gt;&lt;span&gt;(resp));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;TencentCloudSDKException&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;System&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;toString&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Example response:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;SendStatusSet&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;SerialNo&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;3369:294906593316931104718082751&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;PhoneNumber&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;your-phone-number&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;Fee&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;Code&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Ok&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;Message&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;send success&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;IsoCode&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;CN&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;RequestId&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;69aceba9-a43d-434c-9021-e7320ef52d49&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Step 3: Wrap as a Spring Boot Utility&lt;a href=&quot;#step-3-wrap-as-a-spring-boot-utility&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;1. Configuration Properties&lt;a href=&quot;#1-configuration-properties&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;myapp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;secretId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;your-secret-id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;secretKey&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;your-secret-key&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;smsSdkAppId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;your-sdk-app-id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;signName&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;your-sign-name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;templateId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;your-template-id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;2. Configuration Binding Class&lt;a href=&quot;#2-configuration-binding-class&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;ConfigurationProperties&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;prefix&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;myapp&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyAppProperties&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; secretId&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; secretKey&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; smsSdkAppId&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; signName&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; templateId&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// getters and setters&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;p&gt;Note: Don’t make set methods &lt;code&gt;static&lt;/code&gt;, or &lt;code&gt;@ConfigurationProperties&lt;/code&gt; won’t inject values properly.&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;3. SMS Utility Class&lt;a href=&quot;#3-sms-utility-class&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Slf4j&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SmsUtil&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;static&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SmsClient&lt;/span&gt;&lt;span&gt; client &lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;PostConstruct&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;client &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;createClient&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;MyAppProperties&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getSecretId&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;MyAppProperties&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getSecretKey&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;static&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sendVerificationCode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;phone&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;code&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;SendSmsRequest&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SendSmsRequest&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setPhoneNumberSet&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[]{phone});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setSmsSdkAppId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;MyAppProperties&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getSmsSdkAppId&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setSignName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;MyAppProperties&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getSignName&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setTemplateId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;MyAppProperties&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getTemplateId&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setTemplateParamSet&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[]{code});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;SendSmsResponse&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SendSms&lt;/span&gt;&lt;span&gt;(req);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;info&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;SMS send result: {}&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;SendSmsResponse&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;toJsonString&lt;/span&gt;&lt;span&gt;(resp));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;TencentCloudSDKException&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Failed to send SMS&quot;&lt;/span&gt;&lt;span&gt;, e);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;throw&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RuntimeException&lt;/span&gt;&lt;span&gt;(e);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;static&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SmsClient&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;createClient&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;secretId&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;secretKey&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Credential&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cred&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Credential&lt;/span&gt;&lt;span&gt;(secretId, secretKey);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;HttpProfile&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;httpProfile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HttpProfile&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;httpProfile&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setEndpoint&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;sms.tencentcloudapi.com&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ClientProfile&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;clientProfile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ClientProfile&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;clientProfile&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setHttpProfile&lt;/span&gt;&lt;span&gt;(httpProfile);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SmsClient&lt;/span&gt;&lt;span&gt;(cred, &lt;/span&gt;&lt;span&gt;&quot;ap-beijing&quot;&lt;/span&gt;&lt;span&gt;, clientProfile);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;4. API Endpoint&lt;a href=&quot;#4-api-endpoint&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SmsController&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/sms&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sendSms&lt;/span&gt;&lt;span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;SmsUtil&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;sendVerificationCode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;your-phone&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;1234&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;ok&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Summary&lt;a href=&quot;#summary&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The evolution: API debugging (raw SDK) → externalized configuration (ConfigurationProperties) → static utility class (@PostConstruct initialization). In daily development, the wrapped utility class approach is recommended to avoid duplicating SDK calling logic across business code.&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Deploying Mx Space + Shiro with Nginx Proxy Manager Reverse Proxy</title><link>https://blog.zinzin.cc/posts/mxspace-shiro-deploy-en/</link><guid isPermaLink="true">https://blog.zinzin.cc/posts/mxspace-shiro-deploy-en/</guid><description>A complete tutorial on deploying Mx Space frontend and backend using Nginx Proxy Manager reverse proxy, covering the core backend and the Shiro theme.</description><pubDate>Thu, 01 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Deploying Mx Space + Shiro with Nginx Proxy Manager Reverse Proxy&lt;a href=&quot;#deploying-mx-space--shiro-with-nginx-proxy-manager-reverse-proxy&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;Introduction&lt;a href=&quot;#introduction&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Mix Space is a simple yet powerful personal blog system — fast, modern, and clean. You can use it to build your own personal space, record your life, and share knowledge.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://mx-space.js.org/&quot; target=&quot;_blank&quot;&gt;Mix Space Official Docs&lt;/a&gt;&lt;/p&gt;&lt;p&gt;This tutorial uses Nginx Proxy Manager to reverse-proxy both frontend and backend.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Frontend domain: &lt;code&gt;zinzin.top&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Backend domain: &lt;code&gt;mx.zinzin.top&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Prerequisites&lt;a href=&quot;#prerequisites&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You’ll need the following:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;A server (Linux kernel version &amp;gt; 4.18, RAM &amp;gt; 1GiB; this tutorial uses Debian 11)&lt;/li&gt;
&lt;li&gt;A domain name mapped to your server’s IP&lt;/li&gt;
&lt;li&gt;Docker installed&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Install Nginx Proxy Manager&lt;a href=&quot;#install-nginx-proxy-manager&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code&gt;docker-compose.yml&lt;/code&gt; file in any directory:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;services&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&apos;jc21/nginx-proxy-manager:latest&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;unless-stopped&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ports&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;&apos;80:80&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;&apos;81:81&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;&apos;443:443&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;volumes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;./data:/data&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;./letsencrypt:/etc/letsencrypt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Save the file and start the service:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker-compose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Or&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you’re a first-time user, refer to these guides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.zinzin.cc/archives/tui-jian-yi-ge-nginxguan-li-gong-ju-nginx-proxy-manager&quot;&gt;A recommended nginx management tool: Nginx Proxy Manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nginxproxymanager.com/guide/&quot; target=&quot;_blank&quot;&gt;Official guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Deploy the Backend&lt;a href=&quot;#deploy-the-backend&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Pull the configuration file:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp; &lt;/span&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mx-space/core&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp; &lt;/span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$_&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Download docker-compose.yml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;wget&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://fastly.jsdelivr.net/gh/mx-space/core@master/docker-compose.yml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Edit the &lt;code&gt;environment&lt;/code&gt; fields in &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;JWT_SECRET&lt;/strong&gt;: A string of 16 to 32 characters used to encrypt user JWTs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ALLOWED_ORIGINS&lt;/strong&gt;: Usually the frontend domain; separate multiple domains with commas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ENCRYPT_ENABLE&lt;/strong&gt;: Change &lt;code&gt;false&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; if encryption is needed, and fill in the encryption key.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ENCRYPT_KEY&lt;/strong&gt;: Must be 64 characters long.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Here’s an example configuration — set the JWT secret and allowed domains according to your own setup:&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;services&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;container_name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mx-server&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;innei/mx-server:latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;environment&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;TZ=Asia/Shanghai&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;NODE_ENV=production&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;DB_HOST=mongo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;REDIS_HOST=redis&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;ALLOWED_ORIGINS=zinzin.top&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;JWT_SECRET=Yy14003252791400325279&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;volumes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;./data/mx-space:/root/.mx-space&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ports&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;&apos;2333:2333&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;depends_on&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;mongo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;redis&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;networks&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;mx-space&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;unless-stopped&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;healthcheck&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;test&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;span&gt;&apos;CMD&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;curl&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;-f&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;http://127.0.0.1:2333/api/v2/ping&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;interval&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1m30s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;timeout&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;30s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;retries&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;start_period&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;30s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;mongo&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;container_name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mongo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mongo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;volumes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;./data/db:/data/db&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;networks&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;mx-space&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;unless-stopped&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;redis&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;redis:alpine&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;container_name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;redis&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;41&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;volumes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;42&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;./data/redis:/data&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;43&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;healthcheck&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;44&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;test&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;span&gt;&apos;CMD-SHELL&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;redis-cli ping | grep PONG&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;45&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;start_period&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;20s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;46&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;interval&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;30s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;47&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;retries&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;48&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;timeout&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;49&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;networks&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;50&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;mx-space&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;51&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;unless-stopped&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;52&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;53&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;networks&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;54&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;mx-space&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;55&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;driver&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;bridge&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start the backend service:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker-compose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Or&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once done, you’ll see a screen like this:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://yp.zinzin.cc//blog/20250225232113.png&quot; alt=&quot;core setup complete&quot; /&gt;&lt;figcaption&gt;core setup complete&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Reverse Proxy the Mx Space Backend with Nginx Proxy Manager&lt;a href=&quot;#reverse-proxy-the-mx-space-backend-with-nginx-proxy-manager&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Open the Nginx Proxy Manager admin panel and follow these steps:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://yp.zinzin.cc//blog/20250301130133.png&quot; alt=&quot;nginx step 1&quot; /&gt;&lt;figcaption&gt;nginx step 1&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://yp.zinzin.cc//blog/image-20250301130824412.png&quot; alt=&quot;nginx step 2&quot; /&gt;&lt;figcaption&gt;nginx step 2&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: On servers in mainland China, automatic certificate issuance may fail due to network issues. Try a few times, or upload a certificate manually.&lt;/p&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After it succeeds, visit &lt;code&gt;https://mx.zinzin.top/proxy/qaqdmin&lt;/code&gt; for initial setup:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://yp.zinzin.cc//blog/image-20250301131012065.png&quot; alt=&quot;initial backend setup page&quot; /&gt;&lt;figcaption&gt;initial backend setup page&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The admin panel after successful deployment:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://yp.zinzin.cc//blog/image-20250301131533408.png&quot; alt=&quot;backend admin panel&quot; /&gt;&lt;figcaption&gt;backend admin panel&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Deploy the Shiro Frontend&lt;a href=&quot;#deploy-the-shiro-frontend&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;1. Configure the Theme&lt;a href=&quot;#1-configure-the-theme&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In the admin panel, go to “Extras – Config &amp;amp; Cloud Functions” and fill in the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Name&lt;/strong&gt;: &lt;code&gt;shiro&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reference&lt;/strong&gt;: &lt;code&gt;theme&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data type&lt;/strong&gt;: &lt;code&gt;JSON&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data&lt;/strong&gt;: See the JSON config below.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;json&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;footer&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;otherInfo&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;date&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;2020-{{now}}&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;icp&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;萌 ICP 备 20236136 号&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;link&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;https://icp.gov.moe/?keyword=20236136&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;linkSections&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;About&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;links&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;About this site&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;href&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/about-site&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;About me&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;href&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/about&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;About this project&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;href&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;https://github.com/innei/Shiro&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;external&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;More&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;links&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Timeline&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;href&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/timeline&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Friends&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;href&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/friends&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;41&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Monitor&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;42&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;href&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;https://status.innei.in/status/main&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;43&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;external&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;44&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;45&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;46&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;47&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;48&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Contact&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;49&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;links&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;50&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;51&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Leave a message&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;52&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;href&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/message&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;53&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;54&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;55&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Send email&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;56&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;href&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;mailto:i@innei.ren&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;57&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;external&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;58&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;59&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;60&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;GitHub&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;61&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;href&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;https://github.com/innei&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;62&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;external&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;63&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;64&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;65&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;66&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;67&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;68&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;config&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;69&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;color&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;70&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;light&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;71&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#33A6B8&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;72&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#FF6666&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;73&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#26A69A&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;74&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#fb7287&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;75&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#69a6cc&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;76&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#F11A7B&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;77&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#78C1F3&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;78&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#FF6666&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;79&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#7ACDF6&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;80&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;81&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;dark&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;82&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#F596AA&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;83&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#A0A7D4&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;84&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#ff7b7b&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;85&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#99D8CF&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;86&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#838BC6&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;87&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#FFE5AD&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;88&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#9BE8D8&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;89&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#A1CCD1&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;90&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;#EAAEBA&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;91&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;92&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;93&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;94&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;bg&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;95&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;https://github.com/Innei/static/blob/master/images/F0q8mwwaIAEtird.jpeg?raw=true&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;96&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;https://github.com/Innei/static/blob/master/images/IMG_2111.jpeg.webp.jpg?raw=true&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;97&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;98&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;custom&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;99&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;css&quot;&lt;/span&gt;&lt;span&gt;: [],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;100&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;styles&quot;&lt;/span&gt;&lt;span&gt;: [],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;101&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;js&quot;&lt;/span&gt;&lt;span&gt;: [],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;102&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span&gt;: []&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;103&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;104&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;site&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;105&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;favicon&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/innei.svg&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;106&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;faviconDark&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/innei-dark.svg&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;107&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;108&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;hero&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;109&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;title&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;110&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;template&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;111&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;112&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;h1&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;113&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Hi, I&apos;m &quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;114&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;class&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;font-light text-4xl&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;115&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;116&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;117&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;h1&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;118&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;Innei&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;119&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;class&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;font-medium mx-2 text-4xl&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;120&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;121&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;122&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;h1&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;123&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;👋。&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;124&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;class&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;font-light text-4xl&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;125&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;126&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;127&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;br&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;128&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;129&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;130&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;h1&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;131&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;A NodeJS Full Stack &quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;132&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;class&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;font-light text-4xl&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;133&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;134&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;135&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;code&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;136&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&amp;lt;Developer /&amp;gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;137&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;class&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;font-medium mx-2 text-3xl rounded p-1 bg-gray-200 dark:bg-gray-800/0 hover:dark:bg-gray-800/100 bg-opacity-0 hover:bg-opacity-100 transition-background duration-200&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;138&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;139&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;140&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;type&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;span&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;141&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;class&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;inline-block w-[1px] h-8 -bottom-2 relative bg-gray-800/80 dark:bg-gray-200/80 opacity-0 group-hover:opacity-100 transition-opacity duration-200 group-hover:animation-blink&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;142&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;143&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;144&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;145&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;description&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;An independent developer coding with love.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;146&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;147&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;module&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;148&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;activity&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;149&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;enable&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;150&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;endpoint&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;/fn/ps/update&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;151&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;152&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;donate&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;153&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;enable&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;154&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;link&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;https://afdian.net/@Innei&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;155&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;qrcode&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;156&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;https://cdn.jsdelivr.net/gh/Innei/img-bed@master/20191211132347.png&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;157&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;https://cdn.innei.ren/bed/2023/0424213144.png&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;158&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;159&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;160&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;bilibili&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;161&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;liveId&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1434499&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;162&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;163&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;164&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;165&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://yp.zinzin.cc//blog/image-20250301132618667.png&quot; alt=&quot;theme configuration&quot; /&gt;&lt;figcaption&gt;theme configuration&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: For detailed configuration, refer to the official docs: &lt;a href=&quot;https://mx-space.js.org/docs/themes/shiro/config&quot; target=&quot;_blank&quot;&gt;Config Options&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;2. Deploy Shiro with Docker Compose&lt;a href=&quot;#2-deploy-shiro-with-docker-compose&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create and enter the &lt;code&gt;shiro&lt;/code&gt; directory:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shiro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shiro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Download the required files:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;wget&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://raw.githubusercontent.com/Innei/Shiro/main/docker-compose.yml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;wget&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://raw.githubusercontent.com/Innei/Shiro/main/.env.template&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mv&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.env.template&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.env&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update the backend URL in the &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vim&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.env&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# Edit your ENV variables&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://yp.zinzin.cc//blog/image-20250301142658945.png&quot; alt=&quot;set the backend URL in env&quot; /&gt;&lt;figcaption&gt;set the backend URL in env&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After saving, start the service:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Or&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker-compose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To update the image later:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compose&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;3. Reverse Proxy Shiro with Nginx Proxy Manager&lt;a href=&quot;#3-reverse-proxy-shiro-with-nginx-proxy-manager&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://yp.zinzin.cc//blog/image-20250301155851489.png&quot; alt=&quot;Shiro reverse proxy 1&quot; /&gt;&lt;figcaption&gt;Shiro reverse proxy 1&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://yp.zinzin.cc//blog/image-20250301160044646.png&quot; alt=&quot;Shiro reverse proxy 2&quot; /&gt;&lt;figcaption&gt;Shiro reverse proxy 2&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Follow the prompts to configure the reverse proxy. If all services run on the same machine, you can use internal IP addresses directly.&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Access the Main Site&lt;a href=&quot;#access-the-main-site&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Once everything is deployed, visit &lt;code&gt;https://zinzin.top&lt;/code&gt; to see the main site:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://yp.zinzin.cc//blog/image-20250301144546292.png&quot; alt=&quot;main site&quot; /&gt;&lt;figcaption&gt;main site&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Done!!&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;If you run into other issues during deployment, check the community:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://mx-space.js.org/docs/core/community&quot; target=&quot;_blank&quot;&gt;Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://yono233.xlog.app/24_7_12_jjzl?ref=cms.1900.live&amp;amp;locale=ja&quot; target=&quot;_blank&quot;&gt;Additional notes for mainland China servers&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Notes&lt;a href=&quot;#notes&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;If automatic certificate issuance keeps failing with network errors on a mainland China server, you can manually apply for a certificate from your domain registrar and upload it to Nginx Proxy Manager.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://yp.zinzin.cc//blog/image-20250302191136537.png&quot; alt=&quot;certificate upload&quot; /&gt;&lt;figcaption&gt;certificate upload&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item></channel></rss>